From 8d435d44109e0bb4efde6b2d367c47a953ccb667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 15:21:32 +0800 Subject: [PATCH 1/8] test order difficulty --- gateway/order_difficulty/difficulty.go | 150 +++++++++++++++----- gateway/order_difficulty/difficulty_test.go | 84 +++++++++++ gateway/wallet_service.go | 13 ++ node/config.go | 2 + node/node.go | 45 +++--- 5 files changed, 242 insertions(+), 52 deletions(-) create mode 100644 gateway/order_difficulty/difficulty_test.go diff --git a/gateway/order_difficulty/difficulty.go b/gateway/order_difficulty/difficulty.go index 450ccad7..39bf6084 100644 --- a/gateway/order_difficulty/difficulty.go +++ b/gateway/order_difficulty/difficulty.go @@ -19,6 +19,7 @@ package order_difficulty import ( + "encoding/json" "github.com/Loopring/relay-lib/cache" "github.com/Loopring/relay-lib/eventemitter" "github.com/Loopring/relay-lib/types" @@ -33,32 +34,50 @@ import ( const ( OrderCountPerSecond = "o_cnt_per_s_" - OrderDifficulty = "order_diff" + OrderDifficultyKey = "order_diff" ZklockDifficulty = "zklock_diff" ) type OrderDifficultyEvaluator struct { //currentDifficult *OrderDifficulty //parentDifficult *OrderDifficulty - evaluator Evaluator - baseDifficulty *big.Int - orderTraffic int64 - triggerThreshold float64 - stopFuns []func() - calCount int64 //must be odd + evaluator Evaluator + stopFuns []func() + calCount int64 //must be odd + duration int64 } type OrderDifficulty struct { - difficulty *big.Int - ordersNum int64 - timeStamp int64 + Difficulty common.Hash + OrdersNum int64 + TimeStamp int64 } -func (evaluator *OrderDifficultyEvaluator) getCacheKey(createTime int64) (key string, expireAt int64) { +func (evaluator *OrderDifficultyEvaluator) getOrderCacheKey(createTime int64) (key string, expireAt int64) { mod := createTime % evaluator.calCount orderSection := createTime - mod orderSectionStr := strconv.FormatInt(orderSection, 10) - return OrderCountPerSecond + orderSectionStr, createTime + evaluator.calCount + return OrderCountPerSecond + orderSectionStr, createTime + evaluator.calCount*evaluator.duration +} + +func (evaluator *OrderDifficultyEvaluator) getDiffCacheKey(createTime int64) (key string, expireAt int64) { + mod := createTime % evaluator.calCount + orderSection := createTime - mod + orderSectionStr := strconv.FormatInt(orderSection, 10) + return OrderDifficultyKey + orderSectionStr, createTime + evaluator.calCount*evaluator.duration +} + +func NewOrderDifficultyEvaluator(config OrderDifficultyConfig) *OrderDifficultyEvaluator { + evaluator := &OrderDifficultyEvaluator{calCount: config.CalCount, duration: config.Duration} + evaluator.evaluator = &LinearEvaluator{baseDifficulty: config.BaseDifficulty, threshold: config.Threshold} + return evaluator +} + +type OrderDifficultyConfig struct { + BaseDifficulty *big.Int + Threshold int64 + CalCount int64 + Duration int64 } func (evaluator *OrderDifficultyEvaluator) Start() { @@ -68,27 +87,50 @@ func (evaluator *OrderDifficultyEvaluator) Start() { log.Errorf("erro:%s", err.Error()) } else { now := time.Now().Unix() - orderCntList := []int64{} + orderCntList := []*OrderDifficulty{} for i := evaluator.calCount; i > 0; i-- { - t := now - i - cacheKey, _ := evaluator.getCacheKey(t) + t := now - i*evaluator.duration + cacheKey, _ := evaluator.getDiffCacheKey(t) + orderDifficulty := &OrderDifficulty{} if data, err := cache.Get(cacheKey); nil == err { - cnt, _ := strconv.ParseInt(string(data), 10, 0) - orderCntList = append(orderCntList, cnt) + json.Unmarshal(data, orderDifficulty) } + orderCntList = append(orderCntList, orderDifficulty) } for { select { - case <-time.After(2 * time.Second): - cacheKey, _ := evaluator.getCacheKey(time.Now().Unix() - 1) - if data, err := cache.Get(cacheKey); nil == err { - cnt, _ := strconv.ParseInt(string(data), 10, 0) - orderCntList = append(orderCntList, cnt) + case <-time.After(time.Duration(evaluator.duration) * time.Second): + now := time.Now().Unix() + if diffHash, err := GetDifficulty(); nil == err { + currentDiff := diffHash + orderDiff := &OrderDifficulty{} + cacheKey, _ := evaluator.getOrderCacheKey(now) + orderDiff.OrdersNum = 60 + if data, err1 := cache.Get(cacheKey); nil == err1 { + if orderNum, err3 := strconv.Atoi(string(data)); nil == err3 { + orderDiff.OrdersNum = int64(orderNum) + } + } + diffCacheKey, _ := evaluator.getDiffCacheKey(now) + orderDiff.Difficulty = currentDiff + if data, err4 := json.Marshal(orderDiff); nil == err4 { + cache.Set(diffCacheKey, data, (evaluator.calCount+2)*evaluator.duration) + } + } + orderCntList := []*OrderDifficulty{} + for i := evaluator.calCount; i > 0; i-- { + t := now - i*evaluator.duration + diffCacheKey, _ := evaluator.getDiffCacheKey(t) + orderDifficulty := &OrderDifficulty{} + if data, err := cache.Get(diffCacheKey); nil == err { + json.Unmarshal(data, orderDifficulty) + } + orderCntList = append(orderCntList, orderDifficulty) } - diff := evaluator.evaluator.CalcAndSaveDifficulty(orderCntList) + diff := evaluator.evaluator.CalcAndSaveDifficulty(orderCntList, evaluator.duration) diffHash := common.BytesToHash(diff.Bytes()) - cache.Set(OrderDifficulty, []byte(diffHash.Hex()), int64(0)) - orderCntList = orderCntList[1:] + log.Infof("current order difficulty:%s", diff.String()) + cache.Set(OrderDifficultyKey, []byte(diffHash.Hex()), int64(0)) } } } @@ -101,12 +143,12 @@ func (evaluator *OrderDifficultyEvaluator) Stop() { } } -//add ordersNum +//add OrdersNum func (evaluator *OrderDifficultyEvaluator) HandleNewOrder() { watcher := &eventemitter.Watcher{ Concurrent: false, Handle: func(input eventemitter.EventData) error { state := input.(*types.OrderState) - cacheKey, expireAt := evaluator.getCacheKey(state.RawOrder.CreateTime) + cacheKey, expireAt := evaluator.getOrderCacheKey(state.RawOrder.CreateTime) _, err := cache.Incr(cacheKey) if nil == err { err = cache.ExpireAt(cacheKey, expireAt) @@ -122,27 +164,69 @@ func (evaluator *OrderDifficultyEvaluator) HandleNewOrder() { } type Evaluator interface { - CalcAndSaveDifficulty(orderCntList []int64) *big.Int + CalcAndSaveDifficulty(orderCntList []*OrderDifficulty, duration int64) *big.Int + getBaseDifficulty() *big.Int } type LinearEvaluator struct { + baseDifficulty *big.Int + threshold int64 } -//控制订单的提交速度,随着订单的流量增大而增大 -func (evaluator *LinearEvaluator) CalcAndSaveDifficulty(orderCntList []int64) *big.Int { +func (evaluator *LinearEvaluator) getBaseDifficulty() *big.Int { + return new(big.Int).Set(evaluator.baseDifficulty) +} + +func (evaluator *LinearEvaluator) CalNextOrderCnt(orderCntList []*OrderDifficulty, duration int64) int64 { xes := []float64{} yes := []float64{} now := time.Now().Unix() for idx, cnt := range orderCntList { - xes = append(xes, float64(idx)) - yes = append(yes, float64(cnt)) + //println("sum",cnt.OrdersNum) + xes = append(xes, float64(now-duration*int64(len(orderCntList)-idx))) + yes = append(yes, float64(cnt.OrdersNum)) } alpha, beta := stat.LinearRegression(xes, yes, nil, false) return int64(beta*float64(now) + alpha) } +//控制订单的提交速度,随着订单的流量增大而增大 +func (evaluator *LinearEvaluator) CalcAndSaveDifficulty(orderCntList []*OrderDifficulty, duration int64) *big.Int { + nextCnt := evaluator.CalNextOrderCnt(orderCntList, duration) + log.Infof("next order count:%d", nextCnt) + orderList := append(orderCntList, &OrderDifficulty{OrdersNum: nextCnt}) + return evaluator.nextDifficulty(orderList) +} + +func NewOrderDiff(ordersNum int64, diff common.Hash) *OrderDifficulty { + return &OrderDifficulty{OrdersNum: ordersNum, Difficulty: diff} +} + +func NewLinearEvaluator(baseDifficulty *big.Int, threshold int64) *LinearEvaluator { + return &LinearEvaluator{baseDifficulty: baseDifficulty, threshold: threshold} +} + +func (evaluator *LinearEvaluator) nextDifficulty(orderCntList []*OrderDifficulty) *big.Int { + nextOrderDiff := orderCntList[len(orderCntList)-1] + if nextOrderDiff.OrdersNum < evaluator.threshold { + return evaluator.baseDifficulty + } else { + currentDiff := new(big.Int).Set(evaluator.baseDifficulty) + if currentDiffBytes, err := GetDifficulty(); nil == err { + currentDiff = new(big.Int).SetBytes(currentDiffBytes.Bytes()) + } + addRatio := big.NewInt(3) + if nextOrderDiff.OrdersNum > int64(float64(evaluator.threshold)*1.5) { + addRatio = big.NewInt(1) + } else if nextOrderDiff.OrdersNum < int64(float64(evaluator.threshold)*1.2) { + addRatio = big.NewInt(5) + } + return new(big.Int).Add(currentDiff, new(big.Int).Quo(currentDiff, addRatio)) + } +} + func GetDifficulty() (common.Hash, error) { - if data, err := cache.Get(OrderDifficulty); nil == err { + if data, err := cache.Get(OrderDifficultyKey); nil == err { return common.HexToHash(string(data)), nil } else { return common.Hash{}, err diff --git a/gateway/order_difficulty/difficulty_test.go b/gateway/order_difficulty/difficulty_test.go new file mode 100644 index 00000000..19180cad --- /dev/null +++ b/gateway/order_difficulty/difficulty_test.go @@ -0,0 +1,84 @@ +/* + + Copyright 2017 Loopring Project Ltd (Loopring Foundation). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +package order_difficulty_test + +import ( + "encoding/json" + "github.com/Loopring/relay-cluster/gateway/order_difficulty" + "github.com/Loopring/relay-lib/cache" + "github.com/Loopring/relay-lib/cache/redis" + "github.com/Loopring/relay-lib/log" + "github.com/Loopring/relay-lib/zklock" + "github.com/ethereum/go-ethereum/common" + "go.uber.org/zap" + "math/big" + "testing" + "time" +) + +func init() { + logConfig := `{ + "level": "debug", + "development": false, + "encoding": "json", + "outputPaths": ["stdout"], + "errorOutputPaths": ["stderr"], + "encoderConfig": { + "messageKey": "message", + "levelKey": "level", + "levelEncoder": "lowercase" + } + }` + rawJSON := []byte(logConfig) + + var ( + cfg zap.Config + err error + ) + if err = json.Unmarshal(rawJSON, &cfg); err != nil { + panic(err) + } + log.Initialize(cfg) + cache.NewCache(redis.RedisOptions{Host: "127.0.0.1", Port: "6379"}) + zklock.Initialize(zklock.ZkLockConfig{ZkServers: "127.0.0.1:2181", ConnectTimeOut: 10000}) + +} + +func TestEvaluator(t *testing.T) { + config := order_difficulty.OrderDifficultyConfig{BaseDifficulty: big.NewInt(1000), Threshold: 100, Duration: 2, CalCount: 100} + evaluator := order_difficulty.NewOrderDifficultyEvaluator(config) + evaluator.Start() + time.Sleep(1000000 * time.Second) +} + +func TestLinearEvaluator_CalcAndSaveDifficulty(t *testing.T) { + evaluator := order_difficulty.NewLinearEvaluator(big.NewInt(100), 200) + cntList := make([]*order_difficulty.OrderDifficulty, 0) + cntList = append(cntList, order_difficulty.NewOrderDiff(100, common.BytesToHash(big.NewInt(100).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(900, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(900, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(600, common.BytesToHash(big.NewInt(200).Bytes()))) + //cntList = append(cntList, order_difficulty.NewOrderDiff(700, common.BytesToHash(big.NewInt(200).Bytes()))) + //cntList = append(cntList, order_difficulty.NewOrderDiff(700, common.BytesToHash(big.NewInt(200).Bytes()))) + println(evaluator.CalcAndSaveDifficulty(cntList, 10).String()) +} diff --git a/gateway/wallet_service.go b/gateway/wallet_service.go index e5d4c7bc..efd2bfdb 100644 --- a/gateway/wallet_service.go +++ b/gateway/wallet_service.go @@ -24,6 +24,7 @@ import ( "fmt" "github.com/Loopring/relay-cluster/accountmanager" "github.com/Loopring/relay-cluster/dao" + "github.com/Loopring/relay-cluster/gateway/order_difficulty" "github.com/Loopring/relay-cluster/market" "github.com/Loopring/relay-cluster/ordermanager/manager" "github.com/Loopring/relay-cluster/ordermanager/viewer" @@ -411,6 +412,13 @@ type AddTokenReq struct { Decimals string `json:"decimals"` } +type OrderDifficultyReq struct { +} + +type OrderDifficultyRes struct { + Difficulty common.Hash `json:"difficulty"` +} + type WalletServiceImpl struct { trendManager market.TrendManager orderViewer viewer.OrderViewer @@ -546,6 +554,11 @@ func (w *WalletServiceImpl) GetPriceQuote(query PriceQuoteQuery) (result PriceQu return rst, nil } +func (w *WalletServiceImpl) GetOrderDifficulty(req OrderDifficultyReq) (result OrderDifficultyRes, err error) { + diff, err1 := order_difficulty.GetDifficulty() + return OrderDifficultyRes{Difficulty: diff}, err1 +} + func (w *WalletServiceImpl) GetTickers(mkt SingleMarket) (result map[string]market.Ticker, err error) { result = make(map[string]market.Ticker) loopringTicker, err := w.trendManager.GetTickerByMarket(mkt.Market) diff --git a/node/config.go b/node/config.go index bf39d082..b10d4ac1 100644 --- a/node/config.go +++ b/node/config.go @@ -25,6 +25,7 @@ import ( "github.com/Loopring/relay-cluster/accountmanager" "github.com/Loopring/relay-cluster/gateway" + "github.com/Loopring/relay-cluster/gateway/order_difficulty" "github.com/Loopring/relay-cluster/market" ordermanager "github.com/Loopring/relay-cluster/ordermanager/common" "github.com/Loopring/relay-cluster/usermanager" @@ -84,6 +85,7 @@ type GlobalConfig struct { AccountManager accountmanager.AccountManagerOptions MyToken market.MyTokenConfig CloudWatch cloudwatch.CloudWatchConfig + OrderDifficulty order_difficulty.OrderDifficultyConfig } func Validator(cv reflect.Value) (bool, error) { diff --git a/node/node.go b/node/node.go index ebf65f0e..be94a73f 100644 --- a/node/node.go +++ b/node/node.go @@ -25,9 +25,11 @@ import ( "github.com/Loopring/relay-cluster/accountmanager" "github.com/Loopring/relay-cluster/dao" "github.com/Loopring/relay-cluster/gateway" + "github.com/Loopring/relay-cluster/gateway/order_difficulty" "github.com/Loopring/relay-cluster/market" ordermanager "github.com/Loopring/relay-cluster/ordermanager/manager" orderviewer "github.com/Loopring/relay-cluster/ordermanager/viewer" + ringtrackerviewer "github.com/Loopring/relay-cluster/ringtrackermanager/viewer" txmanager "github.com/Loopring/relay-cluster/txmanager/manager" txviewer "github.com/Loopring/relay-cluster/txmanager/viewer" "github.com/Loopring/relay-cluster/usermanager" @@ -46,31 +48,30 @@ import ( "github.com/Loopring/relay-lib/zklock" "github.com/ethereum/go-ethereum/accounts/keystore" "go.uber.org/zap" - ringtrackerviewer "github.com/Loopring/relay-cluster/ringtrackermanager/viewer" ) type Node struct { globalConfig *GlobalConfig rdsService *dao.RdsService //ipfsSubService gateway.IPFSSubService - orderManager ordermanager.OrderManager - orderViewer orderviewer.OrderViewer - userManager usermanager.UserManager - marketCapProvider marketcap.MarketCapProvider - accountManager accountmanager.AccountManager - trendManager market.TrendManager - tickerCollector market.CollectorImpl - tickerManager market.GetTickerImpl - globalMarket market.GlobalMarket - jsonRpcService gateway.JsonrpcServiceImpl - websocketService gateway.WebsocketServiceImpl - socketIOService gateway.SocketIOServiceImpl - walletService gateway.WalletServiceImpl - txManager txmanager.TransactionManager - motanService *gateway.MotanService - - wg *sync.WaitGroup - logger *zap.Logger + orderManager ordermanager.OrderManager + orderViewer orderviewer.OrderViewer + userManager usermanager.UserManager + marketCapProvider marketcap.MarketCapProvider + accountManager accountmanager.AccountManager + trendManager market.TrendManager + tickerCollector market.CollectorImpl + tickerManager market.GetTickerImpl + globalMarket market.GlobalMarket + jsonRpcService gateway.JsonrpcServiceImpl + websocketService gateway.WebsocketServiceImpl + socketIOService gateway.SocketIOServiceImpl + walletService gateway.WalletServiceImpl + txManager txmanager.TransactionManager + motanService *gateway.MotanService + orderDifficultyEvaluator *order_difficulty.OrderDifficultyEvaluator + wg *sync.WaitGroup + logger *zap.Logger ringTrackerViewer ringtrackerviewer.RingTrackerViewer ringTrackerService gateway.RingTrackerServiceImpl @@ -118,6 +119,7 @@ func NewNode(logger *zap.Logger, globalConfig *GlobalConfig) *Node { n.registerRingTrackerViewer() n.registerRingTrackerService() + n.registerOrderDifficultyEvaluator() return n } @@ -135,6 +137,7 @@ func (n *Node) Start() { //n.websocketService.Start() go n.socketIOService.Start() gateway.StartMotanService(n.globalConfig.MotanServer, n.accountManager, n.orderViewer) + n.orderDifficultyEvaluator.Start() n.wg.Add(1) } @@ -268,6 +271,10 @@ func (n *Node) registerCloudWatch() { cloudwatch.Initialize(n.globalConfig.CloudWatch) } +func (n *Node) registerOrderDifficultyEvaluator() { + n.orderDifficultyEvaluator = order_difficulty.NewOrderDifficultyEvaluator(n.globalConfig.OrderDifficulty) +} + func (n *Node) registerRingTrackerViewer() { n.ringTrackerViewer = ringtrackerviewer.NewRingTrackerViewer(n.rdsService, n.marketCapProvider) } From 999f996f7a275abc8d4bd31aa87b491e6091fbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 15:36:42 +0800 Subject: [PATCH 2/8] test order difficulty --- gateway/order_difficulty/difficulty.go | 39 +++++++++++++++------ gateway/order_difficulty/difficulty_test.go | 2 +- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/gateway/order_difficulty/difficulty.go b/gateway/order_difficulty/difficulty.go index 39bf6084..e5f78039 100644 --- a/gateway/order_difficulty/difficulty.go +++ b/gateway/order_difficulty/difficulty.go @@ -68,6 +68,18 @@ func (evaluator *OrderDifficultyEvaluator) getDiffCacheKey(createTime int64) (ke } func NewOrderDifficultyEvaluator(config OrderDifficultyConfig) *OrderDifficultyEvaluator { + if nil == config.BaseDifficulty { + config.BaseDifficulty = big.NewInt(0) + } + if 0 == config.CalCount { + config.CalCount = 1000 + } + if 0 == config.Duration { + config.Duration = 2 + } + if 0 == config.Threshold { + config.Threshold = 10 + } evaluator := &OrderDifficultyEvaluator{calCount: config.CalCount, duration: config.Duration} evaluator.evaluator = &LinearEvaluator{baseDifficulty: config.BaseDifficulty, threshold: config.Threshold} return evaluator @@ -86,17 +98,22 @@ func (evaluator *OrderDifficultyEvaluator) Start() { if err := zklock.TryLock(ZklockDifficulty); nil != err { log.Errorf("erro:%s", err.Error()) } else { - now := time.Now().Unix() - orderCntList := []*OrderDifficulty{} - for i := evaluator.calCount; i > 0; i-- { - t := now - i*evaluator.duration - cacheKey, _ := evaluator.getDiffCacheKey(t) - orderDifficulty := &OrderDifficulty{} - if data, err := cache.Get(cacheKey); nil == err { - json.Unmarshal(data, orderDifficulty) - } - orderCntList = append(orderCntList, orderDifficulty) + if _, err1 := GetDifficulty(); nil != err1 { + println("##########") + diff := common.BytesToHash(evaluator.evaluator.getBaseDifficulty().Bytes()) + cache.Set(OrderDifficultyKey, []byte(diff.Hex()), int64(10000)) } + //now := time.Now().Unix() + //orderCntList := []*OrderDifficulty{} + //for i := evaluator.calCount; i > 0; i-- { + // t := now - i*evaluator.duration + // cacheKey, _ := evaluator.getDiffCacheKey(t) + // orderDifficulty := &OrderDifficulty{} + // if data, err := cache.Get(cacheKey); nil == err { + // json.Unmarshal(data, orderDifficulty) + // } + // orderCntList = append(orderCntList, orderDifficulty) + //} for { select { case <-time.After(time.Duration(evaluator.duration) * time.Second): @@ -105,7 +122,7 @@ func (evaluator *OrderDifficultyEvaluator) Start() { currentDiff := diffHash orderDiff := &OrderDifficulty{} cacheKey, _ := evaluator.getOrderCacheKey(now) - orderDiff.OrdersNum = 60 + orderDiff.OrdersNum = 0 if data, err1 := cache.Get(cacheKey); nil == err1 { if orderNum, err3 := strconv.Atoi(string(data)); nil == err3 { orderDiff.OrdersNum = int64(orderNum) diff --git a/gateway/order_difficulty/difficulty_test.go b/gateway/order_difficulty/difficulty_test.go index 19180cad..9dd69d6d 100644 --- a/gateway/order_difficulty/difficulty_test.go +++ b/gateway/order_difficulty/difficulty_test.go @@ -61,7 +61,7 @@ func init() { } func TestEvaluator(t *testing.T) { - config := order_difficulty.OrderDifficultyConfig{BaseDifficulty: big.NewInt(1000), Threshold: 100, Duration: 2, CalCount: 100} + config := order_difficulty.OrderDifficultyConfig{} evaluator := order_difficulty.NewOrderDifficultyEvaluator(config) evaluator.Start() time.Sleep(1000000 * time.Second) From 5ceecbd39483334ca25e6b535d741cd23ea9b42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 15:41:12 +0800 Subject: [PATCH 3/8] test order difficulty --- gateway/order_difficulty/difficulty.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/order_difficulty/difficulty.go b/gateway/order_difficulty/difficulty.go index e5f78039..08c42f6a 100644 --- a/gateway/order_difficulty/difficulty.go +++ b/gateway/order_difficulty/difficulty.go @@ -22,12 +22,12 @@ import ( "encoding/json" "github.com/Loopring/relay-lib/cache" "github.com/Loopring/relay-lib/eventemitter" + "github.com/Loopring/relay-lib/log" "github.com/Loopring/relay-lib/types" "github.com/Loopring/relay-lib/zklock" "github.com/ethereum/go-ethereum/common" "gonum.org/v1/gonum/stat" "math/big" - "qiniupkg.com/x/log.v7" "strconv" "time" ) From 165a4dcc3c565766c25a7fbe7883ea18eb68d69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 15:46:18 +0800 Subject: [PATCH 4/8] test order difficulty --- vendor/gonum.org/v1/gonum/LICENSE | 23 + vendor/gonum.org/v1/gonum/stat/README.md | 3 + vendor/gonum.org/v1/gonum/stat/doc.go | 6 + vendor/gonum.org/v1/gonum/stat/pca_cca.go | 315 ++++++ vendor/gonum.org/v1/gonum/stat/roc.go | 121 +++ vendor/gonum.org/v1/gonum/stat/stat.go | 1160 +++++++++++++++++++++ vendor/gonum.org/v1/gonum/stat/statmat.go | 146 +++ vendor/vendor.json | 6 + 8 files changed, 1780 insertions(+) create mode 100644 vendor/gonum.org/v1/gonum/LICENSE create mode 100644 vendor/gonum.org/v1/gonum/stat/README.md create mode 100644 vendor/gonum.org/v1/gonum/stat/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/pca_cca.go create mode 100644 vendor/gonum.org/v1/gonum/stat/roc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/stat.go create mode 100644 vendor/gonum.org/v1/gonum/stat/statmat.go diff --git a/vendor/gonum.org/v1/gonum/LICENSE b/vendor/gonum.org/v1/gonum/LICENSE new file mode 100644 index 00000000..76edf5ef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/LICENSE @@ -0,0 +1,23 @@ +Copyright ©2013 The gonum Authors. 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 the gonum project nor the names of its authors and + 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/gonum.org/v1/gonum/stat/README.md b/vendor/gonum.org/v1/gonum/stat/README.md new file mode 100644 index 00000000..31615b05 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/README.md @@ -0,0 +1,3 @@ +# Gonum stat [![GoDoc](https://godoc.org/gonum.org/v1/gonum/stat?status.svg)](https://godoc.org/gonum.org/v1/gonum/stat) + +Package stat is a statistics package for the Go language. diff --git a/vendor/gonum.org/v1/gonum/stat/doc.go b/vendor/gonum.org/v1/gonum/stat/doc.go new file mode 100644 index 00000000..0225eef9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 stat provides generalized statistical functions. +package stat // import "gonum.org/v1/gonum/stat" diff --git a/vendor/gonum.org/v1/gonum/stat/pca_cca.go b/vendor/gonum.org/v1/gonum/stat/pca_cca.go new file mode 100644 index 00000000..59e742eb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/pca_cca.go @@ -0,0 +1,315 @@ +// Copyright ©2016 The gonum 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 stat + +import ( + "errors" + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// PC is a type for computing and extracting the principal components of a +// matrix. The results of the principal components analysis are only valid +// if the call to PrincipalComponents was successful. +type PC struct { + n, d int + weights []float64 + svd *mat.SVD + ok bool +} + +// PrincipalComponents performs a weighted principal components analysis on the +// matrix of the input data which is represented as an n×d matrix a where each +// row is an observation and each column is a variable. +// +// PrincipalComponents centers the variables but does not scale the variance. +// +// The weights slice is used to weight the observations. If weights is nil, each +// weight is considered to have a value of one, otherwise the length of weights +// must match the number of observations or PrincipalComponents will panic. +// +// PrincipalComponents returns whether the analysis was successful. +func (c *PC) PrincipalComponents(a mat.Matrix, weights []float64) (ok bool) { + c.n, c.d = a.Dims() + if weights != nil && len(weights) != c.n { + panic("stat: len(weights) != observations") + } + + c.svd, c.ok = svdFactorizeCentered(c.svd, a, weights) + if c.ok { + c.weights = append(c.weights[:0], weights...) + } + return c.ok +} + +// VectorsTo returns the component direction vectors of a principal components +// analysis. The vectors are returned in the columns of a d×min(n, d) matrix. +// If dst is not nil it must either be zero-sized or be a d×min(n, d) matrix. +// dst will be used as the destination for the direction vector data. If dst +// is nil, a new mat.Dense is allocated for the destination. +func (c *PC) VectorsTo(dst *mat.Dense) *mat.Dense { + if !c.ok { + panic("stat: use of unsuccessful principal components analysis") + } + + if dst != nil { + if d, n := dst.Dims(); !dst.IsZero() && (d != c.d || n != min(c.n, c.d)) { + panic(mat.ErrShape) + } + } + return c.svd.VTo(dst) +} + +// VarsTo returns the column variances of the principal component scores, +// b * vecs, where b is a matrix with centered columns. Variances are returned +// in descending order. +// If dst is not nil it is used to store the variances and returned. +// Vars will panic if the receiver has not successfully performed a principal +// components analysis or dst is not nil and the length of dst is not min(n, d). +func (c *PC) VarsTo(dst []float64) []float64 { + if !c.ok { + panic("stat: use of unsuccessful principal components analysis") + } + if dst != nil && len(dst) != min(c.n, c.d) { + panic("stat: length of slice does not match analysis") + } + + dst = c.svd.Values(dst) + var f float64 + if c.weights == nil { + f = 1 / float64(c.n-1) + } else { + f = 1 / (floats.Sum(c.weights) - 1) + } + for i, v := range dst { + dst[i] = f * v * v + } + return dst +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// CC is a type for computing the canonical correlations of a pair of matrices. +// The results of the canonical correlation analysis are only valid +// if the call to CanonicalCorrelations was successful. +type CC struct { + // n is the number of observations used to + // construct the canonical correlations. + n int + + // xd and yd are used for size checks. + xd, yd int + + x, y, c *mat.SVD + ok bool +} + +// CanonicalCorrelations returns a CC which can provide the results of canonical +// correlation analysis of the input data x and y, columns of which should be +// interpretable as two sets of measurements on the same observations (rows). +// These observations are optionally weighted by weights. +// +// Canonical correlation analysis finds associations between two sets of +// variables on the same observations by finding linear combinations of the two +// sphered datasets that maximize the correlation between them. +// +// Some notation: let Xc and Yc denote the centered input data matrices x +// and y (column means subtracted from each column), let Sx and Sy denote the +// sample covariance matrices within x and y respectively, and let Sxy denote +// the covariance matrix between x and y. The sphered data can then be expressed +// as Xc * Sx^{-1/2} and Yc * Sy^{-1/2} respectively, and the correlation matrix +// between the sphered data is called the canonical correlation matrix, +// Sx^{-1/2} * Sxy * Sy^{-1/2}. In cases where S^{-1/2} is ambiguous for some +// covariance matrix S, S^{-1/2} is taken to be E * D^{-1/2} * E^T where S can +// be eigendecomposed as S = E * D * E^T. +// +// The canonical correlations are the correlations between the corresponding +// pairs of canonical variables and can be obtained with c.Corrs(). Canonical +// variables can be obtained by projecting the sphered data into the left and +// right eigenvectors of the canonical correlation matrix, and these +// eigenvectors can be obtained with c.Left(m, true) and c.Right(m, true) +// respectively. The canonical variables can also be obtained directly from the +// centered raw data by using the back-transformed eigenvectors which can be +// obtained with c.Left(m, false) and c.Right(m, false) respectively. +// +// The first pair of left and right eigenvectors of the canonical correlation +// matrix can be interpreted as directions into which the respective sphered +// data can be projected such that the correlation between the two projections +// is maximized. The second pair and onwards solve the same optimization but +// under the constraint that they are uncorrelated (orthogonal in sphered space) +// to previous projections. +// +// CanonicalCorrelations will panic if the inputs x and y do not have the same +// number of rows. +// +// The slice weights is used to weight the observations. If weights is nil, each +// weight is considered to have a value of one, otherwise the length of weights +// must match the number of observations (rows of both x and y) or +// CanonicalCorrelations will panic. +// +// More details can be found at +// https://en.wikipedia.org/wiki/Canonical_correlation +// or in Chapter 3 of +// Koch, Inge. Analysis of multivariate and high-dimensional data. +// Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 +func (c *CC) CanonicalCorrelations(x, y mat.Matrix, weights []float64) error { + var yn int + c.n, c.xd = x.Dims() + yn, c.yd = y.Dims() + if c.n != yn { + panic("stat: unequal number of observations") + } + if weights != nil && len(weights) != c.n { + panic("stat: len(weights) != observations") + } + + // Center and factorize x and y. + c.x, c.ok = svdFactorizeCentered(c.x, x, weights) + if !c.ok { + return errors.New("stat: failed to factorize x") + } + c.y, c.ok = svdFactorizeCentered(c.y, y, weights) + if !c.ok { + return errors.New("stat: failed to factorize y") + } + xu := c.x.UTo(nil) + xv := c.x.VTo(nil) + yu := c.y.UTo(nil) + yv := c.y.VTo(nil) + + // Calculate and factorise the canonical correlation matrix. + var ccor mat.Dense + ccor.Product(xv, xu.T(), yu, yv.T()) + if c.c == nil { + c.c = &mat.SVD{} + } + c.ok = c.c.Factorize(&ccor, mat.SVDThin) + if !c.ok { + return errors.New("stat: failed to factorize ccor") + } + return nil +} + +// CorrsTo returns the canonical correlations, using dst if it is not nil. +// If dst is not nil and len(dst) does not match the number of columns in +// the y input matrix, Corrs will panic. +func (c *CC) CorrsTo(dst []float64) []float64 { + if !c.ok { + panic("stat: canonical correlations missing or invalid") + } + + if dst != nil && len(dst) != c.yd { + panic("stat: length of destination does not match input dimension") + } + return c.c.Values(dst) +} + +// LeftTo returns the left eigenvectors of the canonical correlation matrix if +// spheredSpace is true. If spheredSpace is false it returns these eigenvectors +// back-transformed to the original data space. +// If dst is not nil it must either be zero-sized or be an xd×yd matrix where xd +// and yd are the number of variables in the input x and y matrices. dst will +// be used as the destination for the vector data. If dst is nil, a new +// mat.Dense is allocated for the destination. +func (c *CC) LeftTo(dst *mat.Dense, spheredSpace bool) *mat.Dense { + if !c.ok || c.n < 2 { + panic("stat: canonical correlations missing or invalid") + } + + if dst != nil { + if d, n := dst.Dims(); !dst.IsZero() && (n != c.yd || d != c.xd) { + panic(mat.ErrShape) + } + } + dst = c.c.UTo(dst) + if spheredSpace { + return dst + } + + xs := c.x.Values(nil) + xv := c.x.VTo(nil) + + scaleColsReciSqrt(xv, xs) + + dst.Product(xv, xv.T(), dst) + dst.Scale(math.Sqrt(float64(c.n-1)), dst) + return dst +} + +// RightTo returns the right eigenvectors of the canonical correlation matrix if +// spheredSpace is true. If spheredSpace is false it returns these eigenvectors +// back-transformed to the original data space. +// If dst is not nil it must either be zero-sized or be an yd×yd matrix where yd +// is the number of variables in the input y matrix. dst will +// be used as the destination for the vector data. If dst is nil, a new +// mat.Dense is allocated for the destination. +func (c *CC) RightTo(dst *mat.Dense, spheredSpace bool) *mat.Dense { + if !c.ok || c.n < 2 { + panic("stat: canonical correlations missing or invalid") + } + + if dst != nil { + if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.yd) { + panic(mat.ErrShape) + } + } + dst = c.c.VTo(dst) + if spheredSpace { + return dst + } + + ys := c.y.Values(nil) + yv := c.y.VTo(nil) + + scaleColsReciSqrt(yv, ys) + + dst.Product(yv, yv.T(), dst) + dst.Scale(math.Sqrt(float64(c.n-1)), dst) + return dst +} + +func svdFactorizeCentered(work *mat.SVD, m mat.Matrix, weights []float64) (svd *mat.SVD, ok bool) { + n, d := m.Dims() + centered := mat.NewDense(n, d, nil) + col := make([]float64, n) + for j := 0; j < d; j++ { + mat.Col(col, j, m) + floats.AddConst(-Mean(col, weights), col) + centered.SetCol(j, col) + } + for i, w := range weights { + floats.Scale(math.Sqrt(w), centered.RawRowView(i)) + } + if work == nil { + work = &mat.SVD{} + } + ok = work.Factorize(centered, mat.SVDThin) + return work, ok +} + +// scaleColsReciSqrt scales the columns of cols +// by the reciprocal square-root of vals. +func scaleColsReciSqrt(cols *mat.Dense, vals []float64) { + if cols == nil { + panic("stat: input nil") + } + n, d := cols.Dims() + if len(vals) != d { + panic("stat: input length mismatch") + } + col := make([]float64, n) + for j := 0; j < d; j++ { + mat.Col(col, j, cols) + floats.Scale(math.Sqrt(1/vals[j]), col) + cols.SetCol(j, col) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/roc.go b/vendor/gonum.org/v1/gonum/stat/roc.go new file mode 100644 index 00000000..73584b61 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/roc.go @@ -0,0 +1,121 @@ +// Copyright ©2016 The gonum 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 stat + +import "sort" + +// ROC returns paired false positive rate (FPR) and true positive rate +// (TPR) values corresponding to n cutoffs spanning the relative +// (or receiver) operator characteristic (ROC) curve obtained when y is +// treated as a binary classifier for classes with weights. +// +// Cutoffs are equally spaced from eps less than the minimum value of y +// to the maximum value of y, including both endpoints meaning that the +// resulting ROC curve will always begin at (0,0) and end at (1,1). +// +// The input y must be sorted, and SortWeightedLabeled can be used in +// order to sort y together with classes and weights. +// +// For a given cutoff value, observations corresponding to entries in y +// greater than the cutoff value are classified as false, while those +// below (or equal to) the cutoff value are classified as true. These +// assigned class labels are compared with the true values in the classes +// slice and used to calculate the FPR and TPR. +// +// If weights is nil, all weights are treated as 1. +// +// When n is zero all possible cutoffs are calculated, resulting +// in fpr and tpr having length one greater than the number of unique +// values in y. When n is greater than one fpr and tpr will be returned +// with length n. ROC will panic if n is equal to one or less than 0. +// +// More details about ROC curves are available at +// https://en.wikipedia.org/wiki/Receiver_operating_characteristic +func ROC(n int, y []float64, classes []bool, weights []float64) (tpr, fpr []float64) { + if len(y) != len(classes) { + panic("stat: slice length mismatch") + } + if weights != nil && len(y) != len(weights) { + panic("stat: slice length mismatch") + } + if !sort.Float64sAreSorted(y) { + panic("stat: input must be sorted") + } + + var incWidth, tol float64 + if n == 0 { + if len(y) == 0 { + return nil, nil + } + tpr = make([]float64, len(y)+1) + fpr = make([]float64, len(y)+1) + } else { + if n < 2 { + panic("stat: cannot calculate fewer than 2 points on a ROC curve") + } + if len(y) == 0 { + return nil, nil + } + tpr = make([]float64, n) + fpr = make([]float64, n) + incWidth = (y[len(y)-1] - y[0]) / float64(n-1) + tol = y[0] + incWidth + if incWidth == 0 { + tpr[n-1] = 1 + fpr[n-1] = 1 + return + } + } + + var bin int = 1 // the initial bin is known to have 0 fpr and 0 tpr + var nPos, nNeg float64 + for i, u := range classes { + var posWeight, negWeight float64 = 0, 1 + if weights != nil { + negWeight = weights[i] + } + if u { + posWeight, negWeight = negWeight, posWeight + } + nPos += posWeight + nNeg += negWeight + tpr[bin] += posWeight + fpr[bin] += negWeight + + // Assess if the bin needs to be updated. If n is zero, + // the bin is always updated, unless consecutive y values + // are equal. Otherwise, the bin must be updated until it + // matches the next y value (skipping empty bins). + if n == 0 { + if i != (len(y)-1) && y[i] != y[i+1] { + bin++ + tpr[bin] = tpr[bin-1] + fpr[bin] = fpr[bin-1] + } + } else { + for i != (len(y)-1) && y[i+1] > tol { + tol += incWidth + bin++ + tpr[bin] = tpr[bin-1] + fpr[bin] = fpr[bin-1] + } + } + } + if n == 0 { + tpr = tpr[:(bin + 1)] + fpr = fpr[:(bin + 1)] + } + + invNeg := 1 / nNeg + invPos := 1 / nPos + for i := range tpr { + tpr[i] *= invPos + fpr[i] *= invNeg + } + tpr[len(tpr)-1] = 1 + fpr[len(fpr)-1] = 1 + + return tpr, fpr +} diff --git a/vendor/gonum.org/v1/gonum/stat/stat.go b/vendor/gonum.org/v1/gonum/stat/stat.go new file mode 100644 index 00000000..11b90e91 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/stat.go @@ -0,0 +1,1160 @@ +// Copyright ©2014 The gonum 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 stat + +import ( + "math" + "sort" + + "gonum.org/v1/gonum/floats" +) + +// CumulantKind specifies the behavior for calculating the empirical CDF or Quantile +type CumulantKind int + +const ( + // Constant values should match the R nomenclature. See + // https://en.wikipedia.org/wiki/Quantile#Estimating_the_quantiles_of_a_population + + // Empirical treats the distribution as the actual empirical distribution. + Empirical CumulantKind = 1 +) + +// bhattacharyyaCoeff computes the Bhattacharyya Coefficient for probability distributions given by: +// \sum_i \sqrt{p_i q_i} +// +// It is assumed that p and q have equal length. +func bhattacharyyaCoeff(p, q []float64) float64 { + var bc float64 + for i, a := range p { + bc += math.Sqrt(a * q[i]) + } + return bc +} + +// Bhattacharyya computes the distance between the probability distributions p and q given by: +// -\ln ( \sum_i \sqrt{p_i q_i} ) +// +// The lengths of p and q must be equal. It is assumed that p and q sum to 1. +func Bhattacharyya(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + bc := bhattacharyyaCoeff(p, q) + return -math.Log(bc) +} + +// CDF returns the empirical cumulative distribution function value of x, that is +// the fraction of the samples less than or equal to q. The +// exact behavior is determined by the CumulantKind. CDF is theoretically +// the inverse of the Quantile function, though it may not be the actual inverse +// for all values q and CumulantKinds. +// +// The x data must be sorted in increasing order. If weights is nil then all +// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). +// +// CumulantKind behaviors: +// - Empirical: Returns the lowest fraction for which q is greater than or equal +// to that fraction of samples +func CDF(q float64, c CumulantKind, x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if floats.HasNaN(x) { + return math.NaN() + } + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + + if q < x[0] { + return 0 + } + if q >= x[len(x)-1] { + return 1 + } + + var sumWeights float64 + if weights == nil { + sumWeights = float64(len(x)) + } else { + sumWeights = floats.Sum(weights) + } + + // Calculate the index + switch c { + case Empirical: + // Find the smallest value that is greater than that percent of the samples + var w float64 + for i, v := range x { + if v > q { + return w / sumWeights + } + if weights == nil { + w++ + } else { + w += weights[i] + } + } + panic("impossible") + default: + panic("stat: bad cumulant kind") + } +} + +// ChiSquare computes the chi-square distance between the observed frequences 'obs' and +// expected frequences 'exp' given by: +// \sum_i (obs_i-exp_i)^2 / exp_i +// +// The lengths of obs and exp must be equal. +func ChiSquare(obs, exp []float64) float64 { + if len(obs) != len(exp) { + panic("stat: slice length mismatch") + } + var result float64 + for i, a := range obs { + b := exp[i] + if a == 0 && b == 0 { + continue + } + result += (a - b) * (a - b) / b + } + return result +} + +// CircularMean returns the circular mean of the dataset. +// atan2(\sum_i w_i * sin(alpha_i), \sum_i w_i * cos(alpha_i)) +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func CircularMean(x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + + var aX, aY float64 + if weights != nil { + for i, v := range x { + aX += weights[i] * math.Cos(v) + aY += weights[i] * math.Sin(v) + } + } else { + for _, v := range x { + aX += math.Cos(v) + aY += math.Sin(v) + } + } + + return math.Atan2(aY, aX) +} + +// Correlation returns the weighted correlation between the samples of x and y +// with the given means. +// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (stdX * stdY) +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func Correlation(x, y, weights []float64) float64 { + // This is a two-pass corrected implementation. It is an adaptation of the + // algorithm used in the MeanVariance function, which applies a correction + // to the typical two pass approach. + + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + xu := Mean(x, weights) + yu := Mean(y, weights) + var ( + sxx float64 + syy float64 + sxy float64 + xcompensation float64 + ycompensation float64 + ) + if weights == nil { + for i, xv := range x { + yv := y[i] + xd := xv - xu + yd := yv - yu + sxx += xd * xd + syy += yd * yd + sxy += xd * yd + xcompensation += xd + ycompensation += yd + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper. + sxx -= xcompensation * xcompensation / float64(len(x)) + syy -= ycompensation * ycompensation / float64(len(x)) + + return (sxy - xcompensation*ycompensation/float64(len(x))) / math.Sqrt(sxx*syy) + + } + + var sumWeights float64 + for i, xv := range x { + w := weights[i] + yv := y[i] + xd := xv - xu + wxd := w * xd + yd := yv - yu + wyd := w * yd + sxx += wxd * xd + syy += wyd * yd + sxy += wxd * yd + xcompensation += wxd + ycompensation += wyd + sumWeights += w + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper, except they use + // the sumWeights instead of the sample count. + sxx -= xcompensation * xcompensation / sumWeights + syy -= ycompensation * ycompensation / sumWeights + + return (sxy - xcompensation*ycompensation/sumWeights) / math.Sqrt(sxx*syy) +} + +// Covariance returns the weighted covariance between the samples of x and y. +// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (sum_j {w_j} - 1) +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func Covariance(x, y, weights []float64) float64 { + // This is a two-pass corrected implementation. It is an adaptation of the + // algorithm used in the MeanVariance function, which applies a correction + // to the typical two pass approach. + + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + xu := Mean(x, weights) + yu := Mean(y, weights) + var ( + ss float64 + xcompensation float64 + ycompensation float64 + ) + if weights == nil { + for i, xv := range x { + yv := y[i] + xd := xv - xu + yd := yv - yu + ss += xd * yd + xcompensation += xd + ycompensation += yd + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper. + return (ss - xcompensation*ycompensation/float64(len(x))) / float64(len(x)-1) + } + + var sumWeights float64 + + for i, xv := range x { + w := weights[i] + yv := y[i] + wxd := w * (xv - xu) + yd := (yv - yu) + ss += wxd * yd + xcompensation += wxd + ycompensation += w * yd + sumWeights += w + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper, except they use + // the sumWeights instead of the sample count. + return (ss - xcompensation*ycompensation/sumWeights) / (sumWeights - 1) +} + +// CrossEntropy computes the cross-entropy between the two distributions specified +// in p and q. +func CrossEntropy(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var ce float64 + for i, v := range p { + if v != 0 { + ce -= v * math.Log(q[i]) + } + } + return ce +} + +// Entropy computes the Shannon entropy of a distribution or the distance between +// two distributions. The natural logarithm is used. +// - sum_i (p_i * log_e(p_i)) +func Entropy(p []float64) float64 { + var e float64 + for _, v := range p { + if v != 0 { // Entropy needs 0 * log(0) == 0 + e -= v * math.Log(v) + } + } + return e +} + +// ExKurtosis returns the population excess kurtosis of the sample. +// The kurtosis is defined by the 4th moment of the mean divided by the squared +// variance. The excess kurtosis subtracts 3.0 so that the excess kurtosis of +// the normal distribution is zero. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func ExKurtosis(x, weights []float64) float64 { + mean, std := MeanStdDev(x, weights) + if weights == nil { + var e float64 + for _, v := range x { + z := (v - mean) / std + e += z * z * z * z + } + mul, offset := kurtosisCorrection(float64(len(x))) + return e*mul - offset + } + + var ( + e float64 + sumWeights float64 + ) + for i, v := range x { + z := (v - mean) / std + e += weights[i] * z * z * z * z + sumWeights += weights[i] + } + mul, offset := kurtosisCorrection(sumWeights) + return e*mul - offset +} + +// n is the number of samples +// see https://en.wikipedia.org/wiki/Kurtosis +func kurtosisCorrection(n float64) (mul, offset float64) { + return ((n + 1) / (n - 1)) * (n / (n - 2)) * (1 / (n - 3)), 3 * ((n - 1) / (n - 2)) * ((n - 1) / (n - 3)) +} + +// GeometricMean returns the weighted geometric mean of the dataset +// \prod_i {x_i ^ w_i} +// This only applies with positive x and positive weights. If weights is nil +// then all of the weights are 1. If weights is not nil, then len(x) must equal +// len(weights). +func GeometricMean(x, weights []float64) float64 { + if weights == nil { + var s float64 + for _, v := range x { + s += math.Log(v) + } + s /= float64(len(x)) + return math.Exp(s) + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + var ( + s float64 + sumWeights float64 + ) + for i, v := range x { + s += weights[i] * math.Log(v) + sumWeights += weights[i] + } + s /= sumWeights + return math.Exp(s) +} + +// HarmonicMean returns the weighted harmonic mean of the dataset +// \sum_i {w_i} / ( sum_i {w_i / x_i} ) +// This only applies with positive x and positive weights. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func HarmonicMean(x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + // TODO: Fix this to make it more efficient and avoid allocation + + // This can be numerically unstable (for example if x is very small) + // W = \sum_i {w_i} + // hm = exp(log(W) - log(\sum_i w_i / x_i)) + + logs := make([]float64, len(x)) + var W float64 + for i := range x { + if weights == nil { + logs[i] = -math.Log(x[i]) + W++ + continue + } + logs[i] = math.Log(weights[i]) - math.Log(x[i]) + W += weights[i] + } + + // Sum all of the logs + v := floats.LogSumExp(logs) // this computes log(\sum_i { w_i / x_i}) + return math.Exp(math.Log(W) - v) +} + +// Hellinger computes the distance between the probability distributions p and q given by: +// \sqrt{ 1 - \sum_i \sqrt{p_i q_i} } +// +// The lengths of p and q must be equal. It is assumed that p and q sum to 1. +func Hellinger(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + bc := bhattacharyyaCoeff(p, q) + return math.Sqrt(1 - bc) +} + +// Histogram sums up the weighted number of data points in each bin. +// The weight of data point x[i] will be placed into count[j] if +// dividers[j] <= x < dividers[j+1]. The "span" function in the floats package can assist +// with bin creation. +// +// The following conditions on the inputs apply: +// - The count variable must either be nil or have length of one less than dividers. +// - The values in dividers must be sorted (use the sort package). +// - The x values must be sorted. +// - If weights is nil then all of the weights are 1. +// - If weights is not nil, then len(x) must equal len(weights). +func Histogram(count, dividers, x, weights []float64) []float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if count == nil { + count = make([]float64, len(dividers)-1) + } + if len(dividers) < 2 { + panic("histogram: fewer than two dividers") + } + if len(count) != len(dividers)-1 { + panic("histogram: bin count mismatch") + } + if !sort.Float64sAreSorted(dividers) { + panic("histogram: dividers are not sorted") + } + if !sort.Float64sAreSorted(x) { + panic("histogram: x data are not sorted") + } + for i := range count { + count[i] = 0 + } + if len(x) == 0 { + return count + } + if x[0] < dividers[0] { + panic("histogram: minimum x value is less than lowest divider") + } + if x[len(x)-1] >= dividers[len(dividers)-1] { + panic("histogram: minimum x value is greater than highest divider") + } + + idx := 0 + comp := dividers[idx+1] + if weights == nil { + for _, v := range x { + if v < comp { + // Still in the current bucket + count[idx]++ + continue + } + // Find the next divider where v is less than the divider + for j := idx + 1; j < len(dividers); j++ { + if v < dividers[j+1] { + idx = j + comp = dividers[j+1] + break + } + } + count[idx]++ + } + return count + } + + for i, v := range x { + if v < comp { + // Still in the current bucket + count[idx] += weights[i] + continue + } + // Need to find the next divider where v is less than the divider. + for j := idx + 1; j < len(count); j++ { + if v < dividers[j+1] { + idx = j + comp = dividers[j+1] + break + } + } + count[idx] += weights[i] + } + return count +} + +// JensenShannon computes the JensenShannon divergence between the distributions +// p and q. The Jensen-Shannon divergence is defined as +// m = 0.5 * (p + q) +// JS(p, q) = 0.5 ( KL(p, m) + KL(q, m) ) +// Unlike Kullback-Liebler, the Jensen-Shannon distance is symmetric. The value +// is between 0 and ln(2). +func JensenShannon(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var js float64 + for i, v := range p { + qi := q[i] + m := 0.5 * (v + qi) + if v != 0 { + // add kl from p to m + js += 0.5 * v * (math.Log(v) - math.Log(m)) + } + if qi != 0 { + // add kl from q to m + js += 0.5 * qi * (math.Log(qi) - math.Log(m)) + } + } + return js +} + +// KolmogorovSmirnov computes the largest distance between two empirical CDFs. +// Each dataset x and y consists of sample locations and counts, xWeights and +// yWeights, respectively. +// +// x and y may have different lengths, though len(x) must equal len(xWeights), and +// len(y) must equal len(yWeights). Both x and y must be sorted. +// +// Special cases are: +// = 0 if len(x) == len(y) == 0 +// = 1 if len(x) == 0, len(y) != 0 or len(x) != 0 and len(y) == 0 +func KolmogorovSmirnov(x, xWeights, y, yWeights []float64) float64 { + if xWeights != nil && len(x) != len(xWeights) { + panic("stat: slice length mismatch") + } + if yWeights != nil && len(y) != len(yWeights) { + panic("stat: slice length mismatch") + } + if len(x) == 0 || len(y) == 0 { + if len(x) == 0 && len(y) == 0 { + return 0 + } + return 1 + } + + if floats.HasNaN(x) { + return math.NaN() + } + if floats.HasNaN(y) { + return math.NaN() + } + + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + if !sort.Float64sAreSorted(y) { + panic("y data are not sorted") + } + + xWeightsNil := xWeights == nil + yWeightsNil := yWeights == nil + + var ( + maxDist float64 + xSum, ySum float64 + xCdf, yCdf float64 + xIdx, yIdx int + ) + + if xWeightsNil { + xSum = float64(len(x)) + } else { + xSum = floats.Sum(xWeights) + } + + if yWeightsNil { + ySum = float64(len(y)) + } else { + ySum = floats.Sum(yWeights) + } + + xVal := x[0] + yVal := y[0] + + // Algorithm description: + // The goal is to find the maximum difference in the empirical CDFs for the + // two datasets. The CDFs are piecewise-constant, and thus the distance + // between the CDFs will only change at the values themselves. + // + // To find the maximum distance, step through the data in ascending order + // of value between the two datasets. At each step, compute the empirical CDF + // and compare the local distance with the maximum distance. + // Due to some corner cases, equal data entries must be tallied simultaneously. + for { + switch { + case xVal < yVal: + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + case yVal < xVal: + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + case xVal == yVal: + newX := x[xIdx] + newY := y[yIdx] + if newX < newY { + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + } else if newY < newX { + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + } else { + // Update them both, they'll be equal next time and the right + // thing will happen + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + } + default: + panic("unreachable") + } + + dist := math.Abs(xCdf - yCdf) + if dist > maxDist { + maxDist = dist + } + + // Both xCdf and yCdf will equal 1 at the end, so if we have reached the + // end of either sample list, the distance is as large as it can be. + if xIdx == len(x) || yIdx == len(y) { + return maxDist + } + } +} + +// updateKS gets the next data point from one of the set. In doing so, it combines +// the weight of all the data points of equal value. Upon return, val is the new +// value of the data set, newCdf is the total combined CDF up until this point, +// and newIdx is the index of the next location in that sample to examine. +func updateKS(idx int, cdf, sum float64, values, weights []float64, isNil bool) (val, newCdf float64, newIdx int) { + // Sum up all the weights of consecutive values that are equal + if isNil { + newCdf = cdf + 1/sum + } else { + newCdf = cdf + weights[idx]/sum + } + newIdx = idx + 1 + for { + if newIdx == len(values) { + return values[newIdx-1], newCdf, newIdx + } + if values[newIdx-1] != values[newIdx] { + return values[newIdx], newCdf, newIdx + } + if isNil { + newCdf += 1 / sum + } else { + newCdf += weights[newIdx] / sum + } + newIdx++ + } +} + +// KullbackLeibler computes the Kullback-Leibler distance between the +// distributions p and q. The natural logarithm is used. +// sum_i(p_i * log(p_i / q_i)) +// Note that the Kullback-Leibler distance is not symmetric; +// KullbackLeibler(p,q) != KullbackLeibler(q,p) +func KullbackLeibler(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var kl float64 + for i, v := range p { + if v != 0 { // Entropy needs 0 * log(0) == 0 + kl += v * (math.Log(v) - math.Log(q[i])) + } + } + return kl +} + +// LinearRegression computes the best-fit line +// y = alpha + beta*x +// to the data in x and y with the given weights. If origin is true, the +// regression is forced to pass through the origin. +// +// Specifically, LinearRegression computes the values of alpha and +// beta such that the total residual +// \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 +// is minimized. If origin is true, then alpha is forced to be zero. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func LinearRegression(x, y, weights []float64, origin bool) (alpha, beta float64) { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + if origin { + var x2Sum, xySum float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + yi := y[i] + xySum += w * xi * yi + x2Sum += w * xi * xi + } + beta = xySum / x2Sum + + return 0, beta + } + + beta = Covariance(x, y, weights) / Variance(x, weights) + alpha = Mean(y, weights) - beta*Mean(x, weights) + return alpha, beta +} + +// RSquared returns the coefficient of determination defined as +// R^2 = 1 - \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 / \sum_i w[i]*(y[i] - mean(y))^2 +// for the line +// y = alpha + beta*x +// and the data in x and y with the given weights. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func RSquared(x, y, weights []float64, alpha, beta float64) float64 { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + yMean := Mean(y, weights) + var res, tot, d float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + yi := y[i] + fi := alpha + beta*xi + d = yi - fi + res += w * d * d + d = yi - yMean + tot += w * d * d + } + return 1 - res/tot +} + +// RSquaredFrom returns the coefficient of determination defined as +// R^2 = 1 - \sum_i w[i]*(estimate[i] - value[i])^2 / \sum_i w[i]*(value[i] - mean(values))^2 +// and the data in estimates and values with the given weights. +// +// The lengths of estimates and values must be equal. If weights is nil then +// all of the weights are 1. If weights is not nil, then len(values) must +// equal len(weights). +func RSquaredFrom(estimates, values, weights []float64) float64 { + if len(estimates) != len(values) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(values) { + panic("stat: slice length mismatch") + } + + w := 1.0 + mean := Mean(values, weights) + var res, tot, d float64 + for i, val := range values { + if weights != nil { + w = weights[i] + } + d = val - estimates[i] + res += w * d * d + d = val - mean + tot += w * d * d + } + return 1 - res/tot +} + +// RNoughtSquared returns the coefficient of determination defined as +// R₀^2 = \sum_i w[i]*(beta*x[i])^2 / \sum_i w[i]*y[i]^2 +// for the line +// y = beta*x +// and the data in x and y with the given weights. RNoughtSquared should +// only be used for best-fit lines regressed through the origin. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func RNoughtSquared(x, y, weights []float64, beta float64) float64 { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + var ssr, tot float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + fi := beta * xi + ssr += w * fi * fi + yi := y[i] + tot += w * yi * yi + } + return ssr / tot +} + +// Mean computes the weighted mean of the data set. +// sum_i {w_i * x_i} / sum_i {w_i} +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Mean(x, weights []float64) float64 { + if weights == nil { + return floats.Sum(x) / float64(len(x)) + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + var ( + sumValues float64 + sumWeights float64 + ) + for i, w := range weights { + sumValues += w * x[i] + sumWeights += w + } + return sumValues / sumWeights +} + +// Mode returns the most common value in the dataset specified by x and the +// given weights. Strict float64 equality is used when comparing values, so users +// should take caution. If several values are the mode, any of them may be returned. +func Mode(x, weights []float64) (val float64, count float64) { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if len(x) == 0 { + return 0, 0 + } + m := make(map[float64]float64) + if weights == nil { + for _, v := range x { + m[v]++ + } + } else { + for i, v := range x { + m[v] += weights[i] + } + } + var ( + maxCount float64 + max float64 + ) + for val, count := range m { + if count > maxCount { + maxCount = count + max = val + } + } + return max, maxCount +} + +// Moment computes the weighted n^th moment of the samples, +// E[(x - μ)^N] +// No degrees of freedom correction is done. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Moment(moment float64, x, weights []float64) float64 { + mean := Mean(x, weights) + if weights == nil { + var m float64 + for _, v := range x { + m += math.Pow(v-mean, moment) + } + return m / float64(len(x)) + } + var ( + m float64 + sumWeights float64 + ) + for i, v := range x { + m += weights[i] * math.Pow(v-mean, moment) + sumWeights += weights[i] + } + return m / sumWeights +} + +// MomentAbout computes the weighted n^th weighted moment of the samples about +// the given mean \mu, +// E[(x - μ)^N] +// No degrees of freedom correction is done. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func MomentAbout(moment float64, x []float64, mean float64, weights []float64) float64 { + if weights == nil { + var m float64 + for _, v := range x { + m += math.Pow(v-mean, moment) + } + m /= float64(len(x)) + return m + } + if len(weights) != len(x) { + panic("stat: slice length mismatch") + } + var ( + m float64 + sumWeights float64 + ) + for i, v := range x { + m += weights[i] * math.Pow(v-mean, moment) + sumWeights += weights[i] + } + return m / sumWeights +} + +// Quantile returns the sample of x such that x is greater than or +// equal to the fraction p of samples. The exact behavior is determined by the +// CumulantKind, and p should be a number between 0 and 1. Quantile is theoretically +// the inverse of the CDF function, though it may not be the actual inverse +// for all values p and CumulantKinds. +// +// The x data must be sorted in increasing order. If weights is nil then all +// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). +// +// CumulantKind behaviors: +// - Empirical: Returns the lowest value q for which q is greater than or equal +// to the fraction p of samples +func Quantile(p float64, c CumulantKind, x, weights []float64) float64 { + if !(p >= 0 && p <= 1) { + panic("stat: percentile out of bounds") + } + + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if floats.HasNaN(x) { + return math.NaN() // This is needed because the algorithm breaks otherwise + } + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + + var sumWeights float64 + if weights == nil { + sumWeights = float64(len(x)) + } else { + sumWeights = floats.Sum(weights) + } + switch c { + case Empirical: + var cumsum float64 + fidx := p * sumWeights + for i := range x { + if weights == nil { + cumsum++ + } else { + cumsum += weights[i] + } + if cumsum >= fidx { + return x[i] + } + } + panic("impossible") + default: + panic("stat: bad cumulant kind") + } +} + +// Skew computes the skewness of the sample data. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Skew(x, weights []float64) float64 { + + mean, std := MeanStdDev(x, weights) + if weights == nil { + var s float64 + for _, v := range x { + z := (v - mean) / std + s += z * z * z + } + return s * skewCorrection(float64(len(x))) + } + var ( + s float64 + sumWeights float64 + ) + for i, v := range x { + z := (v - mean) / std + s += weights[i] * z * z * z + sumWeights += weights[i] + } + return s * skewCorrection(sumWeights) +} + +// From: http://www.amstat.org/publications/jse/v19n2/doane.pdf page 7 +func skewCorrection(n float64) float64 { + return (n / (n - 1)) * (1 / (n - 2)) +} + +// SortWeighted rearranges the data in x along with their corresponding +// weights so that the x data are sorted. The data is sorted in place. +// Weights may be nil, but if weights is non-nil then it must have the same +// length as x. +func SortWeighted(x, weights []float64) { + if weights == nil { + sort.Float64s(x) + return + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + sort.Sort(weightSorter{ + x: x, + w: weights, + }) +} + +type weightSorter struct { + x []float64 + w []float64 +} + +func (w weightSorter) Len() int { return len(w.x) } +func (w weightSorter) Less(i, j int) bool { return w.x[i] < w.x[j] } +func (w weightSorter) Swap(i, j int) { + w.x[i], w.x[j] = w.x[j], w.x[i] + w.w[i], w.w[j] = w.w[j], w.w[i] +} + +// SortWeightedLabeled rearranges the data in x along with their +// corresponding weights and boolean labels so that the x data are sorted. +// The data is sorted in place. Weights and labels may be nil, if either +// is non-nil it must have the same length as x. +func SortWeightedLabeled(x []float64, labels []bool, weights []float64) { + if labels == nil { + SortWeighted(x, weights) + return + } + if weights == nil { + if len(x) != len(labels) { + panic("stat: slice length mismatch") + } + sort.Sort(labelSorter{ + x: x, + l: labels, + }) + return + } + if len(x) != len(labels) || len(x) != len(weights) { + panic("stat: slice length mismatch") + } + sort.Sort(weightLabelSorter{ + x: x, + l: labels, + w: weights, + }) +} + +type labelSorter struct { + x []float64 + l []bool +} + +func (a labelSorter) Len() int { return len(a.x) } +func (a labelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } +func (a labelSorter) Swap(i, j int) { + a.x[i], a.x[j] = a.x[j], a.x[i] + a.l[i], a.l[j] = a.l[j], a.l[i] +} + +type weightLabelSorter struct { + x []float64 + l []bool + w []float64 +} + +func (a weightLabelSorter) Len() int { return len(a.x) } +func (a weightLabelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } +func (a weightLabelSorter) Swap(i, j int) { + a.x[i], a.x[j] = a.x[j], a.x[i] + a.l[i], a.l[j] = a.l[j], a.l[i] + a.w[i], a.w[j] = a.w[j], a.w[i] +} + +// StdDev returns the sample standard deviation. +func StdDev(x, weights []float64) float64 { + _, std := MeanStdDev(x, weights) + return std +} + +// MeanStdDev returns the sample mean and standard deviation +func MeanStdDev(x, weights []float64) (mean, std float64) { + mean, variance := MeanVariance(x, weights) + return mean, math.Sqrt(variance) +} + +// StdErr returns the standard error in the mean with the given values. +func StdErr(std, sampleSize float64) float64 { + return std / math.Sqrt(sampleSize) +} + +// StdScore returns the standard score (a.k.a. z-score, z-value) for the value x +// with the givem mean and standard deviation, i.e. +// (x - mean) / std +func StdScore(x, mean, std float64) float64 { + return (x - mean) / std +} + +// Variance computes the weighted sample variance: +// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Variance(x, weights []float64) float64 { + _, variance := MeanVariance(x, weights) + return variance +} + +// MeanVariance computes the sample mean and variance, where the mean and variance are +// \sum_i w_i * x_i / (sum_i w_i) +// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) +// respectively. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func MeanVariance(x, weights []float64) (mean, variance float64) { + + // This uses the corrected two-pass algorithm (1.7), from "Algorithms for computing + // the sample variance: Analysis and recommendations" by Chan, Tony F., Gene H. Golub, + // and Randall J. LeVeque. + + // note that this will panic if the slice lengths do not match + mean = Mean(x, weights) + var ( + ss float64 + compensation float64 + ) + if weights == nil { + for _, v := range x { + d := v - mean + ss += d * d + compensation += d + } + variance = (ss - compensation*compensation/float64(len(x))) / float64(len(x)-1) + return + } + + var sumWeights float64 + for i, v := range x { + w := weights[i] + d := v - mean + wd := w * d + ss += wd * d + compensation += wd + sumWeights += w + } + variance = (ss - compensation*compensation/sumWeights) / (sumWeights - 1) + return +} diff --git a/vendor/gonum.org/v1/gonum/stat/statmat.go b/vendor/gonum.org/v1/gonum/stat/statmat.go new file mode 100644 index 00000000..1f9bd794 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/statmat.go @@ -0,0 +1,146 @@ +// Copyright ©2014 The gonum 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 stat + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// CovarianceMatrix returns the covariance matrix (also known as the +// variance-covariance matrix) calculated from a matrix of data, x, using +// a two-pass algorithm. +// +// If weights is not nil the weighted covariance of x is calculated. weights +// must have length equal to the number of rows in input data matrix and +// must not contain negative elements. +// If cov is not nil it must either be zero-sized or have the same number of +// columns as the input data matrix. cov will be used as the destination for +// the covariance data. If cov is nil, a new mat.SymDense is allocated for +// the destination. +func CovarianceMatrix(cov *mat.SymDense, x mat.Matrix, weights []float64) *mat.SymDense { + // This is the matrix version of the two-pass algorithm. It doesn't use the + // additional floating point error correction that the Covariance function uses + // to reduce the impact of rounding during centering. + + r, c := x.Dims() + + if cov == nil { + cov = mat.NewSymDense(c, nil) + } else if n := cov.Symmetric(); n != c && n != 0 { + panic(mat.ErrShape) + } + + var xt mat.Dense + xt.Clone(x.T()) + // Subtract the mean of each of the columns. + for i := 0; i < c; i++ { + v := xt.RawRowView(i) + // This will panic with ErrShape if len(weights) != len(v), so + // we don't have to check the size later. + mean := Mean(v, weights) + floats.AddConst(-mean, v) + } + + if weights == nil { + // Calculate the normalization factor + // scaled by the sample size. + cov.SymOuterK(1/(float64(r)-1), &xt) + return cov + } + + // Multiply by the sqrt of the weights, so that multiplication is symmetric. + sqrtwts := make([]float64, r) + for i, w := range weights { + if w < 0 { + panic("stat: negative covariance matrix weights") + } + sqrtwts[i] = math.Sqrt(w) + } + // Weight the rows. + for i := 0; i < c; i++ { + v := xt.RawRowView(i) + floats.Mul(v, sqrtwts) + } + + // Calculate the normalization factor + // scaled by the weighted sample size. + cov.SymOuterK(1/(floats.Sum(weights)-1), &xt) + return cov +} + +// CorrelationMatrix returns the correlation matrix calculated from a matrix +// of data, x, using a two-pass algorithm. +// +// If weights is not nil the weighted correlation of x is calculated. weights +// must have length equal to the number of rows in input data matrix and +// must not contain negative elements. +// If corr is not nil it must either be zero-sized or have the same number of +// columns as the input data matrix. corr will be used as the destination for +// the correlation data. If corr is nil, a new mat.SymDense is allocated for +// the destination. +func CorrelationMatrix(corr *mat.SymDense, x mat.Matrix, weights []float64) *mat.SymDense { + // This will panic if the sizes don't match, or if weights is the wrong size. + corr = CovarianceMatrix(corr, x, weights) + covToCorr(corr) + return corr +} + +// covToCorr converts a covariance matrix to a correlation matrix. +func covToCorr(c *mat.SymDense) { + r := c.Symmetric() + + s := make([]float64, r) + for i := 0; i < r; i++ { + s[i] = 1 / math.Sqrt(c.At(i, i)) + } + for i, sx := range s { + // Ensure that the diagonal has exactly ones. + c.SetSym(i, i, 1) + for j := i + 1; j < r; j++ { + v := c.At(i, j) + c.SetSym(i, j, v*sx*s[j]) + } + } +} + +// corrToCov converts a correlation matrix to a covariance matrix. +// The input sigma should be vector of standard deviations corresponding +// to the covariance. It will panic if len(sigma) is not equal to the +// number of rows in the correlation matrix. +func corrToCov(c *mat.SymDense, sigma []float64) { + r, _ := c.Dims() + + if r != len(sigma) { + panic(mat.ErrShape) + } + for i, sx := range sigma { + // Ensure that the diagonal has exactly sigma squared. + c.SetSym(i, i, sx*sx) + for j := i + 1; j < r; j++ { + v := c.At(i, j) + c.SetSym(i, j, v*sx*sigma[j]) + } + } +} + +// Mahalanobis computes the Mahalanobis distance +// D = sqrt((x-y)^T * Σ^-1 * (x-y)) +// between the vectors x and y given the cholesky decomposition of Σ. +// Mahalanobis returns NaN if the linear solve fails. +// +// See https://en.wikipedia.org/wiki/Mahalanobis_distance for more information. +func Mahalanobis(x, y *mat.VecDense, chol *mat.Cholesky) float64 { + var diff mat.VecDense + diff.SubVec(x, y) + var tmp mat.VecDense + err := chol.SolveVec(&tmp, &diff) + if err != nil { + return math.NaN() + } + return math.Sqrt(mat.Dot(&tmp, &diff)) +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 3fe19d2b..7067e25f 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1113,6 +1113,12 @@ "revision": "505032a0737bf9d1007ff782db67a4e41eac71f7", "revisionTime": "2018-06-28T04:47:44Z" }, + { + "checksumSHA1": "db1fjQUFM01O5HhI1zzREmB9ARQ=", + "path": "gonum.org/v1/gonum/stat", + "revision": "d7342e68fbbe64d7dbbdc0feb4ecf60500444cdc", + "revisionTime": "2017-08-28T20:52:35Z" + }, { "checksumSHA1": "AvVpgwhxhJgjoSledwDtYrEKVE4=", "origin": "github.com/Loopring/relay-lib/vendor/google.golang.org/genproto/googleapis/rpc/status", From 29a9ba28462890238f0df0c22ae00828d2424e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 16:16:48 +0800 Subject: [PATCH 5/8] add vendor --- vendor/gonum.org/v1/gonum/LICENSE | 23 - vendor/gonum.org/v1/gonum/blas/README.md | 79 + vendor/gonum.org/v1/gonum/blas/blas.go | 287 ++ .../gonum.org/v1/gonum/blas/blas32/blas32.go | 457 +++ vendor/gonum.org/v1/gonum/blas/blas32/conv.go | 279 ++ .../v1/gonum/blas/blas32/conv_symmetric.go | 155 + .../gonum/blas/blas32/conv_symmetric_test.go | 307 ++ .../v1/gonum/blas/blas32/conv_test.go | 620 ++++ vendor/gonum.org/v1/gonum/blas/blas32/doc.go | 6 + .../gonum.org/v1/gonum/blas/blas64/blas64.go | 445 +++ vendor/gonum.org/v1/gonum/blas/blas64/conv.go | 277 ++ .../v1/gonum/blas/blas64/conv_symmetric.go | 153 + .../gonum/blas/blas64/conv_symmetric_test.go | 305 ++ .../v1/gonum/blas/blas64/conv_test.go | 618 ++++ vendor/gonum.org/v1/gonum/blas/blas64/doc.go | 6 + .../v1/gonum/blas/cblas128/cblas128.go | 507 +++ .../gonum.org/v1/gonum/blas/cblas128/conv.go | 279 ++ .../v1/gonum/blas/cblas128/conv_hermitian.go | 155 + .../blas/cblas128/conv_hermitian_test.go | 307 ++ .../v1/gonum/blas/cblas128/conv_symmetric.go | 155 + .../blas/cblas128/conv_symmetric_test.go | 307 ++ .../v1/gonum/blas/cblas128/conv_test.go | 620 ++++ .../gonum.org/v1/gonum/blas/cblas128/doc.go | 6 + .../v1/gonum/blas/cblas64/cblas64.go | 507 +++ .../gonum.org/v1/gonum/blas/cblas64/conv.go | 279 ++ .../v1/gonum/blas/cblas64/conv_hermitian.go | 155 + .../gonum/blas/cblas64/conv_hermitian_test.go | 307 ++ .../v1/gonum/blas/cblas64/conv_test.go | 620 ++++ vendor/gonum.org/v1/gonum/blas/cblas64/doc.go | 6 + .../gonum.org/v1/gonum/blas/conversions.bash | 159 + vendor/gonum.org/v1/gonum/blas/doc.go | 108 + .../v1/gonum/blas/gonum/bench_test.go | 22 + vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go | 206 ++ vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go | 261 ++ .../v1/gonum/blas/gonum/dgemmbench_test.go | 51 + .../v1/gonum/blas/gonum/dgemvbench_test.go | 91 + .../v1/gonum/blas/gonum/dgerbench_test.go | 51 + vendor/gonum.org/v1/gonum/blas/gonum/doc.go | 88 + .../v1/gonum/blas/gonum/dtrmvbench_test.go | 54 + .../v1/gonum/blas/gonum/general_double.go | 50 + .../v1/gonum/blas/gonum/general_single.go | 52 + vendor/gonum.org/v1/gonum/blas/gonum/gonum.go | 133 + .../v1/gonum/blas/gonum/level1cmplx128.go | 442 +++ .../blas/gonum/level1cmplx128_bench_test.go | 41 + .../gonum/blas/gonum/level1cmplx128_test.go | 51 + .../v1/gonum/blas/gonum/level1double.go | 595 ++++ .../blas/gonum/level1doubleBench_auto_test.go | 1685 +++++++++ .../v1/gonum/blas/gonum/level1double_ddot.go | 49 + .../v1/gonum/blas/gonum/level1double_test.go | 61 + .../v1/gonum/blas/gonum/level1single.go | 619 ++++ .../v1/gonum/blas/gonum/level1single_dsdot.go | 53 + .../v1/gonum/blas/gonum/level1single_sdot.go | 53 + .../gonum/blas/gonum/level1single_sdsdot.go | 53 + .../v1/gonum/blas/gonum/level2cmplx128.go | 289 ++ .../blas/gonum/level2cmplx128_bench_test.go | 49 + .../gonum/blas/gonum/level2cmplx128_test.go | 27 + .../v1/gonum/blas/gonum/level2double.go | 2234 ++++++++++++ .../v1/gonum/blas/gonum/level2double_test.go | 79 + .../v1/gonum/blas/gonum/level2single.go | 2268 ++++++++++++ .../v1/gonum/blas/gonum/level3double.go | 831 +++++ .../v1/gonum/blas/gonum/level3double_test.go | 35 + .../v1/gonum/blas/gonum/level3single.go | 843 +++++ .../v1/gonum/blas/gonum/pardgemm_test.go | 181 + vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go | 265 ++ .../v1/gonum/blas/gonum/single_precision.bash | 158 + .../autogen_bench_level1double.go | 292 ++ .../v1/gonum/blas/testblas/benchsize.go | 8 + .../v1/gonum/blas/testblas/common.go | 316 ++ .../v1/gonum/blas/testblas/common_test.go | 187 + .../gonum.org/v1/gonum/blas/testblas/dgbmv.go | 131 + .../gonum.org/v1/gonum/blas/testblas/dgemm.go | 244 ++ .../v1/gonum/blas/testblas/dgemmbench.go | 39 + .../gonum.org/v1/gonum/blas/testblas/dgemv.go | 678 ++++ .../gonum.org/v1/gonum/blas/testblas/dger.go | 163 + .../gonum.org/v1/gonum/blas/testblas/doc.go | 6 + .../gonum.org/v1/gonum/blas/testblas/dsbmv.go | 83 + .../gonum.org/v1/gonum/blas/testblas/dspmv.go | 73 + .../gonum.org/v1/gonum/blas/testblas/dspr.go | 71 + .../gonum.org/v1/gonum/blas/testblas/dspr2.go | 76 + .../gonum.org/v1/gonum/blas/testblas/dsymm.go | 277 ++ .../gonum.org/v1/gonum/blas/testblas/dsymv.go | 73 + .../gonum.org/v1/gonum/blas/testblas/dsyr.go | 72 + .../gonum.org/v1/gonum/blas/testblas/dsyr2.go | 76 + .../v1/gonum/blas/testblas/dsyr2k.go | 201 ++ .../gonum.org/v1/gonum/blas/testblas/dsyrk.go | 171 + .../gonum.org/v1/gonum/blas/testblas/dtbmv.go | 123 + .../gonum.org/v1/gonum/blas/testblas/dtbsv.go | 255 ++ .../gonum.org/v1/gonum/blas/testblas/dtpmv.go | 129 + .../gonum.org/v1/gonum/blas/testblas/dtpsv.go | 144 + .../gonum.org/v1/gonum/blas/testblas/dtrmm.go | 806 +++++ .../gonum.org/v1/gonum/blas/testblas/dtrmv.go | 147 + .../v1/gonum/blas/testblas/dtrmvbench.go | 30 + .../gonum.org/v1/gonum/blas/testblas/dtrsm.go | 811 +++++ .../gonum.org/v1/gonum/blas/testblas/dtrsv.go | 144 + .../gonum.org/v1/gonum/blas/testblas/dtxmv.go | 145 + .../v1/gonum/blas/testblas/dzasum.go | 58 + .../v1/gonum/blas/testblas/dznrm2.go | 137 + .../v1/gonum/blas/testblas/izamax.go | 47 + .../v1/gonum/blas/testblas/level1double.go | 2048 +++++++++++ .../v1/gonum/blas/testblas/level2bench.go | 60 + .../gonum.org/v1/gonum/blas/testblas/zaxpy.go | 157 + .../gonum.org/v1/gonum/blas/testblas/zcopy.go | 71 + .../gonum.org/v1/gonum/blas/testblas/zdotc.go | 139 + .../gonum.org/v1/gonum/blas/testblas/zdotu.go | 139 + .../v1/gonum/blas/testblas/zdscal.go | 119 + .../gonum.org/v1/gonum/blas/testblas/zgerc.go | 183 + .../gonum.org/v1/gonum/blas/testblas/zgeru.go | 257 ++ .../gonum.org/v1/gonum/blas/testblas/zher.go | 155 + .../gonum.org/v1/gonum/blas/testblas/zher2.go | 257 ++ .../gonum.org/v1/gonum/blas/testblas/zscal.go | 119 + .../gonum.org/v1/gonum/blas/testblas/zswap.go | 68 + vendor/gonum.org/v1/gonum/diff/README.md | 3 + .../v1/gonum/diff/fd/crosslaplacian.go | 186 + .../v1/gonum/diff/fd/crosslaplacian_test.go | 111 + .../gonum.org/v1/gonum/diff/fd/derivative.go | 71 + .../v1/gonum/diff/fd/derivative_test.go | 145 + vendor/gonum.org/v1/gonum/diff/fd/diff.go | 148 + vendor/gonum.org/v1/gonum/diff/fd/doc.go | 6 + .../v1/gonum/diff/fd/example_test.go | 68 + vendor/gonum.org/v1/gonum/diff/fd/gradient.go | 145 + .../v1/gonum/diff/fd/gradient_test.go | 187 + vendor/gonum.org/v1/gonum/diff/fd/hessian.go | 193 + .../v1/gonum/diff/fd/hessian_test.go | 94 + vendor/gonum.org/v1/gonum/diff/fd/jacobian.go | 200 ++ .../v1/gonum/diff/fd/jacobian_test.go | 268 ++ .../gonum.org/v1/gonum/diff/fd/laplacian.go | 158 + .../v1/gonum/diff/fd/laplacian_test.go | 44 + .../v1/gonum/diff/fd/simplefunctions_test.go | 87 + .../gonum.org/v1/gonum/diff/fd/watson_test.go | 132 + vendor/gonum.org/v1/gonum/floats/README.md | 4 + vendor/gonum.org/v1/gonum/floats/doc.go | 11 + .../v1/gonum/floats/examples_test.go | 104 + vendor/gonum.org/v1/gonum/floats/floats.go | 771 ++++ .../gonum.org/v1/gonum/floats/floats_test.go | 1403 ++++++++ .../v1/gonum/floats/parse_example_test.go | 43 + vendor/gonum.org/v1/gonum/graph/.gitignore | 1 + vendor/gonum.org/v1/gonum/graph/README.md | 3 + .../v1/gonum/graph/community/bisect.go | 248 ++ .../v1/gonum/graph/community/bisect_test.go | 311 ++ .../gonum.org/v1/gonum/graph/community/doc.go | 6 + .../v1/gonum/graph/community/louvain.tex | 466 +++ .../gonum/graph/community/louvain_common.go | 415 +++ .../gonum/graph/community/louvain_directed.go | 650 ++++ .../community/louvain_directed_multiplex.go | 888 +++++ .../louvain_directed_multiplex_test.go | 722 ++++ .../graph/community/louvain_directed_test.go | 719 ++++ .../v1/gonum/graph/community/louvain_test.go | 277 ++ .../graph/community/louvain_undirected.go | 590 ++++ .../community/louvain_undirected_multiplex.go | 826 +++++ .../louvain_undirected_multiplex_test.go | 691 ++++ .../community/louvain_undirected_test.go | 778 +++++ .../v1/gonum/graph/community/printgraphs.go | 142 + vendor/gonum.org/v1/gonum/graph/doc.go | 38 + .../gonum.org/v1/gonum/graph/encoding/doc.go | 6 + .../v1/gonum/graph/encoding/dot/decode.go | 278 ++ .../gonum/graph/encoding/dot/decode_test.go | 247 ++ .../v1/gonum/graph/encoding/dot/doc.go | 14 + .../v1/gonum/graph/encoding/dot/dot.go | 5 + .../v1/gonum/graph/encoding/dot/encode.go | 359 ++ .../gonum/graph/encoding/dot/encode_test.go | 1436 ++++++++ .../v1/gonum/graph/encoding/encoding.go | 30 + .../v1/gonum/graph/encoding/graphql/decode.go | 157 + .../graph/encoding/graphql/decode_test.go | 221 ++ .../v1/gonum/graph/encoding/graphql/doc.go | 7 + .../gonum/graph/encoding/graphql/graphql.go | 5 + .../graph/encoding/graphql/graphs_test.go | 1013 ++++++ .../v1/gonum/graph/ex/fdpclust/gn.go | 278 ++ .../v1/gonum/graph/ex/fdpclust/main.go | 75 + .../v1/gonum/graph/formats/dot/README.md | 9 + .../v1/gonum/graph/formats/dot/ast/ast.go | 406 +++ .../gonum/graph/formats/dot/ast/ast_test.go | 101 + .../v1/gonum/graph/formats/dot/ast/doc.go | 7 + .../v1/gonum/graph/formats/dot/doc.go | 6 + .../v1/gonum/graph/formats/dot/dot.go | 64 + .../gonum/graph/formats/dot/internal/Makefile | 33 + .../graph/formats/dot/internal/astx/astx.go | 326 ++ .../formats/dot/internal/astx/astx_test.go | 90 + .../graph/formats/dot/internal/astx/doc.go | 7 + .../gonum/graph/formats/dot/internal/dot.bnf | 358 ++ .../formats/dot/internal/errors/errors.go | 66 + .../formats/dot/internal/lexer/acttab.go | 597 ++++ .../graph/formats/dot/internal/lexer/lexer.go | 310 ++ .../formats/dot/internal/lexer/lexer_test.go | 54 + .../dot/internal/lexer/testdata/tokens.dot | 39 + .../dot/internal/lexer/testdata/tokens.golden | 37 + .../dot/internal/lexer/transitiontable.go | 2741 +++++++++++++++ .../formats/dot/internal/parser/action.go | 61 + .../dot/internal/parser/actiontable.go | 2199 ++++++++++++ .../formats/dot/internal/parser/gototable.go | 2807 +++++++++++++++ .../formats/dot/internal/parser/parser.go | 221 ++ .../dot/internal/parser/parser_test.go | 114 + .../dot/internal/parser/productionstable.go | 586 ++++ .../formats/dot/internal/paste_copyright.bash | 17 + .../formats/dot/internal/testdata/attr.dot | 4 + .../dot/internal/testdata/attr_lists.dot | 3 + .../dot/internal/testdata/attr_lists.golden | 3 + .../dot/internal/testdata/attr_sep.dot | 3 + .../dot/internal/testdata/attr_sep.golden | 3 + .../dot/internal/testdata/attr_stmt.dot | 6 + .../testdata/backslash_newline_id.dot | 4 + .../testdata/backslash_newline_id.golden | 3 + .../formats/dot/internal/testdata/digraph.dot | 3 + .../dot/internal/testdata/edge_stmt.dot | 4 + .../formats/dot/internal/testdata/empty.dot | 2 + .../dot/internal/testdata/empty_attr.dot | 3 + .../dot/internal/testdata/empty_attr.golden | 3 + .../formats/dot/internal/testdata/error.dot | 3 + .../formats/dot/internal/testdata/graph.dot | 3 + .../formats/dot/internal/testdata/multi.dot | 6 + .../dot/internal/testdata/named_graph.dot | 3 + .../dot/internal/testdata/node_stmt.dot | 3 + .../formats/dot/internal/testdata/port.dot | 11 + .../formats/dot/internal/testdata/port.golden | 11 + .../dot/internal/testdata/quoted_id.dot | 3 + .../formats/dot/internal/testdata/semi.dot | 3 + .../formats/dot/internal/testdata/semi.golden | 4 + .../formats/dot/internal/testdata/strict.dot | 4 + .../dot/internal/testdata/subgraph.dot | 5 + .../dot/internal/testdata/subgraph.golden | 5 + .../dot/internal/testdata/subgraph_vertex.dot | 3 + .../graph/formats/dot/internal/token/token.go | 116 + .../formats/dot/internal/util/litconv.go | 118 + .../graph/formats/dot/internal/util/rune.go | 49 + .../gonum/graph/formats/dot/makeinternal.bash | 4 + .../v1/gonum/graph/formats/dot/sem.go | 160 + .../graph/formats/dot/testdata/.gitignore | 5 + .../gonum/graph/formats/dot/testdata/Makefile | 106 + vendor/gonum.org/v1/gonum/graph/graph.go | 247 ++ .../graph/graphs/gen/batagelj_brandes.go | 357 ++ .../graph/graphs/gen/batagelj_brandes_test.go | 174 + .../v1/gonum/graph/graphs/gen/doc.go | 6 + .../v1/gonum/graph/graphs/gen/duplication.go | 125 + .../graph/graphs/gen/duplication_test.go | 58 + .../v1/gonum/graph/graphs/gen/gen.go | 21 + .../v1/gonum/graph/graphs/gen/holme_kim.go | 160 + .../gonum/graph/graphs/gen/holme_kim_test.go | 55 + .../v1/gonum/graph/graphs/gen/small_world.go | 204 ++ .../graph/graphs/gen/small_world_test.go | 72 + .../v1/gonum/graph/internal/linear/doc.go | 6 + .../v1/gonum/graph/internal/linear/linear.go | 73 + .../v1/gonum/graph/internal/ordered/doc.go | 6 + .../v1/gonum/graph/internal/ordered/sort.go | 69 + .../v1/gonum/graph/internal/set/doc.go | 6 + .../v1/gonum/graph/internal/set/same.go | 36 + .../graph/internal/set/same_appengine.go | 36 + .../v1/gonum/graph/internal/set/set.go | 256 ++ .../v1/gonum/graph/internal/set/set_test.go | 413 +++ .../v1/gonum/graph/network/betweenness.go | 250 ++ .../gonum/graph/network/betweenness_test.go | 338 ++ .../v1/gonum/graph/network/distance.go | 124 + .../v1/gonum/graph/network/distance_test.go | 394 +++ .../gonum.org/v1/gonum/graph/network/doc.go | 6 + .../gonum.org/v1/gonum/graph/network/hits.go | 101 + .../v1/gonum/graph/network/hits_test.go | 98 + .../v1/gonum/graph/network/network.go | 13 + .../v1/gonum/graph/network/network_test.go | 33 + .../gonum.org/v1/gonum/graph/network/page.go | 228 ++ .../v1/gonum/graph/network/page_test.go | 151 + .../gonum.org/v1/gonum/graph/path/a_star.go | 151 + .../v1/gonum/graph/path/a_star_test.go | 310 ++ .../v1/gonum/graph/path/bellman_ford_moore.go | 67 + .../graph/path/bellman_ford_moore_test.go | 70 + .../v1/gonum/graph/path/bench_test.go | 141 + .../v1/gonum/graph/path/control_flow.go | 118 + .../gonum.org/v1/gonum/graph/path/dijkstra.go | 147 + .../v1/gonum/graph/path/dijkstra_test.go | 178 + .../gonum.org/v1/gonum/graph/path/disjoint.go | 87 + .../v1/gonum/graph/path/disjoint_test.go | 63 + vendor/gonum.org/v1/gonum/graph/path/doc.go | 6 + .../v1/gonum/graph/path/dynamic/doc.go | 6 + .../v1/gonum/graph/path/dynamic/dstarlite.go | 491 +++ .../graph/path/dynamic/dstarlite_test.go | 680 ++++ .../gonum/graph/path/dynamic/dumper_test.go | 153 + .../v1/gonum/graph/path/floydwarshall.go | 59 + .../v1/gonum/graph/path/floydwarshall_test.go | 102 + .../v1/gonum/graph/path/internal/grid.go | 296 ++ .../v1/gonum/graph/path/internal/grid_test.go | 258 ++ .../v1/gonum/graph/path/internal/limited.go | 316 ++ .../gonum/graph/path/internal/limited_test.go | 1242 +++++++ .../path/internal/testgraphs/shortest.go | 654 ++++ .../v1/gonum/graph/path/johnson_apsp.go | 142 + .../v1/gonum/graph/path/johnson_apsp_test.go | 102 + .../gonum.org/v1/gonum/graph/path/shortest.go | 319 ++ .../v1/gonum/graph/path/spanning_tree.go | 187 + .../v1/gonum/graph/path/spanning_tree_test.go | 294 ++ .../gonum.org/v1/gonum/graph/path/weight.go | 40 + .../graph/simple/dense_directed_matrix.go | 300 ++ .../graph/simple/dense_undirected_matrix.go | 261 ++ .../v1/gonum/graph/simple/densegraph_test.go | 149 + .../v1/gonum/graph/simple/directed.go | 245 ++ .../v1/gonum/graph/simple/directed_test.go | 65 + vendor/gonum.org/v1/gonum/graph/simple/doc.go | 7 + .../gonum.org/v1/gonum/graph/simple/simple.go | 99 + .../v1/gonum/graph/simple/undirected.go | 205 ++ .../v1/gonum/graph/simple/undirected_test.go | 67 + .../gonum/graph/simple/weighted_directed.go | 285 ++ .../graph/simple/weighted_directed_test.go | 67 + .../gonum/graph/simple/weighted_undirected.go | 260 ++ .../graph/simple/weighted_undirected_test.go | 69 + .../v1/gonum/graph/topo/bench_test.go | 57 + .../v1/gonum/graph/topo/bron_kerbosch.go | 225 ++ .../v1/gonum/graph/topo/bron_kerbosch_test.go | 163 + .../v1/gonum/graph/topo/common_test.go | 47 + vendor/gonum.org/v1/gonum/graph/topo/doc.go | 6 + .../v1/gonum/graph/topo/johnson_cycles.go | 280 ++ .../gonum/graph/topo/johnson_cycles_test.go | 117 + .../v1/gonum/graph/topo/non_tomita_choice.go | 9 + .../v1/gonum/graph/topo/paton_cycles.go | 81 + .../v1/gonum/graph/topo/paton_cycles_test.go | 143 + .../gonum.org/v1/gonum/graph/topo/tarjan.go | 203 ++ .../v1/gonum/graph/topo/tarjan_test.go | 308 ++ .../v1/gonum/graph/topo/tomita_choice.go | 9 + vendor/gonum.org/v1/gonum/graph/topo/topo.go | 68 + .../v1/gonum/graph/topo/topo_test.go | 175 + .../gonum.org/v1/gonum/graph/traverse/doc.go | 6 + .../v1/gonum/graph/traverse/traverse.go | 180 + .../v1/gonum/graph/traverse/traverse_test.go | 433 +++ vendor/gonum.org/v1/gonum/graph/undirect.go | 224 ++ .../gonum.org/v1/gonum/graph/undirect_test.go | 175 + vendor/gonum.org/v1/gonum/integrate/README.md | 3 + vendor/gonum.org/v1/gonum/integrate/doc.go | 7 + .../gonum.org/v1/gonum/integrate/quad/doc.go | 7 + .../v1/gonum/integrate/quad/example_test.go | 47 + .../v1/gonum/integrate/quad/hermite.go | 314 ++ .../v1/gonum/integrate/quad/hermite_data.go | 413 +++ .../v1/gonum/integrate/quad/hermite_test.go | 251 ++ .../integrate/quad/internal/PrintGoSlice.m | 11 + .../gonum/integrate/quad/internal/genherm.m | 32 + .../gonum/integrate/quad/internal/hermpts.m | 609 ++++ .../v1/gonum/integrate/quad/legendre.go | 385 ++ .../v1/gonum/integrate/quad/legendre_test.go | 84 + .../gonum.org/v1/gonum/integrate/quad/quad.go | 157 + .../v1/gonum/integrate/quad/quad_test.go | 126 + .../v1/gonum/integrate/trapezoidal.go | 40 + .../v1/gonum/integrate/trapezoidal_test.go | 82 + vendor/gonum.org/v1/gonum/internal/README.md | 3 + .../v1/gonum/internal/asm/bench_gen.sh | 30 + .../gonum/internal/asm/c128/axpyinc_amd64.s | 134 + .../gonum/internal/asm/c128/axpyincto_amd64.s | 141 + .../internal/asm/c128/axpyunitary_amd64.s | 122 + .../internal/asm/c128/axpyunitaryto_amd64.s | 123 + .../v1/gonum/internal/asm/c128/bench_test.go | 284 ++ .../v1/gonum/internal/asm/c128/doc.go | 6 + .../v1/gonum/internal/asm/c128/dotc.go | 35 + .../v1/gonum/internal/asm/c128/dotu.go | 33 + .../gonum/internal/asm/c128/dscalinc_amd64.s | 69 + .../internal/asm/c128/dscalunitary_amd64.s | 66 + .../v1/gonum/internal/asm/c128/scal.go | 31 + .../internal/asm/c128/scalUnitary_amd64.s | 116 + .../gonum/internal/asm/c128/scalinc_amd64.s | 121 + .../v1/gonum/internal/asm/c128/stubs_amd64.go | 64 + .../v1/gonum/internal/asm/c128/stubs_noasm.go | 105 + .../v1/gonum/internal/asm/c128/stubs_test.go | 335 ++ .../v1/gonum/internal/asm/c128/util_test.go | 123 + .../v1/gonum/internal/asm/c64/axpyinc_amd64.s | 151 + .../gonum/internal/asm/c64/axpyincto_amd64.s | 156 + .../internal/asm/c64/axpyunitary_amd64.s | 160 + .../internal/asm/c64/axpyunitaryto_amd64.s | 157 + .../v1/gonum/internal/asm/c64/bench_test.go | 282 ++ .../v1/gonum/internal/asm/c64/conj.go | 7 + .../v1/gonum/internal/asm/c64/doc.go | 6 + .../v1/gonum/internal/asm/c64/dotc.go | 33 + .../v1/gonum/internal/asm/c64/dotu.go | 33 + .../v1/gonum/internal/asm/c64/scal.go | 55 + .../v1/gonum/internal/asm/c64/stubs_amd64.go | 36 + .../v1/gonum/internal/asm/c64/stubs_noasm.go | 57 + .../v1/gonum/internal/asm/c64/stubs_test.go | 231 ++ .../v1/gonum/internal/asm/f32/axpyinc_amd64.s | 73 + .../gonum/internal/asm/f32/axpyincto_amd64.s | 78 + .../internal/asm/f32/axpyunitary_amd64.s | 97 + .../internal/asm/f32/axpyunitaryto_amd64.s | 98 + .../v1/gonum/internal/asm/f32/bench_test.go | 282 ++ .../v1/gonum/internal/asm/f32/ddot.go | 33 + .../v1/gonum/internal/asm/f32/doc.go | 6 + .../v1/gonum/internal/asm/f32/dot.go | 33 + .../v1/gonum/internal/asm/f32/scal.go | 55 + .../v1/gonum/internal/asm/f32/stubs_amd64.go | 36 + .../v1/gonum/internal/asm/f32/stubs_noasm.go | 57 + .../v1/gonum/internal/asm/f32/stubs_test.go | 217 ++ .../v1/gonum/internal/asm/f64/abssum_amd64.s | 82 + .../gonum/internal/asm/f64/abssuminc_amd64.s | 90 + .../v1/gonum/internal/asm/f64/add_amd64.s | 66 + .../gonum/internal/asm/f64/addconst_amd64.s | 53 + .../v1/gonum/internal/asm/f64/asm_test.go | 204 ++ .../v1/gonum/internal/asm/f64/axpy.go | 57 + .../v1/gonum/internal/asm/f64/axpy_test.go | 274 ++ .../v1/gonum/internal/asm/f64/axpyinc_amd64.s | 142 + .../gonum/internal/asm/f64/axpyincto_amd64.s | 148 + .../internal/asm/f64/axpyunitary_amd64.s | 134 + .../internal/asm/f64/axpyunitaryto_amd64.s | 140 + .../gonum/internal/asm/f64/benchAxpy_test.go | 167 + .../gonum/internal/asm/f64/benchScal_test.go | 87 + .../internal/asm/f64/bench_other_test.go | 443 +++ .../v1/gonum/internal/asm/f64/bench_test.go | 438 +++ .../v1/gonum/internal/asm/f64/cumprod_amd64.s | 71 + .../v1/gonum/internal/asm/f64/cumsum_amd64.s | 64 + .../v1/gonum/internal/asm/f64/div_amd64.s | 67 + .../v1/gonum/internal/asm/f64/divto_amd64.s | 73 + .../v1/gonum/internal/asm/f64/doc.go | 6 + .../v1/gonum/internal/asm/f64/dot.go | 35 + .../v1/gonum/internal/asm/f64/dot_amd64.s | 145 + .../v1/gonum/internal/asm/f64/dot_test.go | 280 ++ .../v1/gonum/internal/asm/f64/l1norm_amd64.s | 58 + .../gonum/internal/asm/f64/linfnorm_amd64.s | 57 + .../v1/gonum/internal/asm/f64/scal.go | 57 + .../v1/gonum/internal/asm/f64/scal_test.go | 179 + .../v1/gonum/internal/asm/f64/scalinc_amd64.s | 113 + .../gonum/internal/asm/f64/scalincto_amd64.s | 122 + .../internal/asm/f64/scalunitary_amd64.s | 112 + .../internal/asm/f64/scalunitaryto_amd64.s | 113 + .../v1/gonum/internal/asm/f64/stubs_amd64.go | 165 + .../v1/gonum/internal/asm/f64/stubs_noasm.go | 157 + .../v1/gonum/internal/asm/f64/stubs_test.go | 574 +++ .../v1/gonum/internal/cmplx64/abs.go | 14 + .../v1/gonum/internal/cmplx64/cmath_test.go | 240 ++ .../v1/gonum/internal/cmplx64/conj.go | 12 + .../v1/gonum/internal/cmplx64/doc.go | 7 + .../v1/gonum/internal/cmplx64/isinf.go | 25 + .../v1/gonum/internal/cmplx64/isnan.go | 29 + .../v1/gonum/internal/cmplx64/sqrt.go | 108 + .../gonum.org/v1/gonum/internal/math32/doc.go | 7 + .../v1/gonum/internal/math32/math.go | 111 + .../v1/gonum/internal/math32/math_test.go | 238 ++ .../v1/gonum/internal/math32/signbit.go | 16 + .../v1/gonum/internal/math32/sqrt.go | 25 + .../v1/gonum/internal/math32/sqrt_amd64.go | 20 + .../v1/gonum/internal/math32/sqrt_amd64.s | 20 + vendor/gonum.org/v1/gonum/lapack/.gitignore | 0 vendor/gonum.org/v1/gonum/lapack/README.md | 50 + .../v1/gonum/lapack/gonum/appengine_test.go | 9 + .../v1/gonum/lapack/gonum/bench_test.go | 15 + .../gonum.org/v1/gonum/lapack/gonum/dbdsqr.go | 488 +++ .../gonum.org/v1/gonum/lapack/gonum/dgebak.go | 78 + .../gonum.org/v1/gonum/lapack/gonum/dgebal.go | 228 ++ .../gonum.org/v1/gonum/lapack/gonum/dgebd2.go | 74 + .../gonum.org/v1/gonum/lapack/gonum/dgebrd.go | 150 + .../gonum.org/v1/gonum/lapack/gonum/dgecon.go | 81 + .../gonum.org/v1/gonum/lapack/gonum/dgeev.go | 284 ++ .../gonum.org/v1/gonum/lapack/gonum/dgehd2.go | 84 + .../gonum.org/v1/gonum/lapack/gonum/dgehrd.go | 183 + .../gonum.org/v1/gonum/lapack/gonum/dgelq2.go | 49 + .../gonum.org/v1/gonum/lapack/gonum/dgelqf.go | 84 + .../gonum.org/v1/gonum/lapack/gonum/dgels.go | 200 ++ .../gonum.org/v1/gonum/lapack/gonum/dgeql2.go | 45 + .../gonum.org/v1/gonum/lapack/gonum/dgeqp3.go | 174 + .../gonum.org/v1/gonum/lapack/gonum/dgeqr2.go | 59 + .../gonum.org/v1/gonum/lapack/gonum/dgeqrf.go | 99 + .../gonum.org/v1/gonum/lapack/gonum/dgerq2.go | 53 + .../gonum.org/v1/gonum/lapack/gonum/dgerqf.go | 128 + .../gonum.org/v1/gonum/lapack/gonum/dgesvd.go | 1356 +++++++ .../gonum.org/v1/gonum/lapack/gonum/dgetf2.go | 69 + .../gonum.org/v1/gonum/lapack/gonum/dgetrf.go | 70 + .../gonum.org/v1/gonum/lapack/gonum/dgetri.go | 92 + .../gonum.org/v1/gonum/lapack/gonum/dgetrs.go | 55 + .../v1/gonum/lapack/gonum/dggsvd3.go | 230 ++ .../v1/gonum/lapack/gonum/dggsvp3.go | 273 ++ .../gonum.org/v1/gonum/lapack/gonum/dhseqr.go | 257 ++ .../gonum.org/v1/gonum/lapack/gonum/dlabrd.go | 150 + .../gonum.org/v1/gonum/lapack/gonum/dlacn2.go | 134 + .../gonum.org/v1/gonum/lapack/gonum/dlacpy.go | 40 + .../gonum.org/v1/gonum/lapack/gonum/dlae2.go | 49 + .../gonum.org/v1/gonum/lapack/gonum/dlaev2.go | 82 + .../gonum.org/v1/gonum/lapack/gonum/dlaexc.go | 261 ++ .../gonum.org/v1/gonum/lapack/gonum/dlags2.go | 182 + .../gonum.org/v1/gonum/lapack/gonum/dlahqr.go | 423 +++ .../gonum.org/v1/gonum/lapack/gonum/dlahr2.go | 169 + .../gonum.org/v1/gonum/lapack/gonum/dlaln2.go | 396 +++ .../gonum.org/v1/gonum/lapack/gonum/dlange.go | 84 + .../gonum.org/v1/gonum/lapack/gonum/dlanst.go | 68 + .../gonum.org/v1/gonum/lapack/gonum/dlansy.go | 125 + .../gonum.org/v1/gonum/lapack/gonum/dlantr.go | 252 ++ .../gonum.org/v1/gonum/lapack/gonum/dlanv2.go | 132 + .../gonum.org/v1/gonum/lapack/gonum/dlapll.go | 36 + .../gonum.org/v1/gonum/lapack/gonum/dlapmt.go | 72 + .../gonum.org/v1/gonum/lapack/gonum/dlapy2.go | 14 + .../gonum.org/v1/gonum/lapack/gonum/dlaqp2.go | 111 + .../gonum.org/v1/gonum/lapack/gonum/dlaqps.go | 217 ++ .../v1/gonum/lapack/gonum/dlaqr04.go | 475 +++ .../gonum.org/v1/gonum/lapack/gonum/dlaqr1.go | 57 + .../v1/gonum/lapack/gonum/dlaqr23.go | 403 +++ .../gonum.org/v1/gonum/lapack/gonum/dlaqr5.go | 616 ++++ .../gonum.org/v1/gonum/lapack/gonum/dlarf.go | 83 + .../gonum.org/v1/gonum/lapack/gonum/dlarfb.go | 431 +++ .../gonum.org/v1/gonum/lapack/gonum/dlarfg.go | 62 + .../gonum.org/v1/gonum/lapack/gonum/dlarft.go | 150 + .../gonum.org/v1/gonum/lapack/gonum/dlarfx.go | 535 +++ .../gonum.org/v1/gonum/lapack/gonum/dlartg.go | 80 + .../gonum.org/v1/gonum/lapack/gonum/dlas2.go | 43 + .../gonum.org/v1/gonum/lapack/gonum/dlascl.go | 89 + .../gonum.org/v1/gonum/lapack/gonum/dlaset.go | 40 + .../gonum.org/v1/gonum/lapack/gonum/dlasq1.go | 97 + .../gonum.org/v1/gonum/lapack/gonum/dlasq2.go | 368 ++ .../gonum.org/v1/gonum/lapack/gonum/dlasq3.go | 161 + .../gonum.org/v1/gonum/lapack/gonum/dlasq4.go | 238 ++ .../gonum.org/v1/gonum/lapack/gonum/dlasq5.go | 127 + .../gonum.org/v1/gonum/lapack/gonum/dlasq6.go | 109 + .../gonum.org/v1/gonum/lapack/gonum/dlasr.go | 268 ++ .../gonum.org/v1/gonum/lapack/gonum/dlasrt.go | 30 + .../gonum.org/v1/gonum/lapack/gonum/dlassq.go | 31 + .../gonum.org/v1/gonum/lapack/gonum/dlasv2.go | 115 + .../gonum.org/v1/gonum/lapack/gonum/dlaswp.go | 47 + .../gonum.org/v1/gonum/lapack/gonum/dlasy2.go | 290 ++ .../gonum.org/v1/gonum/lapack/gonum/dlatrd.go | 145 + .../gonum.org/v1/gonum/lapack/gonum/dlatrs.go | 350 ++ vendor/gonum.org/v1/gonum/lapack/gonum/doc.go | 28 + .../gonum.org/v1/gonum/lapack/gonum/dorg2l.go | 65 + .../gonum.org/v1/gonum/lapack/gonum/dorg2r.go | 65 + .../gonum.org/v1/gonum/lapack/gonum/dorgbr.go | 124 + .../gonum.org/v1/gonum/lapack/gonum/dorghr.go | 93 + .../gonum.org/v1/gonum/lapack/gonum/dorgl2.go | 63 + .../gonum.org/v1/gonum/lapack/gonum/dorglq.go | 117 + .../gonum.org/v1/gonum/lapack/gonum/dorgql.go | 130 + .../gonum.org/v1/gonum/lapack/gonum/dorgqr.go | 120 + .../gonum.org/v1/gonum/lapack/gonum/dorgtr.go | 99 + .../gonum.org/v1/gonum/lapack/gonum/dorm2r.go | 88 + .../gonum.org/v1/gonum/lapack/gonum/dormbr.go | 158 + .../gonum.org/v1/gonum/lapack/gonum/dormhr.go | 121 + .../gonum.org/v1/gonum/lapack/gonum/dorml2.go | 83 + .../gonum.org/v1/gonum/lapack/gonum/dormlq.go | 159 + .../gonum.org/v1/gonum/lapack/gonum/dormqr.go | 167 + .../gonum.org/v1/gonum/lapack/gonum/dormr2.go | 93 + .../gonum.org/v1/gonum/lapack/gonum/dpbtf2.go | 97 + .../gonum.org/v1/gonum/lapack/gonum/dpocon.go | 76 + .../gonum.org/v1/gonum/lapack/gonum/dpotf2.go | 72 + .../gonum.org/v1/gonum/lapack/gonum/dpotrf.go | 72 + .../gonum.org/v1/gonum/lapack/gonum/drscl.go | 47 + .../gonum.org/v1/gonum/lapack/gonum/dsteqr.go | 373 ++ .../gonum.org/v1/gonum/lapack/gonum/dsterf.go | 278 ++ .../gonum.org/v1/gonum/lapack/gonum/dsyev.go | 113 + .../gonum.org/v1/gonum/lapack/gonum/dsytd2.go | 123 + .../gonum.org/v1/gonum/lapack/gonum/dsytrd.go | 178 + .../gonum.org/v1/gonum/lapack/gonum/dtgsja.go | 357 ++ .../gonum.org/v1/gonum/lapack/gonum/dtrcon.go | 82 + .../v1/gonum/lapack/gonum/dtrevc3.go | 866 +++++ .../gonum.org/v1/gonum/lapack/gonum/dtrexc.go | 221 ++ .../gonum.org/v1/gonum/lapack/gonum/dtrti2.go | 57 + .../gonum.org/v1/gonum/lapack/gonum/dtrtri.go | 64 + .../gonum.org/v1/gonum/lapack/gonum/dtrtrs.go | 30 + .../v1/gonum/lapack/gonum/general.go | 143 + .../gonum.org/v1/gonum/lapack/gonum/iladlc.go | 33 + .../gonum.org/v1/gonum/lapack/gonum/iladlr.go | 30 + .../gonum.org/v1/gonum/lapack/gonum/ilaenv.go | 387 ++ .../gonum.org/v1/gonum/lapack/gonum/iparmq.go | 115 + .../v1/gonum/lapack/gonum/lapack_test.go | 441 +++ .../internal/testdata/dlahr2test/main.go | 101 + .../internal/testdata/dlaqr5test/main.go | 185 + .../internal/testdata/dlasqtest/Makefile | 27 + .../internal/testdata/dlasqtest/Readme.md | 23 + .../internal/testdata/dlasqtest/dcopy.f | 115 + .../internal/testdata/dlasqtest/disnan.f | 80 + .../internal/testdata/dlasqtest/dlaisnan.f | 91 + .../internal/testdata/dlasqtest/dlamch.f | 193 + .../internal/testdata/dlasqtest/dlas2.f | 183 + .../internal/testdata/dlasqtest/dlascl.f | 364 ++ .../internal/testdata/dlasqtest/dlasq1.f | 226 ++ .../internal/testdata/dlasqtest/dlasq2.f | 652 ++++ .../internal/testdata/dlasqtest/dlasq3.f | 498 +++ .../internal/testdata/dlasqtest/dlasq4.f | 427 +++ .../internal/testdata/dlasqtest/dlasq5.f | 413 +++ .../internal/testdata/dlasqtest/dlasq6.f | 258 ++ .../internal/testdata/dlasqtest/dlasrt.f | 303 ++ .../internal/testdata/dlasqtest/ieeeck.f | 203 ++ .../internal/testdata/dlasqtest/ilaenv.f | 624 ++++ .../internal/testdata/dlasqtest/iparmq.f | 322 ++ .../internal/testdata/dlasqtest/lsame.f | 125 + .../testdata/dlasqtest/testdlasq1.f90 | 626 ++++ .../testdata/dlasqtest/testdlasq2.f90 | 171 + .../testdata/dlasqtest/testdlasq3.f90 | 132 + .../testdata/dlasqtest/testdlasq4.f90 | 435 +++ .../internal/testdata/dlasqtest/xerbla.f | 99 + .../internal/testdata/dsterftest/Makefile | 20 + .../internal/testdata/dsterftest/disnan.f | 80 + .../internal/testdata/dsterftest/dlae2.f | 185 + .../internal/testdata/dsterftest/dlaisnan.f | 91 + .../internal/testdata/dsterftest/dlamch.f | 193 + .../internal/testdata/dsterftest/dlanst.f | 186 + .../internal/testdata/dsterftest/dlapy2.f | 104 + .../internal/testdata/dsterftest/dlascl.f | 364 ++ .../internal/testdata/dsterftest/dlasrt.f | 303 ++ .../internal/testdata/dsterftest/dlassq.f | 155 + .../internal/testdata/dsterftest/dsterf.f | 448 +++ .../internal/testdata/dsterftest/lsame.f | 125 + .../testdata/dsterftest/testdsterf.f90 | 15 + .../internal/testdata/dsterftest/xerbla.f | 99 + .../lapack/internal/testdata/netlib/daxpy.f | 115 + .../lapack/internal/testdata/netlib/dcopy.f | 115 + .../lapack/internal/testdata/netlib/dgemm.f | 384 ++ .../lapack/internal/testdata/netlib/dgemv.f | 330 ++ .../lapack/internal/testdata/netlib/dlabad.f | 105 + .../lapack/internal/testdata/netlib/dlacpy.f | 156 + .../lapack/internal/testdata/netlib/dlahr2.f | 326 ++ .../lapack/internal/testdata/netlib/dlamch.f | 189 + .../lapack/internal/testdata/netlib/dlapy2.f | 104 + .../lapack/internal/testdata/netlib/dlaqr1.f | 179 + .../lapack/internal/testdata/netlib/dlaqr5.f | 921 +++++ .../lapack/internal/testdata/netlib/dlarfg.f | 196 ++ .../lapack/internal/testdata/netlib/dlaset.f | 184 + .../lapack/internal/testdata/netlib/dnrm2.f | 112 + .../lapack/internal/testdata/netlib/dscal.f | 110 + .../lapack/internal/testdata/netlib/dtrmm.f | 415 +++ .../lapack/internal/testdata/netlib/dtrmv.f | 342 ++ .../lapack/internal/testdata/netlib/lsame.f | 125 + .../lapack/internal/testdata/netlib/netlib.go | 68 + .../lapack/internal/testdata/netlib/xerbla.f | 89 + vendor/gonum.org/v1/gonum/lapack/lapack.go | 188 + .../gonum.org/v1/gonum/lapack/lapack64/doc.go | 20 + .../v1/gonum/lapack/lapack64/lapack64.go | 545 +++ .../v1/gonum/lapack/testlapack/dbdsqr.go | 198 ++ .../v1/gonum/lapack/testlapack/dgebak.go | 110 + .../v1/gonum/lapack/testlapack/dgebal.go | 175 + .../v1/gonum/lapack/testlapack/dgebd2.go | 54 + .../v1/gonum/lapack/testlapack/dgebrd.go | 151 + .../v1/gonum/lapack/testlapack/dgecon.go | 97 + .../v1/gonum/lapack/testlapack/dgeev.go | 735 ++++ .../v1/gonum/lapack/testlapack/dgeev_bench.go | 63 + .../v1/gonum/lapack/testlapack/dgehd2.go | 196 ++ .../v1/gonum/lapack/testlapack/dgehrd.go | 209 ++ .../v1/gonum/lapack/testlapack/dgelq2.go | 113 + .../v1/gonum/lapack/testlapack/dgelqf.go | 98 + .../v1/gonum/lapack/testlapack/dgels.go | 182 + .../v1/gonum/lapack/testlapack/dgeql2.go | 99 + .../v1/gonum/lapack/testlapack/dgeqp3.go | 135 + .../v1/gonum/lapack/testlapack/dgeqr2.go | 111 + .../v1/gonum/lapack/testlapack/dgeqrf.go | 95 + .../v1/gonum/lapack/testlapack/dgerq2.go | 117 + .../v1/gonum/lapack/testlapack/dgerqf.go | 142 + .../v1/gonum/lapack/testlapack/dgesvd.go | 286 ++ .../v1/gonum/lapack/testlapack/dgetf2.go | 195 ++ .../v1/gonum/lapack/testlapack/dgetrf.go | 65 + .../v1/gonum/lapack/testlapack/dgetri.go | 89 + .../v1/gonum/lapack/testlapack/dgetrs.go | 113 + .../v1/gonum/lapack/testlapack/dggsvd3.go | 173 + .../v1/gonum/lapack/testlapack/dggsvp3.go | 146 + .../v1/gonum/lapack/testlapack/dhseqr.go | 861 +++++ .../v1/gonum/lapack/testlapack/dlabrd.go | 107 + .../v1/gonum/lapack/testlapack/dlacn2.go | 72 + .../v1/gonum/lapack/testlapack/dlacpy.go | 89 + .../v1/gonum/lapack/testlapack/dlae2.go | 53 + .../v1/gonum/lapack/testlapack/dlaev2.go | 46 + .../v1/gonum/lapack/testlapack/dlaexc.go | 227 ++ .../v1/gonum/lapack/testlapack/dlags2.go | 100 + .../v1/gonum/lapack/testlapack/dlahqr.go | 441 +++ .../v1/gonum/lapack/testlapack/dlahr2.go | 240 ++ .../v1/gonum/lapack/testlapack/dlaln2.go | 139 + .../v1/gonum/lapack/testlapack/dlange.go | 93 + .../v1/gonum/lapack/testlapack/dlanst.go | 53 + .../v1/gonum/lapack/testlapack/dlansy.go | 80 + .../v1/gonum/lapack/testlapack/dlantr.go | 89 + .../v1/gonum/lapack/testlapack/dlanv2.go | 69 + .../v1/gonum/lapack/testlapack/dlapll.go | 46 + .../v1/gonum/lapack/testlapack/dlapmt.go | 113 + .../v1/gonum/lapack/testlapack/dlapy2.go | 30 + .../v1/gonum/lapack/testlapack/dlaqp2.go | 115 + .../v1/gonum/lapack/testlapack/dlaqps.go | 112 + .../v1/gonum/lapack/testlapack/dlaqr04.go | 449 +++ .../v1/gonum/lapack/testlapack/dlaqr1.go | 91 + .../v1/gonum/lapack/testlapack/dlaqr23.go | 335 ++ .../v1/gonum/lapack/testlapack/dlaqr5.go | 214 ++ .../v1/gonum/lapack/testlapack/dlarf.go | 173 + .../v1/gonum/lapack/testlapack/dlarfb.go | 161 + .../v1/gonum/lapack/testlapack/dlarfg.go | 134 + .../v1/gonum/lapack/testlapack/dlarft.go | 168 + .../v1/gonum/lapack/testlapack/dlarfx.go | 82 + .../v1/gonum/lapack/testlapack/dlartg.go | 98 + .../v1/gonum/lapack/testlapack/dlas2.go | 34 + .../v1/gonum/lapack/testlapack/dlascl.go | 106 + .../v1/gonum/lapack/testlapack/dlaset.go | 76 + .../v1/gonum/lapack/testlapack/dlasq1.go | 87 + .../v1/gonum/lapack/testlapack/dlasq2.go | 714 ++++ .../v1/gonum/lapack/testlapack/dlasq3.go | 2703 ++++++++++++++ .../v1/gonum/lapack/testlapack/dlasq4.go | 3101 +++++++++++++++++ .../v1/gonum/lapack/testlapack/dlasq5.go | 1992 +++++++++++ .../v1/gonum/lapack/testlapack/dlasr.go | 148 + .../v1/gonum/lapack/testlapack/dlasrt.go | 80 + .../v1/gonum/lapack/testlapack/dlasv2.go | 48 + .../v1/gonum/lapack/testlapack/dlaswp.go | 130 + .../v1/gonum/lapack/testlapack/dlasy2.go | 104 + .../v1/gonum/lapack/testlapack/dlatrd.go | 245 ++ .../v1/gonum/lapack/testlapack/dlatrs.go | 141 + .../v1/gonum/lapack/testlapack/doc.go | 6 + .../v1/gonum/lapack/testlapack/dorg2l.go | 75 + .../v1/gonum/lapack/testlapack/dorg2r.go | 79 + .../v1/gonum/lapack/testlapack/dorgbr.go | 156 + .../v1/gonum/lapack/testlapack/dorghr.go | 99 + .../v1/gonum/lapack/testlapack/dorgl2.go | 65 + .../v1/gonum/lapack/testlapack/dorglq.go | 83 + .../v1/gonum/lapack/testlapack/dorgql.go | 130 + .../v1/gonum/lapack/testlapack/dorgqr.go | 83 + .../v1/gonum/lapack/testlapack/dorgtr.go | 136 + .../v1/gonum/lapack/testlapack/dorm2r.go | 139 + .../v1/gonum/lapack/testlapack/dormbr.go | 164 + .../v1/gonum/lapack/testlapack/dormhr.go | 132 + .../v1/gonum/lapack/testlapack/dorml2.go | 144 + .../v1/gonum/lapack/testlapack/dormlq.go | 130 + .../v1/gonum/lapack/testlapack/dormqr.go | 154 + .../v1/gonum/lapack/testlapack/dormr2.go | 137 + .../v1/gonum/lapack/testlapack/dpbtf2.go | 47 + .../v1/gonum/lapack/testlapack/dpocon.go | 157 + .../v1/gonum/lapack/testlapack/dpotf2.go | 117 + .../v1/gonum/lapack/testlapack/dpotrf.go | 135 + .../v1/gonum/lapack/testlapack/drscl.go | 52 + .../v1/gonum/lapack/testlapack/dsteqr.go | 171 + .../v1/gonum/lapack/testlapack/dsterf.go | 126 + .../v1/gonum/lapack/testlapack/dsyev.go | 115 + .../v1/gonum/lapack/testlapack/dsytd2.go | 205 ++ .../v1/gonum/lapack/testlapack/dsytrd.go | 160 + .../v1/gonum/lapack/testlapack/dtgsja.go | 165 + .../v1/gonum/lapack/testlapack/dtrcon.go | 184 + .../v1/gonum/lapack/testlapack/dtrevc3.go | 221 ++ .../v1/gonum/lapack/testlapack/dtrexc.go | 219 ++ .../v1/gonum/lapack/testlapack/dtrti2.go | 163 + .../v1/gonum/lapack/testlapack/dtrtri.go | 95 + .../v1/gonum/lapack/testlapack/fortran.go | 33 + .../v1/gonum/lapack/testlapack/general.go | 1516 ++++++++ .../v1/gonum/lapack/testlapack/iladlc.go | 83 + .../v1/gonum/lapack/testlapack/iladlr.go | 83 + .../v1/gonum/lapack/testlapack/matgen.go | 655 ++++ .../v1/gonum/lapack/testlapack/matgen_test.go | 90 + .../gonum/lapack/testlapack/test_matrices.go | 615 ++++ .../testlapack/testdata/dlahr2data.json.gz | Bin 0 -> 28251 bytes .../testlapack/testdata/dlaqr5data.json.gz | Bin 0 -> 1342926 bytes vendor/gonum.org/v1/gonum/mat/README.md | 3 + vendor/gonum.org/v1/gonum/mat/band.go | 228 ++ vendor/gonum.org/v1/gonum/mat/band_test.go | 377 ++ vendor/gonum.org/v1/gonum/mat/cblas_test.go | 16 + vendor/gonum.org/v1/gonum/mat/cholesky.go | 479 +++ .../v1/gonum/mat/cholesky_example_test.go | 121 + .../gonum.org/v1/gonum/mat/cholesky_test.go | 453 +++ vendor/gonum.org/v1/gonum/mat/cmatrix.go | 71 + vendor/gonum.org/v1/gonum/mat/consts.go | 54 + vendor/gonum.org/v1/gonum/mat/dense.go | 534 +++ .../v1/gonum/mat/dense_arithmetic.go | 719 ++++ vendor/gonum.org/v1/gonum/mat/dense_test.go | 2005 +++++++++++ vendor/gonum.org/v1/gonum/mat/doc.go | 173 + vendor/gonum.org/v1/gonum/mat/eigen.go | 260 ++ vendor/gonum.org/v1/gonum/mat/eigen_test.go | 164 + vendor/gonum.org/v1/gonum/mat/errors.go | 148 + vendor/gonum.org/v1/gonum/mat/errors_test.go | 56 + .../gonum.org/v1/gonum/mat/fao_data_test.go | 122 + vendor/gonum.org/v1/gonum/mat/format.go | 238 ++ .../v1/gonum/mat/format_example_test.go | 112 + vendor/gonum.org/v1/gonum/mat/format_test.go | 150 + vendor/gonum.org/v1/gonum/mat/gsvd.go | 371 ++ .../v1/gonum/mat/gsvd_example_test.go | 85 + vendor/gonum.org/v1/gonum/mat/gsvd_test.go | 117 + vendor/gonum.org/v1/gonum/mat/hogsvd.go | 213 ++ .../v1/gonum/mat/hogsvd_example_test.go | 134 + vendor/gonum.org/v1/gonum/mat/hogsvd_test.go | 87 + .../v1/gonum/mat/index_bound_checks.go | 227 ++ .../v1/gonum/mat/index_no_bound_checks.go | 228 ++ vendor/gonum.org/v1/gonum/mat/inner.go | 102 + vendor/gonum.org/v1/gonum/mat/inner_test.go | 181 + vendor/gonum.org/v1/gonum/mat/io.go | 360 ++ vendor/gonum.org/v1/gonum/mat/io_test.go | 731 ++++ vendor/gonum.org/v1/gonum/mat/list_test.go | 1151 ++++++ vendor/gonum.org/v1/gonum/mat/lq.go | 225 ++ vendor/gonum.org/v1/gonum/mat/lq_test.go | 179 + vendor/gonum.org/v1/gonum/mat/lu.go | 373 ++ vendor/gonum.org/v1/gonum/mat/lu_test.go | 189 + vendor/gonum.org/v1/gonum/mat/matrix.go | 881 +++++ vendor/gonum.org/v1/gonum/mat/matrix_test.go | 624 ++++ vendor/gonum.org/v1/gonum/mat/mul_test.go | 283 ++ vendor/gonum.org/v1/gonum/mat/offset.go | 20 + .../v1/gonum/mat/offset_appengine.go | 24 + vendor/gonum.org/v1/gonum/mat/pool.go | 236 ++ vendor/gonum.org/v1/gonum/mat/pool_test.go | 81 + vendor/gonum.org/v1/gonum/mat/product.go | 193 + vendor/gonum.org/v1/gonum/mat/product_test.go | 251 ++ vendor/gonum.org/v1/gonum/mat/qr.go | 221 ++ vendor/gonum.org/v1/gonum/mat/qr_test.go | 205 ++ vendor/gonum.org/v1/gonum/mat/shadow.go | 280 ++ vendor/gonum.org/v1/gonum/mat/shadow_test.go | 274 ++ vendor/gonum.org/v1/gonum/mat/solve.go | 127 + vendor/gonum.org/v1/gonum/mat/solve_test.go | 296 ++ vendor/gonum.org/v1/gonum/mat/svd.go | 190 + vendor/gonum.org/v1/gonum/mat/svd_test.go | 172 + vendor/gonum.org/v1/gonum/mat/symband.go | 175 + vendor/gonum.org/v1/gonum/mat/symband_test.go | 230 ++ vendor/gonum.org/v1/gonum/mat/symmetric.go | 502 +++ .../v1/gonum/mat/symmetric_example_test.go | 54 + .../gonum.org/v1/gonum/mat/symmetric_test.go | 694 ++++ vendor/gonum.org/v1/gonum/mat/triangular.go | 540 +++ .../gonum.org/v1/gonum/mat/triangular_test.go | 438 +++ vendor/gonum.org/v1/gonum/mat/vector.go | 484 +++ vendor/gonum.org/v1/gonum/mat/vector_test.go | 530 +++ vendor/gonum.org/v1/gonum/mathext/README.md | 3 + vendor/gonum.org/v1/gonum/mathext/airy.go | 37 + .../gonum.org/v1/gonum/mathext/airy_test.go | 28 + vendor/gonum.org/v1/gonum/mathext/beta.go | 34 + .../gonum.org/v1/gonum/mathext/beta_test.go | 177 + vendor/gonum.org/v1/gonum/mathext/betainc.go | 29 + .../v1/gonum/mathext/betainc_test.go | 75 + vendor/gonum.org/v1/gonum/mathext/digamma.go | 28 + .../v1/gonum/mathext/digamma_test.go | 27 + vendor/gonum.org/v1/gonum/mathext/doc.go | 7 + .../gonum.org/v1/gonum/mathext/ell_carlson.go | 156 + .../v1/gonum/mathext/ell_carlson_test.go | 103 + .../v1/gonum/mathext/ell_complete.go | 157 + .../v1/gonum/mathext/ell_complete_test.go | 27 + vendor/gonum.org/v1/gonum/mathext/erf.go | 91 + vendor/gonum.org/v1/gonum/mathext/erf_test.go | 69 + .../gonum.org/v1/gonum/mathext/gamma_inc.go | 50 + .../v1/gonum/mathext/gamma_inc_inv.go | 56 + .../v1/gonum/mathext/gamma_inc_test.go | 138 + .../v1/gonum/mathext/internal/amos/amos.go | 2154 ++++++++++++ .../gonum/mathext/internal/amos/amos_test.go | 521 +++ .../mathext/internal/amos/amoslib/Make.files | 5 + .../mathext/internal/amos/amoslib/d1mach.f | 97 + .../mathext/internal/amos/amoslib/dgamln.f | 189 + .../mathext/internal/amos/amoslib/fortran.go | 366 ++ .../mathext/internal/amos/amoslib/i1mach.f | 113 + .../mathext/internal/amos/amoslib/myabs.f | 5 + .../mathext/internal/amos/amoslib/myatan.f | 5 + .../mathext/internal/amos/amoslib/mycos.f | 5 + .../mathext/internal/amos/amoslib/myexp.f | 5 + .../mathext/internal/amos/amoslib/mylog.f | 5 + .../mathext/internal/amos/amoslib/mymax.f | 5 + .../mathext/internal/amos/amoslib/mymin.f | 5 + .../mathext/internal/amos/amoslib/mysin.f | 5 + .../mathext/internal/amos/amoslib/mysqrt.f | 5 + .../mathext/internal/amos/amoslib/mytan.f | 5 + .../mathext/internal/amos/amoslib/xerror.f | 22 + .../mathext/internal/amos/amoslib/zabs.f | 34 + .../mathext/internal/amos/amoslib/zacai.f | 99 + .../mathext/internal/amos/amoslib/zacon.f | 203 ++ .../mathext/internal/amos/amoslib/zairy.f | 395 +++ .../mathext/internal/amos/amoslib/zasyi.f | 169 + .../mathext/internal/amos/amoslib/zbesh.f | 348 ++ .../mathext/internal/amos/amoslib/zbesi.f | 269 ++ .../mathext/internal/amos/amoslib/zbesj.f | 266 ++ .../mathext/internal/amos/amoslib/zbesk.f | 281 ++ .../mathext/internal/amos/amoslib/zbesy.f | 244 ++ .../mathext/internal/amos/amoslib/zbinu.f | 110 + .../mathext/internal/amos/amoslib/zbiry.f | 364 ++ .../mathext/internal/amos/amoslib/zbknu.f | 568 +++ .../mathext/internal/amos/amoslib/zbuni.f | 174 + .../mathext/internal/amos/amoslib/zbunk.f | 35 + .../mathext/internal/amos/amoslib/zdiv.f | 19 + .../mathext/internal/amos/amoslib/zexp.f | 16 + .../mathext/internal/amos/amoslib/zkscl.f | 121 + .../mathext/internal/amos/amoslib/zlog.f | 41 + .../mathext/internal/amos/amoslib/zmlri.f | 206 ++ .../mathext/internal/amos/amoslib/zmlt.f | 15 + .../mathext/internal/amos/amoslib/zrati.f | 132 + .../mathext/internal/amos/amoslib/zs1s2.f | 51 + .../mathext/internal/amos/amoslib/zseri.f | 195 ++ .../mathext/internal/amos/amoslib/zshch.f | 22 + .../mathext/internal/amos/amoslib/zsqrt.f | 45 + .../mathext/internal/amos/amoslib/zuchk.f | 28 + .../mathext/internal/amos/amoslib/zunhj.f | 714 ++++ .../mathext/internal/amos/amoslib/zuni1.f | 204 ++ .../mathext/internal/amos/amoslib/zuni2.f | 267 ++ .../mathext/internal/amos/amoslib/zunik.f | 211 ++ .../mathext/internal/amos/amoslib/zunk1.f | 426 +++ .../mathext/internal/amos/amoslib/zunk2.f | 505 +++ .../mathext/internal/amos/amoslib/zuoik.f | 194 ++ .../mathext/internal/amos/amoslib/zwrsk.f | 94 + .../v1/gonum/mathext/internal/amos/doc.go | 6 + .../mathext/internal/amos/origcode_test.go | 2276 ++++++++++++ .../gonum/mathext/internal/cephes/cephes.go | 28 + .../v1/gonum/mathext/internal/cephes/doc.go | 6 + .../v1/gonum/mathext/internal/cephes/igam.go | 311 ++ .../v1/gonum/mathext/internal/cephes/igami.go | 153 + .../gonum/mathext/internal/cephes/incbeta.go | 312 ++ .../v1/gonum/mathext/internal/cephes/incbi.go | 248 ++ .../gonum/mathext/internal/cephes/lanczos.go | 153 + .../v1/gonum/mathext/internal/cephes/ndtri.go | 150 + .../gonum/mathext/internal/cephes/polevl.go | 82 + .../v1/gonum/mathext/internal/cephes/unity.go | 170 + .../v1/gonum/mathext/internal/cephes/zeta.go | 110 + .../v1/gonum/mathext/internal/gonum/beta.go | 52 + .../v1/gonum/mathext/internal/gonum/doc.go | 7 + .../v1/gonum/mathext/internal/gonum/gonum.go | 5 + vendor/gonum.org/v1/gonum/mathext/mvgamma.go | 32 + .../v1/gonum/mathext/mvgamma_test.go | 27 + vendor/gonum.org/v1/gonum/mathext/roots.go | 178 + vendor/gonum.org/v1/gonum/mathext/zeta.go | 20 + .../gonum.org/v1/gonum/mathext/zeta_test.go | 42 + vendor/gonum.org/v1/gonum/optimize/README.md | 3 + .../v1/gonum/optimize/backtracking.go | 82 + vendor/gonum.org/v1/gonum/optimize/bfgs.go | 160 + .../gonum.org/v1/gonum/optimize/bisection.go | 146 + vendor/gonum.org/v1/gonum/optimize/cg.go | 313 ++ .../v1/gonum/optimize/convex/lp/convert.go | 137 + .../v1/gonum/optimize/convex/lp/doc.go | 6 + .../v1/gonum/optimize/convex/lp/simplex.go | 619 ++++ .../gonum/optimize/convex/lp/simplex_test.go | 269 ++ .../optimize/convex/lp/simplexexample_test.go | 29 + vendor/gonum.org/v1/gonum/optimize/doc.go | 6 + vendor/gonum.org/v1/gonum/optimize/errors.go | 72 + .../v1/gonum/optimize/functionconvergence.go | 40 + .../v1/gonum/optimize/functions/doc.go | 15 + .../v1/gonum/optimize/functions/functions.go | 1818 ++++++++++ .../optimize/functions/functions_test.go | 326 ++ .../v1/gonum/optimize/functions/minsurf.go | 252 ++ .../gonum/optimize/functions/minsurf_test.go | 48 + .../v1/gonum/optimize/functions/validate.go | 127 + .../v1/gonum/optimize/functions/vlse.go | 325 ++ vendor/gonum.org/v1/gonum/optimize/global.go | 239 ++ .../v1/gonum/optimize/gradientdescent.go | 63 + .../v1/gonum/optimize/guessandcheck.go | 60 + .../v1/gonum/optimize/guessandcheck_test.go | 34 + .../gonum.org/v1/gonum/optimize/interfaces.go | 130 + vendor/gonum.org/v1/gonum/optimize/lbfgs.go | 167 + .../gonum.org/v1/gonum/optimize/linesearch.go | 218 ++ .../v1/gonum/optimize/linesearcher_test.go | 136 + vendor/gonum.org/v1/gonum/optimize/local.go | 225 ++ .../v1/gonum/optimize/local_example_test.go | 43 + .../gonum.org/v1/gonum/optimize/minimize.go | 202 ++ .../v1/gonum/optimize/morethuente.go | 385 ++ .../gonum.org/v1/gonum/optimize/neldermead.go | 314 ++ vendor/gonum.org/v1/gonum/optimize/newton.go | 147 + vendor/gonum.org/v1/gonum/optimize/printer.go | 106 + .../gonum.org/v1/gonum/optimize/stepsizers.go | 185 + .../v1/gonum/optimize/termination.go | 119 + vendor/gonum.org/v1/gonum/optimize/types.go | 262 ++ .../v1/gonum/optimize/unconstrained_test.go | 1305 +++++++ .../gonum.org/v1/gonum/stat/appengine_test.go | 9 + .../v1/gonum/stat/boston_data_test.go | 531 +++ .../gonum.org/v1/gonum/stat/car_data_test.go | 406 +++ .../v1/gonum/stat/cca_example_test.go | 165 + vendor/gonum.org/v1/gonum/stat/cca_test.go | 191 + .../gonum.org/v1/gonum/stat/combin/combin.go | 181 + .../v1/gonum/stat/combin/combin_test.go | 181 + vendor/gonum.org/v1/gonum/stat/combin/doc.go | 7 + vendor/gonum.org/v1/gonum/stat/distmat/doc.go | 6 + .../v1/gonum/stat/distmat/general.go | 7 + .../v1/gonum/stat/distmat/wishart.go | 209 ++ .../v1/gonum/stat/distmat/wishart_test.go | 129 + .../v1/gonum/stat/distmv/dirichlet.go | 144 + .../v1/gonum/stat/distmv/dirichlet_test.go | 67 + vendor/gonum.org/v1/gonum/stat/distmv/doc.go | 6 + .../gonum.org/v1/gonum/stat/distmv/general.go | 30 + .../v1/gonum/stat/distmv/general_test.go | 96 + .../v1/gonum/stat/distmv/interfaces.go | 33 + .../gonum.org/v1/gonum/stat/distmv/normal.go | 345 ++ .../v1/gonum/stat/distmv/normal_test.go | 573 +++ .../v1/gonum/stat/distmv/normalbench_test.go | 73 + .../v1/gonum/stat/distmv/statdist.go | 320 ++ .../v1/gonum/stat/distmv/statdist_test.go | 329 ++ .../v1/gonum/stat/distmv/studentst.go | 354 ++ .../v1/gonum/stat/distmv/studentst_test.go | 265 ++ .../gonum.org/v1/gonum/stat/distmv/uniform.go | 196 ++ .../v1/gonum/stat/distmv/uniform_test.go | 31 + .../v1/gonum/stat/distuv/bernoulli.go | 131 + .../v1/gonum/stat/distuv/bernoulli_test.go | 23 + vendor/gonum.org/v1/gonum/stat/distuv/beta.go | 126 + .../v1/gonum/stat/distuv/beta_test.go | 61 + .../v1/gonum/stat/distuv/categorical.go | 184 + .../v1/gonum/stat/distuv/categorical_test.go | 196 ++ .../v1/gonum/stat/distuv/chisquared.go | 99 + .../v1/gonum/stat/distuv/chisquared_test.go | 78 + .../v1/gonum/stat/distuv/constants.go | 24 + .../v1/gonum/stat/distuv/distribution_test.go | 293 ++ vendor/gonum.org/v1/gonum/stat/distuv/doc.go | 6 + .../v1/gonum/stat/distuv/exponential.go | 259 ++ .../v1/gonum/stat/distuv/exponential_test.go | 71 + vendor/gonum.org/v1/gonum/stat/distuv/f.go | 132 + .../gonum.org/v1/gonum/stat/distuv/f_test.go | 89 + .../gonum.org/v1/gonum/stat/distuv/gamma.go | 244 ++ .../v1/gonum/stat/distuv/gamma_test.go | 63 + .../gonum.org/v1/gonum/stat/distuv/general.go | 24 + .../v1/gonum/stat/distuv/general_test.go | 204 ++ .../v1/gonum/stat/distuv/interfaces.go | 22 + .../gonum.org/v1/gonum/stat/distuv/laplace.go | 251 ++ .../v1/gonum/stat/distuv/laplace_test.go | 58 + .../v1/gonum/stat/distuv/lognormal.go | 112 + .../v1/gonum/stat/distuv/lognormal_test.go | 44 + vendor/gonum.org/v1/gonum/stat/distuv/norm.go | 254 ++ .../v1/gonum/stat/distuv/norm_example_test.go | 35 + .../v1/gonum/stat/distuv/norm_test.go | 171 + .../v1/gonum/stat/distuv/studentst.go | 160 + .../v1/gonum/stat/distuv/studentst_test.go | 83 + .../v1/gonum/stat/distuv/triangle.go | 192 + .../v1/gonum/stat/distuv/triangle_test.go | 101 + .../gonum.org/v1/gonum/stat/distuv/uniform.go | 158 + .../gonum.org/v1/gonum/stat/distuv/weibull.go | 247 ++ .../v1/gonum/stat/distuv/weibull_test.go | 209 ++ .../gonum.org/v1/gonum/stat/faithful_test.go | 81 + .../v1/gonum/stat/moments_bench_test.go | 611 ++++ .../v1/gonum/stat/pca_example_test.go | 60 + vendor/gonum.org/v1/gonum/stat/pca_test.go | 188 + .../v1/gonum/stat/roc_example_test.go | 56 + vendor/gonum.org/v1/gonum/stat/roc_test.go | 178 + .../gonum.org/v1/gonum/stat/samplemv/doc.go | 11 + .../gonum/stat/samplemv/metropolishastings.go | 221 ++ .../v1/gonum/stat/samplemv/sample_test.go | 280 ++ .../v1/gonum/stat/samplemv/samplemv.go | 274 ++ .../gonum.org/v1/gonum/stat/sampleuv/doc.go | 11 + .../stat/sampleuv/example_burnin_test.go | 39 + .../gonum/stat/sampleuv/example_rate_test.go | 49 + .../v1/gonum/stat/sampleuv/sample.go | 393 +++ .../v1/gonum/stat/sampleuv/sample_test.go | 99 + .../v1/gonum/stat/sampleuv/weighted.go | 138 + .../v1/gonum/stat/sampleuv/weighted_test.go | 267 ++ .../gonum/stat/sampleuv/withoutreplacement.go | 59 + .../stat/sampleuv/withoutreplacement_test.go | 65 + vendor/gonum.org/v1/gonum/stat/spatial/doc.go | 6 + .../v1/gonum/stat/spatial/spatial.go | 162 + .../spatial/spatial_areal_example_test.go | 74 + .../stat/spatial/spatial_example_test.go | 142 + .../v1/gonum/stat/spatial/spatial_test.go | 293 ++ vendor/gonum.org/v1/gonum/stat/stat_test.go | 1569 +++++++++ .../gonum.org/v1/gonum/stat/statmat_test.go | 463 +++ vendor/gonum.org/v1/gonum/unit/autogen.go | 363 ++ vendor/gonum.org/v1/gonum/unit/consts.go | 29 + vendor/gonum.org/v1/gonum/unit/dimless.go | 66 + vendor/gonum.org/v1/gonum/unit/doc.go | 83 + vendor/gonum.org/v1/gonum/unit/length.go | 90 + vendor/gonum.org/v1/gonum/unit/mass.go | 90 + vendor/gonum.org/v1/gonum/unit/time.go | 93 + vendor/gonum.org/v1/gonum/unit/unit_test.go | 352 ++ .../v1/gonum/unit/unitexample_test.go | 29 + vendor/gonum.org/v1/gonum/unit/unittype.go | 342 ++ 1014 files changed, 209180 insertions(+), 23 deletions(-) delete mode 100644 vendor/gonum.org/v1/gonum/LICENSE create mode 100644 vendor/gonum.org/v1/gonum/blas/README.md create mode 100644 vendor/gonum.org/v1/gonum/blas/blas.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/blas32.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/conv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/conv_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas32/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/blas64.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/cblas64.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/conv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/conv_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas64/doc.go create mode 100755 vendor/gonum.org/v1/gonum/blas/conversions.bash create mode 100644 vendor/gonum.org/v1/gonum/blas/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dgemmbench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dgemvbench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dgerbench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dtrmvbench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/general_double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/general_single.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/gonum.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1doubleBench_auto_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1double_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1single.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2double_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2single.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3double_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3single.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/pardgemm_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go create mode 100755 vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/benchsize.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/common.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/common_test.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dgbmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dgemm.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dgemmbench.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dgemv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dger.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/doc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsbmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dspmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dspr.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dspr2.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsymm.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsymv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsyr.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsyr2.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsyr2k.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dsyrk.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtbmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtbsv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtpmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtpsv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtrmm.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtrmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtrmvbench.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtrsm.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtrsv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dtxmv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dzasum.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/dznrm2.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/izamax.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/level1double.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/level2bench.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zaxpy.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zcopy.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zdotc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zdotu.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zdscal.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zgerc.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zgeru.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zher.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zher2.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zscal.go create mode 100644 vendor/gonum.org/v1/gonum/blas/testblas/zswap.go create mode 100644 vendor/gonum.org/v1/gonum/diff/README.md create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/derivative.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/derivative_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/diff.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/doc.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/example_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/gradient.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/gradient_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/hessian.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/hessian_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/jacobian.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/jacobian_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/laplacian.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/laplacian_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/simplefunctions_test.go create mode 100644 vendor/gonum.org/v1/gonum/diff/fd/watson_test.go create mode 100644 vendor/gonum.org/v1/gonum/floats/README.md create mode 100644 vendor/gonum.org/v1/gonum/floats/doc.go create mode 100644 vendor/gonum.org/v1/gonum/floats/examples_test.go create mode 100644 vendor/gonum.org/v1/gonum/floats/floats.go create mode 100644 vendor/gonum.org/v1/gonum/floats/floats_test.go create mode 100644 vendor/gonum.org/v1/gonum/floats/parse_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/.gitignore create mode 100644 vendor/gonum.org/v1/gonum/graph/README.md create mode 100644 vendor/gonum.org/v1/gonum/graph/community/bisect.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/bisect_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain.tex create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_common.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_directed.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_directed_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_undirected.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/community/printgraphs.go create mode 100644 vendor/gonum.org/v1/gonum/graph/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/decode_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/dot/encode_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/encoding.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/graphql/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphql.go create mode 100644 vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphs_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/ex/fdpclust/gn.go create mode 100644 vendor/gonum.org/v1/gonum/graph/ex/fdpclust/main.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/README.md create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/ast/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/dot.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/Makefile create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/dot.bnf create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/acttab.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/transitiontable.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/action.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/actiontable.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/gototable.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/productionstable.go create mode 100755 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/paste_copyright.bash create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_stmt.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/digraph.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/edge_stmt.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/error.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/graph.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/multi.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/named_graph.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/node_stmt.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/quoted_id.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/strict.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.golden create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph_vertex.dot create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/token/token.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/litconv.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/rune.go create mode 100755 vendor/gonum.org/v1/gonum/graph/formats/dot/makeinternal.bash create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/sem.go create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/.gitignore create mode 100644 vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/Makefile create mode 100644 vendor/gonum.org/v1/gonum/graph/graph.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/gen.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world.go create mode 100644 vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/set/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/set/same.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/set/set.go create mode 100644 vendor/gonum.org/v1/gonum/graph/internal/set/set_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/betweenness.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/betweenness_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/distance.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/distance_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/hits.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/hits_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/network.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/network_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/page.go create mode 100644 vendor/gonum.org/v1/gonum/graph/network/page_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/a_star.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/a_star_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/control_flow.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dijkstra.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dijkstra_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/disjoint.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/disjoint_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dynamic/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/dynamic/dumper_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/floydwarshall.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/floydwarshall_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/internal/grid.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/internal/grid_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/internal/limited.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/internal/limited_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/internal/testgraphs/shortest.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/johnson_apsp.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/johnson_apsp_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/shortest.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/spanning_tree.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/spanning_tree_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/path/weight.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/densegraph_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/directed.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/directed_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/simple.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/undirected.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/undirected_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/weighted_directed_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go create mode 100644 vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/common_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/paton_cycles_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/tarjan.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/tarjan_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/topo.go create mode 100644 vendor/gonum.org/v1/gonum/graph/topo/topo_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/traverse/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/traverse/traverse.go create mode 100644 vendor/gonum.org/v1/gonum/graph/traverse/traverse_test.go create mode 100644 vendor/gonum.org/v1/gonum/graph/undirect.go create mode 100644 vendor/gonum.org/v1/gonum/graph/undirect_test.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/README.md create mode 100644 vendor/gonum.org/v1/gonum/integrate/doc.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/doc.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/example_test.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/hermite.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/hermite_data.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/hermite_test.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/internal/PrintGoSlice.m create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/internal/genherm.m create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/internal/hermpts.m create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/legendre.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/legendre_test.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/quad.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/quad/quad_test.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/trapezoidal.go create mode 100644 vendor/gonum.org/v1/gonum/integrate/trapezoidal_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/README.md create mode 100755 vendor/gonum.org/v1/gonum/internal/asm/bench_gen.sh create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotu.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/util_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotu.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ddot.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/dot.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/asm_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpy_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/benchAxpy_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/benchScal_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/bench_other_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/dot_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scal_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/cmath_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/math.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/math_test.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/signbit.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/lapack/.gitignore create mode 100644 vendor/gonum.org/v1/gonum/lapack/README.md create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/appengine_test.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/doc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/general.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/lapack_test.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlahr2test/main.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlaqr5test/main.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Makefile create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Readme.md create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dcopy.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/disnan.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlaisnan.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlamch.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlas2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlascl.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq1.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq3.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq4.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq5.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq6.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasrt.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ieeeck.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ilaenv.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/iparmq.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/lsame.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq1.f90 create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq2.f90 create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq3.f90 create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq4.f90 create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/xerbla.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/Makefile create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/disnan.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlae2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlaisnan.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlamch.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlanst.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlapy2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlascl.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlasrt.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlassq.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dsterf.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/lsame.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/testdsterf.f90 create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/xerbla.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/daxpy.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dcopy.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemm.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemv.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlabad.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlacpy.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlahr2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlamch.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlapy2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr1.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr5.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlarfg.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaset.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dnrm2.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dscal.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmm.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmv.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/lsame.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/netlib.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/xerbla.f create mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dbdsqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgebak.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgebal.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgebd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgebrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgecon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev_bench.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgehd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgehrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgelq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgelqf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgels.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeql2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqp3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgerq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgerqf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgesvd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgetf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgetri.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvd3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvp3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dhseqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlabrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlacn2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlacpy.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlae2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaev2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaexc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlags2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlahqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlahr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaln2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlange.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlanst.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlansy.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlantr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlanv2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlapll.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlapmt.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlapy2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqp2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqps.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr04.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr1.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr23.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr5.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlarf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfb.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfg.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlarft.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfx.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlartg.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlas2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlascl.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaset.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq1.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq4.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq5.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasrt.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasv2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlaswp.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlasy2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/doc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2l.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2r.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorgbr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorghr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorgl2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorglq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorgql.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorgqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorgtr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorm2r.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dormbr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dormhr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dorml2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dormlq.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dormqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dormr2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dpbtf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dpocon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dpotf2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dpotrf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/drscl.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dsteqr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dsterf.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dsyev.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dsytd2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dsytrd.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtgsja.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtrcon.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtrevc3.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtrexc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtrti2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/dtrtri.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/fortran.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/general.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/iladlc.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/iladlr.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/matgen.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/matgen_test.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/test_matrices.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlahr2data.json.gz create mode 100644 vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlaqr5data.json.gz create mode 100644 vendor/gonum.org/v1/gonum/mat/README.md create mode 100644 vendor/gonum.org/v1/gonum/mat/band.go create mode 100644 vendor/gonum.org/v1/gonum/mat/band_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cblas_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cholesky.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cholesky_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cholesky_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cmatrix.go create mode 100644 vendor/gonum.org/v1/gonum/mat/consts.go create mode 100644 vendor/gonum.org/v1/gonum/mat/dense.go create mode 100644 vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go create mode 100644 vendor/gonum.org/v1/gonum/mat/dense_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/doc.go create mode 100644 vendor/gonum.org/v1/gonum/mat/eigen.go create mode 100644 vendor/gonum.org/v1/gonum/mat/eigen_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/errors.go create mode 100644 vendor/gonum.org/v1/gonum/mat/errors_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/fao_data_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/format.go create mode 100644 vendor/gonum.org/v1/gonum/mat/format_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/format_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/gsvd.go create mode 100644 vendor/gonum.org/v1/gonum/mat/gsvd_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/gsvd_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/hogsvd.go create mode 100644 vendor/gonum.org/v1/gonum/mat/hogsvd_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/hogsvd_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/index_bound_checks.go create mode 100644 vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go create mode 100644 vendor/gonum.org/v1/gonum/mat/inner.go create mode 100644 vendor/gonum.org/v1/gonum/mat/inner_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/io.go create mode 100644 vendor/gonum.org/v1/gonum/mat/io_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/list_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/lq.go create mode 100644 vendor/gonum.org/v1/gonum/mat/lq_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/lu.go create mode 100644 vendor/gonum.org/v1/gonum/mat/lu_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/matrix.go create mode 100644 vendor/gonum.org/v1/gonum/mat/matrix_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/mul_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/offset.go create mode 100644 vendor/gonum.org/v1/gonum/mat/offset_appengine.go create mode 100644 vendor/gonum.org/v1/gonum/mat/pool.go create mode 100644 vendor/gonum.org/v1/gonum/mat/pool_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/product.go create mode 100644 vendor/gonum.org/v1/gonum/mat/product_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/qr.go create mode 100644 vendor/gonum.org/v1/gonum/mat/qr_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/shadow.go create mode 100644 vendor/gonum.org/v1/gonum/mat/shadow_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/solve.go create mode 100644 vendor/gonum.org/v1/gonum/mat/solve_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/svd.go create mode 100644 vendor/gonum.org/v1/gonum/mat/svd_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/symband.go create mode 100644 vendor/gonum.org/v1/gonum/mat/symband_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/symmetric.go create mode 100644 vendor/gonum.org/v1/gonum/mat/symmetric_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/symmetric_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/triangular.go create mode 100644 vendor/gonum.org/v1/gonum/mat/triangular_test.go create mode 100644 vendor/gonum.org/v1/gonum/mat/vector.go create mode 100644 vendor/gonum.org/v1/gonum/mat/vector_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/README.md create mode 100644 vendor/gonum.org/v1/gonum/mathext/airy.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/airy_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/beta.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/beta_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/betainc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/betainc_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/digamma.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/digamma_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/doc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_carlson.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_carlson_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_complete.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_complete_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/erf.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/erf_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/gamma_inc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/gamma_inc_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amos_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/Make.files create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/d1mach.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/dgamln.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/fortran.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/i1mach.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myabs.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myatan.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mycos.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myexp.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mylog.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymax.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymin.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysin.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysqrt.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mytan.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/xerror.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zabs.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacai.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacon.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zairy.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zasyi.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesh.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesi.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesj.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesk.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesy.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbinu.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbiry.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbknu.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbuni.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbunk.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zdiv.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zexp.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zkscl.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zlog.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlri.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlt.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zrati.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zs1s2.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zseri.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zshch.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zsqrt.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuchk.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunhj.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni1.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni2.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunik.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk1.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk2.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuoik.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zwrsk.f create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/origcode_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/mvgamma.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/mvgamma_test.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/roots.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/zeta.go create mode 100644 vendor/gonum.org/v1/gonum/mathext/zeta_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/README.md create mode 100644 vendor/gonum.org/v1/gonum/optimize/backtracking.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/bfgs.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/bisection.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/cg.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/convex/lp/convert.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/convex/lp/doc.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/convex/lp/simplexexample_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/doc.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/errors.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functionconvergence.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/doc.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/functions.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/functions_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/minsurf.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/minsurf_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/validate.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/functions/vlse.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/global.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/gradientdescent.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/guessandcheck.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/guessandcheck_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/interfaces.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/lbfgs.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/linesearch.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/linesearcher_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/local.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/local_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/minimize.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/morethuente.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/neldermead.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/newton.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/printer.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/stepsizers.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/termination.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/types.go create mode 100644 vendor/gonum.org/v1/gonum/optimize/unconstrained_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/appengine_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/boston_data_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/car_data_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/cca_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/cca_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/combin/combin.go create mode 100644 vendor/gonum.org/v1/gonum/stat/combin/combin_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/combin/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmat/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmat/general.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmat/wishart.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmat/wishart_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/dirichlet.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/dirichlet_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/general.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/general_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/interfaces.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/normal.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/normal_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/normalbench_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/statdist.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/statdist_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/studentst.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/studentst_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/uniform.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distmv/uniform_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/bernoulli_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/beta.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/beta_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/categorical.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/categorical_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/chisquared_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/constants.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/distribution_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/exponential.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/exponential_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/f.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/f_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/gamma.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/gamma_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/general.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/general_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/laplace.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/laplace_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/lognormal_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/norm.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/norm_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/norm_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/studentst.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/studentst_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/triangle.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/triangle_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/uniform.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/weibull.go create mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/weibull_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/faithful_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/moments_bench_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/pca_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/pca_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/roc_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/roc_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/samplemv/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/samplemv/metropolishastings.go create mode 100644 vendor/gonum.org/v1/gonum/stat/samplemv/sample_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/samplemv/samplemv.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/example_burnin_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/example_rate_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/sample.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/sample_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/weighted.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/weighted_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement.go create mode 100644 vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/spatial/doc.go create mode 100644 vendor/gonum.org/v1/gonum/stat/spatial/spatial.go create mode 100644 vendor/gonum.org/v1/gonum/stat/spatial/spatial_areal_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/spatial/spatial_example_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/spatial/spatial_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/stat_test.go create mode 100644 vendor/gonum.org/v1/gonum/stat/statmat_test.go create mode 100644 vendor/gonum.org/v1/gonum/unit/autogen.go create mode 100644 vendor/gonum.org/v1/gonum/unit/consts.go create mode 100644 vendor/gonum.org/v1/gonum/unit/dimless.go create mode 100644 vendor/gonum.org/v1/gonum/unit/doc.go create mode 100644 vendor/gonum.org/v1/gonum/unit/length.go create mode 100644 vendor/gonum.org/v1/gonum/unit/mass.go create mode 100644 vendor/gonum.org/v1/gonum/unit/time.go create mode 100644 vendor/gonum.org/v1/gonum/unit/unit_test.go create mode 100644 vendor/gonum.org/v1/gonum/unit/unitexample_test.go create mode 100644 vendor/gonum.org/v1/gonum/unit/unittype.go diff --git a/vendor/gonum.org/v1/gonum/LICENSE b/vendor/gonum.org/v1/gonum/LICENSE deleted file mode 100644 index 76edf5ef..00000000 --- a/vendor/gonum.org/v1/gonum/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright ©2013 The gonum Authors. 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 the gonum project nor the names of its authors and - 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/gonum.org/v1/gonum/blas/README.md b/vendor/gonum.org/v1/gonum/blas/README.md new file mode 100644 index 00000000..8d0af75f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/README.md @@ -0,0 +1,79 @@ +# Gonum BLAS [![GoDoc](https://godoc.org/gonum.org/v1/gonum/blas?status.svg)](https://godoc.org/gonum.org/v1/gonum/blas) + +A collection of packages to provide BLAS functionality for the [Go programming +language](http://golang.org) + +## Installation +```sh + go get gonum.org/v1/gonum/blas/... +``` + +### BLAS C-bindings + +If you want to use OpenBLAS, install it in any directory: +```sh + git clone https://github.com/xianyi/OpenBLAS + cd OpenBLAS + make +``` + +The blas/cgo package provides bindings to C-backed BLAS packages. blas/cgo needs the `CGO_LDFLAGS` +environment variable to point to the blas installation. More information can be found in the +[cgo command documentation](http://golang.org/cmd/cgo/). + +Then install the blas/cgo package: +```sh + CGO_LDFLAGS="-L/path/to/OpenBLAS -lopenblas" go install gonum.org/v1/netlib/blas +``` + +For Windows you can download binary packages for OpenBLAS at +[SourceForge](http://sourceforge.net/projects/openblas/files/). + +If you want to use a different BLAS package such as the Intel MKL you can +adjust the `CGO_LDFLAGS` variable: +```sh + CGO_LDFLAGS="-lmkl_rt" go install gonum.org/v1/netlib/blas +``` + +On OS X the easiest solution is to use the libraries provided by the system: +```sh + CGO_LDFLAGS="-framework Accelerate" go install gonum.org/v1/netlib/blas +``` + +## Packages + +### blas + +Defines [BLAS API](http://www.netlib.org/blas/blast-forum/cinterface.pdf) split in several +interfaces. + +### blas/gonum + +Go implementation of the BLAS API (incomplete, implements the `float32` and `float64` API). + +### blas/blas64 and blas/blas32 + +Wrappers for an implementation of the double (i.e., `float64`) and single (`float32`) +precision real parts of the BLAS API. + +```Go +package main + +import ( + "fmt" + + "gonum.org/v1/gonum/blas/blas64" +) + +func main() { + v := blas64.Vector{Inc: 1, Data: []float64{1, 1, 1}} + fmt.Println("v has length:", blas64.Nrm2(len(v.Data), v)) +} +``` + +### blas/cblas128 and blas/cblas64 + +Wrappers for an implementation of the double (i.e., `complex128`) and single (`complex64`) +precision complex parts of the blas API. + +Currently blas/cblas64 and blas/cblas128 require gonum.org/v1/netlib/blas. diff --git a/vendor/gonum.org/v1/gonum/blas/blas.go b/vendor/gonum.org/v1/gonum/blas/blas.go new file mode 100644 index 00000000..3fda4ff8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas.go @@ -0,0 +1,287 @@ +// Copyright ©2013 The gonum 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:generate ./conversions.bash + +package blas + +// Flag constants indicate Givens transformation H matrix state. +type Flag int + +const ( + Identity Flag = iota - 2 // H is the identity matrix; no rotation is needed. + Rescaling // H specifies rescaling. + OffDiagonal // Off-diagonal elements of H are units. + Diagonal // Diagonal elements of H are units. +) + +// SrotmParams contains Givens transformation parameters returned +// by the Float32 Srotm method. +type SrotmParams struct { + Flag + H [4]float32 // Column-major 2 by 2 matrix. +} + +// DrotmParams contains Givens transformation parameters returned +// by the Float64 Drotm method. +type DrotmParams struct { + Flag + H [4]float64 // Column-major 2 by 2 matrix. +} + +// Transpose is used to specify the transposition operation for a +// routine. +type Transpose int + +const ( + NoTrans Transpose = 111 + iota + Trans + ConjTrans +) + +// Uplo is used to specify whether the matrix is an upper or lower +// triangular matrix. +type Uplo int + +const ( + All Uplo = 120 + iota + Upper + Lower +) + +// Diag is used to specify whether the matrix is a unit or non-unit +// triangular matrix. +type Diag int + +const ( + NonUnit Diag = 131 + iota + Unit +) + +// Side is used to specify from which side a multiplication operation +// is performed. +type Side int + +const ( + Left Side = 141 + iota + Right +) + +// Float32 implements the single precision real BLAS routines. +type Float32 interface { + Float32Level1 + Float32Level2 + Float32Level3 +} + +// Float32Level1 implements the single precision real BLAS Level 1 routines. +type Float32Level1 interface { + Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 + Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 + Sdot(n int, x []float32, incX int, y []float32, incY int) float32 + Snrm2(n int, x []float32, incX int) float32 + Sasum(n int, x []float32, incX int) float32 + Isamax(n int, x []float32, incX int) int + Sswap(n int, x []float32, incX int, y []float32, incY int) + Scopy(n int, x []float32, incX int, y []float32, incY int) + Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) + Srotg(a, b float32) (c, s, r, z float32) + Srotmg(d1, d2, b1, b2 float32) (p SrotmParams, rd1, rd2, rb1 float32) + Srot(n int, x []float32, incX int, y []float32, incY int, c, s float32) + Srotm(n int, x []float32, incX int, y []float32, incY int, p SrotmParams) + Sscal(n int, alpha float32, x []float32, incX int) +} + +// Float32Level2 implements the single precision real BLAS Level 2 routines. +type Float32Level2 interface { + Sgemv(tA Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Sgbmv(tA Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Strmv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) + Stbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) + Stpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) + Strsv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) + Stbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) + Stpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) + Ssymv(ul Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Ssbmv(ul Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Sspmv(ul Uplo, n int, alpha float32, ap []float32, x []float32, incX int, beta float32, y []float32, incY int) + Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) + Ssyr(ul Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) + Sspr(ul Uplo, n int, alpha float32, x []float32, incX int, ap []float32) + Ssyr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) + Sspr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32) +} + +// Float32Level3 implements the single precision real BLAS Level 3 routines. +type Float32Level3 interface { + Sgemm(tA, tB Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Ssymm(s Side, ul Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Ssyrk(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) + Ssyr2k(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Strmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) + Strsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) +} + +// Float64 implements the single precision real BLAS routines. +type Float64 interface { + Float64Level1 + Float64Level2 + Float64Level3 +} + +// Float64Level1 implements the double precision real BLAS Level 1 routines. +type Float64Level1 interface { + Ddot(n int, x []float64, incX int, y []float64, incY int) float64 + Dnrm2(n int, x []float64, incX int) float64 + Dasum(n int, x []float64, incX int) float64 + Idamax(n int, x []float64, incX int) int + Dswap(n int, x []float64, incX int, y []float64, incY int) + Dcopy(n int, x []float64, incX int, y []float64, incY int) + Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) + Drotg(a, b float64) (c, s, r, z float64) + Drotmg(d1, d2, b1, b2 float64) (p DrotmParams, rd1, rd2, rb1 float64) + Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) + Drotm(n int, x []float64, incX int, y []float64, incY int, p DrotmParams) + Dscal(n int, alpha float64, x []float64, incX int) +} + +// Float64Level2 implements the double precision real BLAS Level 2 routines. +type Float64Level2 interface { + Dgemv(tA Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dgbmv(tA Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dtrmv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) + Dtrsv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) + Dsymv(ul Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dsbmv(ul Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dspmv(ul Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) + Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) + Dsyr(ul Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) + Dspr(ul Uplo, n int, alpha float64, x []float64, incX int, ap []float64) + Dsyr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) + Dspr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64) +} + +// Float64Level3 implements the double precision real BLAS Level 3 routines. +type Float64Level3 interface { + Dgemm(tA, tB Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dsymm(s Side, ul Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dsyrk(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) + Dsyr2k(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dtrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) + Dtrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) +} + +// Complex64 implements the single precision complex BLAS routines. +type Complex64 interface { + Complex64Level1 + Complex64Level2 + Complex64Level3 +} + +// Complex64Level1 implements the single precision complex BLAS Level 1 routines. +type Complex64Level1 interface { + Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) + Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) + Scnrm2(n int, x []complex64, incX int) float32 + Scasum(n int, x []complex64, incX int) float32 + Icamax(n int, x []complex64, incX int) int + Cswap(n int, x []complex64, incX int, y []complex64, incY int) + Ccopy(n int, x []complex64, incX int, y []complex64, incY int) + Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) + Cscal(n int, alpha complex64, x []complex64, incX int) + Csscal(n int, alpha float32, x []complex64, incX int) +} + +// Complex64Level2 implements the single precision complex BLAS routines Level 2 routines. +type Complex64Level2 interface { + Cgemv(tA Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Cgbmv(tA Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Ctrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) + Ctbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) + Ctpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) + Ctrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) + Ctbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) + Ctpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) + Chemv(ul Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Chbmv(ul Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Chpmv(ul Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) + Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Cher(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) + Chpr(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64) + Cher2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Chpr2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) +} + +// Complex64Level3 implements the single precision complex BLAS Level 3 routines. +type Complex64Level3 interface { + Cgemm(tA, tB Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Csymm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Csyrk(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) + Csyr2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Ctrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) + Ctrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) + Chemm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Cherk(ul Uplo, t Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) + Cher2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) +} + +// Complex128 implements the double precision complex BLAS routines. +type Complex128 interface { + Complex128Level1 + Complex128Level2 + Complex128Level3 +} + +// Complex128Level1 implements the double precision complex BLAS Level 1 routines. +type Complex128Level1 interface { + Zdotu(n int, x []complex128, incX int, y []complex128, incY int) (dotu complex128) + Zdotc(n int, x []complex128, incX int, y []complex128, incY int) (dotc complex128) + Dznrm2(n int, x []complex128, incX int) float64 + Dzasum(n int, x []complex128, incX int) float64 + Izamax(n int, x []complex128, incX int) int + Zswap(n int, x []complex128, incX int, y []complex128, incY int) + Zcopy(n int, x []complex128, incX int, y []complex128, incY int) + Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) + Zscal(n int, alpha complex128, x []complex128, incX int) + Zdscal(n int, alpha float64, x []complex128, incX int) +} + +// Complex128Level2 implements the double precision complex BLAS Level 2 routines. +type Complex128Level2 interface { + Zgemv(tA Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zgbmv(tA Transpose, m, n int, kL int, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Ztrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) + Ztbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) + Ztpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) + Ztrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) + Ztbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) + Ztpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) + Zhemv(ul Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zhbmv(ul Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zhpmv(ul Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zher(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) + Zhpr(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128) + Zher2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zhpr2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) +} + +// Complex128Level3 implements the double precision complex BLAS Level 3 routines. +type Complex128Level3 interface { + Zgemm(tA, tB Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zsymm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zsyrk(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) + Zsyr2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Ztrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) + Ztrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) + Zhemm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zherk(ul Uplo, t Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) + Zher2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/blas32.go b/vendor/gonum.org/v1/gonum/blas/blas32/blas32.go new file mode 100644 index 00000000..fe5a144e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/blas32.go @@ -0,0 +1,457 @@ +// Copyright ©2015 The gonum 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 blas32 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/gonum" +) + +var blas32 blas.Float32 = gonum.Implementation{} + +// Use sets the BLAS float32 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(b blas.Float32) { + blas32 = b +} + +// Implementation returns the current BLAS float32 implementation. +// +// Implementation allows direct calls to the current the BLAS float32 implementation +// giving finer control of parameters. +func Implementation() blas.Float32 { + return blas32 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []float32 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []float32 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []float32 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []float32 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []float32 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []float32 + Uplo blas.Uplo +} + +// Level 1 + +const negInc = "blas32: negative vector increment" + +// Dot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func Dot(n int, x, y Vector) float32 { + return blas32.Sdot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// DDot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func DDot(n int, x, y Vector) float64 { + return blas32.Dsdot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// SDDot computes the dot product of the two vectors adding a constant: +// alpha + \sum_i x[i]*y[i]. +func SDDot(n int, alpha float32, x, y Vector) float32 { + return blas32.Sdsdot(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i]*x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Snrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of the absolute values of the elements of x: +// \sum_i |x[i]|. +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Sasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Isamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of the two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + blas32.Sswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + blas32.Scopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy adds x scaled by alpha to y: +// y[i] += alpha*x[i] for all i. +func Axpy(n int, alpha float32, x, y Vector) { + blas32.Saxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Rotg computes the parameters of a Givens plane rotation so that +// ⎡ c s⎤ ⎡a⎤ ⎡r⎤ +// ⎣-s c⎦ * ⎣b⎦ = ⎣0⎦ +// where a and b are the Cartesian coordinates of a given point. +// c, s, and r are defined as +// r = ±Sqrt(a^2 + b^2), +// c = a/r, the cosine of the rotation angle, +// s = a/r, the sine of the rotation angle, +// and z is defined such that +// if |a| > |b|, z = s, +// otherwise if c != 0, z = 1/c, +// otherwise z = 1. +func Rotg(a, b float32) (c, s, r, z float32) { + return blas32.Srotg(a, b) +} + +// Rotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func Rotmg(d1, d2, b1, b2 float32) (p blas.SrotmParams, rd1, rd2, rb1 float32) { + return blas32.Srotmg(d1, d2, b1, b2) +} + +// Rot applies a plane transformation to n points represented by the vectors x +// and y: +// x[i] = c*x[i] + s*y[i], +// y[i] = -s*x[i] + c*y[i], for all i. +func Rot(n int, x, y Vector, c, s float32) { + blas32.Srot(n, x.Data, x.Inc, y.Data, y.Inc, c, s) +} + +// Rotm applies the modified Givens rotation to n points represented by the +// vectors x and y. +func Rotm(n int, x, y Vector, p blas.SrotmParams) { + blas32.Srotm(n, x.Data, x.Inc, y.Data, y.Inc, p) +} + +// Scal scales the vector x by alpha: +// x[i] *= alpha for all i. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha float32, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + blas32.Sscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. +func Gemv(t blas.Transpose, alpha float32, a General, x Vector, beta float32, y Vector) { + blas32.Sgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are scalars. +func Gbmv(t blas.Transpose, alpha float32, a Band, x Vector, beta float32, y Vector) { + blas32.Sgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + blas32.Strmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + blas32.Stbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + blas32.Stpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + blas32.Strsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + blas32.Stbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x and b are +// vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + blas32.Stpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Symv computes +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func Symv(alpha float32, a Symmetric, x Vector, beta float32, y Vector) { + blas32.Ssymv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Sbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Sbmv(alpha float32, a SymmetricBand, x Vector, beta float32, y Vector) { + blas32.Ssbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Spmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Spmv(alpha float32, a SymmetricPacked, x Vector, beta float32, y Vector) { + blas32.Sspmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Ger performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Ger(alpha float32, x, y Vector, a General) { + blas32.Sger(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Syr performs a rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix, x is a vector, and alpha is a scalar. +func Syr(alpha float32, x Vector, a Symmetric) { + blas32.Ssyr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Spr performs the rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func Spr(alpha float32, x Vector, a SymmetricPacked) { + blas32.Sspr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Syr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func Syr2(alpha float32, x, y Vector, a Symmetric) { + blas32.Ssyr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Spr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Spr2(alpha float32, x, y Vector, a SymmetricPacked) { + blas32.Sspr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func Gemm(tA, tB blas.Transpose, alpha float32, a, b General, beta float32, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + blas32.Sgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha is a scalar. +func Symm(s blas.Side, alpha float32, a Symmetric, b General, beta float32, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + blas32.Ssymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans and +// a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha float32, a General, beta float32, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas32.Ssyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha float32, a, b General, beta float32, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas32.Ssyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha float32, a Triangular, b General) { + blas32.Strmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in-place into X. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha float32, a Triangular, b General) { + blas32.Strsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/conv.go b/vendor/gonum.org/v1/gonum/blas/blas32/conv.go new file mode 100644 index 00000000..24107906 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/conv.go @@ -0,0 +1,279 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 blas32 + +import "gonum.org/v1/gonum/blas" + +// GeneralCols represents a matrix using the conventional column-major storage scheme. +type GeneralCols General + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t GeneralCols) From(a General) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas32: mismatched dimension") + } + if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { + panic("blas32: short data slice") + } + for i := 0; i < a.Rows; i++ { + for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { + t.Data[i+j*t.Stride] = v + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t General) From(a GeneralCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas32: mismatched dimension") + } + if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { + panic("blas32: short data slice") + } + for j := 0; j < a.Cols; j++ { + for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { + t.Data[i*t.Stride+j] = v + } + } +} + +// TriangularCols represents a matrix using the conventional column-major storage scheme. +type TriangularCols Triangular + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t TriangularCols) From(a Triangular) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas32: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t Triangular) From(a TriangularCols) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas32: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// BandCols represents a matrix using the band column-major storage scheme. +type BandCols Band + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t BandCols) From(a Band) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas32: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("blas32: short stride for destination") + } + for i := 0; i < a.Rows; i++ { + for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { + t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t Band) From(a BandCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas32: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("blas32: short stride for destination") + } + for j := 0; j < a.Cols; j++ { + for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { + t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] + } + } +} + +// TriangularBandCols represents a symmetric matrix using the band column-major storage scheme. +type TriangularBandCols TriangularBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBandCols) From(a TriangularBand) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.K != a.K { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas32: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas32: mismatched BLAS diag") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBand) From(a TriangularBandCols) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.K != a.K { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas32: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas32: mismatched BLAS diag") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric.go new file mode 100644 index 00000000..e385a641 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 blas32 + +import "gonum.org/v1/gonum/blas" + +// SymmetricCols represents a matrix using the conventional column-major storage scheme. +type SymmetricCols Symmetric + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t SymmetricCols) From(a Symmetric) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Symmetric) From(a SymmetricCols) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. +type SymmetricBandCols SymmetricBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBandCols) From(a SymmetricBand) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.K != a.K { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas32: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBand) From(a SymmetricBandCols) { + if t.N != a.N { + panic("blas32: mismatched dimension") + } + if t.K != a.K { + panic("blas32: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas32: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas32: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas32: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric_test.go b/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric_test.go new file mode 100644 index 00000000..335f0fa0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/conv_symmetric_test.go @@ -0,0 +1,307 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 blas32 + +import ( + math "gonum.org/v1/gonum/internal/math32" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newSymmetricFrom(a SymmetricCols) Symmetric { + t := Symmetric{ + N: a.N, + Stride: a.N, + Data: make([]float32, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Symmetric) n() int { return m.N } +func (m Symmetric) at(i, j int) float32 { + if m.Uplo == blas.Lower && i < j && j < m.N { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j { + i, j = j, i + } + return m.Data[i*m.Stride+j] +} +func (m Symmetric) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricColsFrom(a Symmetric) SymmetricCols { + t := SymmetricCols{ + N: a.N, + Stride: a.N, + Data: make([]float32, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m SymmetricCols) n() int { return m.N } +func (m SymmetricCols) at(i, j int) float32 { + if m.Uplo == blas.Lower && i < j { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j && i < m.N { + i, j = j, i + } + return m.Data[i+j*m.Stride] +} +func (m SymmetricCols) uplo() blas.Uplo { return m.Uplo } + +type symmetric interface { + n() int + at(i, j int) float32 + uplo() blas.Uplo +} + +func sameSymmetric(a, b symmetric) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricTests = []Symmetric{ + {N: 3, Stride: 3, Data: []float32{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertSymmetric(t *testing.T) { + for _, test := range symmetricTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + test.Uplo = uplo + colmajor := newSymmetricColsFrom(test) + if !sameSymmetric(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricFrom(colmajor) + if !sameSymmetric(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } +} +func newSymmetricBandFrom(a SymmetricBandCols) SymmetricBand { + t := SymmetricBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float32, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBand) n() (n int) { return m.N } +func (m SymmetricBand) at(i, j int) float32 { + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBand) bandwidth() (k int) { return m.K } +func (m SymmetricBand) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricBandColsFrom(a SymmetricBand) SymmetricBandCols { + t := SymmetricBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float32, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBandCols) n() (n int) { return m.N } +func (m SymmetricBandCols) at(i, j int) float32 { + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBandCols) bandwidth() (k int) { return m.K } +func (m SymmetricBandCols) uplo() blas.Uplo { return m.Uplo } + +type symmetricBand interface { + n() (n int) + at(i, j int) float32 + bandwidth() (k int) + uplo() blas.Uplo +} + +func sameSymmetricBand(a, b symmetricBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricBandTests = []SymmetricBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []float32{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []float32{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []float32{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []float32{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []float32{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []float32{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []float32{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []float32{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertSymBand(t *testing.T) { + for _, test := range symmetricBandTests { + colmajor := newSymmetricBandColsFrom(test) + if !sameSymmetricBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricBandFrom(colmajor) + if !sameSymmetricBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/conv_test.go b/vendor/gonum.org/v1/gonum/blas/blas32/conv_test.go new file mode 100644 index 00000000..9cff493e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/conv_test.go @@ -0,0 +1,620 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 blas32 + +import ( + math "gonum.org/v1/gonum/internal/math32" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newGeneralFrom(a GeneralCols) General { + t := General{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Cols, + Data: make([]float32, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m General) dims() (r, c int) { return m.Rows, m.Cols } +func (m General) at(i, j int) float32 { return m.Data[i*m.Stride+j] } + +func newGeneralColsFrom(a General) GeneralCols { + t := GeneralCols{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Rows, + Data: make([]float32, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m GeneralCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m GeneralCols) at(i, j int) float32 { return m.Data[i+j*m.Stride] } + +type general interface { + dims() (r, c int) + at(i, j int) float32 +} + +func sameGeneral(a, b general) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var generalTests = []General{ + {Rows: 2, Cols: 3, Stride: 3, Data: []float32{ + 1, 2, 3, + 4, 5, 6, + }}, + {Rows: 3, Cols: 2, Stride: 2, Data: []float32{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 3, Stride: 3, Data: []float32{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 2, Cols: 3, Stride: 5, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + }}, + {Rows: 3, Cols: 2, Stride: 5, Data: []float32{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, Stride: 5, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertGeneral(t *testing.T) { + for _, test := range generalTests { + colmajor := newGeneralColsFrom(test) + if !sameGeneral(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newGeneralFrom(colmajor) + if !sameGeneral(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularFrom(a TriangularCols) Triangular { + t := Triangular{ + N: a.N, + Stride: a.N, + Data: make([]float32, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Triangular) n() int { return m.N } +func (m Triangular) at(i, j int) float32 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j && j < m.N { + return 0 + } + if m.Uplo == blas.Upper && i > j { + return 0 + } + return m.Data[i*m.Stride+j] +} +func (m Triangular) uplo() blas.Uplo { return m.Uplo } +func (m Triangular) diag() blas.Diag { return m.Diag } + +func newTriangularColsFrom(a Triangular) TriangularCols { + t := TriangularCols{ + N: a.N, + Stride: a.N, + Data: make([]float32, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m TriangularCols) n() int { return m.N } +func (m TriangularCols) at(i, j int) float32 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j { + return 0 + } + if m.Uplo == blas.Upper && i > j && i < m.N { + return 0 + } + return m.Data[i+j*m.Stride] +} +func (m TriangularCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularCols) diag() blas.Diag { return m.Diag } + +type triangular interface { + n() int + at(i, j int) float32 + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangular(a, b triangular) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularTests = []Triangular{ + {N: 3, Stride: 3, Data: []float32{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertTriangular(t *testing.T) { + for _, test := range triangularTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, diag := range []blas.Diag{blas.Unit, blas.NonUnit} { + test.Uplo = uplo + test.Diag = diag + colmajor := newTriangularColsFrom(test) + if !sameTriangular(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularFrom(colmajor) + if !sameTriangular(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } + } +} + +func newBandFrom(a BandCols) Band { + t := Band{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]float32, a.Rows*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m Band) dims() (r, c int) { return m.Rows, m.Cols } +func (m Band) at(i, j int) float32 { + pj := j + m.KL - i + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[i*m.Stride+pj] +} +func (m Band) bandwidth() (kl, ku int) { return m.KL, m.KU } + +func newBandColsFrom(a Band) BandCols { + t := BandCols{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]float32, a.Cols*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m BandCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m BandCols) at(i, j int) float32 { + pj := i + m.KU - j + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[j*m.Stride+pj] +} +func (m BandCols) bandwidth() (kl, ku int) { return m.KL, m.KU } + +type band interface { + dims() (r, c int) + at(i, j int) float32 + bandwidth() (kl, ku int) +} + +func sameBand(a, b band) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + akl, aku := a.bandwidth() + bkl, bku := b.bandwidth() + if akl != bkl || aku != bku { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var bandTests = []Band{ + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 1, Data: []float32{ + 1, + 2, + 3, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []float32{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []float32{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 2, Data: []float32{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 2, Data: []float32{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 3, Data: []float32{ + -1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 3, Data: []float32{ + -1, 2, 3, + 4, 5, 6, + 7, 8, -2, + 9, -3, -4, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 4, Data: []float32{ + -2, -1, 3, 4, + -3, 5, 6, 7, + 8, 9, 10, 11, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 4, Data: []float32{ + -2, -1, 2, 3, + -3, 4, 5, 6, + 7, 8, 9, -4, + 10, 11, -5, -6, + }}, + + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 5, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 5, Data: []float32{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 5, Data: []float32{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 5, Data: []float32{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 5, Data: []float32{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, -2, 0, 0, + 9, -3, -4, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 5, Data: []float32{ + -2, -1, 3, 4, 0, + -3, 5, 6, 7, 0, + 8, 9, 10, 11, 0, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 5, Data: []float32{ + -2, -1, 2, 3, 0, + -3, 4, 5, 6, 0, + 7, 8, 9, -4, 0, + 10, 11, -5, -6, 0, + }}, +} + +func TestConvertBand(t *testing.T) { + for _, test := range bandTests { + colmajor := newBandColsFrom(test) + if !sameBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newBandFrom(colmajor) + if !sameBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularBandFrom(a TriangularBandCols) TriangularBand { + t := TriangularBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float32, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBand) n() (n int) { return m.N } +func (m TriangularBand) at(i, j int) float32 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBand) bandwidth() (k int) { return m.K } +func (m TriangularBand) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBand) diag() blas.Diag { return m.Diag } + +func newTriangularBandColsFrom(a TriangularBand) TriangularBandCols { + t := TriangularBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float32, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBandCols) n() (n int) { return m.N } +func (m TriangularBandCols) at(i, j int) float32 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas32: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBandCols) bandwidth() (k int) { return m.K } +func (m TriangularBandCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBandCols) diag() blas.Diag { return m.Diag } + +type triangularBand interface { + n() (n int) + at(i, j int) float32 + bandwidth() (k int) + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangularBand(a, b triangularBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + if a.diag() != b.diag() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularBandTests = []TriangularBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []float32{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []float32{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []float32{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []float32{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []float32{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []float32{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []float32{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []float32{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []float32{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []float32{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertTriBand(t *testing.T) { + for _, test := range triangularBandTests { + colmajor := newTriangularBandColsFrom(test) + if !sameTriangularBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularBandFrom(colmajor) + if !sameTriangularBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas32/doc.go b/vendor/gonum.org/v1/gonum/blas/blas32/doc.go new file mode 100644 index 00000000..d01a5162 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas32/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 blas32 provides a simple interface to the float32 BLAS API. +package blas32 // import "gonum.org/v1/gonum/blas/blas32" diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go b/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go new file mode 100644 index 00000000..88e746bb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go @@ -0,0 +1,445 @@ +// Copyright ©2015 The gonum 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 blas64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/gonum" +) + +var blas64 blas.Float64 = gonum.Implementation{} + +// Use sets the BLAS float64 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(b blas.Float64) { + blas64 = b +} + +// Implementation returns the current BLAS float64 implementation. +// +// Implementation allows direct calls to the current the BLAS float64 implementation +// giving finer control of parameters. +func Implementation() blas.Float64 { + return blas64 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []float64 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []float64 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []float64 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []float64 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []float64 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []float64 + Uplo blas.Uplo +} + +// Level 1 + +const negInc = "blas64: negative vector increment" + +// Dot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func Dot(n int, x, y Vector) float64 { + return blas64.Ddot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i]*x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Dnrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of the absolute values of the elements of x: +// \sum_i |x[i]|. +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Dasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Idamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of the two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + blas64.Dswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + blas64.Dcopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy adds x scaled by alpha to y: +// y[i] += alpha*x[i] for all i. +func Axpy(n int, alpha float64, x, y Vector) { + blas64.Daxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Rotg computes the parameters of a Givens plane rotation so that +// ⎡ c s⎤ ⎡a⎤ ⎡r⎤ +// ⎣-s c⎦ * ⎣b⎦ = ⎣0⎦ +// where a and b are the Cartesian coordinates of a given point. +// c, s, and r are defined as +// r = ±Sqrt(a^2 + b^2), +// c = a/r, the cosine of the rotation angle, +// s = a/r, the sine of the rotation angle, +// and z is defined such that +// if |a| > |b|, z = s, +// otherwise if c != 0, z = 1/c, +// otherwise z = 1. +func Rotg(a, b float64) (c, s, r, z float64) { + return blas64.Drotg(a, b) +} + +// Rotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func Rotmg(d1, d2, b1, b2 float64) (p blas.DrotmParams, rd1, rd2, rb1 float64) { + return blas64.Drotmg(d1, d2, b1, b2) +} + +// Rot applies a plane transformation to n points represented by the vectors x +// and y: +// x[i] = c*x[i] + s*y[i], +// y[i] = -s*x[i] + c*y[i], for all i. +func Rot(n int, x, y Vector, c, s float64) { + blas64.Drot(n, x.Data, x.Inc, y.Data, y.Inc, c, s) +} + +// Rotm applies the modified Givens rotation to n points represented by the +// vectors x and y. +func Rotm(n int, x, y Vector, p blas.DrotmParams) { + blas64.Drotm(n, x.Data, x.Inc, y.Data, y.Inc, p) +} + +// Scal scales the vector x by alpha: +// x[i] *= alpha for all i. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha float64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + blas64.Dscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. +func Gemv(t blas.Transpose, alpha float64, a General, x Vector, beta float64, y Vector) { + blas64.Dgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are scalars. +func Gbmv(t blas.Transpose, alpha float64, a Band, x Vector, beta float64, y Vector) { + blas64.Dgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + blas64.Dtrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + blas64.Dtbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + blas64.Dtpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + blas64.Dtrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + blas64.Dtbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x and b are +// vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + blas64.Dtpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Symv computes +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func Symv(alpha float64, a Symmetric, x Vector, beta float64, y Vector) { + blas64.Dsymv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Sbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Sbmv(alpha float64, a SymmetricBand, x Vector, beta float64, y Vector) { + blas64.Dsbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Spmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Spmv(alpha float64, a SymmetricPacked, x Vector, beta float64, y Vector) { + blas64.Dspmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Ger performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Ger(alpha float64, x, y Vector, a General) { + blas64.Dger(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Syr performs a rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix, x is a vector, and alpha is a scalar. +func Syr(alpha float64, x Vector, a Symmetric) { + blas64.Dsyr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Spr performs the rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func Spr(alpha float64, x Vector, a SymmetricPacked) { + blas64.Dspr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Syr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func Syr2(alpha float64, x, y Vector, a Symmetric) { + blas64.Dsyr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Spr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Spr2(alpha float64, x, y Vector, a SymmetricPacked) { + blas64.Dspr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func Gemm(tA, tB blas.Transpose, alpha float64, a, b General, beta float64, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + blas64.Dgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha is a scalar. +func Symm(s blas.Side, alpha float64, a Symmetric, b General, beta float64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + blas64.Dsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans and +// a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha float64, a General, beta float64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas64.Dsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha float64, a, b General, beta float64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas64.Dsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { + blas64.Dtrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in-place into X. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { + blas64.Dtrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv.go new file mode 100644 index 00000000..17de0943 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/conv.go @@ -0,0 +1,277 @@ +// Copyright ©2015 The gonum 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 blas64 + +import "gonum.org/v1/gonum/blas" + +// GeneralCols represents a matrix using the conventional column-major storage scheme. +type GeneralCols General + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t GeneralCols) From(a General) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas64: mismatched dimension") + } + if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { + panic("blas64: short data slice") + } + for i := 0; i < a.Rows; i++ { + for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { + t.Data[i+j*t.Stride] = v + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t General) From(a GeneralCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas64: mismatched dimension") + } + if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { + panic("blas64: short data slice") + } + for j := 0; j < a.Cols; j++ { + for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { + t.Data[i*t.Stride+j] = v + } + } +} + +// TriangularCols represents a matrix using the conventional column-major storage scheme. +type TriangularCols Triangular + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t TriangularCols) From(a Triangular) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas64: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t Triangular) From(a TriangularCols) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas64: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// BandCols represents a matrix using the band column-major storage scheme. +type BandCols Band + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t BandCols) From(a Band) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas64: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("blas64: short stride for destination") + } + for i := 0; i < a.Rows; i++ { + for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { + t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t Band) From(a BandCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("blas64: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("blas64: short stride for destination") + } + for j := 0; j < a.Cols; j++ { + for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { + t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] + } + } +} + +// TriangularBandCols represents a symmetric matrix using the band column-major storage scheme. +type TriangularBandCols TriangularBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBandCols) From(a TriangularBand) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.K != a.K { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas64: mismatched BLAS diag") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBand) From(a TriangularBandCols) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.K != a.K { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("blas64: mismatched BLAS diag") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go new file mode 100644 index 00000000..a43b2304 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go @@ -0,0 +1,153 @@ +// Copyright ©2015 The gonum 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 blas64 + +import "gonum.org/v1/gonum/blas" + +// SymmetricCols represents a matrix using the conventional column-major storage scheme. +type SymmetricCols Symmetric + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t SymmetricCols) From(a Symmetric) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Symmetric) From(a SymmetricCols) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. +type SymmetricBandCols SymmetricBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBandCols) From(a SymmetricBand) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.K != a.K { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBand) From(a SymmetricBandCols) { + if t.N != a.N { + panic("blas64: mismatched dimension") + } + if t.K != a.K { + panic("blas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("blas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("blas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("blas64: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric_test.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric_test.go new file mode 100644 index 00000000..167de52d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric_test.go @@ -0,0 +1,305 @@ +// Copyright ©2015 The gonum 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 blas64 + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newSymmetricFrom(a SymmetricCols) Symmetric { + t := Symmetric{ + N: a.N, + Stride: a.N, + Data: make([]float64, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Symmetric) n() int { return m.N } +func (m Symmetric) at(i, j int) float64 { + if m.Uplo == blas.Lower && i < j && j < m.N { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j { + i, j = j, i + } + return m.Data[i*m.Stride+j] +} +func (m Symmetric) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricColsFrom(a Symmetric) SymmetricCols { + t := SymmetricCols{ + N: a.N, + Stride: a.N, + Data: make([]float64, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m SymmetricCols) n() int { return m.N } +func (m SymmetricCols) at(i, j int) float64 { + if m.Uplo == blas.Lower && i < j { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j && i < m.N { + i, j = j, i + } + return m.Data[i+j*m.Stride] +} +func (m SymmetricCols) uplo() blas.Uplo { return m.Uplo } + +type symmetric interface { + n() int + at(i, j int) float64 + uplo() blas.Uplo +} + +func sameSymmetric(a, b symmetric) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricTests = []Symmetric{ + {N: 3, Stride: 3, Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertSymmetric(t *testing.T) { + for _, test := range symmetricTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + test.Uplo = uplo + colmajor := newSymmetricColsFrom(test) + if !sameSymmetric(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricFrom(colmajor) + if !sameSymmetric(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } +} +func newSymmetricBandFrom(a SymmetricBandCols) SymmetricBand { + t := SymmetricBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float64, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBand) n() (n int) { return m.N } +func (m SymmetricBand) at(i, j int) float64 { + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBand) bandwidth() (k int) { return m.K } +func (m SymmetricBand) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricBandColsFrom(a SymmetricBand) SymmetricBandCols { + t := SymmetricBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float64, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBandCols) n() (n int) { return m.N } +func (m SymmetricBandCols) at(i, j int) float64 { + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBandCols) bandwidth() (k int) { return m.K } +func (m SymmetricBandCols) uplo() blas.Uplo { return m.Uplo } + +type symmetricBand interface { + n() (n int) + at(i, j int) float64 + bandwidth() (k int) + uplo() blas.Uplo +} + +func sameSymmetricBand(a, b symmetricBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricBandTests = []SymmetricBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []float64{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []float64{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []float64{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []float64{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []float64{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []float64{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []float64{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []float64{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertSymBand(t *testing.T) { + for _, test := range symmetricBandTests { + colmajor := newSymmetricBandColsFrom(test) + if !sameSymmetricBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricBandFrom(colmajor) + if !sameSymmetricBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv_test.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv_test.go new file mode 100644 index 00000000..61645317 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/conv_test.go @@ -0,0 +1,618 @@ +// Copyright ©2015 The gonum 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 blas64 + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newGeneralFrom(a GeneralCols) General { + t := General{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Cols, + Data: make([]float64, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m General) dims() (r, c int) { return m.Rows, m.Cols } +func (m General) at(i, j int) float64 { return m.Data[i*m.Stride+j] } + +func newGeneralColsFrom(a General) GeneralCols { + t := GeneralCols{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Rows, + Data: make([]float64, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m GeneralCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m GeneralCols) at(i, j int) float64 { return m.Data[i+j*m.Stride] } + +type general interface { + dims() (r, c int) + at(i, j int) float64 +} + +func sameGeneral(a, b general) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var generalTests = []General{ + {Rows: 2, Cols: 3, Stride: 3, Data: []float64{ + 1, 2, 3, + 4, 5, 6, + }}, + {Rows: 3, Cols: 2, Stride: 2, Data: []float64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 3, Stride: 3, Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 2, Cols: 3, Stride: 5, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + }}, + {Rows: 3, Cols: 2, Stride: 5, Data: []float64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, Stride: 5, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertGeneral(t *testing.T) { + for _, test := range generalTests { + colmajor := newGeneralColsFrom(test) + if !sameGeneral(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newGeneralFrom(colmajor) + if !sameGeneral(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularFrom(a TriangularCols) Triangular { + t := Triangular{ + N: a.N, + Stride: a.N, + Data: make([]float64, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Triangular) n() int { return m.N } +func (m Triangular) at(i, j int) float64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j && j < m.N { + return 0 + } + if m.Uplo == blas.Upper && i > j { + return 0 + } + return m.Data[i*m.Stride+j] +} +func (m Triangular) uplo() blas.Uplo { return m.Uplo } +func (m Triangular) diag() blas.Diag { return m.Diag } + +func newTriangularColsFrom(a Triangular) TriangularCols { + t := TriangularCols{ + N: a.N, + Stride: a.N, + Data: make([]float64, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m TriangularCols) n() int { return m.N } +func (m TriangularCols) at(i, j int) float64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j { + return 0 + } + if m.Uplo == blas.Upper && i > j && i < m.N { + return 0 + } + return m.Data[i+j*m.Stride] +} +func (m TriangularCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularCols) diag() blas.Diag { return m.Diag } + +type triangular interface { + n() int + at(i, j int) float64 + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangular(a, b triangular) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularTests = []Triangular{ + {N: 3, Stride: 3, Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertTriangular(t *testing.T) { + for _, test := range triangularTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, diag := range []blas.Diag{blas.Unit, blas.NonUnit} { + test.Uplo = uplo + test.Diag = diag + colmajor := newTriangularColsFrom(test) + if !sameTriangular(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularFrom(colmajor) + if !sameTriangular(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } + } +} + +func newBandFrom(a BandCols) Band { + t := Band{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]float64, a.Rows*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m Band) dims() (r, c int) { return m.Rows, m.Cols } +func (m Band) at(i, j int) float64 { + pj := j + m.KL - i + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[i*m.Stride+pj] +} +func (m Band) bandwidth() (kl, ku int) { return m.KL, m.KU } + +func newBandColsFrom(a Band) BandCols { + t := BandCols{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]float64, a.Cols*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m BandCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m BandCols) at(i, j int) float64 { + pj := i + m.KU - j + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[j*m.Stride+pj] +} +func (m BandCols) bandwidth() (kl, ku int) { return m.KL, m.KU } + +type band interface { + dims() (r, c int) + at(i, j int) float64 + bandwidth() (kl, ku int) +} + +func sameBand(a, b band) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + akl, aku := a.bandwidth() + bkl, bku := b.bandwidth() + if akl != bkl || aku != bku { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var bandTests = []Band{ + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 1, Data: []float64{ + 1, + 2, + 3, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []float64{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []float64{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 2, Data: []float64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 2, Data: []float64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 3, Data: []float64{ + -1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 3, Data: []float64{ + -1, 2, 3, + 4, 5, 6, + 7, 8, -2, + 9, -3, -4, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 4, Data: []float64{ + -2, -1, 3, 4, + -3, 5, 6, 7, + 8, 9, 10, 11, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 4, Data: []float64{ + -2, -1, 2, 3, + -3, 4, 5, 6, + 7, 8, 9, -4, + 10, 11, -5, -6, + }}, + + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 5, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 5, Data: []float64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 5, Data: []float64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 5, Data: []float64{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 5, Data: []float64{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, -2, 0, 0, + 9, -3, -4, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 5, Data: []float64{ + -2, -1, 3, 4, 0, + -3, 5, 6, 7, 0, + 8, 9, 10, 11, 0, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 5, Data: []float64{ + -2, -1, 2, 3, 0, + -3, 4, 5, 6, 0, + 7, 8, 9, -4, 0, + 10, 11, -5, -6, 0, + }}, +} + +func TestConvertBand(t *testing.T) { + for _, test := range bandTests { + colmajor := newBandColsFrom(test) + if !sameBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newBandFrom(colmajor) + if !sameBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularBandFrom(a TriangularBandCols) TriangularBand { + t := TriangularBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float64, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBand) n() (n int) { return m.N } +func (m TriangularBand) at(i, j int) float64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBand) bandwidth() (k int) { return m.K } +func (m TriangularBand) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBand) diag() blas.Diag { return m.Diag } + +func newTriangularBandColsFrom(a TriangularBand) TriangularBandCols { + t := TriangularBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]float64, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBandCols) n() (n int) { return m.N } +func (m TriangularBandCols) at(i, j int) float64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("blas64: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBandCols) bandwidth() (k int) { return m.K } +func (m TriangularBandCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBandCols) diag() blas.Diag { return m.Diag } + +type triangularBand interface { + n() (n int) + at(i, j int) float64 + bandwidth() (k int) + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangularBand(a, b triangularBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + if a.diag() != b.diag() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularBandTests = []TriangularBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []float64{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []float64{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []float64{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []float64{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []float64{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []float64{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []float64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []float64{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []float64{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []float64{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertTriBand(t *testing.T) { + for _, test := range triangularBandTests { + colmajor := newTriangularBandColsFrom(test) + if !sameTriangularBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularBandFrom(colmajor) + if !sameTriangularBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/doc.go b/vendor/gonum.org/v1/gonum/blas/blas64/doc.go new file mode 100644 index 00000000..92e588f8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/blas64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 blas64 provides a simple interface to the float64 BLAS API. +package blas64 // import "gonum.org/v1/gonum/blas/blas64" diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go b/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go new file mode 100644 index 00000000..9b463504 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go @@ -0,0 +1,507 @@ +// Copyright ©2015 The gonum 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 cblas128 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/gonum" +) + +var cblas128 blas.Complex128 = gonum.Implementation{} + +// Use sets the BLAS complex128 implementation to be used by subsequent BLAS calls. +// The default implementation is cgo.Implementation. +func Use(b blas.Complex128) { + cblas128 = b +} + +// Implementation returns the current BLAS complex128 implementation. +// +// Implementation allows direct calls to the current the BLAS complex128 implementation +// giving finer control of parameters. +func Implementation() blas.Complex128 { + return cblas128 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []complex128 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []complex128 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []complex128 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []complex128 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []complex128 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []complex128 + Uplo blas.Uplo +} + +// Hermitian represents an Hermitian matrix using the conventional storage scheme. +type Hermitian Symmetric + +// HermitianBand represents an Hermitian matrix using the band storage scheme. +type HermitianBand SymmetricBand + +// HermitianPacked represents an Hermitian matrix using the packed storage scheme. +type HermitianPacked SymmetricPacked + +// Level 1 + +const negInc = "cblas128: negative vector increment" + +// Dotu computes the dot product of the two vectors without +// complex conjugation: +// x^T * y. +func Dotu(n int, x, y Vector) complex128 { + return cblas128.Zdotu(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Dotc computes the dot product of the two vectors with +// complex conjugation: +// x^H * y. +func Dotc(n int, x, y Vector) complex128 { + return cblas128.Zdotc(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i] * x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Dznrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of magnitudes of the real and imaginary parts of +// elements of the vector x: +// \sum_i (|Re x[i]| + |Im x[i]|). +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Dzasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest sum of +// magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|). +// If there are multiple such indices, the earliest is returned. +// +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Izamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + cblas128.Zswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + cblas128.Zcopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy computes +// y = alpha * x + y, +// where x and y are vectors, and alpha is a scalar. +func Axpy(n int, alpha complex128, x, y Vector) { + cblas128.Zaxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Scal computes +// x = alpha * x, +// where x is a vector, and alpha is a scalar. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha complex128, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas128.Zscal(n, alpha, x.Data, x.Inc) +} + +// Dscal computes +// x = alpha * x, +// where x is a vector, and alpha is a real scalar. +// +// Dscal will panic if the vector increment is negative. +func Dscal(n int, alpha float64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas128.Zdscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gemv(t blas.Transpose, alpha complex128, a General, x Vector, beta complex128, y Vector) { + cblas128.Zgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gbmv(t blas.Transpose, alpha complex128, a Band, x Vector, beta complex128, y Vector) { + cblas128.Zgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + cblas128.Ztrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + cblas128.Ztbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas128.Ztpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + cblas128.Ztrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + cblas128.Ztbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas128.Ztpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Hemv computes +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha and +// beta are scalars. +func Hemv(alpha complex128, a Hermitian, x Vector, beta complex128, y Vector) { + cblas128.Zhemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Hbmv(alpha complex128, a HermitianBand, x Vector, beta complex128, y Vector) { + cblas128.Zhbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hpmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Hpmv(alpha complex128, a HermitianPacked, x Vector, beta complex128, y Vector) { + cblas128.Zhpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Geru performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Geru(alpha complex128, x, y Vector, a General) { + cblas128.Zgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Gerc performs a rank-1 update +// A += alpha * x * y^H, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Gerc(alpha complex128, x, y Vector, a General) { + cblas128.Zgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Her performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her(alpha float64, x Vector, a Hermitian) { + cblas128.Zher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Hpr performs a rank-1 update +// A += alpha * x * x^H, +// where A is an n×n Hermitian matrix in packed format, x is a vector, and +// alpha is a scalar. +func Hpr(alpha float64, x Vector, a HermitianPacked) { + cblas128.Zhpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Her2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her2(alpha complex128, x, y Vector, a Hermitian) { + cblas128.Zher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Hpr2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Hpr2(alpha complex128, x, y Vector, a HermitianPacked) { + cblas128.Zhpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed or conjugated. +func Gemm(tA, tB blas.Transpose, alpha complex128, a, b General, beta complex128, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + cblas128.Zgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Symm(s blas.Side, alpha complex128, a Symmetric, b General, beta complex128, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas128.Zsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha complex128, a General, beta complex128, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if +// t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha complex128, a, b General, beta complex128, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans and s == blas.Left, +// B = alpha * A^H * B, if tA == blas.ConjTrans and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans and s == blas.Right, +// B = alpha * B * A^H, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { + cblas128.Ztrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans and s == blas.Left, +// A^H * X = alpha * B, if tA == blas.ConjTrans and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans and s == blas.Right, +// X * A^H = alpha * B, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, b contains the values of B, and the result is +// stored in-place into b. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { + cblas128.Ztrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Hemm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Hemm(s blas.Side, alpha complex128, a Hermitian, b General, beta complex128, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas128.Zhemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Herk performs the Hermitian rank-k update +// C = alpha * A * A^H + beta*C, if t == blas.NoTrans, +// C = alpha * A^H * A + beta*C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Herk(t blas.Transpose, alpha float64, a General, beta float64, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Her2k performs the Hermitian rank-2k update +// C = alpha * A * B^H + conj(alpha) * B * A^H + beta * C, if t == blas.NoTrans, +// C = alpha * A^H * B + conj(alpha) * B^H * A + beta * C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Her2k(t blas.Transpose, alpha complex128, a, b General, beta float64, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go new file mode 100644 index 00000000..cb62b7be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go @@ -0,0 +1,279 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// GeneralCols represents a matrix using the conventional column-major storage scheme. +type GeneralCols General + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t GeneralCols) From(a General) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { + panic("cblas128: short data slice") + } + for i := 0; i < a.Rows; i++ { + for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { + t.Data[i+j*t.Stride] = v + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t General) From(a GeneralCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { + panic("cblas128: short data slice") + } + for j := 0; j < a.Cols; j++ { + for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { + t.Data[i*t.Stride+j] = v + } + } +} + +// TriangularCols represents a matrix using the conventional column-major storage scheme. +type TriangularCols Triangular + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t TriangularCols) From(a Triangular) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t Triangular) From(a TriangularCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// BandCols represents a matrix using the band column-major storage scheme. +type BandCols Band + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t BandCols) From(a Band) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas128: short stride for destination") + } + for i := 0; i < a.Rows; i++ { + for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { + t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t Band) From(a BandCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas128: short stride for destination") + } + for j := 0; j < a.Cols; j++ { + for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { + t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] + } + } +} + +// TriangularBandCols represents a symmetric matrix using the band column-major storage scheme. +type TriangularBandCols TriangularBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBandCols) From(a TriangularBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBand) From(a TriangularBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go new file mode 100644 index 00000000..455668a3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// HermitianCols represents a matrix using the conventional column-major storage scheme. +type HermitianCols Hermitian + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t HermitianCols) From(a Hermitian) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Hermitian) From(a HermitianCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// HermitianBandCols represents an Hermitian matrix using the band column-major storage scheme. +type HermitianBandCols HermitianBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBandCols) From(a HermitianBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBand) From(a HermitianBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian_test.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian_test.go new file mode 100644 index 00000000..21bd3cbf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian_test.go @@ -0,0 +1,307 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import ( + math "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newHermitianFrom(a HermitianCols) Hermitian { + t := Hermitian{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Hermitian) n() int { return m.N } +func (m Hermitian) at(i, j int) complex128 { + if m.Uplo == blas.Lower && i < j && j < m.N { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j { + i, j = j, i + } + return m.Data[i*m.Stride+j] +} +func (m Hermitian) uplo() blas.Uplo { return m.Uplo } + +func newHermitianColsFrom(a Hermitian) HermitianCols { + t := HermitianCols{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m HermitianCols) n() int { return m.N } +func (m HermitianCols) at(i, j int) complex128 { + if m.Uplo == blas.Lower && i < j { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j && i < m.N { + i, j = j, i + } + return m.Data[i+j*m.Stride] +} +func (m HermitianCols) uplo() blas.Uplo { return m.Uplo } + +type hermitian interface { + n() int + at(i, j int) complex128 + uplo() blas.Uplo +} + +func sameHermitian(a, b hermitian) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var hermitianTests = []Hermitian{ + {N: 3, Stride: 3, Data: []complex128{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertHermitian(t *testing.T) { + for _, test := range hermitianTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + test.Uplo = uplo + colmajor := newHermitianColsFrom(test) + if !sameHermitian(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newHermitianFrom(colmajor) + if !sameHermitian(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } +} +func newHermitianBandFrom(a HermitianBandCols) HermitianBand { + t := HermitianBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m HermitianBand) n() (n int) { return m.N } +func (m HermitianBand) at(i, j int) complex128 { + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m HermitianBand) bandwidth() (k int) { return m.K } +func (m HermitianBand) uplo() blas.Uplo { return m.Uplo } + +func newHermitianBandColsFrom(a HermitianBand) HermitianBandCols { + t := HermitianBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m HermitianBandCols) n() (n int) { return m.N } +func (m HermitianBandCols) at(i, j int) complex128 { + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m HermitianBandCols) bandwidth() (k int) { return m.K } +func (m HermitianBandCols) uplo() blas.Uplo { return m.Uplo } + +type hermitianBand interface { + n() (n int) + at(i, j int) complex128 + bandwidth() (k int) + uplo() blas.Uplo +} + +func sameHermitianBand(a, b hermitianBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var hermitianBandTests = []HermitianBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []complex128{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []complex128{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertHermBand(t *testing.T) { + for _, test := range hermitianBandTests { + colmajor := newHermitianBandColsFrom(test) + if !sameHermitianBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newHermitianBandFrom(colmajor) + if !sameHermitianBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go new file mode 100644 index 00000000..ad5e0a65 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// SymmetricCols represents a matrix using the conventional column-major storage scheme. +type SymmetricCols Symmetric + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t SymmetricCols) From(a Symmetric) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Symmetric) From(a SymmetricCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. +type SymmetricBandCols SymmetricBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBandCols) From(a SymmetricBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBand) From(a SymmetricBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric_test.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric_test.go new file mode 100644 index 00000000..eef76f4a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric_test.go @@ -0,0 +1,307 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import ( + math "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newSymmetricFrom(a SymmetricCols) Symmetric { + t := Symmetric{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Symmetric) n() int { return m.N } +func (m Symmetric) at(i, j int) complex128 { + if m.Uplo == blas.Lower && i < j && j < m.N { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j { + i, j = j, i + } + return m.Data[i*m.Stride+j] +} +func (m Symmetric) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricColsFrom(a Symmetric) SymmetricCols { + t := SymmetricCols{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m SymmetricCols) n() int { return m.N } +func (m SymmetricCols) at(i, j int) complex128 { + if m.Uplo == blas.Lower && i < j { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j && i < m.N { + i, j = j, i + } + return m.Data[i+j*m.Stride] +} +func (m SymmetricCols) uplo() blas.Uplo { return m.Uplo } + +type symmetric interface { + n() int + at(i, j int) complex128 + uplo() blas.Uplo +} + +func sameSymmetric(a, b symmetric) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricTests = []Symmetric{ + {N: 3, Stride: 3, Data: []complex128{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertSymmetric(t *testing.T) { + for _, test := range symmetricTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + test.Uplo = uplo + colmajor := newSymmetricColsFrom(test) + if !sameSymmetric(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricFrom(colmajor) + if !sameSymmetric(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } +} +func newSymmetricBandFrom(a SymmetricBandCols) SymmetricBand { + t := SymmetricBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBand) n() (n int) { return m.N } +func (m SymmetricBand) at(i, j int) complex128 { + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBand) bandwidth() (k int) { return m.K } +func (m SymmetricBand) uplo() blas.Uplo { return m.Uplo } + +func newSymmetricBandColsFrom(a SymmetricBand) SymmetricBandCols { + t := SymmetricBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m SymmetricBandCols) n() (n int) { return m.N } +func (m SymmetricBandCols) at(i, j int) complex128 { + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m SymmetricBandCols) bandwidth() (k int) { return m.K } +func (m SymmetricBandCols) uplo() blas.Uplo { return m.Uplo } + +type symmetricBand interface { + n() (n int) + at(i, j int) complex128 + bandwidth() (k int) + uplo() blas.Uplo +} + +func sameSymmetricBand(a, b symmetricBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var symmetricBandTests = []SymmetricBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []complex128{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []complex128{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertSymBand(t *testing.T) { + for _, test := range symmetricBandTests { + colmajor := newSymmetricBandColsFrom(test) + if !sameSymmetricBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newSymmetricBandFrom(colmajor) + if !sameSymmetricBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_test.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_test.go new file mode 100644 index 00000000..8d25fd28 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_test.go @@ -0,0 +1,620 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas128 + +import ( + math "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newGeneralFrom(a GeneralCols) General { + t := General{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Cols, + Data: make([]complex128, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m General) dims() (r, c int) { return m.Rows, m.Cols } +func (m General) at(i, j int) complex128 { return m.Data[i*m.Stride+j] } + +func newGeneralColsFrom(a General) GeneralCols { + t := GeneralCols{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Rows, + Data: make([]complex128, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m GeneralCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m GeneralCols) at(i, j int) complex128 { return m.Data[i+j*m.Stride] } + +type general interface { + dims() (r, c int) + at(i, j int) complex128 +} + +func sameGeneral(a, b general) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var generalTests = []General{ + {Rows: 2, Cols: 3, Stride: 3, Data: []complex128{ + 1, 2, 3, + 4, 5, 6, + }}, + {Rows: 3, Cols: 2, Stride: 2, Data: []complex128{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 3, Stride: 3, Data: []complex128{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 2, Cols: 3, Stride: 5, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + }}, + {Rows: 3, Cols: 2, Stride: 5, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, Stride: 5, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertGeneral(t *testing.T) { + for _, test := range generalTests { + colmajor := newGeneralColsFrom(test) + if !sameGeneral(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newGeneralFrom(colmajor) + if !sameGeneral(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularFrom(a TriangularCols) Triangular { + t := Triangular{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Triangular) n() int { return m.N } +func (m Triangular) at(i, j int) complex128 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j && j < m.N { + return 0 + } + if m.Uplo == blas.Upper && i > j { + return 0 + } + return m.Data[i*m.Stride+j] +} +func (m Triangular) uplo() blas.Uplo { return m.Uplo } +func (m Triangular) diag() blas.Diag { return m.Diag } + +func newTriangularColsFrom(a Triangular) TriangularCols { + t := TriangularCols{ + N: a.N, + Stride: a.N, + Data: make([]complex128, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m TriangularCols) n() int { return m.N } +func (m TriangularCols) at(i, j int) complex128 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j { + return 0 + } + if m.Uplo == blas.Upper && i > j && i < m.N { + return 0 + } + return m.Data[i+j*m.Stride] +} +func (m TriangularCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularCols) diag() blas.Diag { return m.Diag } + +type triangular interface { + n() int + at(i, j int) complex128 + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangular(a, b triangular) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularTests = []Triangular{ + {N: 3, Stride: 3, Data: []complex128{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertTriangular(t *testing.T) { + for _, test := range triangularTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, diag := range []blas.Diag{blas.Unit, blas.NonUnit} { + test.Uplo = uplo + test.Diag = diag + colmajor := newTriangularColsFrom(test) + if !sameTriangular(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularFrom(colmajor) + if !sameTriangular(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } + } +} + +func newBandFrom(a BandCols) Band { + t := Band{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]complex128, a.Rows*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m Band) dims() (r, c int) { return m.Rows, m.Cols } +func (m Band) at(i, j int) complex128 { + pj := j + m.KL - i + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[i*m.Stride+pj] +} +func (m Band) bandwidth() (kl, ku int) { return m.KL, m.KU } + +func newBandColsFrom(a Band) BandCols { + t := BandCols{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]complex128, a.Cols*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m BandCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m BandCols) at(i, j int) complex128 { + pj := i + m.KU - j + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[j*m.Stride+pj] +} +func (m BandCols) bandwidth() (kl, ku int) { return m.KL, m.KU } + +type band interface { + dims() (r, c int) + at(i, j int) complex128 + bandwidth() (kl, ku int) +} + +func sameBand(a, b band) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + akl, aku := a.bandwidth() + bkl, bku := b.bandwidth() + if akl != bkl || aku != bku { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var bandTests = []Band{ + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 1, Data: []complex128{ + 1, + 2, + 3, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []complex128{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []complex128{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 2, Data: []complex128{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 2, Data: []complex128{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 3, Data: []complex128{ + -1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 3, Data: []complex128{ + -1, 2, 3, + 4, 5, 6, + 7, 8, -2, + 9, -3, -4, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 4, Data: []complex128{ + -2, -1, 3, 4, + -3, 5, 6, 7, + 8, 9, 10, 11, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 4, Data: []complex128{ + -2, -1, 2, 3, + -3, 4, 5, 6, + 7, 8, 9, -4, + 10, 11, -5, -6, + }}, + + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 5, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 5, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 5, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 5, Data: []complex128{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 5, Data: []complex128{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, -2, 0, 0, + 9, -3, -4, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 5, Data: []complex128{ + -2, -1, 3, 4, 0, + -3, 5, 6, 7, 0, + 8, 9, 10, 11, 0, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 5, Data: []complex128{ + -2, -1, 2, 3, 0, + -3, 4, 5, 6, 0, + 7, 8, 9, -4, 0, + 10, 11, -5, -6, 0, + }}, +} + +func TestConvertBand(t *testing.T) { + for _, test := range bandTests { + colmajor := newBandColsFrom(test) + if !sameBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newBandFrom(colmajor) + if !sameBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularBandFrom(a TriangularBandCols) TriangularBand { + t := TriangularBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBand) n() (n int) { return m.N } +func (m TriangularBand) at(i, j int) complex128 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBand) bandwidth() (k int) { return m.K } +func (m TriangularBand) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBand) diag() blas.Diag { return m.Diag } + +func newTriangularBandColsFrom(a TriangularBand) TriangularBandCols { + t := TriangularBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex128, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBandCols) n() (n int) { return m.N } +func (m TriangularBandCols) at(i, j int) complex128 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBandCols) bandwidth() (k int) { return m.K } +func (m TriangularBandCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBandCols) diag() blas.Diag { return m.Diag } + +type triangularBand interface { + n() (n int) + at(i, j int) complex128 + bandwidth() (k int) + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangularBand(a, b triangularBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + if a.diag() != b.diag() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularBandTests = []TriangularBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []complex128{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []complex128{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []complex128{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []complex128{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []complex128{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertTriBand(t *testing.T) { + for _, test := range triangularBandTests { + colmajor := newTriangularBandColsFrom(test) + if !sameTriangularBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularBandFrom(colmajor) + if !sameTriangularBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go b/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go new file mode 100644 index 00000000..15398184 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 cblas128 provides a simple interface to the complex128 BLAS API. +package cblas128 // import "gonum.org/v1/gonum/blas/cblas128" diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/cblas64.go b/vendor/gonum.org/v1/gonum/blas/cblas64/cblas64.go new file mode 100644 index 00000000..6164d479 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/cblas64.go @@ -0,0 +1,507 @@ +// Copyright ©2015 The gonum 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 cblas64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/gonum" +) + +var cblas64 blas.Complex64 = gonum.Implementation{} + +// Use sets the BLAS complex64 implementation to be used by subsequent BLAS calls. +// The default implementation is cgo.Implementation. +func Use(b blas.Complex64) { + cblas64 = b +} + +// Implementation returns the current BLAS complex64 implementation. +// +// Implementation allows direct calls to the current the BLAS complex64 implementation +// giving finer control of parameters. +func Implementation() blas.Complex64 { + return cblas64 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []complex64 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []complex64 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []complex64 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []complex64 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []complex64 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []complex64 + Uplo blas.Uplo +} + +// Hermitian represents an Hermitian matrix using the conventional storage scheme. +type Hermitian Symmetric + +// HermitianBand represents an Hermitian matrix using the band storage scheme. +type HermitianBand SymmetricBand + +// HermitianPacked represents an Hermitian matrix using the packed storage scheme. +type HermitianPacked SymmetricPacked + +// Level 1 + +const negInc = "cblas64: negative vector increment" + +// Dotu computes the dot product of the two vectors without +// complex conjugation: +// x^T * y +func Dotu(n int, x, y Vector) complex64 { + return cblas64.Cdotu(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Dotc computes the dot product of the two vectors with +// complex conjugation: +// x^H * y. +func Dotc(n int, x, y Vector) complex64 { + return cblas64.Cdotc(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i] * x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Scnrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of magnitudes of the real and imaginary parts of +// elements of the vector x: +// \sum_i (|Re x[i]| + |Im x[i]|). +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Scasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest sum of +// magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|). +// If there are multiple such indices, the earliest is returned. +// +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Icamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + cblas64.Cswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + cblas64.Ccopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy computes +// y = alpha * x + y, +// where x and y are vectors, and alpha is a scalar. +func Axpy(n int, alpha complex64, x, y Vector) { + cblas64.Caxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Scal computes +// x = alpha * x, +// where x is a vector, and alpha is a scalar. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha complex64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas64.Cscal(n, alpha, x.Data, x.Inc) +} + +// Dscal computes +// x = alpha * x, +// where x is a vector, and alpha is a real scalar. +// +// Dscal will panic if the vector increment is negative. +func Dscal(n int, alpha float32, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas64.Csscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gemv(t blas.Transpose, alpha complex64, a General, x Vector, beta complex64, y Vector) { + cblas64.Cgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gbmv(t blas.Transpose, alpha complex64, a Band, x Vector, beta complex64, y Vector) { + cblas64.Cgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + cblas64.Ctrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + cblas64.Ctbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas64.Ctpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + cblas64.Ctrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + cblas64.Ctbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas64.Ctpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Hemv computes +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha and +// beta are scalars. +func Hemv(alpha complex64, a Hermitian, x Vector, beta complex64, y Vector) { + cblas64.Chemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Hbmv(alpha complex64, a HermitianBand, x Vector, beta complex64, y Vector) { + cblas64.Chbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hpmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Hpmv(alpha complex64, a HermitianPacked, x Vector, beta complex64, y Vector) { + cblas64.Chpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Geru performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Geru(alpha complex64, x, y Vector, a General) { + cblas64.Cgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Gerc performs a rank-1 update +// A += alpha * x * y^H, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Gerc(alpha complex64, x, y Vector, a General) { + cblas64.Cgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Her performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her(alpha float32, x Vector, a Hermitian) { + cblas64.Cher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Hpr performs a rank-1 update +// A += alpha * x * x^H, +// where A is an n×n Hermitian matrix in packed format, x is a vector, and +// alpha is a scalar. +func Hpr(alpha float32, x Vector, a HermitianPacked) { + cblas64.Chpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Her2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her2(alpha complex64, x, y Vector, a Hermitian) { + cblas64.Cher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Hpr2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Hpr2(alpha complex64, x, y Vector, a HermitianPacked) { + cblas64.Chpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed or conjugated. +func Gemm(tA, tB blas.Transpose, alpha complex64, a, b General, beta complex64, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + cblas64.Cgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Symm(s blas.Side, alpha complex64, a Symmetric, b General, beta complex64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas64.Csymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha complex64, a General, beta complex64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Csyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if +// t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha complex64, a, b General, beta complex64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Csyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans and s == blas.Left, +// B = alpha * A^H * B, if tA == blas.ConjTrans and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans and s == blas.Right, +// B = alpha * B * A^H, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha complex64, a Triangular, b General) { + cblas64.Ctrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans and s == blas.Left, +// A^H * X = alpha * B, if tA == blas.ConjTrans and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans and s == blas.Right, +// X * A^H = alpha * B, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, b contains the values of B, and the result is +// stored in-place into b. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha complex64, a Triangular, b General) { + cblas64.Ctrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Hemm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Hemm(s blas.Side, alpha complex64, a Hermitian, b General, beta complex64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas64.Chemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Herk performs the Hermitian rank-k update +// C = alpha * A * A^H + beta*C, if t == blas.NoTrans, +// C = alpha * A^H * A + beta*C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Herk(t blas.Transpose, alpha float32, a General, beta float32, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Cherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Her2k performs the Hermitian rank-2k update +// C = alpha * A * B^H + conj(alpha) * B * A^H + beta * C, if t == blas.NoTrans, +// C = alpha * A^H * B + conj(alpha) * B^H * A + beta * C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Her2k(t blas.Transpose, alpha complex64, a, b General, beta float32, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Cher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/conv.go b/vendor/gonum.org/v1/gonum/blas/cblas64/conv.go new file mode 100644 index 00000000..fa5c9780 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/conv.go @@ -0,0 +1,279 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas64 + +import "gonum.org/v1/gonum/blas" + +// GeneralCols represents a matrix using the conventional column-major storage scheme. +type GeneralCols General + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t GeneralCols) From(a General) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas64: mismatched dimension") + } + if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { + panic("cblas64: short data slice") + } + for i := 0; i < a.Rows; i++ { + for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { + t.Data[i+j*t.Stride] = v + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t General) From(a GeneralCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas64: mismatched dimension") + } + if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { + panic("cblas64: short data slice") + } + for j := 0; j < a.Cols; j++ { + for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { + t.Data[i*t.Stride+j] = v + } + } +} + +// TriangularCols represents a matrix using the conventional column-major storage scheme. +type TriangularCols Triangular + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t TriangularCols) From(a Triangular) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas64: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t Triangular) From(a TriangularCols) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas64: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// BandCols represents a matrix using the band column-major storage scheme. +type BandCols Band + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t BandCols) From(a Band) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas64: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas64: short stride for destination") + } + for i := 0; i < a.Rows; i++ { + for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { + t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t Band) From(a BandCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas64: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas64: short stride for destination") + } + for j := 0; j < a.Cols; j++ { + for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { + t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] + } + } +} + +// TriangularBandCols represents a symmetric matrix using the band column-major storage scheme. +type TriangularBandCols TriangularBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBandCols) From(a TriangularBand) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.K != a.K { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas64: mismatched BLAS diag") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBand) From(a TriangularBandCols) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.K != a.K { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas64: mismatched BLAS diag") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian.go b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian.go new file mode 100644 index 00000000..76598b96 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas64 + +import "gonum.org/v1/gonum/blas" + +// HermitianCols represents a matrix using the conventional column-major storage scheme. +type HermitianCols Hermitian + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t HermitianCols) From(a Hermitian) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Hermitian) From(a HermitianCols) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// HermitianBandCols represents an Hermitian matrix using the band column-major storage scheme. +type HermitianBandCols HermitianBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBandCols) From(a HermitianBand) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.K != a.K { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBand) From(a HermitianBandCols) { + if t.N != a.N { + panic("cblas64: mismatched dimension") + } + if t.K != a.K { + panic("cblas64: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas64: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas64: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas64: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian_test.go b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian_test.go new file mode 100644 index 00000000..5f412647 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_hermitian_test.go @@ -0,0 +1,307 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas64 + +import ( + math "gonum.org/v1/gonum/internal/cmplx64" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newHermitianFrom(a HermitianCols) Hermitian { + t := Hermitian{ + N: a.N, + Stride: a.N, + Data: make([]complex64, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Hermitian) n() int { return m.N } +func (m Hermitian) at(i, j int) complex64 { + if m.Uplo == blas.Lower && i < j && j < m.N { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j { + i, j = j, i + } + return m.Data[i*m.Stride+j] +} +func (m Hermitian) uplo() blas.Uplo { return m.Uplo } + +func newHermitianColsFrom(a Hermitian) HermitianCols { + t := HermitianCols{ + N: a.N, + Stride: a.N, + Data: make([]complex64, a.N*a.N), + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m HermitianCols) n() int { return m.N } +func (m HermitianCols) at(i, j int) complex64 { + if m.Uplo == blas.Lower && i < j { + i, j = j, i + } + if m.Uplo == blas.Upper && i > j && i < m.N { + i, j = j, i + } + return m.Data[i+j*m.Stride] +} +func (m HermitianCols) uplo() blas.Uplo { return m.Uplo } + +type hermitian interface { + n() int + at(i, j int) complex64 + uplo() blas.Uplo +} + +func sameHermitian(a, b hermitian) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var hermitianTests = []Hermitian{ + {N: 3, Stride: 3, Data: []complex64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertHermitian(t *testing.T) { + for _, test := range hermitianTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + test.Uplo = uplo + colmajor := newHermitianColsFrom(test) + if !sameHermitian(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newHermitianFrom(colmajor) + if !sameHermitian(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } +} +func newHermitianBandFrom(a HermitianBandCols) HermitianBand { + t := HermitianBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex64, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m HermitianBand) n() (n int) { return m.N } +func (m HermitianBand) at(i, j int) complex64 { + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m HermitianBand) bandwidth() (k int) { return m.K } +func (m HermitianBand) uplo() blas.Uplo { return m.Uplo } + +func newHermitianBandColsFrom(a HermitianBand) HermitianBandCols { + t := HermitianBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex64, a.N*(a.K+1)), + Uplo: a.Uplo, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m HermitianBandCols) n() (n int) { return m.N } +func (m HermitianBandCols) at(i, j int) complex64 { + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + b.KU = m.K + if i > j { + i, j = j, i + } + case blas.Lower: + b.KL = m.K + if i < j { + i, j = j, i + } + } + return b.at(i, j) +} +func (m HermitianBandCols) bandwidth() (k int) { return m.K } +func (m HermitianBandCols) uplo() blas.Uplo { return m.Uplo } + +type hermitianBand interface { + n() (n int) + at(i, j int) complex64 + bandwidth() (k int) + uplo() blas.Uplo +} + +func sameHermitianBand(a, b hermitianBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var hermitianBandTests = []HermitianBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []complex64{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []complex64{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []complex64{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []complex64{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []complex64{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertHermBand(t *testing.T) { + for _, test := range hermitianBandTests { + colmajor := newHermitianBandColsFrom(test) + if !sameHermitianBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newHermitianBandFrom(colmajor) + if !sameHermitianBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/conv_test.go b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_test.go new file mode 100644 index 00000000..da8d736e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/conv_test.go @@ -0,0 +1,620 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 cblas64 + +import ( + math "gonum.org/v1/gonum/internal/cmplx64" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func newGeneralFrom(a GeneralCols) General { + t := General{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Cols, + Data: make([]complex64, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m General) dims() (r, c int) { return m.Rows, m.Cols } +func (m General) at(i, j int) complex64 { return m.Data[i*m.Stride+j] } + +func newGeneralColsFrom(a General) GeneralCols { + t := GeneralCols{ + Rows: a.Rows, + Cols: a.Cols, + Stride: a.Rows, + Data: make([]complex64, a.Rows*a.Cols), + } + t.From(a) + return t +} + +func (m GeneralCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m GeneralCols) at(i, j int) complex64 { return m.Data[i+j*m.Stride] } + +type general interface { + dims() (r, c int) + at(i, j int) complex64 +} + +func sameGeneral(a, b general) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var generalTests = []General{ + {Rows: 2, Cols: 3, Stride: 3, Data: []complex64{ + 1, 2, 3, + 4, 5, 6, + }}, + {Rows: 3, Cols: 2, Stride: 2, Data: []complex64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 3, Stride: 3, Data: []complex64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 2, Cols: 3, Stride: 5, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + }}, + {Rows: 3, Cols: 2, Stride: 5, Data: []complex64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, Stride: 5, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertGeneral(t *testing.T) { + for _, test := range generalTests { + colmajor := newGeneralColsFrom(test) + if !sameGeneral(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newGeneralFrom(colmajor) + if !sameGeneral(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularFrom(a TriangularCols) Triangular { + t := Triangular{ + N: a.N, + Stride: a.N, + Data: make([]complex64, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m Triangular) n() int { return m.N } +func (m Triangular) at(i, j int) complex64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j && j < m.N { + return 0 + } + if m.Uplo == blas.Upper && i > j { + return 0 + } + return m.Data[i*m.Stride+j] +} +func (m Triangular) uplo() blas.Uplo { return m.Uplo } +func (m Triangular) diag() blas.Diag { return m.Diag } + +func newTriangularColsFrom(a Triangular) TriangularCols { + t := TriangularCols{ + N: a.N, + Stride: a.N, + Data: make([]complex64, a.N*a.N), + Diag: a.Diag, + Uplo: a.Uplo, + } + t.From(a) + return t +} + +func (m TriangularCols) n() int { return m.N } +func (m TriangularCols) at(i, j int) complex64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + if m.Uplo == blas.Lower && i < j { + return 0 + } + if m.Uplo == blas.Upper && i > j && i < m.N { + return 0 + } + return m.Data[i+j*m.Stride] +} +func (m TriangularCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularCols) diag() blas.Diag { return m.Diag } + +type triangular interface { + n() int + at(i, j int) complex64 + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangular(a, b triangular) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularTests = []Triangular{ + {N: 3, Stride: 3, Data: []complex64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {N: 3, Stride: 5, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, +} + +func TestConvertTriangular(t *testing.T) { + for _, test := range triangularTests { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, diag := range []blas.Diag{blas.Unit, blas.NonUnit} { + test.Uplo = uplo + test.Diag = diag + colmajor := newTriangularColsFrom(test) + if !sameTriangular(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularFrom(colmajor) + if !sameTriangular(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } + } + } +} + +func newBandFrom(a BandCols) Band { + t := Band{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]complex64, a.Rows*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m Band) dims() (r, c int) { return m.Rows, m.Cols } +func (m Band) at(i, j int) complex64 { + pj := j + m.KL - i + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[i*m.Stride+pj] +} +func (m Band) bandwidth() (kl, ku int) { return m.KL, m.KU } + +func newBandColsFrom(a Band) BandCols { + t := BandCols{ + Rows: a.Rows, + Cols: a.Cols, + KL: a.KL, + KU: a.KU, + Stride: a.KL + a.KU + 1, + Data: make([]complex64, a.Cols*(a.KL+a.KU+1)), + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m BandCols) dims() (r, c int) { return m.Rows, m.Cols } +func (m BandCols) at(i, j int) complex64 { + pj := i + m.KU - j + if pj < 0 || m.KL+m.KU+1 <= pj { + return 0 + } + return m.Data[j*m.Stride+pj] +} +func (m BandCols) bandwidth() (kl, ku int) { return m.KL, m.KU } + +type band interface { + dims() (r, c int) + at(i, j int) complex64 + bandwidth() (kl, ku int) +} + +func sameBand(a, b band) bool { + ar, ac := a.dims() + br, bc := b.dims() + if ar != br || ac != bc { + return false + } + akl, aku := a.bandwidth() + bkl, bku := b.bandwidth() + if akl != bkl || aku != bku { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var bandTests = []Band{ + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 1, Data: []complex64{ + 1, + 2, + 3, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []complex64{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 1, Data: []complex64{ + 1, + 2, + 3, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 2, Data: []complex64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 2, Data: []complex64{ + 1, 2, + 3, 4, + 5, 6, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 3, Data: []complex64{ + -1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 3, Data: []complex64{ + -1, 2, 3, + 4, 5, 6, + 7, 8, -2, + 9, -3, -4, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 4, Data: []complex64{ + -2, -1, 3, 4, + -3, 5, 6, 7, + 8, 9, 10, 11, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 4, Data: []complex64{ + -2, -1, 2, 3, + -3, 4, 5, 6, + 7, 8, 9, -4, + 10, 11, -5, -6, + }}, + + {Rows: 3, Cols: 4, KL: 0, KU: 0, Stride: 5, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 3, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 0, Stride: 5, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 0, KU: 1, Stride: 5, Data: []complex64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 0, KU: 1, Stride: 5, Data: []complex64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, 6, 0, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 1, KU: 1, Stride: 5, Data: []complex64{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, 9, 0, 0, + }}, + {Rows: 4, Cols: 3, KL: 1, KU: 1, Stride: 5, Data: []complex64{ + -1, 2, 3, 0, 0, + 4, 5, 6, 0, 0, + 7, 8, -2, 0, 0, + 9, -3, -4, 0, 0, + }}, + {Rows: 3, Cols: 4, KL: 2, KU: 1, Stride: 5, Data: []complex64{ + -2, -1, 3, 4, 0, + -3, 5, 6, 7, 0, + 8, 9, 10, 11, 0, + }}, + {Rows: 4, Cols: 3, KL: 2, KU: 1, Stride: 5, Data: []complex64{ + -2, -1, 2, 3, 0, + -3, 4, 5, 6, 0, + 7, 8, 9, -4, 0, + 10, 11, -5, -6, 0, + }}, +} + +func TestConvertBand(t *testing.T) { + for _, test := range bandTests { + colmajor := newBandColsFrom(test) + if !sameBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newBandFrom(colmajor) + if !sameBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} + +func newTriangularBandFrom(a TriangularBandCols) TriangularBand { + t := TriangularBand{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex64, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBand) n() (n int) { return m.N } +func (m TriangularBand) at(i, j int) complex64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := Band{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBand) bandwidth() (k int) { return m.K } +func (m TriangularBand) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBand) diag() blas.Diag { return m.Diag } + +func newTriangularBandColsFrom(a TriangularBand) TriangularBandCols { + t := TriangularBandCols{ + N: a.N, + K: a.K, + Stride: a.K + 1, + Data: make([]complex64, a.N*(a.K+1)), + Uplo: a.Uplo, + Diag: a.Diag, + } + for i := range t.Data { + t.Data[i] = math.NaN() + } + t.From(a) + return t +} + +func (m TriangularBandCols) n() (n int) { return m.N } +func (m TriangularBandCols) at(i, j int) complex64 { + if m.Diag == blas.Unit && i == j { + return 1 + } + b := BandCols{ + Rows: m.N, Cols: m.N, + Stride: m.Stride, + Data: m.Data, + } + switch m.Uplo { + default: + panic("cblas64: bad BLAS uplo") + case blas.Upper: + if i > j { + return 0 + } + b.KU = m.K + case blas.Lower: + if i < j { + return 0 + } + b.KL = m.K + } + return b.at(i, j) +} +func (m TriangularBandCols) bandwidth() (k int) { return m.K } +func (m TriangularBandCols) uplo() blas.Uplo { return m.Uplo } +func (m TriangularBandCols) diag() blas.Diag { return m.Diag } + +type triangularBand interface { + n() (n int) + at(i, j int) complex64 + bandwidth() (k int) + uplo() blas.Uplo + diag() blas.Diag +} + +func sameTriangularBand(a, b triangularBand) bool { + an := a.n() + bn := b.n() + if an != bn { + return false + } + if a.uplo() != b.uplo() { + return false + } + if a.diag() != b.diag() { + return false + } + ak := a.bandwidth() + bk := b.bandwidth() + if ak != bk { + return false + } + for i := 0; i < an; i++ { + for j := 0; j < an; j++ { + if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) { + return false + } + } + } + return true +} + +var triangularBandTests = []TriangularBand{ + {N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []complex64{ + 1, + 2, + 3, + }}, + {N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []complex64{ + 1, + 2, + 3, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []complex64{ + 1, 2, + 3, 4, + 5, -1, + }}, + {N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []complex64{ + -1, 1, + 2, 3, + 4, 5, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 3, + 4, 5, -1, + 6, -2, -3, + }}, + {N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []complex64{ + -2, -1, 1, + -3, 2, 4, + 3, 5, 6, + }}, + + {N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + 1, 0, 0, 0, 0, + 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 0, 0, 0, + 3, 4, 0, 0, 0, + 5, -1, 0, 0, 0, + }}, + {N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + -1, 1, 0, 0, 0, + 2, 3, 0, 0, 0, + 4, 5, 0, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []complex64{ + 1, 2, 3, 0, 0, + 4, 5, -1, 0, 0, + 6, -2, -3, 0, 0, + }}, + {N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []complex64{ + -2, -1, 1, 0, 0, + -3, 2, 4, 0, 0, + 3, 5, 6, 0, 0, + }}, +} + +func TestConvertTriBand(t *testing.T) { + for _, test := range triangularBandTests { + colmajor := newTriangularBandColsFrom(test) + if !sameTriangularBand(colmajor, test) { + t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v", + colmajor, test) + } + rowmajor := newTriangularBandFrom(colmajor) + if !sameTriangularBand(rowmajor, test) { + t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v", + rowmajor, test) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas64/doc.go b/vendor/gonum.org/v1/gonum/blas/cblas64/doc.go new file mode 100644 index 00000000..bb9c70b1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 cblas64 provides a simple interface to the complex64 BLAS API. +package cblas64 // import "gonum.org/v1/gonum/blas/cblas64" diff --git a/vendor/gonum.org/v1/gonum/blas/conversions.bash b/vendor/gonum.org/v1/gonum/blas/conversions.bash new file mode 100755 index 00000000..96ff2272 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/conversions.bash @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +# Copyright ©2017 The gonum Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Generate code for blas32. +echo Generating blas32/conv.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv.go +cat blas64/conv.go \ +| gofmt -r 'float64 -> float32' \ +\ +| sed -e 's/blas64/blas32/' \ +\ +>> blas32/conv.go + +echo Generating blas32/conv_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_test.go +cat blas64/conv_test.go \ +| gofmt -r 'float64 -> float32' \ +\ +| sed -e 's/blas64/blas32/' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ +\ +>> blas32/conv_test.go + +echo Generating blas32/conv_symmetric.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_symmetric.go +cat blas64/conv_symmetric.go \ +| gofmt -r 'float64 -> float32' \ +\ +| sed -e 's/blas64/blas32/' \ +\ +>> blas32/conv_symmetric.go + +echo Generating blas32/conv_symmetric_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_symmetric_test.go +cat blas64/conv_symmetric_test.go \ +| gofmt -r 'float64 -> float32' \ +\ +| sed -e 's/blas64/blas32/' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ +\ +>> blas32/conv_symmetric_test.go + + +# Generate code for cblas128. +echo Generating cblas128/conv.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv.go +cat blas64/conv.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ +\ +>> cblas128/conv.go + +echo Generating cblas128/conv_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_test.go +cat blas64/conv_test.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ + -e 's_"math"_math "math/cmplx"_' \ +\ +>> cblas128/conv_test.go + +echo Generating cblas128/conv_symmetric.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_symmetric.go +cat blas64/conv_symmetric.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ +\ +>> cblas128/conv_symmetric.go + +echo Generating cblas128/conv_symmetric_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_symmetric_test.go +cat blas64/conv_symmetric_test.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ + -e 's_"math"_math "math/cmplx"_' \ +\ +>> cblas128/conv_symmetric_test.go + +echo Generating cblas128/conv_hermitian.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_hermitian.go +cat blas64/conv_symmetric.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ + -e 's/Symmetric/Hermitian/g' \ + -e 's/a symmetric/an Hermitian/g' \ + -e 's/symmetric/hermitian/g' \ + -e 's/Sym/Herm/g' \ +\ +>> cblas128/conv_hermitian.go + +echo Generating cblas128/conv_hermitian_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_hermitian_test.go +cat blas64/conv_symmetric_test.go \ +| gofmt -r 'float64 -> complex128' \ +\ +| sed -e 's/blas64/cblas128/' \ + -e 's/Symmetric/Hermitian/g' \ + -e 's/a symmetric/an Hermitian/g' \ + -e 's/symmetric/hermitian/g' \ + -e 's/Sym/Herm/g' \ + -e 's_"math"_math "math/cmplx"_' \ +\ +>> cblas128/conv_hermitian_test.go + + +# Generate code for cblas64. +echo Generating cblas64/conv.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv.go +cat blas64/conv.go \ +| gofmt -r 'float64 -> complex64' \ +\ +| sed -e 's/blas64/cblas64/' \ +\ +>> cblas64/conv.go + +echo Generating cblas64/conv_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_test.go +cat blas64/conv_test.go \ +| gofmt -r 'float64 -> complex64' \ +\ +| sed -e 's/blas64/cblas64/' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/cmplx64"_' \ +\ +>> cblas64/conv_test.go + +echo Generating cblas64/conv_hermitian.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_hermitian.go +cat blas64/conv_symmetric.go \ +| gofmt -r 'float64 -> complex64' \ +\ +| sed -e 's/blas64/cblas64/' \ + -e 's/Symmetric/Hermitian/g' \ + -e 's/a symmetric/an Hermitian/g' \ + -e 's/symmetric/hermitian/g' \ + -e 's/Sym/Herm/g' \ +\ +>> cblas64/conv_hermitian.go + +echo Generating cblas64/conv_hermitian_test.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_hermitian_test.go +cat blas64/conv_symmetric_test.go \ +| gofmt -r 'float64 -> complex64' \ +\ +| sed -e 's/blas64/cblas64/' \ + -e 's/Symmetric/Hermitian/g' \ + -e 's/a symmetric/an Hermitian/g' \ + -e 's/symmetric/hermitian/g' \ + -e 's/Sym/Herm/g' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/cmplx64"_' \ +\ +>> cblas64/conv_hermitian_test.go diff --git a/vendor/gonum.org/v1/gonum/blas/doc.go b/vendor/gonum.org/v1/gonum/blas/doc.go new file mode 100644 index 00000000..99231c46 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/doc.go @@ -0,0 +1,108 @@ +// Copyright ©2017 The gonum 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 blas provides interfaces for the BLAS linear algebra standard. + +All methods must perform appropriate parameter checking and panic if +provided parameters that do not conform to the requirements specified +by the BLAS standard. + +Quick Reference Guide to the BLAS from http://www.netlib.org/lapack/lug/node145.html + +This version is modified to remove the "order" option. All matrix operations are +on row-order matrices. + +Level 1 BLAS + + dim scalar vector vector scalars 5-element prefixes + struct + + _rotg ( a, b ) S, D + _rotmg( d1, d2, a, b ) S, D + _rot ( n, x, incX, y, incY, c, s ) S, D + _rotm ( n, x, incX, y, incY, param ) S, D + _swap ( n, x, incX, y, incY ) S, D, C, Z + _scal ( n, alpha, x, incX ) S, D, C, Z, Cs, Zd + _copy ( n, x, incX, y, incY ) S, D, C, Z + _axpy ( n, alpha, x, incX, y, incY ) S, D, C, Z + _dot ( n, x, incX, y, incY ) S, D, Ds + _dotu ( n, x, incX, y, incY ) C, Z + _dotc ( n, x, incX, y, incY ) C, Z + __dot ( n, alpha, x, incX, y, incY ) Sds + _nrm2 ( n, x, incX ) S, D, Sc, Dz + _asum ( n, x, incX ) S, D, Sc, Dz + I_amax( n, x, incX ) s, d, c, z + +Level 2 BLAS + + options dim b-width scalar matrix vector scalar vector prefixes + + _gemv ( trans, m, n, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z + _gbmv ( trans, m, n, kL, kU, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z + _hemv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) C, Z + _hbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) C, Z + _hpmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) C, Z + _symv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) S, D + _sbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) S, D + _spmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) S, D + _trmv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z + _tbmv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z + _tpmv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z + _trsv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z + _tbsv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z + _tpsv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z + + options dim scalar vector vector matrix prefixes + + _ger ( m, n, alpha, x, incX, y, incY, a, lda ) S, D + _geru ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z + _gerc ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z + _her ( uplo, n, alpha, x, incX, a, lda ) C, Z + _hpr ( uplo, n, alpha, x, incX, ap ) C, Z + _her2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) C, Z + _hpr2 ( uplo, n, alpha, x, incX, y, incY, ap ) C, Z + _syr ( uplo, n, alpha, x, incX, a, lda ) S, D + _spr ( uplo, n, alpha, x, incX, ap ) S, D + _syr2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) S, D + _spr2 ( uplo, n, alpha, x, incX, y, incY, ap ) S, D + +Level 3 BLAS + + options dim scalar matrix matrix scalar matrix prefixes + + _gemm ( transA, transB, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _symm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _hemm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z + _syrk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) S, D, C, Z + _herk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) C, Z + _syr2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _her2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z + _trmm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z + _trsm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z + +Meaning of prefixes + + S - float32 C - complex64 + D - float64 Z - complex128 + +Matrix types + + GE - GEneral GB - General Band + SY - SYmmetric SB - Symmetric Band SP - Symmetric Packed + HE - HErmitian HB - Hermitian Band HP - Hermitian Packed + TR - TRiangular TB - Triangular Band TP - Triangular Packed + +Options + + trans = NoTrans, Trans, ConjTrans + uplo = Upper, Lower + diag = Nonunit, Unit + side = Left, Right (A or op(A) on the left, or A or op(A) on the right) + +For real matrices, Trans and ConjTrans have the same meaning. +For Hermitian matrices, trans = Trans is not allowed. +For complex symmetric matrices, trans = ConjTrans is not allowed. +*/ +package blas // import "gonum.org/v1/gonum/blas" diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/bench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/bench_test.go new file mode 100644 index 00000000..81124fea --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/bench_test.go @@ -0,0 +1,22 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +const ( + Sm = testblas.SmallMat + Med = testblas.MediumMat + Lg = testblas.LargeMat + Hg = testblas.HugeMat +) + +const ( + T = blas.Trans + NT = blas.NoTrans +) diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go b/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go new file mode 100644 index 00000000..24ff57c9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go @@ -0,0 +1,206 @@ +// Copyright ©2017 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +var ( + _ blas.Complex64 = Implementation{} + _ blas.Complex128 = Implementation{} +) + +// TODO(btracey): Replace this as complex routines are added, and instead +// automatically generate the complex64 routines from the complex128 ones. + +var noComplex = "native: implementation does not implement this routine, see the cgo wrapper in gonum.org/v1/netlib/blas" + +// Level 1 complex64 routines. + +func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) { + panic(noComplex) +} +func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) { + panic(noComplex) +} +func (Implementation) Scnrm2(n int, x []complex64, incX int) float32 { + panic(noComplex) +} +func (Implementation) Scasum(n int, x []complex64, incX int) float32 { + panic(noComplex) +} +func (Implementation) Icamax(n int, x []complex64, incX int) int { + panic(noComplex) +} +func (Implementation) Cswap(n int, x []complex64, incX int, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Ccopy(n int, x []complex64, incX int, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Cscal(n int, alpha complex64, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Csscal(n int, alpha float32, x []complex64, incX int) { + panic(noComplex) +} + +// Level 2 complex64 routines. + +func (Implementation) Cgemv(tA blas.Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Cgbmv(tA blas.Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Ctrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Ctbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Ctpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex64, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Ctrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Ctbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Ctpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex64, x []complex64, incX int) { + panic(noComplex) +} +func (Implementation) Chemv(ul blas.Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Chbmv(ul blas.Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Chpmv(ul blas.Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) { + panic(noComplex) +} +func (Implementation) Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + panic(noComplex) +} +func (Implementation) Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + panic(noComplex) +} +func (Implementation) Cher(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) { + panic(noComplex) +} +func (Implementation) Chpr(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64) { + panic(noComplex) +} +func (Implementation) Cher2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + panic(noComplex) +} +func (Implementation) Chpr2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) { + panic(noComplex) +} + +// Level 3 complex64 routines. + +func (Implementation) Cgemm(tA, tB blas.Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Csymm(s blas.Side, ul blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Csyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Csyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Ctrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + panic(noComplex) +} +func (Implementation) Ctrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + panic(noComplex) +} +func (Implementation) Chemm(s blas.Side, ul blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Cherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) { + panic(noComplex) +} +func (Implementation) Cher2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) { + panic(noComplex) +} + +// Level 2 complex128 routines. + +func (Implementation) Zgemv(tA blas.Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + panic(noComplex) +} +func (Implementation) Zgbmv(tA blas.Transpose, m, n int, kL int, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + panic(noComplex) +} +func (Implementation) Ztrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Ztbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Ztpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex128, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Ztrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Ztbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Ztpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex128, x []complex128, incX int) { + panic(noComplex) +} +func (Implementation) Zhemv(ul blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + panic(noComplex) +} +func (Implementation) Zhbmv(ul blas.Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + panic(noComplex) +} +func (Implementation) Zhpmv(ul blas.Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) { + panic(noComplex) +} +func (Implementation) Zhpr(ul blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128) { + panic(noComplex) +} +func (Implementation) Zhpr2(ul blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) { + panic(noComplex) +} + +// Level 3 complex128 routines. + +func (Implementation) Zgemm(tA, tB blas.Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Zsymm(s blas.Side, ul blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Zsyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Zsyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Ztrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + panic(noComplex) +} +func (Implementation) Ztrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + panic(noComplex) +} +func (Implementation) Zhemm(s blas.Side, ul blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Zherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) { + panic(noComplex) +} +func (Implementation) Zher2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) { + panic(noComplex) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go new file mode 100644 index 00000000..a9291d9b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go @@ -0,0 +1,261 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "runtime" + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Dgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func (Implementation) Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic(badTranspose) + } + aTrans := tA == blas.Trans || tA == blas.ConjTrans + if aTrans { + checkDMatrix('a', k, m, a, lda) + } else { + checkDMatrix('a', m, k, a, lda) + } + bTrans := tB == blas.Trans || tB == blas.ConjTrans + if bTrans { + checkDMatrix('b', n, k, b, ldb) + } else { + checkDMatrix('b', k, n, b, ldb) + } + checkDMatrix('c', m, n, c, ldc) + + // scale c + if beta != 1 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + } + } + + dgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) +} + +func dgemmParallel(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // dgemmParallel computes a parallel matrix multiplication by partitioning + // a and b into sub-blocks, and updating c with the multiplication of the sub-block + // In all cases, + // A = [ A_11 A_12 ... A_1j + // A_21 A_22 ... A_2j + // ... + // A_i1 A_i2 ... A_ij] + // + // and same for B. All of the submatrix sizes are blockSize×blockSize except + // at the edges. + // + // In all cases, there is one dimension for each matrix along which + // C must be updated sequentially. + // Cij = \sum_k Aik Bki, (A * B) + // Cij = \sum_k Aki Bkj, (A^T * B) + // Cij = \sum_k Aik Bjk, (A * B^T) + // Cij = \sum_k Aki Bjk, (A^T * B^T) + // + // This code computes one {i, j} block sequentially along the k dimension, + // and computes all of the {i, j} blocks concurrently. This + // partitioning allows Cij to be updated in-place without race-conditions. + // Instead of launching a goroutine for each possible concurrent computation, + // a number of worker goroutines are created and channels are used to pass + // available and completed cases. + // + // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix + // multiplies, though this code does not copy matrices to attempt to eliminate + // cache misses. + + maxKLen := k + parBlocks := blocks(m, blockSize) * blocks(n, blockSize) + if parBlocks < minParBlock { + // The matrix multiplication is small in the dimensions where it can be + // computed concurrently. Just do it in serial. + dgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + } + + nWorkers := runtime.GOMAXPROCS(0) + if parBlocks < nWorkers { + nWorkers = parBlocks + } + // There is a tradeoff between the workers having to wait for work + // and a large buffer making operations slow. + buf := buffMul * nWorkers + if buf > parBlocks { + buf = parBlocks + } + + sendChan := make(chan subMul, buf) + + // Launch workers. A worker receives an {i, j} submatrix of c, and computes + // A_ik B_ki (or the transposed version) storing the result in c_ij. When the + // channel is finally closed, it signals to the waitgroup that it has finished + // computing. + var wg sync.WaitGroup + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // Make local copies of otherwise global variables to reduce shared memory. + // This has a noticeable effect on benchmarks in some cases. + alpha := alpha + aTrans := aTrans + bTrans := bTrans + m := m + n := n + for sub := range sendChan { + i := sub.i + j := sub.j + leni := blockSize + if i+leni > m { + leni = m - i + } + lenj := blockSize + if j+lenj > n { + lenj = n - j + } + + cSub := sliceView64(c, ldc, i, j, leni, lenj) + + // Compute A_ik B_kj for all k + for k := 0; k < maxKLen; k += blockSize { + lenk := blockSize + if k+lenk > maxKLen { + lenk = maxKLen - k + } + var aSub, bSub []float64 + if aTrans { + aSub = sliceView64(a, lda, k, i, lenk, leni) + } else { + aSub = sliceView64(a, lda, i, k, leni, lenk) + } + if bTrans { + bSub = sliceView64(b, ldb, j, k, lenj, lenk) + } else { + bSub = sliceView64(b, ldb, k, j, lenk, lenj) + } + dgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) + } + } + }() + } + + // Send out all of the {i, j} subblocks for computation. + for i := 0; i < m; i += blockSize { + for j := 0; j < n; j += blockSize { + sendChan <- subMul{ + i: i, + j: j, + } + } + } + close(sendChan) + wg.Wait() +} + +// dgemmSerial is serial matrix multiply +func dgemmSerial(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + switch { + case !aTrans && !bTrans: + dgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && !bTrans: + dgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case !aTrans && bTrans: + dgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && bTrans: + dgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + default: + panic("unreachable") + } +} + +// dgemmSerial where neither a nor b are transposed +func dgemmSerialNotNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for l, v := range a[i*lda : i*lda+k] { + tmp := alpha * v + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, b[l*ldb:l*ldb+n], ctmp) + } + } + } +} + +// dgemmSerial where neither a is transposed and b is not +func dgemmSerialTransNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + btmp := b[l*ldb : l*ldb+n] + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + } + } + } +} + +// dgemmSerial where neither a is not transposed and b is +func dgemmSerialNotTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + atmp := a[i*lda : i*lda+k] + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] += alpha * f64.DotUnitary(atmp, b[j*ldb:j*ldb+k]) + } + } +} + +// dgemmSerial where both are transposed +func dgemmSerialTransTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) + } + } + } +} + +func sliceView64(a []float64, lda, i, j, r, c int) []float64 { + return a[i*lda+j : (i+r-1)*lda+j+c] +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgemmbench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgemmbench_test.go new file mode 100644 index 00000000..55a44997 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dgemmbench_test.go @@ -0,0 +1,51 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemmSmSmSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Sm, Sm, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, NT) +} + +func BenchmarkDgemmMedLgMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Lg, Med, NT, NT) +} + +func BenchmarkDgemmLgLgLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Lg, NT, NT) +} + +func BenchmarkDgemmLgSmLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Sm, Lg, NT, NT) +} + +func BenchmarkDgemmLgLgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Sm, NT, NT) +} + +func BenchmarkDgemmHgHgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Hg, Hg, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMedTNT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, NT) +} + +func BenchmarkDgemmMedMedMedNTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, T) +} + +func BenchmarkDgemmMedMedMedTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, T) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgemvbench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgemvbench_test.go new file mode 100644 index 00000000..97899809 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dgemvbench_test.go @@ -0,0 +1,91 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemvSmSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvSmSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvMedMedNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 2, 3) +} + +func BenchmarkDgemvMedMedTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 2, 3) +} + +func BenchmarkDgemvLgLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvLgSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvSmLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 2, 3) +} + +func BenchmarkDgemvSmLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 2, 3) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgerbench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgerbench_test.go new file mode 100644 index 00000000..e1f85939 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dgerbench_test.go @@ -0,0 +1,51 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgerSmSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 1, 1) +} + +func BenchmarkDgerSmSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 2, 3) +} + +func BenchmarkDgerMedMedInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 1, 1) +} + +func BenchmarkDgerMedMedIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 2, 3) +} + +func BenchmarkDgerLgLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 1, 1) +} + +func BenchmarkDgerLgLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 2, 3) +} + +func BenchmarkDgerLgSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 1, 1) +} + +func BenchmarkDgerLgSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 2, 3) +} + +func BenchmarkDgerSmLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 1, 1) +} + +func BenchmarkDgerSmLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 2, 3) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/doc.go b/vendor/gonum.org/v1/gonum/blas/gonum/doc.go new file mode 100644 index 00000000..3b6b4077 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/doc.go @@ -0,0 +1,88 @@ +// Copyright ©2015 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Ensure changes made to blas/native are reflected in blas/cgo where relevant. + +/* +Package native is a Go implementation of the BLAS API. This implementation +panics when the input arguments are invalid as per the standard, for example +if a vector increment is zero. Please note that the treatment of NaN values +is not specified, and differs among the BLAS implementations. +gonum.org/v1/gonum/blas/blas64 provides helpful wrapper functions to the BLAS +interface. The rest of this text describes the layout of the data for the input types. + +Please note that in the function documentation, x[i] refers to the i^th element +of the vector, which will be different from the i^th element of the slice if +incX != 1. + +See http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html +for more license information. + +Vector arguments are effectively strided slices. They have two input arguments, +a number of elements, n, and an increment, incX. The increment specifies the +distance between elements of the vector. The actual Go slice may be longer +than necessary. +The increment may be positive or negative, except in functions with only +a single vector argument where the increment may only be positive. If the increment +is negative, s[0] is the last element in the slice. Note that this is not the same +as counting backward from the end of the slice, as len(s) may be longer than +necessary. So, for example, if n = 5 and incX = 3, the elements of s are + [0 * * 1 * * 2 * * 3 * * 4 * * * ...] +where ∗ elements are never accessed. If incX = -3, the same elements are +accessed, just in reverse order (4, 3, 2, 1, 0). + +Dense matrices are specified by a number of rows, a number of columns, and a stride. +The stride specifies the number of entries in the slice between the first element +of successive rows. The stride must be at least as large as the number of columns +but may be longer. + [a00 ... a0n a0* ... a1stride-1 a21 ... amn am* ... amstride-1] +Thus, dense[i*ld + j] refers to the {i, j}th element of the matrix. + +Symmetric and triangular matrices (non-packed) are stored identically to Dense, +except that only elements in one triangle of the matrix are accessed. + +Packed symmetric and packed triangular matrices are laid out with the entries +condensed such that all of the unreferenced elements are removed. So, the upper triangular +matrix + [ + 1 2 3 + 0 4 5 + 0 0 6 + ] +and the lower-triangular matrix + [ + 1 0 0 + 2 3 0 + 4 5 6 + ] +will both be compacted as [1 2 3 4 5 6]. The (i, j) element of the original +dense matrix can be found at element i*n - (i-1)*i/2 + j for upper triangular, +and at element i * (i+1) /2 + j for lower triangular. + +Banded matrices are laid out in a compact format, constructed by removing the +zeros in the rows and aligning the diagonals. For example, the matrix + [ + 1 2 3 0 0 0 + 4 5 6 7 0 0 + 0 8 9 10 11 0 + 0 0 12 13 14 15 + 0 0 0 16 17 18 + 0 0 0 0 19 20 + ] + +implicitly becomes (∗ entries are never accessed) + [ + * 1 2 3 + 4 5 6 7 + 8 9 10 11 + 12 13 14 15 + 16 17 18 * + 19 20 * * + ] +which is given to the BLAS routine as [∗ 1 2 3 4 ...]. + +See http://www.crest.iu.edu/research/mtl/reference/html/banded.html +for more information +*/ +package gonum // import "gonum.org/v1/gonum/blas/gonum" diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dtrmvbench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/dtrmvbench_test.go new file mode 100644 index 00000000..371c0192 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dtrmvbench_test.go @@ -0,0 +1,54 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package gonum + +import ( + "strconv" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDtrmv(b *testing.B) { + for _, n := range []int{testblas.MediumMat, testblas.LargeMat} { + for _, incX := range []int{1, 5} { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, unit := range []blas.Diag{blas.NonUnit, blas.Unit} { + var str string + if n == testblas.MediumMat { + str += "Med" + } else if n == testblas.LargeMat { + str += "Large" + } + str += "_Inc" + strconv.Itoa(incX) + if uplo == blas.Upper { + str += "_UP" + } else { + str += "_LO" + } + if trans == blas.NoTrans { + str += "_NT" + } else { + str += "_TR" + } + if unit == blas.NonUnit { + str += "_NU" + } else { + str += "_UN" + } + lda := n + b.Run(str, func(b *testing.B) { + testblas.DtrmvBenchmark(b, Implementation{}, n, lda, incX, uplo, trans, unit) + }) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/general_double.go b/vendor/gonum.org/v1/gonum/blas/gonum/general_double.go new file mode 100644 index 00000000..58ded80c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/general_double.go @@ -0,0 +1,50 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "math" +) + +type general64 struct { + data []float64 + rows, cols int + stride int +} + +func (g general64) clone() general64 { + data := make([]float64, len(g.data)) + copy(data, g.data) + return general64{ + data: data, + rows: g.rows, + cols: g.cols, + stride: g.stride, + } +} + +func (g general64) equal(a general64) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if a.data[i] != v { + return false + } + } + return true +} + +func (g general64) equalWithinAbs(a general64, tol float64) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if math.Abs(a.data[i]-v) > tol { + return false + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/general_single.go b/vendor/gonum.org/v1/gonum/blas/gonum/general_single.go new file mode 100644 index 00000000..ca360a72 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/general_single.go @@ -0,0 +1,52 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 gonum + +import ( + math "gonum.org/v1/gonum/internal/math32" +) + +type general32 struct { + data []float32 + rows, cols int + stride int +} + +func (g general32) clone() general32 { + data := make([]float32, len(g.data)) + copy(data, g.data) + return general32{ + data: data, + rows: g.rows, + cols: g.cols, + stride: g.stride, + } +} + +func (g general32) equal(a general32) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if a.data[i] != v { + return false + } + } + return true +} + +func (g general32) equalWithinAbs(a general32, tol float32) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if math.Abs(a.data[i]-v) > tol { + return false + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go b/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go new file mode 100644 index 00000000..e65f745a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go @@ -0,0 +1,133 @@ +// Copyright ©2015 The gonum 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:generate ./single_precision.bash + +package gonum + +import "math" + +type Implementation struct{} + +// The following are panic strings used during parameter checks. +const ( + negativeN = "blas: n < 0" + zeroIncX = "blas: zero x index increment" + zeroIncY = "blas: zero y index increment" + badLenX = "blas: x index out of range" + badLenY = "blas: y index out of range" + + mLT0 = "blas: m < 0" + nLT0 = "blas: n < 0" + kLT0 = "blas: k < 0" + kLLT0 = "blas: kL < 0" + kULT0 = "blas: kU < 0" + + badUplo = "blas: illegal triangle" + badTranspose = "blas: illegal transpose" + badDiag = "blas: illegal diagonal" + badSide = "blas: illegal side" + + badLdA = "blas: index of a out of range" + badLdB = "blas: index of b out of range" + badLdC = "blas: index of c out of range" + + badX = "blas: x index out of range" + badY = "blas: y index out of range" +) + +// [SD]gemm behavior constants. These are kept here to keep them out of the +// way during single precision code genration. +const ( + blockSize = 64 // b x b matrix + minParBlock = 4 // minimum number of blocks needed to go parallel + buffMul = 4 // how big is the buffer relative to the number of workers +) + +// subMul is a common type shared by [SD]gemm. +type subMul struct { + i, j int // index of block +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +func checkSMatrix(name byte, m, n int, a []float32, lda int) { + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic("blas: illegal stride of " + string(name)) + } + if len(a) < (m-1)*lda+n { + panic("blas: index of " + string(name) + " out of range") + } +} + +func checkDMatrix(name byte, m, n int, a []float64, lda int) { + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic("blas: illegal stride of " + string(name)) + } + if len(a) < (m-1)*lda+n { + panic("blas: index of " + string(name) + " out of range") + } +} + +func checkZMatrix(name byte, m, n int, a []complex128, lda int) { + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic("blas: illegal stride of " + string(name)) + } + if len(a) < (m-1)*lda+n { + panic("blas: insufficient " + string(name) + " matrix slice length") + } +} + +func checkZVector(name byte, n int, x []complex128, incX int) { + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: insufficient " + string(name) + " vector slice length") + } +} + +// blocks returns the number of divisions of the dimension length with the given +// block size. +func blocks(dim, bsize int) int { + return (dim + bsize - 1) / bsize +} + +// dcabs1 returns |real(z)|+|imag(z)|. +func dcabs1(z complex128) float64 { + return math.Abs(real(z)) + math.Abs(imag(z)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go new file mode 100644 index 00000000..b759c902 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go @@ -0,0 +1,442 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/internal/asm/c128" +) + +// Dzasum returns the sum of the absolute values of the elements of x +// \sum_i |Re(x[i])| + |Im(x[i])| +// Dzasum returns 0 if incX is negative. +func (Implementation) Dzasum(n int, x []complex128, incX int) float64 { + if n < 0 { + panic(negativeN) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + var sum float64 + if incX == 1 { + if len(x) < n { + panic(badX) + } + for _, v := range x[:n] { + sum += dcabs1(v) + } + return sum + } + if (n-1)*incX >= len(x) { + panic(badX) + } + for i := 0; i < n; i++ { + v := x[i*incX] + sum += dcabs1(v) + } + return sum +} + +// Dznrm2 computes the Euclidean norm of the complex vector x, +// ‖x‖_2 = sqrt(\sum_i x[i] * conj(x[i])). +// This function returns 0 if incX is negative. +func (Implementation) Dznrm2(n int, x []complex128, incX int) float64 { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if n < 1 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if (n-1)*incX >= len(x) { + panic(badX) + } + var ( + scale float64 + ssq float64 = 1 + ) + if incX == 1 { + for _, v := range x[:n] { + re, im := math.Abs(real(v)), math.Abs(imag(v)) + if re != 0 { + if re > scale { + ssq = 1 + ssq*(scale/re)*(scale/re) + scale = re + } else { + ssq += (re / scale) * (re / scale) + } + } + if im != 0 { + if im > scale { + ssq = 1 + ssq*(scale/im)*(scale/im) + scale = im + } else { + ssq += (im / scale) * (im / scale) + } + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(ssq) + } + for ix := 0; ix < n*incX; ix += incX { + re, im := math.Abs(real(x[ix])), math.Abs(imag(x[ix])) + if re != 0 { + if re > scale { + ssq = 1 + ssq*(scale/re)*(scale/re) + scale = re + } else { + ssq += (re / scale) * (re / scale) + } + } + if im != 0 { + if im > scale { + ssq = 1 + ssq*(scale/im)*(scale/im) + scale = im + } else { + ssq += (im / scale) * (im / scale) + } + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(ssq) +} + +// Izamax returns the index of the first element of x having largest |Re(·)|+|Im(·)|. +// Izamax returns -1 if n is 0 or incX is negative. +func (Implementation) Izamax(n int, x []complex128, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + // Return invalid index. + return -1 + } + if n < 1 { + if n == 0 { + // Return invalid index. + return -1 + } + panic(negativeN) + } + if len(x) <= (n-1)*incX { + panic(badX) + } + idx := 0 + max := dcabs1(x[0]) + if incX == 1 { + for i, v := range x[1:n] { + absV := dcabs1(v) + if absV > max { + max = absV + idx = i + 1 + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + absV := dcabs1(x[ix]) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Zaxpy adds alpha times x to y: +// y[i] += alpha * x[i] for all i +func (Implementation) Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + c128.AxpyUnitary(alpha, x[:n], y[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (1 - n) * incX + } + if incY < 0 { + iy = (1 - n) * incY + } + c128.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Zcopy copies the vector x to vector y. +func (Implementation) Zcopy(n int, x []complex128, incX int, y []complex128, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + copy(y[:n], x[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + y[iy] = x[ix] + ix += incX + iy += incY + } +} + +// Zdotc computes the dot product +// x^H · y +// of two complex vectors x and y. +func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, incY int) complex128 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badX) + } + if len(y) < n { + panic(badY) + } + return c128.DotcUnitary(x[:n], y[:n]) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || (n-1)*incX >= len(x) { + panic(badX) + } + if iy >= len(y) || (n-1)*incY >= len(y) { + panic(badY) + } + return c128.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Zdotu computes the dot product +// x^T · y +// of two complex vectors x and y. +func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, incY int) complex128 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badX) + } + if len(y) < n { + panic(badY) + } + return c128.DotuUnitary(x[:n], y[:n]) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || (n-1)*incX >= len(x) { + panic(badX) + } + if iy >= len(y) || (n-1)*incY >= len(y) { + panic(badY) + } + return c128.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Zdscal scales the vector x by a real scalar alpha. +// Zdscal has no effect if incX < 0. +func (Implementation) Zdscal(n int, alpha float64, x []complex128, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + x = x[:n] + for i, v := range x { + x[i] = complex(alpha*real(v), alpha*imag(v)) + } + return + } + for ix := 0; ix < n*incX; ix += incX { + v := x[ix] + x[ix] = complex(alpha*real(v), alpha*imag(v)) + } +} + +// Zscal scales the vector x by a complex scalar alpha. +// Zscal has no effect if incX < 0. +func (Implementation) Zscal(n int, alpha complex128, x []complex128, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + c128.ScalUnitary(alpha, x[:n]) + return + } + c128.ScalInc(alpha, x, uintptr(n), uintptr(incX)) +} + +// Zswap exchanges the elements of two complex vectors x and y. +func (Implementation) Zswap(n int, x []complex128, incX int, y []complex128, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, v := range x { + x[i], y[i] = y[i], v + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + x[ix], y[iy] = y[iy], x[ix] + ix += incX + iy += incY + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_bench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_bench_test.go new file mode 100644 index 00000000..af536365 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_bench_test.go @@ -0,0 +1,41 @@ +// Copyright ©2017 The Gonum 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 gonum + +import ( + "math/rand" + "testing" +) + +func benchmarkZdscal(b *testing.B, n, inc int) { + rnd := rand.New(rand.NewSource(1)) + alpha := rnd.NormFloat64() + x := make([]complex128, (n-1)*inc+1) + for i := range x { + x[i] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Zdscal(n, alpha, x, inc) + } +} + +func BenchmarkZdscalN10Inc1(b *testing.B) { benchmarkZdscal(b, 10, 1) } +func BenchmarkZdscalN100Inc1(b *testing.B) { benchmarkZdscal(b, 100, 1) } +func BenchmarkZdscalN1000Inc1(b *testing.B) { benchmarkZdscal(b, 1000, 1) } +func BenchmarkZdscalN10000Inc1(b *testing.B) { benchmarkZdscal(b, 10000, 1) } +func BenchmarkZdscalN100000Inc1(b *testing.B) { benchmarkZdscal(b, 100000, 1) } + +func BenchmarkZdscalN10Inc10(b *testing.B) { benchmarkZdscal(b, 10, 10) } +func BenchmarkZdscalN100Inc10(b *testing.B) { benchmarkZdscal(b, 100, 10) } +func BenchmarkZdscalN1000Inc10(b *testing.B) { benchmarkZdscal(b, 1000, 10) } +func BenchmarkZdscalN10000Inc10(b *testing.B) { benchmarkZdscal(b, 10000, 10) } +func BenchmarkZdscalN100000Inc10(b *testing.B) { benchmarkZdscal(b, 100000, 10) } + +func BenchmarkZdscalN10Inc1000(b *testing.B) { benchmarkZdscal(b, 10, 1000) } +func BenchmarkZdscalN100Inc1000(b *testing.B) { benchmarkZdscal(b, 100, 1000) } +func BenchmarkZdscalN1000Inc1000(b *testing.B) { benchmarkZdscal(b, 1000, 1000) } +func BenchmarkZdscalN10000Inc1000(b *testing.B) { benchmarkZdscal(b, 10000, 1000) } +func BenchmarkZdscalN100000Inc1000(b *testing.B) { benchmarkZdscal(b, 100000, 1000) } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_test.go new file mode 100644 index 00000000..1755e9e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128_test.go @@ -0,0 +1,51 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDzasum(t *testing.T) { + testblas.DzasumTest(t, impl) +} + +func TestDznrm2(t *testing.T) { + testblas.Dznrm2Test(t, impl) +} + +func TestIzamax(t *testing.T) { + testblas.IzamaxTest(t, impl) +} + +func TestZaxpy(t *testing.T) { + testblas.ZaxpyTest(t, impl) +} + +func TestZcopy(t *testing.T) { + testblas.ZcopyTest(t, impl) +} + +func TestZdotc(t *testing.T) { + testblas.ZdotcTest(t, impl) +} + +func TestZdotu(t *testing.T) { + testblas.ZdotuTest(t, impl) +} + +func TestZdscal(t *testing.T) { + testblas.ZdscalTest(t, impl) +} + +func TestZscal(t *testing.T) { + testblas.ZscalTest(t, impl) +} + +func TestZswap(t *testing.T) { + testblas.ZswapTest(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1double.go new file mode 100644 index 00000000..e433fddf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1double.go @@ -0,0 +1,595 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var _ blas.Float64Level1 = Implementation{} + +// Dnrm2 computes the Euclidean norm of a vector, +// sqrt(\sum_i x[i] * x[i]). +// This function returns 0 if incX is negative. +func (Implementation) Dnrm2(n int, x []float64, incX int) float64 { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return math.Abs(x[0]) + } + if n == 0 { + return 0 + } + if n < 1 { + panic(negativeN) + } + } + var ( + scale float64 = 0 + sumSquares float64 = 1 + ) + if incX == 1 { + x = x[:n] + for _, v := range x { + if v == 0 { + continue + } + absxi := math.Abs(v) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) + } + for ix := 0; ix < n*incX; ix += incX { + val := x[ix] + if val == 0 { + continue + } + absxi := math.Abs(val) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) +} + +// Dasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Dasum returns 0 if incX is negative. +func (Implementation) Dasum(n int, x []float64, incX int) float64 { + var sum float64 + if n < 0 { + panic(negativeN) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if incX == 1 { + x = x[:n] + for _, v := range x { + sum += math.Abs(v) + } + return sum + } + for i := 0; i < n; i++ { + sum += math.Abs(x[i*incX]) + } + return sum +} + +// Idamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Idamax returns -1 if n == 0. +func (Implementation) Idamax(n int, x []float64, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return 0 + } + if n == 0 { + return -1 // Netlib returns invalid index when n == 0 + } + if n < 1 { + panic(negativeN) + } + } + idx := 0 + max := math.Abs(x[0]) + if incX == 1 { + for i, v := range x[:n] { + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + v := x[ix] + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Dswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, v := range x { + x[i], y[i] = y[i], v + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + x[ix], y[iy] = y[iy], x[ix] + ix += incX + iy += incY + } +} + +// Dcopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + copy(y[:n], x[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + y[iy] = x[ix] + ix += incX + iy += incY + } +} + +// Daxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + f64.AxpyUnitary(alpha, x[:n], y[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + f64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Drotg computes the plane rotation +// _ _ _ _ _ _ +// | c s | | a | | r | +// | -s c | * | b | = | 0 | +// ‾ ‾ ‾ ‾ ‾ ‾ +// where +// r = ±√(a^2 + b^2) +// c = a/r, the cosine of the plane rotation +// s = b/r, the sine of the plane rotation +// +// NOTE: There is a discrepancy between the refence implementation and the BLAS +// technical manual regarding the sign for r when a or b are zero. +// Drotg agrees with the definition in the manual and other +// common BLAS implementations. +func (Implementation) Drotg(a, b float64) (c, s, r, z float64) { + if b == 0 && a == 0 { + return 1, 0, a, 0 + } + absA := math.Abs(a) + absB := math.Abs(b) + aGTb := absA > absB + r = math.Hypot(a, b) + if aGTb { + r = math.Copysign(r, a) + } else { + r = math.Copysign(r, b) + } + c = a / r + s = b / r + if aGTb { + z = s + } else if c != 0 { // r == 0 case handled above + z = 1 / c + } else { + z = 1 + } + return +} + +// Drotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func (Implementation) Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) { + var p1, p2, q1, q2, u float64 + + const ( + gam = 4096.0 + gamsq = 16777216.0 + rgamsq = 5.9604645e-8 + ) + + if d1 < 0 { + p.Flag = blas.Rescaling + return + } + + p2 = d2 * y1 + if p2 == 0 { + p.Flag = blas.Identity + rd1 = d1 + rd2 = d2 + rx1 = x1 + return + } + p1 = d1 * x1 + q2 = p2 * y1 + q1 = p1 * x1 + + absQ1 := math.Abs(q1) + absQ2 := math.Abs(q2) + + if absQ1 < absQ2 && q2 < 0 { + p.Flag = blas.Rescaling + return + } + + if d1 == 0 { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1, rd2 = d2/u, d1/u + rx1 = y1 / u + return + } + + // Now we know that d1 != 0, and d2 != 0. If d2 == 0, it would be caught + // when p2 == 0, and if d1 == 0, then it is caught above + + if absQ1 > absQ2 { + p.H[1] = -y1 / x1 + p.H[2] = p2 / p1 + u = 1 - p.H[2]*p.H[1] + rd1 = d1 + rd2 = d2 + rx1 = x1 + p.Flag = blas.OffDiagonal + // u must be greater than zero because |q1| > |q2|, so check from netlib + // is unnecessary + // This is left in for ease of comparison with complex routines + //if u > 0 { + rd1 /= u + rd2 /= u + rx1 *= u + //} + } else { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1 = d2 / u + rd2 = d1 / u + rx1 = y1 * u + } + + for rd1 <= rgamsq || rd1 >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if rd1 <= rgamsq { + rd1 *= gam * gam + rx1 /= gam + p.H[0] /= gam + p.H[2] /= gam + } else { + rd1 /= gam * gam + rx1 *= gam + p.H[0] *= gam + p.H[2] *= gam + } + } + + for math.Abs(rd2) <= rgamsq || math.Abs(rd2) >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if math.Abs(rd2) <= rgamsq { + rd2 *= gam * gam + p.H[1] /= gam + p.H[3] /= gam + } else { + rd2 /= gam * gam + p.H[1] *= gam + p.H[3] *= gam + } + } + return +} + +// Drot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = c*vx+s*vy, c*vy-s*vx + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx + ix += incX + iy += incY + } +} + +// Drotm applies the modified Givens rotation to the 2×n matrix. +func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + + var h11, h12, h21, h22 float64 + var ix, iy int + switch p.Flag { + case blas.Identity: + return + case blas.Rescaling: + h11 = p.H[0] + h12 = p.H[2] + h21 = p.H[1] + h22 = p.H[3] + case blas.OffDiagonal: + h11 = 1 + h12 = p.H[2] + h21 = p.H[1] + h22 = 1 + case blas.Diagonal: + h11 = p.H[0] + h12 = 1 + h21 = -1 + h22 = p.H[3] + } + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = vx*h11+vy*h12, vx*h21+vy*h22 + } + return + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = vx*h11+vy*h12, vx*h21+vy*h22 + ix += incX + iy += incY + } +} + +// Dscal scales x by alpha. +// x[i] *= alpha +// Dscal has no effect if incX < 0. +func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + f64.ScalUnitary(alpha, x[:n]) + return + } + f64.ScalInc(alpha, x, uintptr(n), uintptr(incX)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1doubleBench_auto_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1doubleBench_auto_test.go new file mode 100644 index 00000000..08296957 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1doubleBench_auto_test.go @@ -0,0 +1,1685 @@ +// Code generated by "go run github.com/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go"; DO NOT EDIT. + +// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package gonum + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +const ( + posInc1 = 5 + posInc2 = 3 + negInc1 = -3 + negInc2 = -4 + SMALL_SLICE = 10 + MEDIUM_SLICE = 1000 + LARGE_SLICE = 100000 + HUGE_SLICE = 10000000 +) + +func randomSlice(l, idx int) []float64 { + if idx < 0 { + idx = -idx + } + s := make([]float64, l*idx) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkDdot(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Ddot(n, x, incX, y, incY) + } +} + +func BenchmarkDdotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDnrm2(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dnrm2(n, x, incX) + } +} + +func BenchmarkDnrm2SmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2SmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDasum(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dasum(n, x, incX) + } +} + +func BenchmarkDasumSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkIdamax(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Idamax(n, x, incX) + } +} + +func BenchmarkIdamaxSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDswap(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dswap(n, x, incX, y, incY) + } +} + +func BenchmarkDswapSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDcopy(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dcopy(n, x, incX, y, incY) + } +} + +func BenchmarkDcopySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDaxpy(b *testing.B, n int, alpha float64, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Daxpy(n, alpha, x, incX, y, incY) + } +} + +func BenchmarkDaxpySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDrot(b *testing.B, n int, x []float64, incX int, y []float64, incY int, c, s float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drot(n, x, incX, y, incY, c, s) + } +} + +func BenchmarkDrotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +/* ------------------ */ +func benchmarkDrotmOffDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmOffDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmResc(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmRescSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDscal(b *testing.B, n int, alpha float64, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dscal(n, alpha, x, incX) + } +} + +func BenchmarkDscalSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +/* ------------------ */ diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go new file mode 100644 index 00000000..30c01100 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Ddot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) float64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f64.DotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f64.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1double_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1double_test.go new file mode 100644 index 00000000..45adc85f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1double_test.go @@ -0,0 +1,61 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +var impl Implementation + +func TestDasum(t *testing.T) { + testblas.DasumTest(t, impl) +} + +func TestDaxpy(t *testing.T) { + testblas.DaxpyTest(t, impl) +} + +func TestDdot(t *testing.T) { + testblas.DdotTest(t, impl) +} + +func TestDnrm2(t *testing.T) { + testblas.Dnrm2Test(t, impl) +} + +func TestIdamax(t *testing.T) { + testblas.IdamaxTest(t, impl) +} + +func TestDswap(t *testing.T) { + testblas.DswapTest(t, impl) +} + +func TestDcopy(t *testing.T) { + testblas.DcopyTest(t, impl) +} + +func TestDrotg(t *testing.T) { + testblas.DrotgTest(t, impl) +} + +func TestDrotmg(t *testing.T) { + testblas.DrotmgTest(t, impl) +} + +func TestDrot(t *testing.T) { + testblas.DrotTest(t, impl) +} + +func TestDrotm(t *testing.T) { + testblas.DrotmTest(t, impl) +} + +func TestDscal(t *testing.T) { + testblas.DscalTest(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1single.go new file mode 100644 index 00000000..8081c814 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1single.go @@ -0,0 +1,619 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 gonum + +import ( + math "gonum.org/v1/gonum/internal/math32" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level1 = Implementation{} + +// Snrm2 computes the Euclidean norm of a vector, +// sqrt(\sum_i x[i] * x[i]). +// This function returns 0 if incX is negative. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Snrm2(n int, x []float32, incX int) float32 { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return math.Abs(x[0]) + } + if n == 0 { + return 0 + } + if n < 1 { + panic(negativeN) + } + } + var ( + scale float32 = 0 + sumSquares float32 = 1 + ) + if incX == 1 { + x = x[:n] + for _, v := range x { + if v == 0 { + continue + } + absxi := math.Abs(v) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) + } + for ix := 0; ix < n*incX; ix += incX { + val := x[ix] + if val == 0 { + continue + } + absxi := math.Abs(val) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) +} + +// Sasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Sasum returns 0 if incX is negative. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sasum(n int, x []float32, incX int) float32 { + var sum float32 + if n < 0 { + panic(negativeN) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if incX == 1 { + x = x[:n] + for _, v := range x { + sum += math.Abs(v) + } + return sum + } + for i := 0; i < n; i++ { + sum += math.Abs(x[i*incX]) + } + return sum +} + +// Isamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Isamax returns -1 if n == 0. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Isamax(n int, x []float32, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return 0 + } + if n == 0 { + return -1 // Netlib returns invalid index when n == 0 + } + if n < 1 { + panic(negativeN) + } + } + idx := 0 + max := math.Abs(x[0]) + if incX == 1 { + for i, v := range x[:n] { + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + v := x[ix] + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Sswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sswap(n int, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, v := range x { + x[i], y[i] = y[i], v + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + x[ix], y[iy] = y[iy], x[ix] + ix += incX + iy += incY + } +} + +// Scopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Scopy(n int, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + copy(y[:n], x[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + y[iy] = x[ix] + ix += incX + iy += incY + } +} + +// Saxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + f32.AxpyUnitary(alpha, x[:n], y[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + f32.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Srotg computes the plane rotation +// _ _ _ _ _ _ +// | c s | | a | | r | +// | -s c | * | b | = | 0 | +// ‾ ‾ ‾ ‾ ‾ ‾ +// where +// r = ±√(a^2 + b^2) +// c = a/r, the cosine of the plane rotation +// s = b/r, the sine of the plane rotation +// +// NOTE: There is a discrepancy between the refence implementation and the BLAS +// technical manual regarding the sign for r when a or b are zero. +// Srotg agrees with the definition in the manual and other +// common BLAS implementations. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotg(a, b float32) (c, s, r, z float32) { + if b == 0 && a == 0 { + return 1, 0, a, 0 + } + absA := math.Abs(a) + absB := math.Abs(b) + aGTb := absA > absB + r = math.Hypot(a, b) + if aGTb { + r = math.Copysign(r, a) + } else { + r = math.Copysign(r, b) + } + c = a / r + s = b / r + if aGTb { + z = s + } else if c != 0 { // r == 0 case handled above + z = 1 / c + } else { + z = 1 + } + return +} + +// Srotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotmg(d1, d2, x1, y1 float32) (p blas.SrotmParams, rd1, rd2, rx1 float32) { + var p1, p2, q1, q2, u float32 + + const ( + gam = 4096.0 + gamsq = 16777216.0 + rgamsq = 5.9604645e-8 + ) + + if d1 < 0 { + p.Flag = blas.Rescaling + return + } + + p2 = d2 * y1 + if p2 == 0 { + p.Flag = blas.Identity + rd1 = d1 + rd2 = d2 + rx1 = x1 + return + } + p1 = d1 * x1 + q2 = p2 * y1 + q1 = p1 * x1 + + absQ1 := math.Abs(q1) + absQ2 := math.Abs(q2) + + if absQ1 < absQ2 && q2 < 0 { + p.Flag = blas.Rescaling + return + } + + if d1 == 0 { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1, rd2 = d2/u, d1/u + rx1 = y1 / u + return + } + + // Now we know that d1 != 0, and d2 != 0. If d2 == 0, it would be caught + // when p2 == 0, and if d1 == 0, then it is caught above + + if absQ1 > absQ2 { + p.H[1] = -y1 / x1 + p.H[2] = p2 / p1 + u = 1 - p.H[2]*p.H[1] + rd1 = d1 + rd2 = d2 + rx1 = x1 + p.Flag = blas.OffDiagonal + // u must be greater than zero because |q1| > |q2|, so check from netlib + // is unnecessary + // This is left in for ease of comparison with complex routines + //if u > 0 { + rd1 /= u + rd2 /= u + rx1 *= u + //} + } else { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1 = d2 / u + rd2 = d1 / u + rx1 = y1 * u + } + + for rd1 <= rgamsq || rd1 >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if rd1 <= rgamsq { + rd1 *= gam * gam + rx1 /= gam + p.H[0] /= gam + p.H[2] /= gam + } else { + rd1 /= gam * gam + rx1 *= gam + p.H[0] *= gam + p.H[2] *= gam + } + } + + for math.Abs(rd2) <= rgamsq || math.Abs(rd2) >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if math.Abs(rd2) <= rgamsq { + rd2 *= gam * gam + p.H[1] /= gam + p.H[3] /= gam + } else { + rd2 /= gam * gam + p.H[1] *= gam + p.H[3] *= gam + } + } + return +} + +// Srot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srot(n int, x []float32, incX int, y []float32, incY int, c float32, s float32) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = c*vx+s*vy, c*vy-s*vx + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx + ix += incX + iy += incY + } +} + +// Srotm applies the modified Givens rotation to the 2×n matrix. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, p blas.SrotmParams) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + + var h11, h12, h21, h22 float32 + var ix, iy int + switch p.Flag { + case blas.Identity: + return + case blas.Rescaling: + h11 = p.H[0] + h12 = p.H[2] + h21 = p.H[1] + h22 = p.H[3] + case blas.OffDiagonal: + h11 = 1 + h12 = p.H[2] + h21 = p.H[1] + h22 = 1 + case blas.Diagonal: + h11 = p.H[0] + h12 = 1 + h21 = -1 + h22 = p.H[3] + } + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = vx*h11+vy*h12, vx*h21+vy*h22 + } + return + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = vx*h11+vy*h12, vx*h21+vy*h22 + ix += incX + iy += incY + } +} + +// Sscal scales x by alpha. +// x[i] *= alpha +// Sscal has no effect if incX < 0. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sscal(n int, alpha float32, x []float32, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + f32.ScalUnitary(alpha, x[:n]) + return + } + f32.ScalInc(alpha, x, uintptr(n), uintptr(incX)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go new file mode 100644 index 00000000..cfe6e75b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Dsdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f32.DdotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go new file mode 100644 index 00000000..cf930ecf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) float32 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f32.DotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f32.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go new file mode 100644 index 00000000..600c2f99 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sdsdot computes the dot product of the two vectors plus a constant +// alpha + \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return alpha + float32(f32.DdotUnitary(x[:n], y)) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return alpha + float32(f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go new file mode 100644 index 00000000..ca241752 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go @@ -0,0 +1,289 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math/cmplx" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/c128" +) + +// Zgerc performs the rank-one operation +// A += alpha * x * y^H +// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, +// and y is an n element vector. +func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + checkZMatrix('A', m, n, a, lda) + checkZVector('x', m, x, incX) + checkZVector('y', n, y, incY) + + if m == 0 || n == 0 || alpha == 0 { + return + } + + var kx, jy int + if incX < 0 { + kx = (1 - m) * incX + } + if incY < 0 { + jy = (1 - n) * incY + } + for j := 0; j < n; j++ { + if y[jy] != 0 { + tmp := alpha * cmplx.Conj(y[jy]) + c128.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0) + } + jy += incY + } +} + +// Zgeru performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, +// and y is an n element vector. +func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + checkZMatrix('A', m, n, a, lda) + checkZVector('x', m, x, incX) + checkZVector('y', n, y, incY) + + if m == 0 || n == 0 || alpha == 0 { + return + } + + var kx int + if incX < 0 { + kx = (1 - m) * incX + } + if incY == 1 { + for i := 0; i < m; i++ { + if x[kx] != 0 { + tmp := alpha * x[kx] + c128.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n]) + } + kx += incX + } + return + } + var jy int + if incY < 0 { + jy = (1 - n) * incY + } + for i := 0; i < m; i++ { + if x[kx] != 0 { + tmp := alpha * x[kx] + c128.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0) + } + kx += incX + } +} + +// Zher performs the Hermitian rank-one operation +// A += alpha * x * x^H +// where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n +// element vector. On entry, the imaginary parts of the diagonal elements of A +// are ignored and assumed to be zero, on return they will be set to zero. +func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + checkZMatrix('A', n, n, a, lda) + checkZVector('x', n, x, incX) + + if n == 0 || alpha == 0 { + return + } + + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 { + tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii+xtmp, 0) + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[j]) + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + + ix := kx + for i := 0; i < n; i++ { + if x[ix] != 0 { + tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii+xtmp, 0) + jx := ix + incX + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + } + return + } + + if incX == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 { + tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) + for j := 0; j < i; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[j]) + } + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii+xtmp, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + + ix := kx + for i := 0; i < n; i++ { + if x[ix] != 0 { + tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) + jx := kx + for j := 0; j < i; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii+xtmp, 0) + + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + } +} + +// Zher2 performs the Hermitian rank-two operation +// A += alpha*x*y^H + conj(alpha)*y*x^H +// where alpha is a scalar, x and y are n element vectors and A is an n×n +// Hermitian matrix. On entry, the imaginary parts of the diagonal elements are +// ignored and assumed to be zero. On return they will be set to zero. +func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + checkZMatrix('A', n, n, a, lda) + checkZVector('x', n, x, incX) + checkZVector('y', n, y, incY) + + if n == 0 || alpha == 0 { + return + } + + var kx, ky int + var ix, iy int + if incX != 1 || incY != 1 { + if incX < 0 { + kx = (1 - n) * incX + } + if incY < 0 { + ky = (1 - n) * incY + } + ix = kx + iy = ky + } + if uplo == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii, 0) + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii, 0) + jx := ix + incX + jy := iy + incY + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + iy += incY + } + return + } + + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + for j := 0; j < i; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + } + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + jx := kx + jy := ky + for j := 0; j < i; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + iy += incY + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_bench_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_bench_test.go new file mode 100644 index 00000000..915a1918 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_bench_test.go @@ -0,0 +1,49 @@ +// Copyright ©2017 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package gonum + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +var benchSinkZ []complex128 + +func BenchmarkZher(b *testing.B) { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, n := range []int{10, 100, 1000, 10000} { + for _, inc := range []int{1, 10, 1000} { + benchmarkZher(b, uplo, n, inc) + } + } + } +} + +func benchmarkZher(b *testing.B, uplo blas.Uplo, n, inc int) { + b.Run(fmt.Sprintf("Uplo%d-N%d-Inc%d", uplo, n, inc), func(b *testing.B) { + rnd := rand.New(rand.NewSource(1)) + alpha := rnd.NormFloat64() + x := make([]complex128, (n-1)*inc+1) + for i := range x { + x[i] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + } + a := make([]complex128, len(benchSinkZ)) + for i := range a { + a[i] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + } + benchSinkZ = make([]complex128, n*n) + copy(benchSinkZ, a) + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Zher(uplo, n, alpha, x, inc, benchSinkZ, n) + copy(benchSinkZ, a) + } + }) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_test.go new file mode 100644 index 00000000..0649675a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128_test.go @@ -0,0 +1,27 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestZgerc(t *testing.T) { + testblas.ZgercTest(t, impl) +} + +func TestZgeru(t *testing.T) { + testblas.ZgeruTest(t, impl) +} + +func TestZher(t *testing.T) { + testblas.ZherTest(t, impl) +} + +func TestZher2(t *testing.T) { + testblas.Zher2Test(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2double.go new file mode 100644 index 00000000..9b828c2e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2double.go @@ -0,0 +1,2234 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var _ blas.Float64Level2 = Implementation{} + +// Dgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // Form y := alpha * A * x + y + if tA == blas.NoTrans { + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + y[i] += alpha * f64.DotUnitary(a[lda*i:lda*i+n], x) + } + return + } + iy := ky + for i := 0; i < m; i++ { + y[iy] += alpha * f64.DotInc(x, a[lda*i:lda*i+n], uintptr(n), uintptr(incX), 1, uintptr(kx), 0) + iy += incY + } + return + } + // Cases where a is transposed. + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + tmp := alpha * x[i] + if tmp != 0 { + f64.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y) + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f64.AxpyInc(tmp, a[lda*i:lda*i+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) + } + ix += incX + } +} + +// Dger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + // Check inputs + if m < 0 { + panic("m < 0") + } + if n < 0 { + panic(negativeN) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + if incX > 0 { + kx = 0 + } else { + kx = -(m - 1) * incX + } + + if incX == 1 && incY == 1 { + x = x[:m] + y = y[:n] + for i, xv := range x { + tmp := alpha * xv + if tmp != 0 { + atmp := a[i*lda : i*lda+n] + f64.AxpyUnitaryTo(atmp, tmp, y, atmp) + } + } + return + } + + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f64.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(ky), 0) + } + ix += incX + } +} + +// Dgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kL < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(min(m, n+kL)-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // i and j are indices of the compacted banded matrix. + // off is the offset into the dense matrix (off + j = densej) + ld := min(m, n) + nCol := kU + 1 + kL + if tA == blas.NoTrans { + iy := ky + if incX == 1 { + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + xtmp := x[off : off+u-l] + var sum float64 + for j, v := range atmp { + sum += xtmp[j] * v + } + y[iy] += sum * alpha + iy += incY + } + return + } + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + jx := kx + var sum float64 + for _, v := range atmp { + sum += x[off*incX+jx] * v + jx += incX + } + y[iy] += sum * alpha + iy += incY + } + return + } + if incX == 1 { + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[i] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + } + return + } + ix := kx + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[ix] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + ix += incX + } +} + +// Dtrmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if n == 0 { + return + } + nonUnit := d != blas.Unit + if n == 1 { + if nonUnit { + x[0] *= a[0] + } + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[i] + } else { + tmp = x[i] + } + xtmp := x[i+1:] + x[i] = tmp + f64.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f64.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp += a[ilda+i] * x[i] + } else { + tmp = x[i] + } + x[i] = tmp + f64.DotUnitary(a[ilda:ilda+i], x) + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f64.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + ix -= incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[i] + f64.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) + if nonUnit { + x[i] *= a[ilda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[ix] + f64.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[i] + f64.AxpyUnitary(xi, a[ilda:ilda+i], x) + if nonUnit { + x[i] *= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[ix] + f64.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix += incX + } +} + +// Dtrsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + // Test the input parameters + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + // Quick return if possible + if n == 0 { + return + } + if n == 1 { + if d == blas.NonUnit { + x[0] /= a[0] + } + return + } + + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } + nonUnit := d == blas.NonUnit + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + var sum float64 + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := i + j + 1 + sum += x[jv] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + var sum float64 + jx := ix + incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + var sum float64 + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + sum += x[j] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + var sum float64 + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := j + i + 1 + x[jv] -= v * xi + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + (i+1)*incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + x[j] -= v * xi + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix -= incX + } +} + +// Dsymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // Check inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(negativeN) + } + if lda > 1 && lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Dscal(n, beta, y, incY) + } else { + Implementation{}.Dscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := x[i] * a[i*lda+i] + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jp := j + i + 1 + sum += x[jp] * v + y[jy] += xv * v + jy += incY + } + y[iy] += alpha * sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := x[ix] * a[i*lda+i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + jy := ky + xv := alpha * x[i] + atmp := a[i*lda : i*lda+i] + var sum float64 + for j, v := range atmp { + sum += x[j] * v + y[jy] += xv * v + jy += incY + } + sum += x[i] * a[i*lda+i] + sum *= alpha + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xv := alpha * x[ix] + atmp := a[i*lda : i*lda+i] + var sum float64 + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + sum += x[ix] * a[i*lda+i] + sum *= alpha + y[iy] += sum + ix += incX + iy += incY + } +} + +// Dtbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } else if incX != 1 { + kx = 0 + } + + nonunit := d != blas.Unit + + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float64 + atmp := a[i*lda:] + xtmp := x[i:] + for j := 1; j < u; j++ { + sum += xtmp[j] * atmp[j] + } + if nonunit { + sum += xtmp[0] * atmp[0] + } else { + sum += xtmp[0] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float64 + atmp := a[i*lda:] + jx := incX + for j := 1; j < u; j++ { + sum += x[ix+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[0] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float64 + for j := l; j < k; j++ { + sum += x[i-k+j] * atmp[j] + } + if nonunit { + sum += x[i] * atmp[k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float64 + jx := l * incX + for j := l; j < k; j++ { + sum += x[ix-k*incX+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[k] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float64 + for j := 1; j < u; j++ { + sum += x[i-j] * a[(i-j)*lda+j] + } + if nonunit { + sum += x[i] * a[i*lda] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float64 + jx := incX + for j := 1; j < u; j++ { + sum += x[ix-jx] * a[(i-j)*lda+j] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var sum float64 + for j := 0; j < u; j++ { + sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] + } + if nonunit { + sum += x[i] * a[i*lda+k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var ( + sum float64 + jx int + ) + for j := 0; j < u; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda+k] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } +} + +// Dtpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +func (Implementation) Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xi += v * xtmp[j] + } + x[i] = xi + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset += n - i + ix += incX + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset-i : offset] + for j, v := range atmp { + xi += v * x[j] + } + x[i] = xi + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset -= i + 1 + ix -= incX + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + jx := kx + (i+1)*incX + atmp := ap[offset+1 : offset+n-i] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + offset -= n - i + 1 + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + jx := kx + atmp := ap[offset-i : offset] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + ix += incX + offset += i + 2 + } +} + +// Dtbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } else { + kx = 0 + } + nonUnit := d == blas.NonUnit + // Form x = A^-1 x. + // Several cases below use subslices for speed improvement. + // The incX != 1 cases usually do not because incX may be negative. + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + atmp := a[i*lda+1:] + xtmp := x[i+1 : i+bands+1] + var sum float64 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + max := k + 1 + if i+max > n { + max = n - i + } + atmp := a[i*lda:] + var ( + jx int + sum float64 + ) + for j := 1; j < max; j++ { + jx += incX + sum += x[ix+jx] * atmp[j] + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[0] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + xtmp := x[i-bands : i] + var sum float64 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= atmp[bands] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * atmp[j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[bands] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var sum float64 + for j := 0; j < bands; j++ { + sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda] + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var sum float64 + xtmp := x[i+1 : i+1+bands] + for j, v := range xtmp { + sum += v * a[(i+j+1)*lda+k-j-1] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+k] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+k] + } + ix -= incX + } +} + +// Dsbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up indexes + lenX := n + lenY := n + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[i] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[i+j] * v + y[iy+jy] += tmp * v + jy += incY + } + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[ix] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jx := incX + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[ix+jx] * v + y[iy+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += sum + ix += incX + iy += incY + } + return + } + + // Casses where a has bands below the diagonal. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[i] + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[i-k+j] + y[iy-k*incY+jy] += tmp * v + jy += incY + } + y[iy] += tmp * atmp[k] + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[ix] + jx := l * incX + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[ix-k*incX+jx] + y[iy-k*incY+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += tmp * atmp[k] + ix += incX + iy += incY + } +} + +// Dsyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +func (Implementation) Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda+i : i*lda+n] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += v * tmp + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + jx := ix + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += x[jx] * tmp + jx += incX + } + } + ix += incX + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda:] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += tmp * v + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + atmp := a[i*lda:] + jx := kx + for j := 0; j < i+1; j++ { + atmp[j] += tmp * x[jx] + jx += incX + } + } + ix += incX + } +} + +// Dsyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } +} + +// Dtpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + offset = n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + var sum float64 + for j, v := range atmp { + sum += v * xtmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix -= incX + offset -= n - i + 1 + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i : offset] + var sum float64 + for j, v := range atmp { + sum += v * x[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := ap[offset-i : offset] + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix += incX + offset += i + 2 + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] -= v * xi + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] -= v * xi + } + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix -= incX + offset -= i + 1 + } +} + +// Dspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x []float64, incX int, beta float64, y []float64, incY int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Dscal(n, beta, y, incY) + } else { + Implementation{}.Dscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := a[offset] * x[i] + atmp := a[offset+1 : offset+n-i] + xtmp := x[i+1:] + jy := ky + (i+1)*incY + for j, v := range atmp { + sum += v * xtmp[j] + y[jy] += v * xv + jy += incY + } + y[iy] += alpha * sum + iy += incY + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := a[offset] * x[ix] + atmp := a[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + atmp := a[offset-i : offset] + jy := ky + var sum float64 + for j, v := range atmp { + sum += v * x[j] + y[jy] += v * xv + jy += incY + } + sum += a[offset] * x[i] + y[iy] += alpha * sum + iy += incY + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + atmp := a[offset-i : offset] + jx := kx + jy := ky + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + + sum += a[offset] * x[ix] + y[iy] += alpha * sum + ix += incX + iy += incY + offset += i + 2 + } +} + +// Dspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset:] + xv := alpha * x[i] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + i*incX + atmp := a[offset:] + xv := alpha * x[ix] + for j := 0; j < n-i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset-i:] + xv := alpha * x[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := a[offset-i:] + xv := alpha * x[ix] + for j := 0; j <= i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += i + 2 + } +} + +// Dspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func (Implementation) Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, ap []float64) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 { + return + } + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset:] + xi := x[i] + yi := y[i] + xtmp := x[i:n] + ytmp := y[i:n] + for j, v := range xtmp { + atmp[j] += alpha * (xi*ytmp[j] + v*yi) + } + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + atmp := ap[offset:] + xi := x[ix] + yi := y[iy] + for j := 0; j < n-i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i:] + xi := x[i] + yi := y[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += alpha * (xi*y[j] + v*yi) + } + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + atmp := ap[offset-i:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += i + 2 + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2double_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2double_test.go new file mode 100644 index 00000000..42ac4798 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2double_test.go @@ -0,0 +1,79 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemv(t *testing.T) { + testblas.DgemvTest(t, impl) +} + +func TestDger(t *testing.T) { + testblas.DgerTest(t, impl) +} + +func TestDtxmv(t *testing.T) { + testblas.DtxmvTest(t, impl) +} + +func TestDgbmv(t *testing.T) { + testblas.DgbmvTest(t, impl) +} + +func TestDtbsv(t *testing.T) { + testblas.DtbsvTest(t, impl) +} + +func TestDsbmv(t *testing.T) { + testblas.DsbmvTest(t, impl) +} + +func TestDtbmv(t *testing.T) { + testblas.DtbmvTest(t, impl) +} + +func TestDtrsv(t *testing.T) { + testblas.DtrsvTest(t, impl) +} + +func TestDtrmv(t *testing.T) { + testblas.DtrmvTest(t, impl) +} + +func TestDsymv(t *testing.T) { + testblas.DsymvTest(t, impl) +} + +func TestDsyr(t *testing.T) { + testblas.DsyrTest(t, impl) +} + +func TestDsyr2(t *testing.T) { + testblas.Dsyr2Test(t, impl) +} + +func TestDspr2(t *testing.T) { + testblas.Dspr2Test(t, impl) +} + +func TestDspr(t *testing.T) { + testblas.DsprTest(t, impl) +} + +func TestDspmv(t *testing.T) { + testblas.DspmvTest(t, impl) +} + +func TestDtpsv(t *testing.T) { + testblas.DtpsvTest(t, impl) +} + +func TestDtpmv(t *testing.T) { + testblas.DtpmvTest(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2single.go new file mode 100644 index 00000000..84ca967b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2single.go @@ -0,0 +1,2268 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level2 = Implementation{} + +// Sgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // Form y := alpha * A * x + y + if tA == blas.NoTrans { + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + y[i] += alpha * f32.DotUnitary(a[lda*i:lda*i+n], x) + } + return + } + iy := ky + for i := 0; i < m; i++ { + y[iy] += alpha * f32.DotInc(x, a[lda*i:lda*i+n], uintptr(n), uintptr(incX), 1, uintptr(kx), 0) + iy += incY + } + return + } + // Cases where a is transposed. + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + tmp := alpha * x[i] + if tmp != 0 { + f32.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y) + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f32.AxpyInc(tmp, a[lda*i:lda*i+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) + } + ix += incX + } +} + +// Sger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + // Check inputs + if m < 0 { + panic("m < 0") + } + if n < 0 { + panic(negativeN) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + if incX > 0 { + kx = 0 + } else { + kx = -(m - 1) * incX + } + + if incX == 1 && incY == 1 { + x = x[:m] + y = y[:n] + for i, xv := range x { + tmp := alpha * xv + if tmp != 0 { + atmp := a[i*lda : i*lda+n] + f32.AxpyUnitaryTo(atmp, tmp, y, atmp) + } + } + return + } + + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f32.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(ky), 0) + } + ix += incX + } +} + +// Sgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kL < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(min(m, n+kL)-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // i and j are indices of the compacted banded matrix. + // off is the offset into the dense matrix (off + j = densej) + ld := min(m, n) + nCol := kU + 1 + kL + if tA == blas.NoTrans { + iy := ky + if incX == 1 { + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + xtmp := x[off : off+u-l] + var sum float32 + for j, v := range atmp { + sum += xtmp[j] * v + } + y[iy] += sum * alpha + iy += incY + } + return + } + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + jx := kx + var sum float32 + for _, v := range atmp { + sum += x[off*incX+jx] * v + jx += incX + } + y[iy] += sum * alpha + iy += incY + } + return + } + if incX == 1 { + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[i] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + } + return + } + ix := kx + for i := 0; i < min(m, n+kL); i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[ix] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + ix += incX + } +} + +// Strmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if n == 0 { + return + } + nonUnit := d != blas.Unit + if n == 1 { + if nonUnit { + x[0] *= a[0] + } + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[i] + } else { + tmp = x[i] + } + xtmp := x[i+1:] + x[i] = tmp + f32.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f32.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp += a[ilda+i] * x[i] + } else { + tmp = x[i] + } + x[i] = tmp + f32.DotUnitary(a[ilda:ilda+i], x) + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f32.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + ix -= incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[i] + f32.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) + if nonUnit { + x[i] *= a[ilda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[ix] + f32.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[i] + f32.AxpyUnitary(xi, a[ilda:ilda+i], x) + if nonUnit { + x[i] *= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[ix] + f32.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix += incX + } +} + +// Strsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + // Test the input parameters + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + // Quick return if possible + if n == 0 { + return + } + if n == 1 { + if d == blas.NonUnit { + x[0] /= a[0] + } + return + } + + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } + nonUnit := d == blas.NonUnit + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + var sum float32 + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := i + j + 1 + sum += x[jv] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + var sum float32 + jx := ix + incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + var sum float32 + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + sum += x[j] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + var sum float32 + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := j + i + 1 + x[jv] -= v * xi + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + (i+1)*incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + x[j] -= v * xi + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix -= incX + } +} + +// Ssymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // Check inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(negativeN) + } + if lda > 1 && lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Sscal(n, beta, y, incY) + } else { + Implementation{}.Sscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := x[i] * a[i*lda+i] + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jp := j + i + 1 + sum += x[jp] * v + y[jy] += xv * v + jy += incY + } + y[iy] += alpha * sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := x[ix] * a[i*lda+i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + jy := ky + xv := alpha * x[i] + atmp := a[i*lda : i*lda+i] + var sum float32 + for j, v := range atmp { + sum += x[j] * v + y[jy] += xv * v + jy += incY + } + sum += x[i] * a[i*lda+i] + sum *= alpha + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xv := alpha * x[ix] + atmp := a[i*lda : i*lda+i] + var sum float32 + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + sum += x[ix] * a[i*lda+i] + sum *= alpha + y[iy] += sum + ix += incX + iy += incY + } +} + +// Stbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } else if incX != 1 { + kx = 0 + } + + nonunit := d != blas.Unit + + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float32 + atmp := a[i*lda:] + xtmp := x[i:] + for j := 1; j < u; j++ { + sum += xtmp[j] * atmp[j] + } + if nonunit { + sum += xtmp[0] * atmp[0] + } else { + sum += xtmp[0] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float32 + atmp := a[i*lda:] + jx := incX + for j := 1; j < u; j++ { + sum += x[ix+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[0] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float32 + for j := l; j < k; j++ { + sum += x[i-k+j] * atmp[j] + } + if nonunit { + sum += x[i] * atmp[k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float32 + jx := l * incX + for j := l; j < k; j++ { + sum += x[ix-k*incX+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[k] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float32 + for j := 1; j < u; j++ { + sum += x[i-j] * a[(i-j)*lda+j] + } + if nonunit { + sum += x[i] * a[i*lda] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float32 + jx := incX + for j := 1; j < u; j++ { + sum += x[ix-jx] * a[(i-j)*lda+j] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var sum float32 + for j := 0; j < u; j++ { + sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] + } + if nonunit { + sum += x[i] * a[i*lda+k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var ( + sum float32 + jx int + ) + for j := 0; j < u; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda+k] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } +} + +// Stpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xi += v * xtmp[j] + } + x[i] = xi + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset += n - i + ix += incX + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset-i : offset] + for j, v := range atmp { + xi += v * x[j] + } + x[i] = xi + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset -= i + 1 + ix -= incX + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + jx := kx + (i+1)*incX + atmp := ap[offset+1 : offset+n-i] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + offset -= n - i + 1 + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + jx := kx + atmp := ap[offset-i : offset] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + ix += incX + offset += i + 2 + } +} + +// Stbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } else { + kx = 0 + } + nonUnit := d == blas.NonUnit + // Form x = A^-1 x. + // Several cases below use subslices for speed improvement. + // The incX != 1 cases usually do not because incX may be negative. + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + atmp := a[i*lda+1:] + xtmp := x[i+1 : i+bands+1] + var sum float32 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + max := k + 1 + if i+max > n { + max = n - i + } + atmp := a[i*lda:] + var ( + jx int + sum float32 + ) + for j := 1; j < max; j++ { + jx += incX + sum += x[ix+jx] * atmp[j] + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[0] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + xtmp := x[i-bands : i] + var sum float32 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= atmp[bands] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * atmp[j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[bands] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var sum float32 + for j := 0; j < bands; j++ { + sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda] + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var sum float32 + xtmp := x[i+1 : i+1+bands] + for j, v := range xtmp { + sum += v * a[(i+j+1)*lda+k-j-1] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+k] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+k] + } + ix -= incX + } +} + +// Ssbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up indexes + lenX := n + lenY := n + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[i] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[i+j] * v + y[iy+jy] += tmp * v + jy += incY + } + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[ix] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jx := incX + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[ix+jx] * v + y[iy+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += sum + ix += incX + iy += incY + } + return + } + + // Casses where a has bands below the diagonal. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[i] + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[i-k+j] + y[iy-k*incY+jy] += tmp * v + jy += incY + } + y[iy] += tmp * atmp[k] + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[ix] + jx := l * incX + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[ix-k*incX+jx] + y[iy-k*incY+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += tmp * atmp[k] + ix += incX + iy += incY + } +} + +// Ssyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda+i : i*lda+n] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += v * tmp + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + jx := ix + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += x[jx] * tmp + jx += incX + } + } + ix += incX + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda:] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += tmp * v + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + atmp := a[i*lda:] + jx := kx + for j := 0; j < i+1; j++ { + atmp[j] += tmp * x[jx] + jx += incX + } + } + ix += incX + } +} + +// Ssyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } +} + +// Stpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + offset = n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + var sum float32 + for j, v := range atmp { + sum += v * xtmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix -= incX + offset -= n - i + 1 + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i : offset] + var sum float32 + for j, v := range atmp { + sum += v * x[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := ap[offset-i : offset] + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix += incX + offset += i + 2 + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] -= v * xi + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] -= v * xi + } + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix -= incX + offset -= i + 1 + } +} + +// Sspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x []float32, incX int, beta float32, y []float32, incY int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Sscal(n, beta, y, incY) + } else { + Implementation{}.Sscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := a[offset] * x[i] + atmp := a[offset+1 : offset+n-i] + xtmp := x[i+1:] + jy := ky + (i+1)*incY + for j, v := range atmp { + sum += v * xtmp[j] + y[jy] += v * xv + jy += incY + } + y[iy] += alpha * sum + iy += incY + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := a[offset] * x[ix] + atmp := a[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + atmp := a[offset-i : offset] + jy := ky + var sum float32 + for j, v := range atmp { + sum += v * x[j] + y[jy] += v * xv + jy += incY + } + sum += a[offset] * x[i] + y[iy] += alpha * sum + iy += incY + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + atmp := a[offset-i : offset] + jx := kx + jy := ky + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + + sum += a[offset] * x[ix] + y[iy] += alpha * sum + ix += incX + iy += incY + offset += i + 2 + } +} + +// Sspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset:] + xv := alpha * x[i] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + i*incX + atmp := a[offset:] + xv := alpha * x[ix] + for j := 0; j < n-i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset-i:] + xv := alpha * x[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := a[offset-i:] + xv := alpha * x[ix] + for j := 0; j <= i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += i + 2 + } +} + +// Sspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, ap []float32) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 { + return + } + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset:] + xi := x[i] + yi := y[i] + xtmp := x[i:n] + ytmp := y[i:n] + for j, v := range xtmp { + atmp[j] += alpha * (xi*ytmp[j] + v*yi) + } + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + atmp := ap[offset:] + xi := x[ix] + yi := y[iy] + for j := 0; j < n-i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i:] + xi := x[i] + yi := y[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += alpha * (xi*y[j] + v*yi) + } + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + atmp := ap[offset-i:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += i + 2 + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3double.go new file mode 100644 index 00000000..b5001dcb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3double.go @@ -0,0 +1,831 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var _ blas.Float64Level3 = Implementation{} + +// Dtrsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if ldb < n { + panic(badLdB) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + + if m == 0 || n == 0 { + return + } + + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := m - 1; i >= 0; i-- { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := range btmp { + btmp[j] *= alpha + } + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + if va != 0 { + f64.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, va := range a[i*lda : i*lda+i] { + if va != 0 { + f64.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + // Cases where a is transposed + if ul == blas.Upper { + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f64.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for i, va := range a[k*lda : k*lda+k] { + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f64.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + // Cases where a is to the right of X. + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, vb := range btmp { + if vb != 0 { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + btmpk := btmp[k+1 : n] + f64.AxpyUnitaryTo(btmpk, -btmp[k], a[k*lda+k+1:k*lda+n], btmpk) + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k := n - 1; k >= 0; k-- { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f64.AxpyUnitaryTo(btmp, -btmp[k], a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := n - 1; j >= 0; j-- { + tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := 0; j < n; j++ { + tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda:j*lda+j], btmp) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } +} + +// Dsymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if s != blas.Right && s != blas.Left { + panic("goblas: bad side") + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if m == 0 || n == 0 { + return + } + if alpha == 0 && beta == 1 { + return + } + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] *= beta + } + } + return + } + + isUpper := ul == blas.Upper + if s == blas.Left { + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + btmp := b[i*ldb : i*ldb+n] + ctmp := c[i*ldc : i*ldc+n] + for j, v := range btmp { + ctmp[j] *= beta + ctmp[j] += atmp * v + } + + for k := 0; k < i; k++ { + var atmp float64 + if isUpper { + atmp = a[k*lda+i] + } else { + atmp = a[i*lda+k] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + for k := i + 1; k < m; k++ { + var atmp float64 + if isUpper { + atmp = a[i*lda+k] + } else { + atmp = a[k*lda+i] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + } + return + } + if isUpper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + tmp := alpha * b[i*ldb+j] + var tmp2 float64 + atmp := a[j*lda+j+1 : j*lda+n] + btmp := b[i*ldb+j+1 : i*ldb+n] + ctmp := c[i*ldc+j+1 : i*ldc+n] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } + return + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + tmp := alpha * b[i*ldb+j] + var tmp2 float64 + atmp := a[j*lda : j*lda+j] + btmp := b[i*ldb : i*ldb+j] + ctmp := c[i*ldc : i*ldc+j] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } +} + +// Dsyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + atmp := a[i*lda : i*lda+k] + for jc, vc := range ctmp { + j := jc + i + ctmp[jc] = vc*beta + alpha*f64.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + for j, vc := range c[i*ldc : i*ldc+i+1] { + c[i*ldc+j] = vc*beta + alpha*f64.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, a[l*lda+i:l*lda+n], ctmp) + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 0 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, a[l*lda:l*lda+i+1], ctmp) + } + } + } +} + +// Dsyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic(badLdB) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc+i : i*ldc+n] + for jc := range ctmp { + j := i + jc + var tmp1, tmp2 float64 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[jc] *= beta + ctmp[jc] += alpha * (tmp1 + tmp2) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc : i*ldc+i+1] + for j := 0; j <= i; j++ { + var tmp1, tmp2 float64 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[j] *= beta + ctmp[j] += alpha * (tmp1 + tmp2) + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb+i : l*ldb+n] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda+i : l*lda+n] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb : l*ldb+i+1] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda : l*lda+i+1] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } +} + +// Dtrmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + for i := m - 1; i >= 0; i-- { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for k, va := range a[i*lda : i*lda+i] { + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + for i, va := range a[k*lda : k*lda+k] { + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + // Cases where a is on the right + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + for ja, v := range a[k*lda+k+1 : k*lda+n] { + j := ja + k + 1 + btmp[j] += tmp * v + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f64.AxpyUnitaryTo(btmp, tmp, a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j, vb := range btmp { + tmp := vb + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) + btmp[j] = alpha * tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + tmp := btmp[j] + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f64.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) + btmp[j] = alpha * tmp + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3double_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3double_test.go new file mode 100644 index 00000000..70459803 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3double_test.go @@ -0,0 +1,35 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemm(t *testing.T) { + testblas.TestDgemm(t, impl) +} + +func TestDsymm(t *testing.T) { + testblas.DsymmTest(t, impl) +} + +func TestDtrsm(t *testing.T) { + testblas.DtrsmTest(t, impl) +} + +func TestDsyrk(t *testing.T) { + testblas.DsyrkTest(t, impl) +} + +func TestDsyr2k(t *testing.T) { + testblas.Dsyr2kTest(t, impl) +} + +func TestDtrmm(t *testing.T) { + testblas.DtrmmTest(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3single.go new file mode 100644 index 00000000..ba158498 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3single.go @@ -0,0 +1,843 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level3 = Implementation{} + +// Strsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if ldb < n { + panic(badLdB) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + + if m == 0 || n == 0 { + return + } + + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := m - 1; i >= 0; i-- { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := range btmp { + btmp[j] *= alpha + } + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + if va != 0 { + f32.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, va := range a[i*lda : i*lda+i] { + if va != 0 { + f32.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + // Cases where a is transposed + if ul == blas.Upper { + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f32.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for i, va := range a[k*lda : k*lda+k] { + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f32.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + // Cases where a is to the right of X. + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, vb := range btmp { + if vb != 0 { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + btmpk := btmp[k+1 : n] + f32.AxpyUnitaryTo(btmpk, -btmp[k], a[k*lda+k+1:k*lda+n], btmpk) + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k := n - 1; k >= 0; k-- { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f32.AxpyUnitaryTo(btmp, -btmp[k], a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := n - 1; j >= 0; j-- { + tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := 0; j < n; j++ { + tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda:j*lda+j], btmp) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } +} + +// Ssymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if s != blas.Right && s != blas.Left { + panic("goblas: bad side") + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if m == 0 || n == 0 { + return + } + if alpha == 0 && beta == 1 { + return + } + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] *= beta + } + } + return + } + + isUpper := ul == blas.Upper + if s == blas.Left { + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + btmp := b[i*ldb : i*ldb+n] + ctmp := c[i*ldc : i*ldc+n] + for j, v := range btmp { + ctmp[j] *= beta + ctmp[j] += atmp * v + } + + for k := 0; k < i; k++ { + var atmp float32 + if isUpper { + atmp = a[k*lda+i] + } else { + atmp = a[i*lda+k] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + for k := i + 1; k < m; k++ { + var atmp float32 + if isUpper { + atmp = a[i*lda+k] + } else { + atmp = a[k*lda+i] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + } + return + } + if isUpper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + tmp := alpha * b[i*ldb+j] + var tmp2 float32 + atmp := a[j*lda+j+1 : j*lda+n] + btmp := b[i*ldb+j+1 : i*ldb+n] + ctmp := c[i*ldc+j+1 : i*ldc+n] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } + return + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + tmp := alpha * b[i*ldb+j] + var tmp2 float32 + atmp := a[j*lda : j*lda+j] + btmp := b[i*ldb : i*ldb+j] + ctmp := c[i*ldc : i*ldc+j] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } +} + +// Ssyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + atmp := a[i*lda : i*lda+k] + for jc, vc := range ctmp { + j := jc + i + ctmp[jc] = vc*beta + alpha*f32.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + for j, vc := range c[i*ldc : i*ldc+i+1] { + c[i*ldc+j] = vc*beta + alpha*f32.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, a[l*lda+i:l*lda+n], ctmp) + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 0 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, a[l*lda:l*lda+i+1], ctmp) + } + } + } +} + +// Ssyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic(badLdB) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc+i : i*ldc+n] + for jc := range ctmp { + j := i + jc + var tmp1, tmp2 float32 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[jc] *= beta + ctmp[jc] += alpha * (tmp1 + tmp2) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc : i*ldc+i+1] + for j := 0; j <= i; j++ { + var tmp1, tmp2 float32 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[j] *= beta + ctmp[j] += alpha * (tmp1 + tmp2) + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb+i : l*ldb+n] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda+i : l*lda+n] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb : l*ldb+i+1] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda : l*lda+i+1] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } +} + +// Strmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + for i := m - 1; i >= 0; i-- { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for k, va := range a[i*lda : i*lda+i] { + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + for i, va := range a[k*lda : k*lda+k] { + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + // Cases where a is on the right + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + for ja, v := range a[k*lda+k+1 : k*lda+n] { + j := ja + k + 1 + btmp[j] += tmp * v + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f32.AxpyUnitaryTo(btmp, tmp, a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j, vb := range btmp { + tmp := vb + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) + btmp[j] = alpha * tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + tmp := btmp[j] + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f32.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) + btmp[j] = alpha * tmp + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/pardgemm_test.go b/vendor/gonum.org/v1/gonum/blas/gonum/pardgemm_test.go new file mode 100644 index 00000000..b88cd606 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/pardgemm_test.go @@ -0,0 +1,181 @@ +// Copyright ©2014 The gonum 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 gonum + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func TestDgemmParallel(t *testing.T) { + for i, test := range []struct { + m int + n int + k int + alpha float64 + tA blas.Transpose + tB blas.Transpose + }{ + { + m: 3, + n: 4, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize*2 + 5, + n: 3, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize * 2, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 2, + n: 3, + k: blockSize*3 - 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: 3, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize * minParBlock, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 2, + n: 3, + k: blockSize * minParBlock, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize*minParBlock + 1, + n: blockSize * minParBlock, + k: 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize*minParBlock + 2, + k: blockSize * 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: 3, + k: blockSize * minParBlock, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: blockSize * minParBlock, + k: blockSize * 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize + blockSize/2, + n: blockSize + blockSize/2, + k: blockSize + blockSize/2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + } { + testMatchParallelSerial(t, i, blas.NoTrans, blas.NoTrans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.Trans, blas.NoTrans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.NoTrans, blas.Trans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.Trans, blas.Trans, test.m, test.n, test.k, test.alpha) + } +} + +func testMatchParallelSerial(t *testing.T, i int, tA, tB blas.Transpose, m, n, k int, alpha float64) { + var ( + rowA, colA int + rowB, colB int + ) + if tA == blas.NoTrans { + rowA = m + colA = k + } else { + rowA = k + colA = m + } + if tB == blas.NoTrans { + rowB = k + colB = n + } else { + rowB = n + colB = k + } + a := randmat(rowA, colA, colA) + b := randmat(rowB, colB, colB) + c := randmat(m, n, n) + + aClone := a.clone() + bClone := b.clone() + cClone := c.clone() + + lda := colA + ldb := colB + ldc := n + dgemmSerial(tA == blas.Trans, tB == blas.Trans, m, n, k, a.data, lda, b.data, ldb, cClone.data, ldc, alpha) + dgemmParallel(tA == blas.Trans, tB == blas.Trans, m, n, k, a.data, lda, b.data, ldb, c.data, ldc, alpha) + if !a.equal(aClone) { + t.Errorf("Case %v: a changed during call to dgemmParallel", i) + } + if !b.equal(bClone) { + t.Errorf("Case %v: b changed during call to dgemmParallel", i) + } + if !c.equalWithinAbs(cClone, 1e-12) { + t.Errorf("Case %v: answer not equal parallel and serial", i) + } +} + +func randmat(r, c, stride int) general64 { + data := make([]float64, r*stride+c) + for i := range data { + data[i] = rand.Float64() + } + return general64{ + data: data, + rows: r, + cols: c, + stride: stride, + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go new file mode 100644 index 00000000..06dd39bd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go @@ -0,0 +1,265 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 gonum + +import ( + "runtime" + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgemm(tA, tB blas.Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic(badTranspose) + } + aTrans := tA == blas.Trans || tA == blas.ConjTrans + if aTrans { + checkSMatrix('a', k, m, a, lda) + } else { + checkSMatrix('a', m, k, a, lda) + } + bTrans := tB == blas.Trans || tB == blas.ConjTrans + if bTrans { + checkSMatrix('b', n, k, b, ldb) + } else { + checkSMatrix('b', k, n, b, ldb) + } + checkSMatrix('c', m, n, c, ldc) + + // scale c + if beta != 1 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + } + } + + sgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) +} + +func sgemmParallel(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // dgemmParallel computes a parallel matrix multiplication by partitioning + // a and b into sub-blocks, and updating c with the multiplication of the sub-block + // In all cases, + // A = [ A_11 A_12 ... A_1j + // A_21 A_22 ... A_2j + // ... + // A_i1 A_i2 ... A_ij] + // + // and same for B. All of the submatrix sizes are blockSize×blockSize except + // at the edges. + // + // In all cases, there is one dimension for each matrix along which + // C must be updated sequentially. + // Cij = \sum_k Aik Bki, (A * B) + // Cij = \sum_k Aki Bkj, (A^T * B) + // Cij = \sum_k Aik Bjk, (A * B^T) + // Cij = \sum_k Aki Bjk, (A^T * B^T) + // + // This code computes one {i, j} block sequentially along the k dimension, + // and computes all of the {i, j} blocks concurrently. This + // partitioning allows Cij to be updated in-place without race-conditions. + // Instead of launching a goroutine for each possible concurrent computation, + // a number of worker goroutines are created and channels are used to pass + // available and completed cases. + // + // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix + // multiplies, though this code does not copy matrices to attempt to eliminate + // cache misses. + + maxKLen := k + parBlocks := blocks(m, blockSize) * blocks(n, blockSize) + if parBlocks < minParBlock { + // The matrix multiplication is small in the dimensions where it can be + // computed concurrently. Just do it in serial. + sgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + } + + nWorkers := runtime.GOMAXPROCS(0) + if parBlocks < nWorkers { + nWorkers = parBlocks + } + // There is a tradeoff between the workers having to wait for work + // and a large buffer making operations slow. + buf := buffMul * nWorkers + if buf > parBlocks { + buf = parBlocks + } + + sendChan := make(chan subMul, buf) + + // Launch workers. A worker receives an {i, j} submatrix of c, and computes + // A_ik B_ki (or the transposed version) storing the result in c_ij. When the + // channel is finally closed, it signals to the waitgroup that it has finished + // computing. + var wg sync.WaitGroup + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // Make local copies of otherwise global variables to reduce shared memory. + // This has a noticeable effect on benchmarks in some cases. + alpha := alpha + aTrans := aTrans + bTrans := bTrans + m := m + n := n + for sub := range sendChan { + i := sub.i + j := sub.j + leni := blockSize + if i+leni > m { + leni = m - i + } + lenj := blockSize + if j+lenj > n { + lenj = n - j + } + + cSub := sliceView32(c, ldc, i, j, leni, lenj) + + // Compute A_ik B_kj for all k + for k := 0; k < maxKLen; k += blockSize { + lenk := blockSize + if k+lenk > maxKLen { + lenk = maxKLen - k + } + var aSub, bSub []float32 + if aTrans { + aSub = sliceView32(a, lda, k, i, lenk, leni) + } else { + aSub = sliceView32(a, lda, i, k, leni, lenk) + } + if bTrans { + bSub = sliceView32(b, ldb, j, k, lenj, lenk) + } else { + bSub = sliceView32(b, ldb, k, j, lenk, lenj) + } + sgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) + } + } + }() + } + + // Send out all of the {i, j} subblocks for computation. + for i := 0; i < m; i += blockSize { + for j := 0; j < n; j += blockSize { + sendChan <- subMul{ + i: i, + j: j, + } + } + } + close(sendChan) + wg.Wait() +} + +// sgemmSerial is serial matrix multiply +func sgemmSerial(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + switch { + case !aTrans && !bTrans: + sgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && !bTrans: + sgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case !aTrans && bTrans: + sgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && bTrans: + sgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + default: + panic("unreachable") + } +} + +// sgemmSerial where neither a nor b are transposed +func sgemmSerialNotNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for l, v := range a[i*lda : i*lda+k] { + tmp := alpha * v + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, b[l*ldb:l*ldb+n], ctmp) + } + } + } +} + +// sgemmSerial where neither a is transposed and b is not +func sgemmSerialTransNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + btmp := b[l*ldb : l*ldb+n] + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + } + } + } +} + +// sgemmSerial where neither a is not transposed and b is +func sgemmSerialNotTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + atmp := a[i*lda : i*lda+k] + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] += alpha * f32.DotUnitary(atmp, b[j*ldb:j*ldb+k]) + } + } +} + +// sgemmSerial where both are transposed +func sgemmSerialTransTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) + } + } + } +} + +func sliceView32(a []float32, lda, i, j, r, c int) []float32 { + return a[i*lda+j : (i+r-1)*lda+j+c] +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash b/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash new file mode 100755 index 00000000..5213f0f2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash @@ -0,0 +1,158 @@ +#!/usr/bin/env bash + +# Copyright ©2015 The gonum Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +WARNING='//\ +// Float32 implementations are autogenerated and not directly tested.\ +' + +# Level1 routines. + +echo Generating level1single.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single.go +cat level1double.go \ +| gofmt -r 'blas.Float64Level1 -> blas.Float32Level1' \ +\ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'blas.DrotmParams -> blas.SrotmParams' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +| gofmt -r 'f64.ScalInc -> f32.ScalInc' \ +| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e "s_^\(func (Implementation) \)Id\(.*\)\$_$WARNING\1Is\2_" \ + -e 's_^// Id_// Is_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ +>> level1single.go + +echo Generating level1single_sdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_sdot.go +cat level1double_ddot.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.DotInc -> f32.DotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> level1single_sdot.go + +echo Generating level1single_dsdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_dsdot.go +cat level1double_ddot.go \ +| gofmt -r '[]float64 -> []float32' \ +\ +| gofmt -r 'f64.DotInc -> f32.DdotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DdotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1Ds\2_" \ + -e 's_^// D_// Ds_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> level1single_dsdot.go + +echo Generating level1single_sdsdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_sdsdot.go +cat level1double_ddot.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.DotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)) -> alpha + float32(f32.DdotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)))' \ +| gofmt -r 'f64.DotUnitary(a, b) -> alpha + float32(f32.DdotUnitary(a, b))' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1Sds\2_" \ + -e 's_^// D\(.*\)$_// Sds\1 plus a constant_' \ + -e 's_\\sum_alpha + \\sum_' \ + -e 's/n int/n int, alpha float32/' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> level1single_sdsdot.go + + +# Level2 routines. + +echo Generating level2single.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2single.go +cat level2double.go \ +| gofmt -r 'blas.Float64Level2 -> blas.Float32Level2' \ +\ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'Dscal -> Sscal' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotInc -> f32.DotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> level2single.go + + +# Level3 routines. + +echo Generating level3single.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3single.go +cat level3double.go \ +| gofmt -r 'blas.Float64Level3 -> blas.Float32Level3' \ +\ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> level3single.go + +echo Generating general_single.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > general_single.go +cat general_double.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'general64 -> general32' \ +| gofmt -r 'newGeneral64 -> newGeneral32' \ +\ +| sed -e 's/(g general64) print()/(g general32) print()/' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> general_single.go + +echo Generating sgemm.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > sgemm.go +cat dgemm.go \ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'general64 -> general32' \ +| gofmt -r 'sliceView64 -> sliceView32' \ +| gofmt -r 'checkDMatrix -> checkSMatrix' \ +\ +| gofmt -r 'dgemmParallel -> sgemmParallel' \ +| gofmt -r 'computeNumBlocks64 -> computeNumBlocks32' \ +| gofmt -r 'dgemmSerial -> sgemmSerial' \ +| gofmt -r 'dgemmSerialNotNot -> sgemmSerialNotNot' \ +| gofmt -r 'dgemmSerialTransNot -> sgemmSerialTransNot' \ +| gofmt -r 'dgemmSerialNotTrans -> sgemmSerialNotTrans' \ +| gofmt -r 'dgemmSerialTransTrans -> sgemmSerialTransTrans' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_^// d_// s_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ +>> sgemm.go diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go b/vendor/gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go new file mode 100644 index 00000000..35e08c1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go @@ -0,0 +1,292 @@ +// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +// Script for automatic code generation of the benchmark routines. +package main + +import ( + "fmt" + "os" + "os/exec" + "path" + "path/filepath" + "strconv" +) + +var gopath string + +var copyrightnotice = []byte(`// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file`) + +var autogen = []byte("// Code generated by \"go run gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go\"; DO NOT EDIT.\n") + +var imports = []byte(`import( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +)`) + +var randomSliceFunction = []byte(`func randomSlice(l, idx int) ([]float64) { + if idx < 0{ + idx = -idx + } + s := make([]float64, l * idx) + for i := range s { + s[i] = rand.Float64() + } + return s +}`) + +const ( + posInc1 = 5 + posInc2 = 3 + negInc1 = -3 + negInc2 = -4 +) + +var level1Sizes = []struct { + lower string + upper string + camel string + size int +}{ + { + lower: "small", + upper: "SMALL_SLICE", + camel: "Small", + size: 10, + }, + { + lower: "medium", + upper: "MEDIUM_SLICE", + camel: "Medium", + size: 1000, + }, + { + lower: "large", + upper: "LARGE_SLICE", + camel: "Large", + size: 100000, + }, + { + lower: "huge", + upper: "HUGE_SLICE", + camel: "Huge", + size: 10000000, + }, +} + +type level1functionStruct struct { + camel string + sig string + call string + extraSetup string + oneInput bool + extraName string // if have a couple different cases for the same function +} + +var level1Functions = []level1functionStruct{ + { + camel: "Ddot", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Dnrm2", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Dasum", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Idamax", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Dswap", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Dcopy", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Daxpy", + sig: "n int, alpha float64, x []float64, incX int, y []float64, incY int", + call: "n, alpha, x, incX, y, incY", + extraSetup: "alpha := 2.4", + oneInput: false, + }, + { + camel: "Drot", + sig: "n int, x []float64, incX int, y []float64, incY int, c, s float64", + call: "n, x, incX, y, incY, c, s", + extraSetup: "c := 0.89725836967\ns:= 0.44150585279", + oneInput: false, + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375,0}}", + oneInput: false, + extraName: "OffDia", + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}}", + oneInput: false, + extraName: "Dia", + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}}", + oneInput: false, + extraName: "Resc", + }, + { + camel: "Dscal", + sig: "n int, alpha float64, x []float64, incX int", + call: "n, alpha, x, incX", + extraSetup: "alpha := 2.4", + oneInput: true, + }, +} + +func init() { + gopath = os.Getenv("GOPATH") + if gopath == "" { + panic("gopath not set") + } +} + +func main() { + blasPath := filepath.Join(gopath, "src", "gonum.org", "v1", "gonum", "blas") + + pkgs := []struct{ name string }{{name: "native"}, {name: "cgo"}} + + for _, pkg := range pkgs { + err := level1(filepath.Join(blasPath, pkg.name), pkg.name) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + err = exec.Command("go", "fmt", path.Join("gonum.org", "v1", "gonum", "blas", pkg.name)).Run() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } +} + +func printHeader(f *os.File, name string) error { + if _, err := f.Write(autogen); err != nil { + return err + } + f.WriteString("\n\n") + f.Write(copyrightnotice) + f.WriteString("\n\n") + f.WriteString("package " + name) + f.WriteString("\n\n") + f.Write(imports) + f.WriteString("\n\n") + return nil +} + +// Generate the benchmark scripts for level1 +func level1(benchPath string, pkgname string) error { + // Generate level 1 benchmarks + level1Filepath := filepath.Join(benchPath, "level1doubleBench_auto_test.go") + f, err := os.Create(level1Filepath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer f.Close() + printHeader(f, pkgname) + + // Print all of the constants + f.WriteString("const (\n") + f.WriteString("\tposInc1 = " + strconv.Itoa(posInc1) + "\n") + f.WriteString("\tposInc2 = " + strconv.Itoa(posInc2) + "\n") + f.WriteString("\tnegInc1 = " + strconv.Itoa(negInc1) + "\n") + f.WriteString("\tnegInc2 = " + strconv.Itoa(negInc2) + "\n") + for _, con := range level1Sizes { + f.WriteString("\t" + con.upper + " = " + strconv.Itoa(con.size) + "\n") + } + f.WriteString(")\n") + f.WriteString("\n") + + // Write the randomSlice function + f.Write(randomSliceFunction) + f.WriteString("\n\n") + + // Start writing the benchmarks + for _, fun := range level1Functions { + writeLevel1Benchmark(fun, f) + f.WriteString("\n/* ------------------ */ \n") + } + + return nil +} + +func writeLevel1Benchmark(fun level1functionStruct, f *os.File) { + // First, write the base benchmark file + f.WriteString("func benchmark" + fun.camel + fun.extraName + "(b *testing.B, ") + f.WriteString(fun.sig) + f.WriteString(") {\n") + + f.WriteString("b.ResetTimer()\n") + f.WriteString("for i := 0; i < b.N; i++{\n") + f.WriteString("\timpl." + fun.camel + "(") + + f.WriteString(fun.call) + f.WriteString(")\n}\n}\n") + f.WriteString("\n") + + // Write all of the benchmarks to call it + for _, sz := range level1Sizes { + lambda := func(incX, incY, name string, twoInput bool) { + f.WriteString("func Benchmark" + fun.camel + fun.extraName + sz.camel + name + "(b *testing.B){\n") + f.WriteString("n := " + sz.upper + "\n") + f.WriteString("incX := " + incX + "\n") + f.WriteString("x := randomSlice(n, incX)\n") + if twoInput { + f.WriteString("incY := " + incY + "\n") + f.WriteString("y := randomSlice(n, incY)\n") + } + f.WriteString(fun.extraSetup + "\n") + f.WriteString("benchmark" + fun.camel + fun.extraName + "(b, " + fun.call + ")\n") + f.WriteString("}\n\n") + } + if fun.oneInput { + lambda("1", "", "UnitaryInc", false) + lambda("posInc1", "", "PosInc", false) + } else { + lambda("1", "1", "BothUnitary", true) + lambda("posInc1", "1", "IncUni", true) + lambda("1", "negInc1", "UniInc", true) + lambda("posInc1", "negInc1", "BothInc", true) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/benchsize.go b/vendor/gonum.org/v1/gonum/blas/testblas/benchsize.go new file mode 100644 index 00000000..41d132be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/benchsize.go @@ -0,0 +1,8 @@ +package testblas + +const ( + SmallMat = 10 + MediumMat = 100 + LargeMat = 1000 + HugeMat = 10000 +) diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/common.go b/vendor/gonum.org/v1/gonum/blas/testblas/common.go new file mode 100644 index 00000000..68a4c05a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/common.go @@ -0,0 +1,316 @@ +// Copyright ©2014 The gonum 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 testblas + +import ( + "math" + "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +// throwPanic will throw unexpected panics if true, or will just report them as errors if false +const throwPanic = true + +func dTolEqual(a, b float64) bool { + if math.IsNaN(a) && math.IsNaN(b) { + return true + } + if a == b { + return true + } + m := math.Max(math.Abs(a), math.Abs(b)) + if m > 1 { + a /= m + b /= m + } + if math.Abs(a-b) < 1e-14 { + return true + } + return false +} + +func dSliceTolEqual(a, b []float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !dTolEqual(a[i], b[i]) { + return false + } + } + return true +} + +func dStridedSliceTolEqual(n int, a []float64, inca int, b []float64, incb int) bool { + ia := 0 + ib := 0 + if inca <= 0 { + ia = -(n - 1) * inca + } + if incb <= 0 { + ib = -(n - 1) * incb + } + for i := 0; i < n; i++ { + if !dTolEqual(a[ia], b[ib]) { + return false + } + ia += inca + ib += incb + } + return true +} + +func dSliceEqual(a, b []float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !(a[i] == b[i]) { + return false + } + } + return true +} + +func dCopyTwoTmp(x, xTmp, y, yTmp []float64) { + if len(x) != len(xTmp) { + panic("x size mismatch") + } + if len(y) != len(yTmp) { + panic("y size mismatch") + } + copy(xTmp, x) + copy(yTmp, y) +} + +// returns true if the function panics +func panics(f func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + f() + return +} + +func testpanics(f func(), name string, t *testing.T) { + b := panics(f) + if !b { + t.Errorf("%v should panic and does not", name) + } +} + +func sliceOfSliceCopy(a [][]float64) [][]float64 { + n := make([][]float64, len(a)) + for i := range a { + n[i] = make([]float64, len(a[i])) + copy(n[i], a[i]) + } + return n +} + +func sliceCopy(a []float64) []float64 { + n := make([]float64, len(a)) + copy(n, a) + return n +} + +func flatten(a [][]float64) []float64 { + if len(a) == 0 { + return nil + } + m := len(a) + n := len(a[0]) + s := make([]float64, m*n) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + s[i*n+j] = a[i][j] + } + } + return s +} + +func unflatten(a []float64, m, n int) [][]float64 { + s := make([][]float64, m) + for i := 0; i < m; i++ { + s[i] = make([]float64, n) + for j := 0; j < n; j++ { + s[i][j] = a[i*n+j] + } + } + return s +} + +// flattenTriangular turns the upper or lower triangle of a dense slice of slice +// into a single slice with packed storage. a must be a square matrix. +func flattenTriangular(a [][]float64, ul blas.Uplo) []float64 { + m := len(a) + aFlat := make([]float64, m*(m+1)/2) + var k int + if ul == blas.Upper { + for i := 0; i < m; i++ { + k += copy(aFlat[k:], a[i][i:]) + } + return aFlat + } + for i := 0; i < m; i++ { + k += copy(aFlat[k:], a[i][:i+1]) + } + return aFlat +} + +// flattenBanded turns a dense banded slice of slice into the compact banded matrix format +func flattenBanded(a [][]float64, ku, kl int) []float64 { + m := len(a) + n := len(a[0]) + if ku < 0 || kl < 0 { + panic("testblas: negative band length") + } + nRows := m + nCols := (ku + kl + 1) + aflat := make([]float64, nRows*nCols) + for i := range aflat { + aflat[i] = math.NaN() + } + // loop over the rows, and then the bands + // elements in the ith row stay in the ith row + // order in bands is kept + for i := 0; i < nRows; i++ { + min := -kl + if i-kl < 0 { + min = -i + } + max := ku + if i+ku >= n { + max = n - i - 1 + } + for j := min; j <= max; j++ { + col := kl + j + aflat[i*nCols+col] = a[i][i+j] + } + } + return aflat +} + +// makeIncremented takes a slice with inc == 1 and makes an incremented version +// and adds extra values on the end +func makeIncremented(x []float64, inc int, extra int) []float64 { + if inc == 0 { + panic("zero inc") + } + absinc := inc + if absinc < 0 { + absinc = -inc + } + xcopy := make([]float64, len(x)) + if inc > 0 { + copy(xcopy, x) + } else { + for i := 0; i < len(x); i++ { + xcopy[i] = x[len(x)-i-1] + } + } + + // don't use NaN because it makes comparison hard + // Do use a weird unique value for easier debugging + counter := 100.0 + var xnew []float64 + for i, v := range xcopy { + xnew = append(xnew, v) + if i != len(x)-1 { + for j := 0; j < absinc-1; j++ { + xnew = append(xnew, counter) + counter++ + } + } + } + for i := 0; i < extra; i++ { + xnew = append(xnew, counter) + counter++ + } + return xnew +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} + +func allPairs(x, y []int) [][2]int { + var p [][2]int + for _, v0 := range x { + for _, v1 := range y { + p = append(p, [2]int{v0, v1}) + } + } + return p +} + +func zsame(x, y []complex128) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + w := y[i] + if v != w && !math.IsNaN(real(v)) && !math.IsNaN(imag(v)) && !math.IsNaN(real(w)) && !math.IsNaN(imag(w)) { + return false + } + } + return true +} + +func makeZVector(data []complex128, inc int) []complex128 { + if inc == 0 { + panic("bad test") + } + if len(data) == 0 { + return nil + } + inc = abs(inc) + x := make([]complex128, (len(data)-1)*inc+1) + for i := range x { + x[i] = cmplx.NaN() + } + for i, v := range data { + x[i*inc] = v + } + return x +} + +func makeZGeneral(data []complex128, m, n int, ld int) []complex128 { + if m < 0 || n < 0 { + panic("bad test") + } + if len(data) != m*n { + panic("bad test") + } + if ld < max(1, n) { + panic("bad test") + } + if len(data) == 0 { + return nil + } + a := make([]complex128, (m-1)*ld+n) + for i := range a { + a[i] = cmplx.NaN() + } + for i := 0; i < m; i++ { + copy(a[i*ld:i*ld+n], data[i*n:i*n+n]) + } + return a +} + +func max(a, b int) int { + if a < b { + return b + } + return a +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/common_test.go b/vendor/gonum.org/v1/gonum/blas/testblas/common_test.go new file mode 100644 index 00000000..852a939e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/common_test.go @@ -0,0 +1,187 @@ +package testblas + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +func TestFlattenBanded(t *testing.T) { + for i, test := range []struct { + dense [][]float64 + ku int + kl int + condensed [][]float64 + }{ + { + dense: [][]float64{{3}}, + ku: 0, + kl: 0, + condensed: [][]float64{{3}}, + }, + { + dense: [][]float64{ + {3, 4, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + }, + }, + { + dense: [][]float64{ + {3, 4, 0, 0, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + }, + }, + { + dense: [][]float64{ + {3, 4, 0}, + {0, 5, 8}, + {0, 0, 2}, + {0, 0, 0}, + {0, 0, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + {5, 8}, + {2, math.NaN()}, + {math.NaN(), math.NaN()}, + {math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {3, 4, 6}, + {0, 5, 8}, + {0, 0, 2}, + {0, 0, 0}, + {0, 0, 0}, + }, + ku: 2, + kl: 0, + condensed: [][]float64{ + {3, 4, 6}, + {5, 8, math.NaN()}, + {2, math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {3, 4, 6}, + {1, 5, 8}, + {0, 6, 2}, + {0, 0, 7}, + {0, 0, 0}, + }, + ku: 2, + kl: 1, + condensed: [][]float64{ + {math.NaN(), 3, 4, 6}, + {1, 5, 8, math.NaN()}, + {6, 2, math.NaN(), math.NaN()}, + {7, math.NaN(), math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 2, 0}, + {3, 4, 5}, + {6, 7, 8}, + {0, 9, 10}, + {0, 0, 11}, + }, + ku: 1, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1, 2}, + {math.NaN(), 3, 4, 5}, + {6, 7, 8, math.NaN()}, + {9, 10, math.NaN(), math.NaN()}, + {11, math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 0, 0}, + {3, 4, 0}, + {6, 7, 8}, + {0, 9, 10}, + {0, 0, 11}, + }, + ku: 0, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1}, + {math.NaN(), 3, 4}, + {6, 7, 8}, + {9, 10, math.NaN()}, + {11, math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 4, 0, 0, 0}, + {1, 3, 5, 0, 0}, + }, + ku: 0, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1}, + {math.NaN(), 3, 4}, + {1, 3, 5}, + }, + }, + } { + condensed := flattenBanded(test.dense, test.ku, test.kl) + correct := flatten(test.condensed) + if !floats.Same(condensed, correct) { + t.Errorf("Case %v mismatch. Want %v, got %v.", i, correct, condensed) + } + } +} + +func TestFlattenTriangular(t *testing.T) { + for i, test := range []struct { + a [][]float64 + ans []float64 + ul blas.Uplo + }{ + { + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + ul: blas.Upper, + ans: []float64{1, 2, 3, 4, 5, 6}, + }, + { + a: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + ul: blas.Lower, + ans: []float64{1, 2, 3, 4, 5, 6}, + }, + } { + a := flattenTriangular(test.a, test.ul) + if !floats.Equal(a, test.ans) { + t.Errorf("Case %v. Want %v, got %v.", i, test.ans, a) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dgbmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dgbmv.go new file mode 100644 index 00000000..1e0a5c18 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dgbmv.go @@ -0,0 +1,131 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dgbmver interface { + Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DgbmvTest(t *testing.T, blasser Dgbmver) { + for i, test := range []struct { + tA blas.Transpose + m, n int + kL, kU int + alpha float64 + a [][]float64 + lda int + x []float64 + beta float64 + y []float64 + ans []float64 + }{ + { + tA: blas.NoTrans, + m: 9, + n: 6, + lda: 4, + kL: 2, + kU: 1, + alpha: 3.0, + beta: 2.0, + a: [][]float64{ + {5, 3, 0, 0, 0, 0}, + {-1, 2, 9, 0, 0, 0}, + {4, 8, 3, 6, 0, 0}, + {0, -1, 8, 2, 1, 0}, + {0, 0, 9, 9, 9, 5}, + {0, 0, 0, 2, -3, 2}, + {0, 0, 0, 0, 1, 5}, + {0, 0, 0, 0, 0, 6}, + }, + x: []float64{1, 2, 3, 4, 5, 6}, + y: []float64{-1, -2, -3, -4, -5, -6, -7, -8, -9}, + ans: []float64{31, 86, 153, 97, 404, 3, 91, 92, -18}, + }, + { + tA: blas.Trans, + m: 9, + n: 6, + lda: 4, + kL: 2, + kU: 1, + alpha: 3.0, + beta: 2.0, + a: [][]float64{ + {5, 3, 0, 0, 0, 0}, + {-1, 2, 9, 0, 0, 0}, + {4, 8, 3, 6, 0, 0}, + {0, -1, 8, 2, 1, 0}, + {0, 0, 9, 9, 9, 5}, + {0, 0, 0, 2, -3, 2}, + {0, 0, 0, 0, 1, 5}, + {0, 0, 0, 0, 0, 6}, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + y: []float64{-1, -2, -3, -4, -5, -6}, + ans: []float64{43, 77, 306, 241, 104, 348}, + }, + { + tA: blas.NoTrans, + m: 6, + n: 3, + lda: 1, + kL: 0, + kU: 0, + alpha: 2.0, + beta: 1.0, + a: [][]float64{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + }, + x: []float64{1, 2, 3}, + y: []float64{-1, -2, -3, -4, -5, -6}, + ans: []float64{1, 2, 3, -4, -5, -6}, + }, + { + tA: blas.Trans, + m: 6, + n: 3, + lda: 1, + kL: 0, + kU: 0, + alpha: 2.0, + beta: 1.0, + a: [][]float64{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + }, + x: []float64{1, 2, 3, 4, 5, 6}, + y: []float64{-1, -2, -3}, + ans: []float64{1, 2, 3}, + }, + } { + extra := 3 + aFlat := flattenBanded(test.a, test.kU, test.kL) + incTest := func(incX, incY, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ynew := makeIncremented(test.y, incY, extra) + ans := makeIncremented(test.ans, incY, extra) + blasser.Dgbmv(test.tA, test.m, test.n, test.kL, test.kU, test.alpha, aFlat, test.lda, xnew, incX, test.beta, ynew, incY) + if !dSliceTolEqual(ans, ynew) { + t.Errorf("Case %v: Want %v, got %v", i, ans, ynew) + } + } + incTest(1, 1, extra) + incTest(1, 3, extra) + incTest(1, -3, extra) + incTest(2, 3, extra) + incTest(2, -3, extra) + incTest(3, 2, extra) + incTest(-3, 2, extra) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dgemm.go b/vendor/gonum.org/v1/gonum/blas/testblas/dgemm.go new file mode 100644 index 00000000..f4bcddd8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dgemm.go @@ -0,0 +1,244 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dgemmer interface { + Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +type DgemmCase struct { + m, n, k int + alpha, beta float64 + a [][]float64 + b [][]float64 + c [][]float64 + ans [][]float64 +} + +var DgemmCases = []DgemmCase{ + + { + m: 4, + n: 3, + k: 2, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2}, + {4, 5}, + {7, 8}, + {10, 11}, + }, + b: [][]float64{ + {1, 5, 6}, + {5, -8, 8}, + }, + c: [][]float64{ + {4, 8, -9}, + {12, 16, -8}, + {1, 5, 15}, + {-3, -4, 7}, + }, + ans: [][]float64{ + {24, -18, 39.5}, + {64, -32, 124}, + {94.5, -55.5, 219.5}, + {128.5, -78, 299.5}, + }, + }, + { + m: 4, + n: 2, + k: 3, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + b: [][]float64{ + {1, 5}, + {5, -8}, + {6, 2}, + }, + c: [][]float64{ + {4, 8}, + {12, 16}, + {1, 5}, + {-3, -4}, + }, + ans: [][]float64{ + {60, -6}, + {136, -8}, + {202.5, -19.5}, + {272.5, -30}, + }, + }, + { + m: 3, + n: 2, + k: 4, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3, 4}, + {4, 5, 6, 7}, + {8, 9, 10, 11}, + }, + b: [][]float64{ + {1, 5}, + {5, -8}, + {6, 2}, + {8, 10}, + }, + c: [][]float64{ + {4, 8}, + {12, 16}, + {9, -10}, + }, + ans: [][]float64{ + {124, 74}, + {248, 132}, + {406.5, 191}, + }, + }, + { + m: 3, + n: 4, + k: 2, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2}, + {4, 5}, + {8, 9}, + }, + b: [][]float64{ + {1, 5, 2, 1}, + {5, -8, 2, 1}, + }, + c: [][]float64{ + {4, 8, 2, 2}, + {12, 16, 8, 9}, + {9, -10, 10, 10}, + }, + ans: [][]float64{ + {24, -18, 13, 7}, + {64, -32, 40, 22.5}, + {110.5, -69, 73, 39}, + }, + }, + { + m: 2, + n: 4, + k: 3, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3}, + {4, 5, 6}, + }, + b: [][]float64{ + {1, 5, 8, 8}, + {5, -8, 9, 10}, + {6, 2, -3, 2}, + }, + c: [][]float64{ + {4, 8, 7, 8}, + {12, 16, -2, 6}, + }, + ans: [][]float64{ + {60, -6, 37.5, 72}, + {136, -8, 117, 191}, + }, + }, + { + m: 2, + n: 3, + k: 4, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3, 4}, + {4, 5, 6, 7}, + }, + b: [][]float64{ + {1, 5, 8}, + {5, -8, 9}, + {6, 2, -3}, + {8, 10, 2}, + }, + c: [][]float64{ + {4, 8, 1}, + {12, 16, 6}, + }, + ans: [][]float64{ + {124, 74, 50.5}, + {248, 132, 149}, + }, + }, +} + +// assumes [][]float64 is actually a matrix +func transpose(a [][]float64) [][]float64 { + b := make([][]float64, len(a[0])) + for i := range b { + b[i] = make([]float64, len(a)) + for j := range b[i] { + b[i][j] = a[j][i] + } + } + return b +} + +func TestDgemm(t *testing.T, blasser Dgemmer) { + for i, test := range DgemmCases { + // Test that it passes row major + dgemmcomp(i, "RowMajorNoTrans", t, blasser, blas.NoTrans, blas.NoTrans, + test.m, test.n, test.k, test.alpha, test.beta, test.a, test.b, test.c, test.ans) + // Try with A transposed + dgemmcomp(i, "RowMajorTransA", t, blasser, blas.Trans, blas.NoTrans, + test.m, test.n, test.k, test.alpha, test.beta, transpose(test.a), test.b, test.c, test.ans) + // Try with B transposed + dgemmcomp(i, "RowMajorTransB", t, blasser, blas.NoTrans, blas.Trans, + test.m, test.n, test.k, test.alpha, test.beta, test.a, transpose(test.b), test.c, test.ans) + // Try with both transposed + dgemmcomp(i, "RowMajorTransBoth", t, blasser, blas.Trans, blas.Trans, + test.m, test.n, test.k, test.alpha, test.beta, transpose(test.a), transpose(test.b), test.c, test.ans) + } +} + +func dgemmcomp(i int, name string, t *testing.T, blasser Dgemmer, tA, tB blas.Transpose, m, n, k int, + alpha, beta float64, a [][]float64, b [][]float64, c [][]float64, ans [][]float64) { + + aFlat := flatten(a) + aCopy := flatten(a) + bFlat := flatten(b) + bCopy := flatten(b) + cFlat := flatten(c) + ansFlat := flatten(ans) + lda := len(a[0]) + ldb := len(b[0]) + ldc := len(c[0]) + + // Compute the matrix multiplication + blasser.Dgemm(tA, tB, m, n, k, alpha, aFlat, lda, bFlat, ldb, beta, cFlat, ldc) + + if !dSliceEqual(aFlat, aCopy) { + t.Errorf("Test %v case %v: a changed during call to Dgemm", i, name) + } + if !dSliceEqual(bFlat, bCopy) { + t.Errorf("Test %v case %v: b changed during call to Dgemm", i, name) + } + + if !dSliceTolEqual(ansFlat, cFlat) { + t.Errorf("Test %v case %v: answer mismatch. Expected %v, Found %v", i, name, ansFlat, cFlat) + } + // TODO: Need to add a sub-slice test where don't use up full matrix +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dgemmbench.go b/vendor/gonum.org/v1/gonum/blas/testblas/dgemmbench.go new file mode 100644 index 00000000..512f4eca --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dgemmbench.go @@ -0,0 +1,39 @@ +package testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DgemmBenchmark(b *testing.B, dgemm Dgemmer, m, n, k int, tA, tB blas.Transpose) { + a := make([]float64, m*k) + for i := range a { + a[i] = rand.Float64() + } + bv := make([]float64, k*n) + for i := range bv { + bv[i] = rand.Float64() + } + c := make([]float64, m*n) + for i := range c { + c[i] = rand.Float64() + } + var lda, ldb int + if tA == blas.Trans { + lda = m + } else { + lda = k + } + if tB == blas.Trans { + ldb = k + } else { + ldb = n + } + ldc := n + b.ResetTimer() + for i := 0; i < b.N; i++ { + dgemm.Dgemm(tA, tB, m, n, k, 3.0, a, lda, bv, ldb, 1.0, c, ldc) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dgemv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dgemv.go new file mode 100644 index 00000000..d18dde2f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dgemv.go @@ -0,0 +1,678 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type DgemvCase struct { + Name string + m int + n int + A [][]float64 + tA blas.Transpose + x []float64 + incX int + y []float64 + incY int + + Subcases []DgemvSubcase +} + +type DgemvSubcase struct { + mulXNeg1 bool + mulYNeg1 bool + alpha float64 + beta float64 + ans []float64 +} + +var DgemvCases = []DgemvCase{ + { + Name: "M_gt_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 8, 9, 10, 11}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 8, 9, 10, 11}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 43.9, 33, 9, 28}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 303.2, 210, 12, 158}, + }, + }, + }, + { + Name: "M_gt_N_Inc1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3, -4, 5}, + y: []float64{7, 8, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 8, 9}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{94.3, 40.2, 52.3}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{712.4, 273.6, 364.4}, + }, + }, + }, + { + Name: "M_eq_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 2, 2}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 43.9, 33}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{40.8*8 - 6*7, 43.9*8 - 6*2, 33*8 - 6*2}, + }, + }, + }, + { + Name: "M_eq_N_Inc1_Trans", + tA: blas.Trans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 261.6, 270.4}, + }, + }, + }, + { + Name: "M_lt_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 7}, + {9.6, 3.5, 9.1, -2, 9}, + {10, 7, 3, 1, -5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3, -7.6, 8.1}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 2, 2}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{21.5, 132, -15.1}, + }, + + { + alpha: 8, + beta: -6, + ans: []float64{21.5*8 - 6*7, 132*8 - 6*2, -15.1*8 - 6*2}, + }, + }, + }, + { + Name: "M_lt_N_Inc1_Trans", + tA: blas.Trans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 7}, + {9.6, 3.5, 9.1, -2, 9}, + {10, 7, 3, 1, -5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2, -3, 5}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 261.6, 270.4, 90, 50}, + }, + }, + }, + { + Name: "M_gt_N_Part1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 2, + x: []float64{1, 2, 3}, + y: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 100, 0, 101, 0, 102, 0, 103, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 100, 43.9, 101, 33, 102, 9, 103, 28}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 100, 303.2, 101, 210, 102, 12, 103, 158}, + }, + }, + }, + { + Name: "M_gt_N_Part1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 2, + x: []float64{1, 2, 3, -4, 5}, + y: []float64{7, 100, 8, 101, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 100, 0, 101, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 100, 8, 101, 9}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{94.3, 100, 40.2, 101, 52.3}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{712.4, 100, 273.6, 101, 364.4}, + }, + }, + }, + { + Name: "M_gt_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9, 1, 1, 10, 19, 22, 11}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210, 1, 1, 12, 19, 22, 158}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322, 1, 1, -4, 19, 22, 222}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{182, 2, 6, 24, -4, -5, 210, 1, 1, 291.2, 19, 22, 260.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{246, 2, 6, 8, -4, -5, 322, 1, 1, 299.2, 19, 22, 196.4}, + }, + }, + }, + { + Name: "M_gt_N_IncNot1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3, 8, -3, 6, 5}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{720.4, 2, 6, 281.6, -4, -5, 380.4}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{219.6, 2, 6, 316, -4, -5, 195.6}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{392.4, 2, 6, 281.6, -4, -5, 708.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{207.6, 2, 6, 316, -4, -5, 207.6}, + }, + }, + }, + { + Name: "M_eq_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{222, 2, 6, 303.2, -4, -5, 272.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{334, 2, 6, 311.2, -4, -5, 208.4}, + }, + }, + }, + { + Name: "M_eq_N_IncNot1_Trans", + tA: blas.Trans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{290, 2, 6, 212.8, -4, -5, 310}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{240.4, 2, 6, 225.6, -4, -5, 372.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{322, 2, 6, 212.8, -4, -5, 278}, + }, + }, + }, + { + Name: "M_lt_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 11}, + {9.6, 3.5, 9.1, -3, -2}, + {10, 7, 3, -7, -4}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3, -2, -4, 8, -9}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{-827.6, 2, 6, 543.2, -4, -5, 722}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-93.2, 2, 6, -696.8, -4, -5, -1070}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{734, 2, 6, 543.2, -4, -5, -839.6}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-1058, 2, 6, -696.8, -4, -5, -105.2}, + }, + }, + }, + { + Name: "M_lt_N_IncNot1_Trans", + tA: blas.Trans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 11}, + {9.6, 3.5, 9.1, -3, -2}, + {10, 7, 3, -7, -4}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9, -4, -1, -9, 1, 1, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4, -4, -1, -82, 1, 1, -52}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{290, 2, 6, 212.8, -4, -5, 310, -4, -1, 190, 1, 1, 188}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-82, 2, 6, -184, -4, -5, 228.4, -4, -1, 327.6, 1, 1, 414.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{158, 2, 6, 88, -4, -5, 310, -4, -1, 314.8, 1, 1, 320}, + }, + }, + }, + + // TODO: A can be longer than mxn. Add cases where it is longer + // TODO: x and y can also be longer. Add tests for these + // TODO: Add tests for dimension mismatch + // TODO: Add places with a "submatrix view", where lda != m +} + +type Dgemver interface { + Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DgemvTest(t *testing.T, blasser Dgemver) { + for _, test := range DgemvCases { + for i, cas := range test.Subcases { + // Test that it passes with row-major + dgemvcomp(t, test, cas, i, blasser) + + // Test the bad inputs + dgemvbad(t, test, cas, i, blasser) + } + } +} + +func dgemvcomp(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { + x := sliceCopy(test.x) + y := sliceCopy(test.y) + a := sliceOfSliceCopy(test.A) + aFlat := flatten(a) + + lda := test.n + + incX := test.incX + if cas.mulXNeg1 { + incX *= -1 + } + incY := test.incY + if cas.mulYNeg1 { + incY *= -1 + } + + f := func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) + } + if panics(f) { + t.Errorf("Test %v case %v: unexpected panic", test.Name, i) + if throwPanic { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) + } + return + } + // Check that x and a are unchanged + if !dSliceEqual(x, test.x) { + t.Errorf("Test %v, case %v: x modified during call", test.Name, i) + } + aFlat2 := flatten(sliceOfSliceCopy(test.A)) + if !dSliceEqual(aFlat2, aFlat) { + t.Errorf("Test %v, case %v: a modified during call", test.Name, i) + } + + // Check that the answer matches + if !dSliceTolEqual(cas.ans, y) { + t.Errorf("Test %v, case %v: answer mismatch: Expected %v, Found %v", test.Name, i, cas.ans, y) + } +} + +func dgemvbad(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { + x := sliceCopy(test.x) + y := sliceCopy(test.y) + a := sliceOfSliceCopy(test.A) + aFlatRow := flatten(a) + ldaRow := test.n + + f := func() { + blasser.Dgemv(312, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for bad transpose", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, -2, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for m negative", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, -4, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for n negative", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, 0, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for incX zero", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, 0) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for incY zero", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow-1, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for lda too small row major", test.Name, i) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dger.go b/vendor/gonum.org/v1/gonum/blas/testblas/dger.go new file mode 100644 index 00000000..0a905812 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dger.go @@ -0,0 +1,163 @@ +package testblas + +import "testing" + +type Dgerer interface { + Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) +} + +func DgerTest(t *testing.T, blasser Dgerer) { + for _, test := range []struct { + name string + a [][]float64 + m int + n int + x []float64 + y []float64 + incX int + incY int + + trueAns [][]float64 + }{ + { + name: "M gt N inc 1", + m: 5, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + {8, 9, -10}, + {-12, -14, -6}, + }, + x: []float64{-2, -3, 0, 1, 2}, + y: []float64{-1.1, 5, 0}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5}, {5.9, -12.2, 3.3}, {-1.3, -4.3, -9.7}, {6.9, 14, -10}, {-14.2, -4, -6}}, + }, + { + name: "M eq N inc 1", + m: 3, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + }, + x: []float64{-2, -3, 0}, + y: []float64{-1.1, 5, 0}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5}, {5.9, -12.2, 3.3}, {-1.3, -4.3, -9.7}}, + }, + + { + name: "M lt N inc 1", + m: 3, + n: 6, + a: [][]float64{ + {1.3, 2.4, 3.5, 4.8, 1.11, -9}, + {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, + {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}, + }, + x: []float64{-2, -3, 0}, + y: []float64{-1.1, 5, 0, 9, 19, 22}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5, -13.2, -36.89, -53}, {5.9, -12.2, 3.3, -30.4, -50.8, -74.7}, {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}}, + }, + { + name: "M gt N inc not 1", + m: 5, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + {8, 9, -10}, + {-12, -14, -6}, + }, + x: []float64{-2, -3, 0, 1, 2, 6, 0, 9, 7}, + y: []float64{-1.1, 5, 0, 8, 7, -5, 7}, + incX: 2, + incY: 3, + trueAns: [][]float64{{3.5, -13.6, -10.5}, {2.6, 2.8, 3.3}, {-3.5, 11.7, 4.3}, {8, 9, -10}, {-19.700000000000003, 42, 43}}, + }, + { + name: "M eq N inc not 1", + m: 3, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + }, + x: []float64{-2, -3, 0, 8, 7, -9, 7, -6, 12, 6, 6, 6, -11}, + y: []float64{-1.1, 5, 0, 0, 9, 8, 6}, + incX: 4, + incY: 3, + trueAns: [][]float64{{3.5, 2.4, -8.5}, {-5.1, 2.8, 45.3}, {-14.5, -4.3, 62.3}}, + }, + { + name: "M lt N inc not 1", + m: 3, + n: 6, + a: [][]float64{ + {1.3, 2.4, 3.5, 4.8, 1.11, -9}, + {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, + {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}, + }, + x: []float64{-2, -3, 0, 0, 8, 0, 9, -3}, + y: []float64{-1.1, 5, 0, 9, 19, 22, 11, -8.11, -9.22, 9.87, 7}, + incX: 3, + incY: 2, + trueAns: [][]float64{{3.5, 2.4, -34.5, -17.2, 19.55, -23}, {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, {-11.2, -4.3, 161.3, 95.9, -74.08, 71.9}}, + }, + } { + // TODO: Add tests where a is longer + // TODO: Add panic tests + // TODO: Add negative increment tests + + x := sliceCopy(test.x) + y := sliceCopy(test.y) + + a := sliceOfSliceCopy(test.a) + + // Test with row major + alpha := 1.0 + aFlat := flatten(a) + blasser.Dger(test.m, test.n, alpha, x, test.incX, y, test.incY, aFlat, test.n) + ans := unflatten(aFlat, test.m, test.n) + dgercomp(t, x, test.x, y, test.y, ans, test.trueAns, test.name+" row maj") + + // Test with different alpha + alpha = 4.0 + aFlat = flatten(a) + blasser.Dger(test.m, test.n, alpha, x, test.incX, y, test.incY, aFlat, test.n) + ans = unflatten(aFlat, test.m, test.n) + trueCopy := sliceOfSliceCopy(test.trueAns) + for i := range trueCopy { + for j := range trueCopy[i] { + trueCopy[i][j] = alpha*(trueCopy[i][j]-a[i][j]) + a[i][j] + } + } + dgercomp(t, x, test.x, y, test.y, ans, trueCopy, test.name+" row maj alpha") + } +} + +func dgercomp(t *testing.T, x, xCopy, y, yCopy []float64, ans [][]float64, trueAns [][]float64, name string) { + if !dSliceEqual(x, xCopy) { + t.Errorf("case %v: x modified during call to dger", name) + } + if !dSliceEqual(y, yCopy) { + t.Errorf("case %v: x modified during call to dger", name) + } + + for i := range ans { + if !dSliceTolEqual(ans[i], trueAns[i]) { + t.Errorf("case %v: answer mismatch. Expected %v, Found %v", name, trueAns, ans) + break + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/doc.go b/vendor/gonum.org/v1/gonum/blas/testblas/doc.go new file mode 100644 index 00000000..fc113147 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 testblas provides tests for blas implementations. +package testblas // import "gonum.org/v1/gonum/blas/testblas" diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsbmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsbmv.go new file mode 100644 index 00000000..1a8c9c35 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsbmv.go @@ -0,0 +1,83 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsbmver interface { + Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DsbmvTest(t *testing.T, blasser Dsbmver) { + for i, test := range []struct { + ul blas.Uplo + n int + k int + alpha float64 + beta float64 + a [][]float64 + x []float64 + y []float64 + + ans []float64 + }{ + { + ul: blas.Upper, + n: 4, + k: 2, + alpha: 2, + beta: 3, + a: [][]float64{ + {7, 8, 2, 0}, + {0, 8, 2, -3}, + {0, 0, 3, 6}, + {0, 0, 0, 9}, + }, + x: []float64{1, 2, 3, 4}, + y: []float64{-1, -2, -3, -4}, + ans: []float64{55, 30, 69, 84}, + }, + { + ul: blas.Lower, + n: 4, + k: 2, + alpha: 2, + beta: 3, + a: [][]float64{ + {7, 0, 0, 0}, + {8, 8, 0, 0}, + {2, 2, 3, 0}, + {0, -3, 6, 9}, + }, + x: []float64{1, 2, 3, 4}, + y: []float64{-1, -2, -3, -4}, + ans: []float64{55, 30, 69, 84}, + }, + } { + extra := 0 + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + incTest := func(incX, incY, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ynew := makeIncremented(test.y, incY, extra) + ans := makeIncremented(test.ans, incY, extra) + blasser.Dsbmv(test.ul, test.n, test.k, test.alpha, aFlat, test.k+1, xnew, incX, test.beta, ynew, incY) + if !dSliceTolEqual(ans, ynew) { + t.Errorf("Case %v: Want %v, got %v", i, ans, ynew) + } + } + incTest(1, 1, extra) + incTest(1, 3, extra) + incTest(1, -3, extra) + incTest(2, 3, extra) + incTest(2, -3, extra) + incTest(3, 2, extra) + incTest(-3, 2, extra) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dspmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dspmv.go new file mode 100644 index 00000000..352bc4a9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dspmv.go @@ -0,0 +1,73 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dspmver interface { + Dspmv(ul blas.Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DspmvTest(t *testing.T, blasser Dspmver) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + y []float64 + alpha float64 + beta float64 + ans []float64 + }{ + { + ul: blas.Upper, + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 8, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 8, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + } { + incTest := func(incX, incY, extra int) { + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + aFlat := flattenTriangular(test.a, test.ul) + ans := makeIncremented(test.ans, incY, extra) + + blasser.Dspmv(test.ul, test.n, test.alpha, aFlat, x, incX, test.beta, y, incY) + if !floats.EqualApprox(ans, y, 1e-14) { + t.Errorf("Case %v, incX=%v, incY=%v: Want %v, got %v.", i, incX, incY, ans, y) + } + } + incTest(1, 1, 0) + incTest(2, 3, 0) + incTest(3, 2, 0) + incTest(-3, 2, 0) + incTest(-2, 4, 0) + incTest(2, -1, 0) + incTest(-3, -4, 3) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dspr.go b/vendor/gonum.org/v1/gonum/blas/testblas/dspr.go new file mode 100644 index 00000000..25e0ee40 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dspr.go @@ -0,0 +1,71 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsprer interface { + Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64) +} + +func DsprTest(t *testing.T, blasser Dsprer) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + alpha float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + n: 4, + a: [][]float64{ + {10, 2, 0, 1}, + {0, 1, 2, 3}, + {0, 0, 9, 15}, + {0, 0, 0, -6}, + }, + x: []float64{1, 2, 0, 5}, + alpha: 8, + ans: [][]float64{ + {18, 18, 0, 41}, + {0, 33, 2, 83}, + {0, 0, 9, 15}, + {0, 0, 0, 194}, + }, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {10, 2, 0}, + {4, 1, 2}, + {2, 7, 9}, + }, + x: []float64{3, 0, 5}, + alpha: 8, + ans: [][]float64{ + {82, 2, 0}, + {4, 1, 2}, + {122, 7, 209}, + }, + }, + } { + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + aFlat := flattenTriangular(test.a, test.ul) + ans := flattenTriangular(test.ans, test.ul) + blasser.Dspr(test.ul, test.n, test.alpha, xnew, incX, aFlat) + if !dSliceTolEqual(aFlat, ans) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, aFlat) + } + } + incTest(1, 3) + incTest(1, 0) + incTest(3, 2) + incTest(-2, 2) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dspr2.go b/vendor/gonum.org/v1/gonum/blas/testblas/dspr2.go new file mode 100644 index 00000000..40b0cd32 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dspr2.go @@ -0,0 +1,76 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dspr2er interface { + Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64) +} + +func Dspr2Test(t *testing.T, blasser Dspr2er) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + x []float64 + y []float64 + alpha float64 + ans [][]float64 + }{ + { + n: 3, + a: [][]float64{ + {7, 2, 4}, + {0, 3, 5}, + {0, 0, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Upper, + ans: [][]float64{ + {47, 56, 72}, + {0, 75, 95}, + {0, 0, 118}, + }, + }, + { + n: 3, + a: [][]float64{ + {7, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Lower, + ans: [][]float64{ + {47, 0, 0}, + {56, 75, 0}, + {72, 95, 118}, + }, + }, + } { + incTest := func(incX, incY, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + blasser.Dspr2(test.ul, test.n, test.alpha, x, incX, y, incY, aFlat) + ansFlat := flattenTriangular(test.ans, test.ul) + if !floats.EqualApprox(aFlat, ansFlat, 1e-14) { + t.Errorf("Case %v, incX = %v, incY = %v. Want %v, got %v.", i, incX, incY, ansFlat, aFlat) + } + } + incTest(1, 1, 0) + incTest(-2, 1, 0) + incTest(-2, 3, 0) + incTest(2, -3, 0) + incTest(3, -2, 0) + incTest(-3, -4, 0) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsymm.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsymm.go new file mode 100644 index 00000000..5e07e07d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsymm.go @@ -0,0 +1,277 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsymmer interface { + Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +func DsymmTest(t *testing.T, blasser Dsymmer) { + for i, test := range []struct { + m int + n int + side blas.Side + ul blas.Uplo + a [][]float64 + b [][]float64 + c [][]float64 + alpha float64 + beta float64 + ans [][]float64 + }{ + { + side: blas.Left, + ul: blas.Upper, + m: 3, + n: 4, + a: [][]float64{ + {2, 3, 4}, + {0, 6, 7}, + {0, 0, 10}, + }, + b: [][]float64{ + {2, 3, 4, 8}, + {5, 6, 7, 15}, + {8, 9, 10, 20}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {126, 156, 144, 285}, + {211, 252, 275, 535}, + {282, 291, 327, 689}, + }, + }, + { + side: blas.Left, + ul: blas.Upper, + m: 4, + n: 3, + a: [][]float64{ + {2, 3, 4, 8}, + {0, 6, 7, 9}, + {0, 0, 10, 10}, + {0, 0, 0, 11}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {158, 172, 160}, + {247, 270, 293}, + {322, 311, 347}, + {329, 385, 427}, + }, + }, + { + side: blas.Left, + ul: blas.Lower, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4, 8}, + {5, 6, 7, 15}, + {8, 9, 10, 20}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {126, 156, 144, 285}, + {211, 252, 275, 535}, + {282, 291, 327, 689}, + }, + }, + { + side: blas.Left, + ul: blas.Lower, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {8, 9, 10, 11}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {158, 172, 160}, + {247, 270, 293}, + {322, 311, 347}, + {329, 385, 427}, + }, + }, + { + side: blas.Right, + ul: blas.Upper, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {3, 4, 5, 6}, + }, + b: [][]float64{ + {2, 3, 4, 9}, + {5, 6, 7, -3}, + {8, 9, 10, -2}, + }, + c: [][]float64{ + {8, 12, 2, 10}, + {9, 12, 9, 10}, + {12, 1, -1, 10}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {32, 72, 86, 138}, + {47, 108, 167, -6}, + {68, 111, 197, 6}, + }, + }, + { + side: blas.Right, + ul: blas.Upper, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {32, 72, 86}, + {47, 108, 167}, + {68, 111, 197}, + {11, 39, 35}, + }, + }, + { + side: blas.Right, + ul: blas.Lower, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {3, 4, 5, 6}, + }, + b: [][]float64{ + {2, 3, 4, 2}, + {5, 6, 7, 1}, + {8, 9, 10, 1}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {94, 156, 164, 103}, + {145, 244, 301, 187}, + {208, 307, 397, 247}, + }, + }, + { + side: blas.Right, + ul: blas.Lower, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {82, 140, 144}, + {139, 236, 291}, + {202, 299, 387}, + {25, 65, 65}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsymm(test.side, test.ul, test.m, test.n, test.alpha, aFlat, len(test.a[0]), bFlat, test.n, test.beta, cFlat, test.n) + if !floats.EqualApprox(cFlat, ansFlat, 1e-14) { + t.Errorf("Case %v: Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsymv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsymv.go new file mode 100644 index 00000000..b3fd4ec2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsymv.go @@ -0,0 +1,73 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsymver interface { + Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DsymvTest(t *testing.T, blasser Dsymver) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + y []float64 + alpha float64 + beta float64 + ans []float64 + }{ + { + ul: blas.Upper, + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 8, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 8, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + } { + incTest := func(incX, incY, extra int) { + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + aFlat := flatten(test.a) + ans := makeIncremented(test.ans, incY, extra) + + blasser.Dsymv(test.ul, test.n, test.alpha, aFlat, test.n, x, incX, test.beta, y, incY) + if !floats.EqualApprox(ans, y, 1e-14) { + t.Errorf("Case %v, incX=%v, incY=%v: Want %v, got %v.", i, incX, incY, ans, y) + } + } + incTest(1, 1, 0) + incTest(2, 3, 0) + incTest(3, 2, 0) + incTest(-3, 2, 0) + incTest(-2, 4, 0) + incTest(2, -1, 0) + incTest(-3, -4, 3) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsyr.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr.go new file mode 100644 index 00000000..4c404794 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr.go @@ -0,0 +1,72 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsyrer interface { + Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) +} + +func DsyrTest(t *testing.T, blasser Dsyrer) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + alpha float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + n: 4, + a: [][]float64{ + {10, 2, 0, 1}, + {0, 1, 2, 3}, + {0, 0, 9, 15}, + {0, 0, 0, -6}, + }, + x: []float64{1, 2, 0, 5}, + alpha: 8, + ans: [][]float64{ + {18, 18, 0, 41}, + {0, 33, 2, 83}, + {0, 0, 9, 15}, + {0, 0, 0, 194}, + }, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {10, 2, 0}, + {4, 1, 2}, + {2, 7, 9}, + }, + x: []float64{3, 0, 5}, + alpha: 8, + ans: [][]float64{ + {82, 2, 0}, + {4, 1, 2}, + {122, 7, 209}, + }, + }, + } { + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + aFlat := flatten(test.a) + ans := flatten(test.ans) + lda := test.n + blasser.Dsyr(test.ul, test.n, test.alpha, xnew, incX, aFlat, lda) + if !dSliceTolEqual(aFlat, ans) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, aFlat) + } + } + incTest(1, 3) + incTest(1, 0) + incTest(3, 2) + incTest(-2, 2) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2.go new file mode 100644 index 00000000..e9069592 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2.go @@ -0,0 +1,76 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyr2er interface { + Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) +} + +func Dsyr2Test(t *testing.T, blasser Dsyr2er) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + x []float64 + y []float64 + alpha float64 + ans [][]float64 + }{ + { + n: 3, + a: [][]float64{ + {7, 2, 4}, + {0, 3, 5}, + {0, 0, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Upper, + ans: [][]float64{ + {47, 56, 72}, + {0, 75, 95}, + {0, 0, 118}, + }, + }, + { + n: 3, + a: [][]float64{ + {7, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Lower, + ans: [][]float64{ + {47, 0, 0}, + {56, 75, 0}, + {72, 95, 118}, + }, + }, + } { + incTest := func(incX, incY, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + blasser.Dsyr2(test.ul, test.n, test.alpha, x, incX, y, incY, aFlat, test.n) + ansFlat := flatten(test.ans) + if !floats.EqualApprox(aFlat, ansFlat, 1e-14) { + t.Errorf("Case %v, incX = %v, incY = %v. Want %v, got %v.", i, incX, incY, ansFlat, aFlat) + } + } + incTest(1, 1, 0) + incTest(-2, 1, 0) + incTest(-2, 3, 0) + incTest(2, -3, 0) + incTest(3, -2, 0) + incTest(-3, -4, 0) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2k.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2k.go new file mode 100644 index 00000000..7c8600b5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsyr2k.go @@ -0,0 +1,201 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyr2ker interface { + Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +func Dsyr2kTest(t *testing.T, blasser Dsyr2ker) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + n int + k int + alpha float64 + a [][]float64 + b [][]float64 + c [][]float64 + beta float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 5, 6}, + {0, 0, 9}, + }, + beta: 2, + ans: [][]float64{ + {2, 4, 6}, + {0, 10, 12}, + {0, 0, 18}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {2, 0, 0}, + {4, 6, 0}, + {8, 10, 12}, + }, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 250, 360}, + {0, 410, 568}, + {0, 0, 774}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 0, 0}, + {250, 410, 0}, + {360, 568, 774}, + }, + }, + { + ul: blas.Upper, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + b: [][]float64{ + {7, 9, 11}, + {8, 10, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 250, 360}, + {0, 410, 568}, + {0, 0, 774}, + }, + }, + { + ul: blas.Lower, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + b: [][]float64{ + {7, 9, 11}, + {8, 10, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 0, 0}, + {250, 410, 0}, + {360, 568, 774}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsyr2k(test.ul, test.tA, test.n, test.k, test.alpha, aFlat, len(test.a[0]), bFlat, len(test.b[0]), test.beta, cFlat, len(test.c[0])) + if !floats.EqualApprox(ansFlat, cFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dsyrk.go b/vendor/gonum.org/v1/gonum/blas/testblas/dsyrk.go new file mode 100644 index 00000000..99e18ebb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dsyrk.go @@ -0,0 +1,171 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyker interface { + Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) +} + +func DsyrkTest(t *testing.T, blasser Dsyker) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + n int + k int + alpha float64 + a [][]float64 + c [][]float64 + beta float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 5, 6}, + {0, 0, 9}, + }, + beta: 2, + ans: [][]float64{ + {2, 4, 6}, + {0, 10, 12}, + {0, 0, 18}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {2, 0, 0}, + {4, 6, 0}, + {8, 10, 12}, + }, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 37, 57}, + {0, 83, 127}, + {0, 0, 195}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 0, 0}, + {37, 83, 0}, + {57, 127, 195}, + }, + }, + { + ul: blas.Upper, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 37, 57}, + {0, 83, 127}, + {0, 0, 195}, + }, + }, + { + ul: blas.Lower, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 0, 0}, + {37, 83, 0}, + {57, 127, 195}, + }, + }, + } { + aFlat := flatten(test.a) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsyrk(test.ul, test.tA, test.n, test.k, test.alpha, aFlat, len(test.a[0]), test.beta, cFlat, len(test.c[0])) + if !floats.EqualApprox(ansFlat, cFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtbmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtbmv.go new file mode 100644 index 00000000..b0dee676 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtbmv.go @@ -0,0 +1,123 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtbmver interface { + Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) +} + +func DtbmvTest(t *testing.T, blasser Dtbmver) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + d blas.Diag + n int + k int + a [][]float64 + x []float64 + ans []float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + n: 3, + k: 1, + a: [][]float64{ + {1, 2, 0}, + {0, 1, 4}, + {0, 0, 1}, + }, + x: []float64{2, 3, 4}, + ans: []float64{8, 19, 4}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 33, 10, 63, -5}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {7, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {0, 7, 2, 0, 0}, + {0, 0, 1, 12, 0}, + {0, 0, 0, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 15, 20, 51, 7}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {7, 3, 9, 0, 0}, + {0, 6, 7, 10, 0}, + {0, 0, 2, 1, 11}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 15, 29, 71, 40}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {7, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {9, 7, 2, 0, 0}, + {0, 10, 1, 12, 0}, + {0, 0, 11, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{40, 73, 65, 63, -5}, + }, + } { + extra := 0 + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ans := makeIncremented(test.ans, incX, extra) + lda := test.k + 1 + blasser.Dtbmv(test.ul, test.tA, test.d, test.n, test.k, aFlat, lda, xnew, incX) + if !dSliceTolEqual(ans, xnew) { + t.Errorf("Case %v, Inc %v: Want %v, got %v", i, incX, ans, xnew) + } + } + incTest(1, extra) + incTest(3, extra) + incTest(-2, extra) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtbsv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtbsv.go new file mode 100644 index 00000000..d3fad1ec --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtbsv.go @@ -0,0 +1,255 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtbsver interface { + Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtbsvTest(t *testing.T, blasser Dtbsver) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + d blas.Diag + n, k int + a [][]float64 + x []float64 + incX int + ans []float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{2.479166666666667, -0.493055555555556, 0.708333333333333, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{-15.854166666666664, -16.395833333333336, 13.208333333333334, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{2.479166666666667, -101, -0.493055555555556, -201, 0.708333333333333, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{-15.854166666666664, -101, -16.395833333333336, -201, 13.208333333333334, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{1, -0.166666666666667, -0.416666666666667, 0.437500000000000, -5.770833333333334}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{1, -101, -0.166666666666667, -201, -0.416666666666667, -301, 0.437500000000000, -401, -5.770833333333334, -501, -601, -701}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{1, -0.166666666666667, -0.416666666666667, 0.437500000000000, -5.770833333333334}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{1, -101, -0.166666666666667, -201, -0.416666666666667, -301, 0.437500000000000, -401, -5.770833333333334, -501, -601, -701}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{-15.854166666666664, -16.395833333333336, 13.208333333333334, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{-15.854166666666664, -101, -16.395833333333336, -201, 13.208333333333334, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + } { + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + xCopy := sliceCopy(test.x) + // TODO: Have tests where the banded matrix is constructed explicitly + // to allow testing for lda =! k+1 + blasser.Dtbsv(test.ul, test.tA, test.d, test.n, test.k, aFlat, test.k+1, xCopy, test.incX) + if !dSliceTolEqual(test.ans, xCopy) { + t.Errorf("Case %v: Want %v, got %v", i, test.ans, xCopy) + } + } + + /* + // TODO: Uncomment when Dtrsv is fixed + // Compare with dense for larger matrices + for _, ul := range [...]blas.Uplo{blas.Upper, blas.Lower} { + for _, tA := range [...]blas.Transpose{blas.NoTrans, blas.Trans} { + for _, n := range [...]int{7, 8, 11} { + for _, d := range [...]blas.Diag{blas.NonUnit, blas.Unit} { + for _, k := range [...]int{0, 1, 3} { + for _, incX := range [...]int{1, 3} { + a := make([][]float64, n) + for i := range a { + a[i] = make([]float64, n) + for j := range a[i] { + a[i][j] = rand.Float64() + } + } + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + extra := 3 + xinc := makeIncremented(x, incX, extra) + bandX := sliceCopy(xinc) + var aFlatBand []float64 + if ul == blas.Upper { + aFlatBand = flattenBanded(a, k, 0) + } else { + aFlatBand = flattenBanded(a, 0, k) + } + blasser.Dtbsv(ul, tA, d, n, k, aFlatBand, k+1, bandX, incX) + + aFlatDense := flatten(a) + denseX := sliceCopy(xinc) + blasser.Dtrsv(ul, tA, d, n, aFlatDense, n, denseX, incX) + if !dSliceTolEqual(denseX, bandX) { + t.Errorf("Case %v: dense banded mismatch") + } + } + } + } + } + } + } + */ +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtpmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtpmv.go new file mode 100644 index 00000000..04af1641 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtpmv.go @@ -0,0 +1,129 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtpmver interface { + Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) +} + +func DtpmvTest(t *testing.T, blasser Dtpmver) { + for i, test := range []struct { + n int + a [][]float64 + x []float64 + d blas.Diag + ul blas.Uplo + tA blas.Transpose + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{74, 86, 65}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{62, 54, 5}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {6, 1, 0}, + {7, 10, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 6, 7}, + {0, 1, 10}, + {0, 0, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.Trans, + ans: []float64{74, 86, 65}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + blasser.Dtpmv(test.ul, test.tA, test.d, test.n, aFlat, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-3, 3) + incTest(4, 3) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtpsv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtpsv.go new file mode 100644 index 00000000..9fee545e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtpsv.go @@ -0,0 +1,144 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtpsver interface { + Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) +} + +func DtpsvTest(t *testing.T, blasser Dtpsver) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + tA blas.Transpose + d blas.Diag + x []float64 + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 1, 15}, + {0, 0, 1}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 1, 0}, + {3, 15, 1}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + blasser.Dtpsv(test.ul, test.tA, test.d, test.n, aFlat, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, incX = %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-2, 0) + incTest(3, 0) + incTest(-3, 8) + incTest(4, 2) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtrmm.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmm.go new file mode 100644 index 00000000..95cccec5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmm.go @@ -0,0 +1,806 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrmmer interface { + Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) +} + +func DtrmmTest(t *testing.T, blasser Dtrmmer) { + for i, test := range []struct { + s blas.Side + ul blas.Uplo + tA blas.Transpose + d blas.Diag + m int + n int + alpha float64 + a [][]float64 + b [][]float64 + ans [][]float64 + }{ + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {588, 624, 660}, + {598, 632, 666}, + {380, 400, 420}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {130, 140, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {484, 512, 540}, + {374, 394, 414}, + {38, 40, 42}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {26, 28, 30}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + {472, 506, 540}, + {930, 990, 1050}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + {248, 268, 288}, + {588, 630, 672}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + {472, 506, 540}, + {930, 990, 1050}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + {248, 268, 288}, + {588, 630, 672}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {588, 624, 660}, + {598, 632, 666}, + {380, 400, 420}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {130, 140, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {484, 512, 540}, + {374, 394, 414}, + {38, 40, 42}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {26, 28, 30}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + {32, 200, 482}, + {38, 236, 566}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + {32, 98, 302}, + {38, 116, 356}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + {208, 316, 216}, + {244, 370, 252}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + {208, 214, 36}, + {244, 250, 42}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + }, + }, + + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + {208, 316, 216}, + {244, 370, 252}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + {208, 214, 36}, + {244, 250, 42}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + }, + }, + + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + {32, 200, 482}, + {38, 236, 566}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + {32, 98, 302}, + {38, 116, 356}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + ansFlat := flatten(test.ans) + blasser.Dtrmm(test.s, test.ul, test.tA, test.d, test.m, test.n, test.alpha, aFlat, len(test.a[0]), bFlat, len(test.b[0])) + if !floats.EqualApprox(ansFlat, bFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, bFlat) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtrmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmv.go new file mode 100644 index 00000000..8f3b6d35 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmv.go @@ -0,0 +1,147 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrmver interface { + Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtrmvTest(t *testing.T, blasser Dtrmver) { + for i, test := range []struct { + n int + a [][]float64 + x []float64 + d blas.Diag + ul blas.Uplo + tA blas.Transpose + ans []float64 + }{ + { + n: 1, + a: [][]float64{{5}}, + x: []float64{2}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{10}, + }, + { + n: 1, + a: [][]float64{{5}}, + x: []float64{2}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{2}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{74, 86, 65}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{62, 54, 5}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {6, 1, 0}, + {7, 10, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 6, 7}, + {0, 1, 10}, + {0, 0, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.Trans, + ans: []float64{74, 86, 65}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + blasser.Dtrmv(test.ul, test.tA, test.d, test.n, aFlat, test.n, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 3) + incTest(-3, 3) + incTest(4, 3) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtrmvbench.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmvbench.go new file mode 100644 index 00000000..c6b439e9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtrmvbench.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum 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 testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DtrmvBenchmark(b *testing.B, dtrmv Dtrmver, n, lda, incX int, ul blas.Uplo, tA blas.Transpose, d blas.Diag) { + rnd := rand.New(rand.NewSource(0)) + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + + x := make([]float64, n*incX) + for i := range x { + x[i] = rnd.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + dtrmv.Dtrmv(ul, tA, d, n, a, lda, x, incX) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtrsm.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtrsm.go new file mode 100644 index 00000000..9623397c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtrsm.go @@ -0,0 +1,811 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrsmer interface { + Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, + alpha float64, a []float64, lda int, b []float64, ldb int) +} + +func DtrsmTest(t *testing.T, blasser Dtrsmer) { + for i, test := range []struct { + s blas.Side + ul blas.Uplo + tA blas.Transpose + d blas.Diag + m int + n int + alpha float64 + a [][]float64 + b [][]float64 + ans [][]float64 + }{ + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {1, 3.4}, + {-0.5, -0.5}, + {2, 3.2}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {60, 96}, + {-42, -66}, + {10, 16}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {1, 3.4, 1.2, 13}, + {-0.5, -0.5, -4, -3.5}, + {2, 3.2, 3.6, 4}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {60, 96, 126, 146}, + {-42, -66, -88, -94}, + {10, 16, 18, 20}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {4.5, 9}, + {-0.375, -1.5}, + {-0.75, -12.0 / 7}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {9, 18}, + {-15, -33}, + {60, 132}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {4.5, 9, 3, 13.5}, + {-0.375, -1.5, -1.5, -63.0 / 8}, + {-0.75, -12.0 / 7, 3, 39.0 / 28}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {9, 18, 6, 27}, + {-15, -33, -15, -72}, + {60, 132, 87, 327}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {4.5, 9}, + {-0.30, -1.2}, + {-6.0 / 35, -24.0 / 35}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {9, 18}, + {-15, -33}, + {69, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6, 6, 7}, + {4, 7, 8, 9}, + {5, 8, 10, 11}, + }, + ans: [][]float64{ + {4.5, 9, 9, 10.5}, + {-0.3, -1.2, -0.6, -0.9}, + {-6.0 / 35, -24.0 / 35, -12.0 / 35, -18.0 / 35}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6, 6, 7}, + {4, 7, 8, 9}, + {5, 8, 10, 11}, + }, + ans: [][]float64{ + {9, 18, 18, 21}, + {-15, -33, -30, -36}, + {69, 150, 138, 165}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {-0.46875, 0.375}, + {0.1875, 0.75}, + {1.875, 3}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {168, 267}, + {-78, -123}, + {15, 24}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6, 2, 3}, + {4, 7, 4, 5}, + {5, 8, 6, 7}, + }, + ans: [][]float64{ + {-0.46875, 0.375, -2.0625, -1.78125}, + {0.1875, 0.75, -0.375, -0.1875}, + {1.875, 3, 2.25, 2.625}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6, 2, 3}, + {4, 7, 4, 5}, + {5, 8, 6, 7}, + }, + ans: [][]float64{ + {168, 267, 204, 237}, + {-78, -123, -96, -111}, + {15, 24, 18, 21}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {15, -2.4, -48.0 / 35}, + {19.5, -3.3, -66.0 / 35}, + {24, -4.2, -2.4}, + {28.5, -5.1, -102.0 / 35}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + {48, -93, 420}, + {57, -111, 501}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {15, -2.4, -48.0 / 35}, + {19.5, -3.3, -66.0 / 35}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + {7.35, 2.1, 6.75}, + {8.925, 2.55, 7.875}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + {651, -273, 54}, + {759, -318, 63}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + {7.35, 2.1, 6.75}, + {8.925, 2.55, 7.875}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + {651, -273, 54}, + {759, -318, 63}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {15, -2.4, -1.2}, + {19.5, -3.3, -1.65}, + {24, -4.2, -2.1}, + {28.5, -5.1, -2.55}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + {48, -93, 420}, + {57, -111, 501}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {15, -2.4, -1.2}, + {19.5, -3.3, -1.65}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + ansFlat := flatten(test.ans) + var lda int + if test.s == blas.Left { + lda = test.m + } else { + lda = test.n + } + blasser.Dtrsm(test.s, test.ul, test.tA, test.d, test.m, test.n, test.alpha, aFlat, lda, bFlat, test.n) + if !floats.EqualApprox(ansFlat, bFlat, 1e-13) { + t.Errorf("Case %v: Want %v, got %v.", i, ansFlat, bFlat) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtrsv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtrsv.go new file mode 100644 index 00000000..1638177c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtrsv.go @@ -0,0 +1,144 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrsver interface { + Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtrsvTest(t *testing.T, blasser Dtrsver) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + tA blas.Transpose + d blas.Diag + x []float64 + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 1, 15}, + {0, 0, 1}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 1, 0}, + {3, 15, 1}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + blasser.Dtrsv(test.ul, test.tA, test.d, test.n, aFlat, test.n, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, incX = %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-2, 0) + incTest(3, 0) + incTest(-3, 8) + incTest(4, 2) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dtxmv.go b/vendor/gonum.org/v1/gonum/blas/testblas/dtxmv.go new file mode 100644 index 00000000..c55da3bd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dtxmv.go @@ -0,0 +1,145 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtxmver interface { + Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, x []float64, incX int) +} + +type vec struct { + data []float64 + inc int +} + +var cases = []struct { + n, k int + ul blas.Uplo + d blas.Diag + ldab int + tr, tb, tp []float64 + ins []vec + solNoTrans []float64 + solTrans []float64 +}{ + { + n: 3, + k: 1, + ul: blas.Upper, + d: blas.NonUnit, + tr: []float64{1, 2, 0, 0, 3, 4, 0, 0, 5}, + tb: []float64{1, 2, 3, 4, 5, 0}, + ldab: 2, + tp: []float64{1, 2, 0, 3, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{8, 25, 20}, + solTrans: []float64{2, 13, 32}, + }, + { + n: 3, + k: 1, + ul: blas.Upper, + d: blas.Unit, + tr: []float64{1, 2, 0, 0, 3, 4, 0, 0, 5}, + tb: []float64{1, 2, 3, 4, 5, 0}, + ldab: 2, + tp: []float64{1, 2, 0, 3, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{8, 19, 4}, + solTrans: []float64{2, 7, 16}, + }, + { + n: 3, + k: 1, + ul: blas.Lower, + d: blas.NonUnit, + tr: []float64{1, 0, 0, 2, 3, 0, 0, 4, 5}, + tb: []float64{0, 1, 2, 3, 4, 5}, + ldab: 2, + tp: []float64{1, 2, 3, 0, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{2, 13, 32}, + solTrans: []float64{8, 25, 20}, + }, + { + n: 3, + k: 1, + ul: blas.Lower, + d: blas.Unit, + tr: []float64{1, 0, 0, 2, 3, 0, 0, 4, 5}, + tb: []float64{0, 1, 2, 3, 4, 5}, + ldab: 2, + tp: []float64{1, 2, 3, 0, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{2, 7, 16}, + solTrans: []float64{8, 19, 4}, + }, +} + +func DtxmvTest(t *testing.T, blasser Dtxmver) { + + for nc, c := range cases { + for nx, x := range c.ins { + in := make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtrmv(c.ul, blas.NoTrans, c.d, c.n, c.tr, c.n, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtrmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtrmv(c.ul, blas.Trans, c.d, c.n, c.tr, c.n, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtrmv result for: Trans in Case:", nc, "input:", nx) + } + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtbmv(c.ul, blas.NoTrans, c.d, c.n, c.k, c.tb, c.ldab, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtbmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtbmv(c.ul, blas.Trans, c.d, c.n, c.k, c.tb, c.ldab, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtbmv result for: Trans in Case:", nc, "input:", nx) + } + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtpmv(c.ul, blas.NoTrans, c.d, c.n, c.tp, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtpmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtpmv(c.ul, blas.Trans, c.d, c.n, c.tp, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtpmv result for: Trans in Case:", nc, "input:", nx) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dzasum.go b/vendor/gonum.org/v1/gonum/blas/testblas/dzasum.go new file mode 100644 index 00000000..ab376a4c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dzasum.go @@ -0,0 +1,58 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dzasumer interface { + Dzasum(n int, x []complex128, incX int) float64 +} + +func DzasumTest(t *testing.T, impl Dzasumer) { + const tol = 1e-14 + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 50, 100} { + for _, incX := range []int{-5, 1, 2, 10} { + aincX := abs(incX) + var x []complex128 + if n > 0 { + x = make([]complex128, (n-1)*aincX+1) + } + for i := range x { + x[i] = cmplx.NaN() + } + for i := 0; i < n; i++ { + re := float64(2*i + 1) + if rnd.Intn(2) == 0 { + re *= -1 + } + im := float64(2 * (i + 1)) + if rnd.Intn(2) == 0 { + im *= -1 + } + x[i*aincX] = complex(re, im) + } + + want := float64(n * (2*n + 1)) + got := impl.Dzasum(n, x, incX) + + if incX < 0 { + if got != 0 { + t.Errorf("Case n=%v,incX=%v: non-zero result when incX < 0. got %v", n, incX, got) + } + continue + } + if !floats.EqualWithinAbsOrRel(got, want, tol, tol) { + t.Errorf("Case n=%v,incX=%v: unexpected result. want %v, got %v", n, incX, want, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/dznrm2.go b/vendor/gonum.org/v1/gonum/blas/testblas/dznrm2.go new file mode 100644 index 00000000..3742347a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/dznrm2.go @@ -0,0 +1,137 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dznrm2er interface { + Dznrm2(n int, x []complex128, incX int) float64 + Dnrm2er +} + +func Dznrm2Test(t *testing.T, impl Dznrm2er) { + tol := 1e-12 + for tc, test := range []struct { + x []complex128 + want float64 + }{ + { + x: nil, + want: 0, + }, + { + x: []complex128{1 + 2i}, + want: 2.2360679774998, + }, + { + x: []complex128{1 + 2i, 3 + 4i}, + want: 5.4772255750517, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + want: 9.5393920141695, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + want: 1.4282856857086e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + want: 1.9621416870349e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + want: 2.5495097567964e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + want: 3.1859064644148e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + want: 3.8678159211627e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + want: 4.5923850012820e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + want: 5.3572380943915e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + want: 6.1603571325046e+01, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + want: 70, + }, + } { + n := len(test.x) + for _, incX := range []int{-10, -1, 1, 2, 9, 17} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + got := impl.Dznrm2(n, x, incX) + + prefix := fmt.Sprintf("Case %v (n=%v,incX=%v):", tc, n, incX) + + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x", prefix) + } + + if incX < 0 { + if got != 0 { + t.Errorf("%v: non-zero result when incX < 0. got %v", prefix, got) + } + continue + } + + if !floats.EqualWithinAbsOrRel(test.want, got, tol, tol) { + t.Errorf("%v: unexpected result. want %v, got %v", prefix, test.want, got) + } + } + } + + tol = 1e-14 + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{10, 50, 100} { + for _, incX := range []int{1, 2, 10} { + re := make([]float64, n) + for i := range re { + re[i] = rnd.NormFloat64() + } + im := make([]float64, n) + for i := range im { + im[i] = rnd.NormFloat64() + } + want := math.Hypot(impl.Dnrm2(n, re, 1), impl.Dnrm2(n, im, 1)) + + x := make([]complex128, (n-1)*incX+1) + for i := range x { + x[i] = cmplx.NaN() + } + for i := range re { + x[i*incX] = complex(re[i], im[i]) + } + + got := impl.Dznrm2(n, x, incX) + + if !floats.EqualWithinAbsOrRel(want, got, tol, tol) { + t.Errorf("Case n=%v,incX=%v: unexpected result using Dnrm2. want %v, got %v", n, incX, want, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/izamax.go b/vendor/gonum.org/v1/gonum/blas/testblas/izamax.go new file mode 100644 index 00000000..76798c7a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/izamax.go @@ -0,0 +1,47 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "math/cmplx" + "math/rand" + "testing" +) + +type Izamaxer interface { + Izamax(n int, x []complex128, incX int) int +} + +func IzamaxTest(t *testing.T, impl Izamaxer) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 50, 100} { + for _, incX := range []int{-5, 1, 2, 10} { + aincX := abs(incX) + var x []complex128 + if n > 0 { + x = make([]complex128, (n-1)*aincX+1) + } + for i := range x { + x[i] = cmplx.NaN() + } + for i := 0; i < n; i++ { + re := 2*rnd.Float64() - 1 + im := 2*rnd.Float64() - 1 + x[i*aincX] = complex(re, im) + } + + want := -1 + if incX > 0 && n > 0 { + want = rnd.Intn(n) + x[want*incX] = 10 + 10i + } + got := impl.Izamax(n, x, incX) + + if got != want { + t.Errorf("Case n=%v,incX=%v: unexpected result. want %v, got %v", n, incX, want, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/level1double.go b/vendor/gonum.org/v1/gonum/blas/testblas/level1double.go new file mode 100644 index 00000000..8673891f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/level1double.go @@ -0,0 +1,2048 @@ +// Copyright ©2015 The gonum 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 testblas + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" + + "math" + "testing" +) + +type DoubleOneVectorCase struct { + Name string + X []float64 + Incx int + N int + Panic bool + Dasum float64 + Dnrm2 float64 + Idamax int + DscalCases []DScalCase +} + +type DScalCase struct { + Alpha float64 + Ans []float64 + Name string +} + +var DoubleOneVectorCases = []DoubleOneVectorCase{ + { + Name: "AllPositive", + X: []float64{6, 5, 4, 2, 6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + { + Alpha: 1, + Ans: []float64{6, 5, 4, 2, 6}, + }, + { + Alpha: -2, + Ans: []float64{-12, -10, -8, -4, -12}, + }, + }, + }, + { + Name: "LeadingZero", + X: []float64{0, 1}, + Incx: 1, + N: 2, + Panic: false, + Dasum: 1, + Dnrm2: 1, + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: 0, + Ans: []float64{0, 0}, + }, + { + Alpha: 1, + Ans: []float64{0, 1}, + }, + { + Alpha: -2, + Ans: []float64{0, -2}, + }, + }, + }, + { + Name: "MaxInMiddle", + X: []float64{6, 5, 9, 0, 6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 26, + Dnrm2: 13.34166406412633371248943627250846646911846482744007727141318, + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-12, -10, -18, 0, -12}, + }, + }, + }, + { + Name: "MaxAtEnd", + X: []float64{6, 5, -9, 0, 10}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 30, + Dnrm2: 15.55634918610404553681857596630667886426639062914642880494347, + Idamax: 4, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-12, -10, 18, 0, -20}, + }, + }, + }, + { + Name: "AllNegative", + X: []float64{-6, -5, -4, -2, -6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 10, 8, 4, 12}, + }, + }, + }, + { + Name: "AllMixed", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, -10, -8, 4, 12}, + }, + }, + }, + { + Name: "ZeroN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "OneN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 1, + Panic: false, + Dasum: 6, + Dnrm2: 6, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "PositiveExactInc", + X: []float64{-6, 5, 10, -2, -5}, + Incx: 2, + N: 3, + Panic: false, + Dasum: 21, + Dnrm2: 12.68857754044952038019377274608948979173952662752515253090272, + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, -20, -2, 10}, + }, + }, + }, + { + Name: "PositiveOffInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: 3, + N: 3, + Panic: false, + Dasum: 18, + Dnrm2: 11.83215956619923208513465658312323409683100246158868064575943, + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, 4, -6, 8, -20, 11}, + }, + }, + }, + { + Name: "PositiveShortInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: 3, + N: 2, + Panic: false, + Dasum: 8, + Dnrm2: 6.324555320336758663997787088865437067439110278650433653715009, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, 4, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -1, + N: 5, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeExactInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -2, + N: 3, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeOffInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: -3, + N: 2, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeShortInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: -3, + N: 2, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 2, + N: -5, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "ZeroInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 0, + N: 5, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "OutOfBounds", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 2, + N: 6, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeOutOfBounds", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -2, + N: 6, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NaN", + X: []float64{math.NaN(), 2.0}, + Incx: 1, + N: 2, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{math.NaN(), -4.0}, + }, + { + Alpha: 0, + Ans: []float64{0, 0}, + }, + }, + }, + { + Name: "NaNInc", + X: []float64{math.NaN(), math.NaN(), 2.0}, + Incx: 2, + N: 2, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{math.NaN(), math.NaN(), -4.0}, + }, + { + Alpha: 0, + Ans: []float64{0, math.NaN(), 0}, + }, + }, + }, + { + Name: "Empty", + X: []float64{}, + Incx: 1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroInc", + X: []float64{}, + Incx: 0, + N: 0, + Panic: true, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "EmptyReverse", + X: []float64{}, + Incx: -1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "MultiInf", + X: []float64{5, math.Inf(1), math.Inf(-1), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.Inf(1), + Dnrm2: math.Inf(1), + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.Inf(-1), math.Inf(1), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, + { + Name: "NaNInf", + X: []float64{5, math.NaN(), math.Inf(-1), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.NaN(), math.Inf(1), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, + { + Name: "InfNaN", + X: []float64{5, math.Inf(1), math.NaN(), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.Inf(-1), math.NaN(), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, +} + +type DoubleTwoVectorCase struct { + Name string + X []float64 + Y []float64 + XTmp []float64 + YTmp []float64 + Incx int + Incy int + N int + Panic bool + // For Daxpy + DaxpyCases []DaxpyCase + DdotAns float64 + DswapAns DTwoVecAnswer + DcopyAns DTwoVecAnswer + DrotCases []DrotCase + DrotmCases []DrotmCase +} + +type DaxpyCase struct { + Alpha float64 + Ans []float64 +} + +type DrotCase struct { + C float64 + S float64 + XAns []float64 + YAns []float64 +} + +type DrotmCase struct { + P blas.DrotmParams + XAns []float64 + YAns []float64 + Name string +} + +type DTwoVecAnswer struct { + X []float64 + Y []float64 +} + +var DoubleTwoVectorCases = []DoubleTwoVectorCase{ + { + Name: "UnitaryInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 1, + N: 6, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 1, + Ans: []float64{18, 13, -2, 10, 20, 4}, + }, + { + Alpha: 2, + Ans: []float64{28, 28, -8, 13, 34, 11}, + }, + { + Alpha: -3, + Ans: []float64{-22, -47, 22, -2, -36, -24}, + }, + { + Alpha: 0, + Ans: []float64{8, -2, 4, 7, 6, -3}, + }, + }, + DdotAns: 110, + DswapAns: DTwoVecAnswer{ + X: []float64{8, -2, 4, 7, 6, -3}, + Y: []float64{10, 15, -6, 3, 14, 7}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, 15, -6, 3, 14, 7}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(0), + S: math.Sin(0), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3}, + }, + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 12.749380282068351, -3.7473736752571014, 5.677251193294846, 15.224018588957296, 5.076299724034451}, + YAns: []float64{3.024279678886205, -8.151889500183792, 6.160940718590796, 5.076299724034451, -0.4788089421498931, -5.677251193294846}, + }, + { + C: math.Cos(0.5 * math.Pi), + S: math.Sin(0.5 * math.Pi), + XAns: []float64{8, -2, 4, 7, 6, -3}, + YAns: []float64{-10, -15, 6, -3, -14, -7}, + }, + { + C: math.Cos(math.Pi), + S: math.Sin(math.Pi), + XAns: []float64{-10, -15, 6, -3, -14, -7}, + YAns: []float64{-8, 2, -4, -7, -6, 3}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Identity, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3}, + Name: "Neg2Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + Name: "Neg1Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15.2, -6.4, 2.3, 13.4, 7.3}, + YAns: []float64{9, -0.5, 3.4, 7.3, 7.4, -2.3}, + Name: "ZeroFlag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 5.5, 1, 8.5, 13, 0.5}, + YAns: []float64{-4.4, -16.4, 8.8, 1.9, -9.8, -9.1}, + Name: "OneFlag", + }, + }, + }, + { + Name: "UnitaryIncLong", + X: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + Y: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + XTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 1, + N: 6, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 1, + Ans: []float64{18, 13, -2, 10, 20, 4, 7, -6}, + }, + { + Alpha: 2, + Ans: []float64{28, 28, -8, 13, 34, 11, 7, -6}, + }, + { + Alpha: -3, + Ans: []float64{-22, -47, 22, -2, -36, -24, 7, -6}, + }, + { + Alpha: 0, + Ans: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + }, + }, + DdotAns: 110, + DswapAns: DTwoVecAnswer{ + X: []float64{8, -2, 4, 7, 6, -3, 8, -9, 10}, + Y: []float64{10, 15, -6, 3, 14, 7, 7, -6}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + Y: []float64{10, 15, -6, 3, 14, 7, 7, -6}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(0), + S: math.Sin(0), + XAns: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + YAns: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + }, + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 12.749380282068351, -3.7473736752571014, 5.677251193294846, 15.224018588957296, 5.076299724034451, 8, -9, 10}, + YAns: []float64{3.024279678886205, -8.151889500183792, 6.160940718590796, 5.076299724034451, -0.4788089421498931, -5.677251193294846, 7, -6}, + }, + { + C: math.Cos(0.5 * math.Pi), + S: math.Sin(0.5 * math.Pi), + XAns: []float64{8, -2, 4, 7, 6, -3, 8, -9, 10}, + YAns: []float64{-10, -15, 6, -3, -14, -7, 7, -6}, + }, + { + C: math.Cos(math.Pi), + S: math.Sin(math.Pi), + XAns: []float64{-10, -15, 6, -3, -14, -7, 8, -9, 10}, + YAns: []float64{-8, 2, -4, -7, -6, 3, 7, -6}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Identity, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + YAns: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + Name: "Neg2Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6, 8, -9, 10}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8, 7, -6}, + Name: "Neg1Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15.2, -6.4, 2.3, 13.4, 7.3, 8, -9, 10}, + YAns: []float64{9, -0.5, 3.4, 7.3, 7.4, -2.3, 7, -6}, + Name: "ZeroFlag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 5.5, 1, 8.5, 13, 0.5, 8, -9, 10}, + YAns: []float64{-4.4, -16.4, 8.8, 1.9, -9.8, -9.1, 7, -6}, + Name: "OneFlag", + }, + }, + }, + { + Name: "PositiveInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: 3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{28, -2, 4, -5, 6, -3, 24, 10}, + }, + }, + DdotAns: -18, + DswapAns: DTwoVecAnswer{ + X: []float64{8, 15, 7, 3, -4, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 15, -2.479518890035003, 3, 10.997835971550302, 7}, + YAns: []float64{3.024279678886205, -2, 4, 8.879864079700745, 6, -3, -9.541886812516392, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 15, -6.1, 3, 13, 7}, + YAns: []float64{5, -2, 4, 2.9, 6, -3, -0.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15, -6.7, 3, 14.4, 7}, + YAns: []float64{9, -2, 4, 6.4, 6, -3, -2.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 15, 4, 3, 3, 7}, + YAns: []float64{-4.4, -2, 4, 10.9, 6, -3, -16.8, 10}, + }, + }, + }, + { + Name: "NegativeInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: -3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{28, -2, 4, -5, 6, -3, 24, 10}, + }, + }, + DdotAns: -18, + DswapAns: DTwoVecAnswer{ + X: []float64{8, 15, 7, 3, -4, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 15, -2.479518890035003, 3, 10.997835971550302, 7}, + YAns: []float64{3.024279678886205, -2, 4, 8.879864079700745, 6, -3, -9.541886812516392, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 15, -6.1, 3, 13, 7}, + YAns: []float64{5, -2, 4, 2.9, 6, -3, -0.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15, -6.7, 3, 14.4, 7}, + YAns: []float64{9, -2, 4, 6.4, 6, -3, -2.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 15, 4, 3, 3, 7}, + YAns: []float64{-4.4, -2, 4, 10.9, 6, -3, -16.8, 10}, + }, + }, + }, + { + Name: "MixedInc1", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: -3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DdotAns: 30, + DswapAns: DTwoVecAnswer{ + X: []float64{-4, 15, 7, 3, 8, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{7.372604823403701, 15, -2.479518890035003, 3, 16.069255112438693, 7}, + YAns: []float64{1.333806631923407, -2, 4, 8.879864079700745, 6, -3, -7.851413765553595, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{9.4, 15, -6.1, 3, 11.8, 7}, + YAns: []float64{5.4, -2, 4, 2.9, 6, -3, -1, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{10.4, 15, -6.7, 3, 13.2, 7}, + YAns: []float64{9.4, -2, 4, 6.4, 6, -3, -3, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{1, 15, 4, 3, 15, 7}, + YAns: []float64{-8.4, -2, 4, 10.9, 6, -3, -12.8, 10}, + }, + }, + }, + { + Name: "MixedInc2", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DdotAns: 30, + DswapAns: DTwoVecAnswer{ + X: []float64{-4, 15, 7, 3, 8, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{7.372604823403701, 15, -2.479518890035003, 3, 16.069255112438693, 7}, + YAns: []float64{1.333806631923407, -2, 4, 8.879864079700745, 6, -3, -7.851413765553595, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{9.4, 15, -6.1, 3, 11.8, 7}, + YAns: []float64{5.4, -2, 4, 2.9, 6, -3, -1, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{10.4, 15, -6.7, 3, 13.2, 7}, + YAns: []float64{9.4, -2, 4, 6.4, 6, -3, -3, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{1, 15, 4, 3, 15, 7}, + YAns: []float64{-8.4, -2, 4, 10.9, 6, -3, -12.8, 10}, + }, + }, + }, + { + Name: "ZeroN", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DswapAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + }, + { + Name: "NegativeN", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: -3, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "ZeroIncX", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 0, + Incy: 3, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "ZeroIncY", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 0, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "OutOfBoundsX", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 8, + Incy: 2, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "OutOfBoundsY", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: 8, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + }, + { + Name: "Empty", + X: []float64{}, + Y: []float64{}, + Incx: 1, + Incy: 1, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroIncX", + X: []float64{}, + Y: []float64{}, + Incx: 0, + Incy: 1, + N: 0, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroIncY", + X: []float64{}, + Y: []float64{}, + Incx: 1, + Incy: 0, + N: 0, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyReverse", + X: []float64{}, + Y: []float64{}, + Incx: -1, + Incy: -1, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, +} + +type Ddotter interface { + Ddot(n int, x []float64, incX int, y []float64, incY int) float64 +} + +func DdotTest(t *testing.T, d Ddotter) { + ddot := d.Ddot + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { ddot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dot := ddot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dTolEqual(dot, c.DdotAns) { + t.Errorf("ddot: mismatch %v: expected %v, found %v", c.Name, c.DdotAns, dot) + } + } + + // check it works for 16-byte unaligned slices + x := []float64{1, 1, 1, 1, 1} + if n := ddot(4, x[:4], 1, x[1:], 1); n != 4 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 4, n) + } + if n := ddot(2, x[:4], 2, x[1:], 2); n != 2 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 2, n) + } + if n := ddot(2, x[:4], 3, x[1:], 3); n != 2 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 2, n) + } +} + +type Dnrm2er interface { + Dnrm2(n int, x []float64, incX int) float64 +} + +func Dnrm2Test(t *testing.T, blasser Dnrm2er) { + dnrm2 := blasser.Dnrm2 + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { dnrm2(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := dnrm2(c.N, c.X, c.Incx) + if !dTolEqual(v, c.Dnrm2) { + t.Errorf("dnrm2: mismatch %v: expected %v, found %v", c.Name, c.Dnrm2, v) + } + } +} + +type Dasumer interface { + Dasum(n int, x []float64, incX int) float64 +} + +func DasumTest(t *testing.T, blasser Dasumer) { + dasum := blasser.Dasum + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { dasum(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := dasum(c.N, c.X, c.Incx) + if !dTolEqual(v, c.Dasum) { + t.Errorf("dasum: mismatch %v: expected %v, found %v", c.Name, c.Dasum, v) + } + } +} + +type Idamaxer interface { + Idamax(n int, x []float64, incX int) int +} + +func IdamaxTest(t *testing.T, blasser Idamaxer) { + idamax := blasser.Idamax + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { idamax(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := idamax(c.N, c.X, c.Incx) + if v != c.Idamax { + s := fmt.Sprintf("idamax: mismatch %v: expected %v, found %v", c.Name, c.Idamax, v) + if floats.HasNaN(c.X) { + log.Println(s) + } else { + t.Errorf(s) + } + } + } +} + +type Dswapper interface { + Dswap(n int, x []float64, incX int, y []float64, incY int) +} + +func DswapTest(t *testing.T, d Dswapper) { + dswap := d.Dswap + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { dswap(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dswap(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.XTmp, c.DswapAns.X) { + t.Errorf("dswap: x mismatch %v: expected %v, found %v", c.Name, c.DswapAns.X, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, c.DswapAns.Y) { + t.Errorf("dswap: y mismatch %v: expected %v, found %v", c.Name, c.DswapAns.Y, c.YTmp) + } + } +} + +type Dcopier interface { + Dcopy(n int, x []float64, incX int, y []float64, incY int) +} + +func DcopyTest(t *testing.T, d Dcopier) { + dcopy := d.Dcopy + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { dcopy(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dcopy(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.XTmp, c.DcopyAns.X) { + t.Errorf("dswap: x mismatch %v: expected %v, found %v", c.Name, c.DcopyAns.X, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, c.DcopyAns.Y) { + t.Errorf("dswap: y mismatch %v: expected %v, found %v", c.Name, c.DcopyAns.Y, c.YTmp) + } + } +} + +type Daxpyer interface { + Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) +} + +func DaxpyTest(t *testing.T, d Daxpyer) { + daxpy := d.Daxpy + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DaxpyCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { daxpy(c.N, kind.Alpha, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + daxpy(c.N, kind.Alpha, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.YTmp, kind.Ans) { + t.Errorf("daxpy: mismatch %v: expected %v, found %v", c.Name, kind.Ans, c.YTmp) + } + } + } +} + +type DrotgTestStruct struct { + Name string + A, B float64 + C, S, R, Z float64 +} + +var DrotgTests = []DrotgTestStruct{ + { + Name: "ZeroAB", + C: 1, + }, + { + Name: "PosA_ZeroB", + A: 0.5, + C: 1, + R: 0.5, + }, + { + Name: "NegA_ZeroB", + A: -4.6, + C: 1, + R: -4.6, + }, + { + Name: "ZeroA_PosB", + B: 3, + S: 1, + R: 3, + Z: 1, + }, + { + Name: "ZeroA_NegB", + B: -0.3, + S: 1, + R: -0.3, + Z: 1, + }, + { + Name: "PosA_PosB_AGTB", + A: 5, + B: 0.3, + C: 0.99820484546577868593549038000, + S: 0.05989229072794672115612942280, + R: 5.00899191454727744602429072688, + Z: 0.05989229072794672115612942280, + }, + { + Name: "PosA_PosB_ALTB", + A: 3, + B: 4, + C: 3.0 / 5, + S: 4.0 / 5, + R: 5, + Z: 5.0 / 3.0, + }, + + { + Name: "PosA_NegB_AGTB", + A: 2.6, + B: -0.9, + C: 0.94498607344025815971847507095, + S: -0.32711056388316628605639521686, + R: 2.751363298439520872718790879655, + Z: -0.3271105638831662860563952168, + }, + { + Name: "PosA_NegB_ALTB", + A: 2.6, + B: -2.9, + C: -0.6675450157520258540548049558, + S: 0.7445694406464903756765132200, + R: -3.8948684188300893100043812234, + Z: 1 / -0.6675450157520258540548049558, + }, + { + Name: "NegA_PosB_AGTB", + A: -11.4, + B: 10.3, + C: 0.7419981952497362418487847947, + S: -0.6704018781642353764072353847, + R: -15.363918770938617534070671122, + Z: -0.6704018781642353764072353847, + }, + { + Name: "NegA_PosB_ALTB", + A: -1.4, + B: 10.3, + C: -0.1346838895922121112404717523, + S: 0.9908886162855605326977564640, + R: 10.394710193170370442523552032, + Z: 1 / -0.1346838895922121112404717523, + }, + { + Name: "NegA_NegB_AGTB", + A: -11.4, + B: 10.3, + C: 0.7419981952497362418487847947, + S: -0.6704018781642353764072353847, + R: -15.363918770938617534070671122, + Z: -0.6704018781642353764072353847, + }, + { + Name: "NegA_NegB_ALTB", + A: -1.4, + B: -10.3, + C: 0.1346838895922121112404717523, + S: 0.9908886162855605326977564640, + R: -10.394710193170370442523552032, + Z: 1 / 0.1346838895922121112404717523, + }, +} + +type Drotger interface { + Drotg(a, b float64) (c, s, r, z float64) +} + +func DrotgTest(t *testing.T, d Drotger) { + drotg := d.Drotg + for _, test := range DrotgTests { + c, s, r, z := drotg(test.A, test.B) + if !dTolEqual(c, test.C) { + t.Errorf("drotg: c mismatch %v: expected %v, found %v", test.Name, test.C, c) + } + if !dTolEqual(s, test.S) { + t.Errorf("drotg: s mismatch %v: expected %v, found %v", test.Name, test.S, s) + } + if !dTolEqual(r, test.R) { + t.Errorf("drotg: r mismatch %v: expected %v, found %v", test.Name, test.R, r) + } + if !dTolEqual(z, test.Z) { + t.Errorf("drotg: z mismatch %v: expected %v, found %v", test.Name, test.Z, z) + } + } +} + +type DrotmgTestStruct struct { + Name string + D1, D2, X1, Y1 float64 + P *blas.DrotmParams + Rd1, Rd2, Rx1 float64 +} + +var DrotmgTests = []DrotmgTestStruct{ + { + Name: "NegD1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + }, + D1: -4, + D2: 6, + X1: 8, + Y1: -4, + }, + { + Name: "ZeroD2", + P: &blas.DrotmParams{ + Flag: blas.Identity, + }, + D1: 4, + X1: 8, + Y1: -5, + Rd1: 4, + Rx1: 8, + }, + { + Name: "ZeroY1", + P: &blas.DrotmParams{ + Flag: blas.Identity, + }, + D1: 4, + D2: -6, + X1: 8, + Rd1: 4, + Rd2: -6, + Rx1: 8, + }, + { + Name: "NegQ2_and_AQ1_LT_AQ2", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + }, + D1: 8, + D2: -6, + X1: 4, + Y1: 8, + Rd1: 0, + Rd2: 0, + Rx1: 0, + }, + { + Name: "ZeroD1", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0, 0, 0, 2}, + }, + D1: 0, + D2: 2, + X1: 8, + Y1: 4, + Rd1: 2, + Rd2: 0, + Rx1: 4, + }, + { + Name: "AbsQ1_GT_AbsQU__D2_Pos", + P: &blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{0, -0.625, 0.9375, 0}, + }, + D1: 2, + D2: 3, + X1: 8, + Y1: 5, + Rd1: 1.2610837438423645, + Rd2: 1.8916256157635467, + Rx1: 12.6875, + }, + { + Name: "AbsQ1_GT_AbsQU__D2_Neg", + P: &blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{0, -0.625, -0.9375, 0}, + }, + D1: 2, + D2: -3, + X1: 8, + Y1: 5, + Rd1: 4.830188679245283, + Rd2: -7.245283018867925, + Rx1: 3.3125, + }, + { + Name: "AbsQ1_LT_AbsQU__D2_Pos", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{5.0 / 12, 0, 0, 0.625}, + }, + D1: 2, + D2: 3, + X1: 5, + Y1: 8, + Rd1: 2.3801652892561984, + Rd2: 1.586776859504132, + Rx1: 121.0 / 12, + }, + { + Name: "D1=D2_X1=X2", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{1, 0, 0, 1}, + }, + D1: 2, + D2: 2, + X1: 8, + Y1: 8, + Rd1: 1, + Rd2: 1, + Rx1: 16, + }, + { + Name: "RD1_Big_RD2_Big_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4096, -3584, 1792, 4096}, + }, + D1: 1600000000, + D2: 800000000, + X1: 8, + Y1: 7, + Rd1: 68.96627824858757, + Rd2: 34.483139124293785, + Rx1: 45312, + }, + { + Name: "RD1_Big_RD2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2340.5714285714284, -4096, 4096, 4681.142857142857}, + }, + D1: 800000000, + D2: 1600000000, + X1: 8, + Y1: 7, + Rd1: 57.6914092640818, + Rd2: 28.8457046320409, + Rx1: 47396.57142857142, + }, + { + Name: "RD1_Big_RD2_Med_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4096, -1, 0.0004096, 1}, + }, + D1: 20000000, + D2: 2, + X1: 8, + Y1: 8, + Rd1: 1.1920927762985347, + Rd2: 1.9999998000000199, + Rx1: 32768.0032768, + }, + { + Name: "RD1_Big_RD2_Med_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4.096e-17, -1, 4096, 1e-10}, + }, + D1: 2, + D2: 20000000000, + X1: 8, + Y1: 80000000000, + Rd1: 1192.0928955078125, + Rd2: 2, + Rx1: 3.2768e+14, + }, + + // TODO: Add D1 big, D2 small, Flag = 0 + { + Name: "D1_Big_D2_Small_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2.8671999999999997e-26, -0.000244140625, 4096, 2.44140625e-16}, + }, + D1: 0.000000014, + D2: 2000000000, + X1: 0.000008, + Y1: 8000000, + Rd1: 119.20928955078125, + Rd2: 0.234881024, + Rx1: 3.2768e+10, + }, + + { + Name: "RD1_Med_RD2_Big_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{1, -0.0004096, 1000, 4096}, + }, + D1: 2, + D2: 20000000000, + X1: 80000000, + Y1: 8, + Rd1: 1.9998000199980002, + Rd2: 1191.9736981379988, + Rx1: 8.0008e+07, + }, + { + Name: "D1_Med_D2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{50, -4096, 1, 4.096e-06}, + }, + D1: 20000000000, + D2: 0.4, + X1: 80000000, + Y1: 80000000000000000, + Rd1: 0.39999998000000103, + Rd2: 1192.092835903171, + Rx1: 8.0000004e+16, + }, + { + Name: "RD1_Med_RD2_Small_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{1, -0.0007233796296296296, 1.1111111111111111e-10, 0.000244140625}, + }, + D1: 1.2, + D2: 0.000000000045, + X1: 2.7, + Y1: 8, + Rd1: 1.1999999996049382, + Rd2: 0.0007549747197514486, + Rx1: 2.700000000888889, + }, + { + Name: "RD1_Med_RD2_Small_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.0002197265625, -1, 0.000244140625, 3.375e-11}, + }, + D1: 1.2, + D2: 0.000000000045, + X1: 2.7, + Y1: 80000000000, + Rd1: 0.0007549747199770676, + Rd2: 1.19999999996355, + Rx1: 1.9531250000593264e+07, + }, + // TODO: Add Small, Big, 0 case + { + Name: "D1_Small_D2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2.3731773997569866e+10, -1.6777216e+07, 0.000244140625, 1.6777216e-07}, + }, + D1: 120000000000000000, + D2: 0.000000000012345, + X1: 0.08, + Y1: 8000000000000, + Rd1: 0.00010502490698765249, + Rd2: 216.1836123957717, + Rx1: 3.8516669198055897e+09, + }, + { + Name: "RD1_Small_RD2_Med_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.000244140625, -1e-08, 0.24414062499999997, 1}, + }, + D1: 0.0000000002, + D2: 20, + X1: 0.8, + Y1: 0.000000008, + Rd1: 0.003355409645903541, + Rd2: 19.99980000199998, + Rx1: 0.000195314453125, + }, + { + Name: "RD1_Small_RD2_Med_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.0012207031250000002, -1, 0.000244140625, 1e-09}, + }, + D1: 0.02, + D2: 0.000000000004, + X1: 0.008, + Y1: 8000000, + Rd1: 6.710886366445568e-05, + Rd2: 0.019999999900000003, + Rx1: 1953.125009765625, + }, + // TODO: Add Small, Small, 0 case + // TODO: Add Small, Small, 1 case +} + +type Drotmger interface { + Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) +} + +func DrotmgTest(t *testing.T, d Drotmger) { + for _, test := range DrotmgTests { + + p, rd1, rd2, rx1 := d.Drotmg(test.D1, test.D2, test.X1, test.Y1) + + if p.Flag != test.P.Flag { + t.Errorf("drotmg flag mismatch %v: expected %v, found %v", test.Name, test.P.Flag, p.Flag) + } + for i, val := range p.H { + if !dTolEqual(test.P.H[i], val) { + t.Errorf("drotmg H mismatch %v: expected %v, found %v", test.Name, test.P.H, p.H) + break + } + } + if !dTolEqual(rd1, test.Rd1) { + t.Errorf("drotmg rd1 mismatch %v: expected %v, found %v", test.Name, test.Rd1, rd1) + } + if !dTolEqual(rd2, test.Rd2) { + t.Errorf("drotmg rd2 mismatch %v: expected %v, found %v", test.Name, test.Rd2, rd2) + } + if !dTolEqual(rx1, test.Rx1) { + t.Errorf("drotmg rx1 mismatch %v: expected %v, found %v", test.Name, test.Rx1, rx1) + } + } +} + +type Droter interface { + Drot(n int, x []float64, incX int, y []float64, incY int, c, s float64) +} + +func DrotTest(t *testing.T, d Droter) { + drot := d.Drot + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DrotCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { drot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.C, kind.S) } + testpanics(f, c.Name, t) + continue + } + drot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.C, kind.S) + if !dSliceTolEqual(c.XTmp, kind.XAns) { + t.Errorf("drot: x mismatch %v: expected %v, found %v", c.Name, kind.XAns, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, kind.YAns) { + t.Errorf("drot: y mismatch %v: expected %v, found %v", c.Name, kind.YAns, c.YTmp) + } + } + } +} + +type Drotmer interface { + Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) +} + +func DrotmTest(t *testing.T, d Drotmer) { + drotm := d.Drotm + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DrotmCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { drotm(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.P) } + testpanics(f, c.Name+", "+kind.Name, t) + continue + } + drotm(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.P) + if !dSliceTolEqual(c.XTmp, kind.XAns) { + t.Errorf("drotm: mismatch %v: expected %v, found %v", c.Name, kind.XAns, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, kind.YAns) { + t.Errorf("drotm: mismatch %v: expected %v, found %v", c.Name, kind.YAns, c.YTmp) + } + } + } +} + +type Dscaler interface { + Dscal(n int, alpha float64, x []float64, incX int) +} + +func DscalTest(t *testing.T, blasser Dscaler) { + dscal := blasser.Dscal + for _, c := range DoubleOneVectorCases { + for _, kind := range c.DscalCases { + xTmp := make([]float64, len(c.X)) + copy(xTmp, c.X) + if c.Panic { + f := func() { dscal(c.N, kind.Alpha, xTmp, c.Incx) } + testpanics(f, c.Name, t) + continue + } + dscal(c.N, kind.Alpha, xTmp, c.Incx) + if !dSliceTolEqual(xTmp, kind.Ans) { + t.Errorf("dscal: mismatch %v, %v: expected %v, found %v", c.Name, kind.Name, kind.Ans, xTmp) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/level2bench.go b/vendor/gonum.org/v1/gonum/blas/testblas/level2bench.go new file mode 100644 index 00000000..387ffcce --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/level2bench.go @@ -0,0 +1,60 @@ +package testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DgemvBenchmark(b *testing.B, blasser Dgemver, tA blas.Transpose, m, n, incX, incY int) { + var lenX, lenY int + if tA == blas.NoTrans { + lenX = n + lenY = m + } else { + lenX = m + lenY = n + } + xr := make([]float64, lenX) + for i := range xr { + xr[i] = rand.Float64() + } + x := makeIncremented(xr, incX, 0) + yr := make([]float64, lenY) + for i := range yr { + yr[i] = rand.Float64() + } + y := makeIncremented(yr, incY, 0) + a := make([]float64, m*n) + for i := range a { + a[i] = rand.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + blasser.Dgemv(tA, m, n, 2, a, n, x, incX, 3, y, incY) + } +} + +func DgerBenchmark(b *testing.B, blasser Dgerer, m, n, incX, incY int) { + xr := make([]float64, m) + for i := range xr { + xr[i] = rand.Float64() + } + x := makeIncremented(xr, incX, 0) + yr := make([]float64, n) + for i := range yr { + yr[i] = rand.Float64() + } + y := makeIncremented(yr, incY, 0) + a := make([]float64, m*n) + for i := range a { + a[i] = rand.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + blasser.Dger(m, n, 2, x, incX, y, incY, a, n) + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zaxpy.go b/vendor/gonum.org/v1/gonum/blas/testblas/zaxpy.go new file mode 100644 index 00000000..9aeace52 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zaxpy.go @@ -0,0 +1,157 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "testing" +) + +type Zaxpyer interface { + Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) +} + +func ZaxpyTest(t *testing.T, impl Zaxpyer) { + for tc, test := range []struct { + alpha complex128 + x, y []complex128 + + want []complex128 // Result when both increments have the same sign. + wantRev []complex128 // Result when the increments have opposite sign. + }{ + { + alpha: 0, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + want: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + wantRev: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + }, + { + alpha: 1, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + want: []complex128{31 + 33i, 36 + 38i, 41 + 43i, 46 + 48i, 51 + 53i, 56 + 58i, 61 + 63i, 66 + 68i, 71 + 73i, 76 + 78i, 81 + 83i, 86 + 88i}, + wantRev: []complex128{53 + 55i, 54 + 56i, 55 + 57i, 56 + 58i, 57 + 59i, 58 + 60i, 59 + 61i, 60 + 62i, 61 + 63i, 62 + 64i, 63 + 65i, 64 + 66i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i}, + y: []complex128{30 + 31i}, + want: []complex128{19 + 44i}, + wantRev: []complex128{19 + 44i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i}, + y: []complex128{30 + 31i, 33 + 34i}, + want: []complex128{19 + 44i, 14 + 67i}, + wantRev: []complex128{11 + 64i, 22 + 47i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i}, + wantRev: []complex128{3 + 84i, 14 + 67i, 25 + 50i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i}, + wantRev: []complex128{-5 + 104i, 6 + 87i, 17 + 70i, 28 + 53i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i}, + wantRev: []complex128{-13 + 124i, -2 + 107i, 9 + 90i, 20 + 73i, 31 + 56i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i}, + wantRev: []complex128{-21 + 144i, -10 + 127i, 1 + 110i, 12 + 93i, 23 + 76i, 34 + 59i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i}, + wantRev: []complex128{-29 + 164i, -18 + 147i, -7 + 130i, 4 + 113i, 15 + 96i, 26 + 79i, 37 + 62i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i, -16 + 205i}, + wantRev: []complex128{-37 + 184i, -26 + 167i, -15 + 150i, -4 + 133i, 7 + 116i, 18 + 99i, 29 + 82i, 40 + 65i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i, -16 + 205i, -21 + 228i}, + wantRev: []complex128{-45 + 204i, -34 + 187i, -23 + 170i, -12 + 153i, -1 + 136i, 10 + 119i, 21 + 102i, 32 + 85i, 43 + 68i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i, -16 + 205i, -21 + 228i, -26 + 251i}, + wantRev: []complex128{-53 + 224i, -42 + 207i, -31 + 190i, -20 + 173i, -9 + 156i, 2 + 139i, 13 + 122i, 24 + 105i, 35 + 88i, 46 + 71i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i, -16 + 205i, -21 + 228i, -26 + 251i, -31 + 274i}, + wantRev: []complex128{-61 + 244i, -50 + 227i, -39 + 210i, -28 + 193i, -17 + 176i, -6 + 159i, 5 + 142i, 16 + 125i, 27 + 108i, 38 + 91i, 49 + 74i}, + }, + { + alpha: 3 + 7i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + want: []complex128{19 + 44i, 14 + 67i, 9 + 90i, 4 + 113i, -1 + 136i, -6 + 159i, -11 + 182i, -16 + 205i, -21 + 228i, -26 + 251i, -31 + 274i, -36 + 297i}, + wantRev: []complex128{-69 + 264i, -58 + 247i, -47 + 230i, -36 + 213i, -25 + 196i, -14 + 179i, -3 + 162i, 8 + 145i, 19 + 128i, 30 + 111i, 41 + 94i, 52 + 77i}, + }, + } { + n := len(test.x) + if len(test.y) != n || len(test.want) != n || len(test.wantRev) != n { + panic("bad test") + } + for _, inc := range allPairs([]int{-7, -3, 1, 13}, []int{-11, -5, 1, 17}) { + incX := inc[0] + incY := inc[1] + + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + + var want []complex128 + if incX*incY > 0 { + want = makeZVector(test.want, incY) + } else { + want = makeZVector(test.wantRev, incY) + } + + impl.Zaxpy(n, test.alpha, x, incX, y, incY) + + prefix := fmt.Sprintf("Case %v (incX=%v,incY=%v):", tc, incX, incY) + + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x", prefix) + } + + if !zsame(y, want) { + t.Errorf("%v: unexpected y:\nwant %v\ngot %v", prefix, want, y) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zcopy.go b/vendor/gonum.org/v1/gonum/blas/testblas/zcopy.go new file mode 100644 index 00000000..9aba717d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zcopy.go @@ -0,0 +1,71 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "math" + "math/rand" + "testing" +) + +type Zcopyer interface { + Zcopy(n int, x []complex128, incX int, y []complex128, incY int) +} + +func ZcopyTest(t *testing.T, impl Zcopyer) { + rnd := rand.New(rand.NewSource(1)) + for n := 0; n <= 20; n++ { + for _, inc := range allPairs([]int{-7, -3, 1, 13}, []int{-11, -5, 1, 17}) { + incX := inc[0] + incY := inc[1] + aincX := abs(incX) + aincY := abs(incY) + + var x []complex128 + if n > 0 { + x = make([]complex128, (n-1)*aincX+1) + } + for i := range x { + x[i] = complex(math.NaN(), math.NaN()) + } + for i := 0; i < n; i++ { + x[i*aincX] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + } + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + var y []complex128 + if n > 0 { + y = make([]complex128, (n-1)*aincY+1) + } + for i := range y { + y[i] = complex(math.NaN(), math.NaN()) + } + + want := make([]complex128, len(y)) + if incX*incY > 0 { + for i := 0; i < n; i++ { + want[i*aincY] = x[i*aincX] + } + } else { + for i := 0; i < n; i++ { + want[i*aincY] = x[(n-1-i)*aincX] + } + } + + impl.Zcopy(n, x, incX, y, incY) + + prefix := fmt.Sprintf("Case n=%v,incX=%v,incY=%v:", n, incX, incY) + + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x", prefix) + } + if !zsame(y, want) { + t.Errorf("%v: unexpected y:\nwant %v\ngot %v", prefix, want, y) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zdotc.go b/vendor/gonum.org/v1/gonum/blas/testblas/zdotc.go new file mode 100644 index 00000000..a28b0c1a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zdotc.go @@ -0,0 +1,139 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "testing" +) + +type Zdotcer interface { + Zdotc(n int, x []complex128, incX int, y []complex128, incY int) complex128 +} + +func ZdotcTest(t *testing.T, impl Zdotcer) { + for tc, test := range []struct { + x, y []complex128 + + want complex128 // Result when both increments have the same sign. + wantRev complex128 // Result when the increments have opposite sign. + }{ + { + x: nil, + y: nil, + want: 0, + wantRev: 0, + }, + { + x: []complex128{1 + 2i}, + y: []complex128{30 + 31i}, + want: 92 - 29i, + wantRev: 92 - 29i, + }, + { + x: []complex128{1 + 2i, 3 + 4i}, + y: []complex128{30 + 31i, 33 + 34i}, + want: 327 - 59i, + wantRev: 315 - 59i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i}, + want: 729 - 90i, + wantRev: 681 - 90i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i}, + want: 1322 - 122i, + wantRev: 1202 - 122i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i}, + want: 2130 - 155i, + wantRev: 1890 - 155i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i}, + want: 3177 - 189i, + wantRev: 2757 - 189i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i}, + want: 4487 - 224i, + wantRev: 3815 - 224i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i}, + want: 6084 - 260i, + wantRev: 5076 - 260i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i}, + want: 7992 - 297i, + wantRev: 6552 - 297i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i}, + want: 10235 - 335i, + wantRev: 8255 - 335i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i}, + want: 12837 - 374i, + wantRev: 10197 - 374i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + want: 15822 - 414i, + wantRev: 12390 - 414i, + }, + } { + n := len(test.x) + if len(test.y) != n { + panic("bad test") + } + for _, inc := range allPairs([]int{-7, -3, 1, 13}, []int{-11, -5, 1, 17}) { + incX := inc[0] + incY := inc[1] + + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + yCopy := make([]complex128, len(y)) + copy(yCopy, y) + + want := test.want + if incX*incY < 0 { + want = test.wantRev + } + + got := impl.Zdotc(n, x, incX, y, incY) + + prefix := fmt.Sprintf("Case %v (incX=%v,incY=%v):", tc, incX, incY) + + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x", prefix) + } + if !zsame(y, yCopy) { + t.Errorf("%v: unexpected modification of y", prefix) + } + + if got != want { + t.Errorf("%v: unexpected result. want %v, got %v", prefix, want, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zdotu.go b/vendor/gonum.org/v1/gonum/blas/testblas/zdotu.go new file mode 100644 index 00000000..7b83b735 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zdotu.go @@ -0,0 +1,139 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "testing" +) + +type Zdotuer interface { + Zdotu(n int, x []complex128, incX int, y []complex128, incY int) complex128 +} + +func ZdotuTest(t *testing.T, impl Zdotuer) { + for tc, test := range []struct { + x, y []complex128 + + want complex128 // Result when both increments have the same sign. + wantRev complex128 // Result when the increments have opposite sign. + }{ + { + x: nil, + y: nil, + want: 0, + wantRev: 0, + }, + { + x: []complex128{1 + 2i}, + y: []complex128{30 + 31i}, + want: -32 + 91i, + wantRev: -32 + 91i, + }, + { + x: []complex128{1 + 2i, 3 + 4i}, + y: []complex128{30 + 31i, 33 + 34i}, + want: -69 + 325i, + wantRev: -69 + 313i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i}, + want: -111 + 726i, + wantRev: -111 + 678i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i}, + want: -158 + 1318i, + wantRev: -158 + 1198i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i}, + want: -210 + 2125i, + wantRev: -210 + 1885i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i}, + want: -267 + 3171i, + wantRev: -267 + 2751i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i}, + want: -329 + 4480i, + wantRev: -329 + 3808i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i}, + want: -396 + 6076i, + wantRev: -396 + 5068i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i}, + want: -468 + 7983i, + wantRev: -468 + 6543i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i}, + want: -545 + 10225i, + wantRev: -545 + 8245i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i}, + want: -627 + 12826i, + wantRev: -627 + 10186i, + }, + { + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + y: []complex128{30 + 31i, 33 + 34i, 36 + 37i, 39 + 40i, 42 + 43i, 45 + 46i, 48 + 49i, 51 + 52i, 54 + 55i, 57 + 58i, 60 + 61i, 63 + 64i}, + want: -714 + 15810i, + wantRev: -714 + 12378i, + }, + } { + n := len(test.x) + if len(test.y) != n { + panic("bad test") + } + for _, inc := range allPairs([]int{-7, -3, 1, 13}, []int{-11, -5, 1, 17}) { + incX := inc[0] + incY := inc[1] + + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + yCopy := make([]complex128, len(y)) + copy(yCopy, y) + + want := test.want + if incX*incY < 0 { + want = test.wantRev + } + + got := impl.Zdotu(n, x, incX, y, incY) + + prefix := fmt.Sprintf("Case %v (incX=%v,incY=%v):", tc, incX, incY) + + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x", prefix) + } + if !zsame(y, yCopy) { + t.Errorf("%v: unexpected modification of y", prefix) + } + + if got != want { + t.Errorf("%v: unexpected result. want %v, got %v", prefix, want, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zdscal.go b/vendor/gonum.org/v1/gonum/blas/testblas/zdscal.go new file mode 100644 index 00000000..9037d841 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zdscal.go @@ -0,0 +1,119 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "testing" +) + +type Zdscaler interface { + Zdscal(n int, alpha float64, x []complex128, incX int) +} + +func ZdscalTest(t *testing.T, impl Zdscaler) { + for tc, test := range []struct { + alpha float64 + x []complex128 + want []complex128 + }{ + { + alpha: 3, + x: nil, + want: nil, + }, + { + alpha: 3, + x: []complex128{1 + 2i}, + want: []complex128{3 + 6i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i}, + want: []complex128{3 + 6i, 9 + 12i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i, 45 + 48i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i, 45 + 48i, 51 + 54i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i, 45 + 48i, 51 + 54i, 57 + 60i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i, 45 + 48i, 51 + 54i, 57 + 60i, 63 + 66i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + want: []complex128{3 + 6i, 9 + 12i, 15 + 18i, 21 + 24i, 27 + 30i, 33 + 36i, 39 + 42i, 45 + 48i, 51 + 54i, 57 + 60i, 63 + 66i, 69 + 72i}, + }, + { + alpha: 0, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + want: []complex128{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + } { + n := len(test.x) + if len(test.want) != n { + panic("bad test") + } + for _, incX := range []int{-3, -1, 1, 2, 4, 7, 10} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + want := makeZVector(test.want, incX) + + impl.Zdscal(n, test.alpha, x, incX) + + prefix := fmt.Sprintf("Case %v (n=%v,incX=%v):", tc, n, incX) + + if incX < 0 { + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x\nwant %v\ngot %v", prefix, want, x) + } + continue + } + if !zsame(x, want) { + t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, want, x) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zgerc.go b/vendor/gonum.org/v1/gonum/blas/testblas/zgerc.go new file mode 100644 index 00000000..15a83745 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zgerc.go @@ -0,0 +1,183 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "testing" +) + +type Zgercer interface { + Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) +} + +func ZgercTest(t *testing.T, impl Zgercer) { + for tc, test := range []struct { + alpha complex128 + x []complex128 + incX int + y []complex128 + incY int + a []complex128 + + want []complex128 + }{ + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + }, + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 10 + 9i, 6 + 17i, 3 + 10i, 6 + 7i, + 3 + 4i, 11 + 16i, 5 + 14i, 11 + 18i, + 18 + 6i, 4 + 1i, 13 + 2i, 14 + 3i}, + want: []complex128{ + -185 + 534i, 26 + 277i, 118 + 485i, -289 + 592i, + 435 + 913i, 371 + 316i, 761 + 461i, 395 + 1131i, + 84 + 888i, 204 + 361i, 491 + 608i, -24 + 1037i}, + }, + { + incX: 7, + incY: 13, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 10 + 9i, 6 + 17i, 3 + 10i, 6 + 7i, + 3 + 4i, 11 + 16i, 5 + 14i, 11 + 18i, + 18 + 6i, 4 + 1i, 13 + 2i, 14 + 3i}, + want: []complex128{ + -185 + 534i, 26 + 277i, 118 + 485i, -289 + 592i, + 435 + 913i, 371 + 316i, 761 + 461i, 395 + 1131i, + 84 + 888i, 204 + 361i, 491 + 608i, -24 + 1037i}, + }, + { + incX: -7, + incY: -13, + alpha: 1 + 2i, + x: []complex128{10 + 18i, 18 + 15i, 1 + 13i}, + y: []complex128{19 + 12i, 5 + 16i, 4 + 8i, 15 + 12i}, + a: []complex128{ + 10 + 9i, 6 + 17i, 3 + 10i, 6 + 7i, + 3 + 4i, 11 + 16i, 5 + 14i, 11 + 18i, + 18 + 6i, 4 + 1i, 13 + 2i, 14 + 3i}, + want: []complex128{ + -185 + 534i, 26 + 277i, 118 + 485i, -289 + 592i, + 435 + 913i, 371 + 316i, 761 + 461i, 395 + 1131i, + 84 + 888i, 204 + 361i, 491 + 608i, -24 + 1037i}, + }, + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + x: []complex128{5 + 16i, 12 + 19i, 9 + 7i, 2 + 4i}, + y: []complex128{18 + 7i, 20 + 15i, 12 + 14i}, + a: []complex128{ + 11 + 4i, 17 + 18i, 7 + 13i, + 14 + 20i, 14 + 10i, 7 + 5i, + 7 + 17i, 10 + 6i, 11 + 13i, + 7 + 6i, 19 + 16i, 8 + 8i, + }, + want: []complex128{ + -293 + 661i, -133 + 943i, 47 + 703i, + -153 + 976i, 139 + 1260i, 297 + 885i, + 92 + 502i, 285 + 581i, 301 + 383i, + -45 + 192i, 19 + 266i, 48 + 188i, + }, + }, + { + incX: 7, + incY: 13, + alpha: 1 + 2i, + x: []complex128{5 + 16i, 12 + 19i, 9 + 7i, 2 + 4i}, + y: []complex128{18 + 7i, 20 + 15i, 12 + 14i}, + a: []complex128{ + 11 + 4i, 17 + 18i, 7 + 13i, + 14 + 20i, 14 + 10i, 7 + 5i, + 7 + 17i, 10 + 6i, 11 + 13i, + 7 + 6i, 19 + 16i, 8 + 8i, + }, + want: []complex128{ + -293 + 661i, -133 + 943i, 47 + 703i, + -153 + 976i, 139 + 1260i, 297 + 885i, + 92 + 502i, 285 + 581i, 301 + 383i, + -45 + 192i, 19 + 266i, 48 + 188i, + }, + }, + { + incX: -7, + incY: -13, + alpha: 1 + 2i, + x: []complex128{2 + 4i, 9 + 7i, 12 + 19i, 5 + 16i}, + y: []complex128{12 + 14i, 20 + 15i, 18 + 7i}, + a: []complex128{ + 11 + 4i, 17 + 18i, 7 + 13i, + 14 + 20i, 14 + 10i, 7 + 5i, + 7 + 17i, 10 + 6i, 11 + 13i, + 7 + 6i, 19 + 16i, 8 + 8i, + }, + want: []complex128{ + -293 + 661i, -133 + 943i, 47 + 703i, + -153 + 976i, 139 + 1260i, 297 + 885i, + 92 + 502i, 285 + 581i, 301 + 383i, + -45 + 192i, 19 + 266i, 48 + 188i, + }, + }, + { + incX: -7, + incY: -13, + alpha: 0, + x: []complex128{2 + 4i, 9 + 7i, 12 + 19i, 5 + 16i}, + y: []complex128{12 + 14i, 20 + 15i, 18 + 7i}, + a: []complex128{ + 11 + 4i, 17 + 18i, 7 + 13i, + 14 + 20i, 14 + 10i, 7 + 5i, + 7 + 17i, 10 + 6i, 11 + 13i, + 7 + 6i, 19 + 16i, 8 + 8i, + }, + want: []complex128{ + 11 + 4i, 17 + 18i, 7 + 13i, + 14 + 20i, 14 + 10i, 7 + 5i, + 7 + 17i, 10 + 6i, 11 + 13i, + 7 + 6i, 19 + 16i, 8 + 8i, + }, + }, + } { + m := len(test.x) + n := len(test.y) + incX := test.incX + incY := test.incY + + for _, lda := range []int{max(1, n), n + 20} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + yCopy := make([]complex128, len(y)) + copy(yCopy, y) + + a := makeZGeneral(test.a, m, n, lda) + want := makeZGeneral(test.want, m, n, lda) + + impl.Zgerc(m, n, test.alpha, x, incX, y, incY, a, lda) + + if !zsame(x, xCopy) { + t.Errorf("Case %v: unexpected modification of x", tc) + } + if !zsame(y, yCopy) { + t.Errorf("Case %v: unexpected modification of y", tc) + } + if !zsame(want, a) { + t.Errorf("Case %v: unexpected result\nwant %v\ngot %v", tc, want, a) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zgeru.go b/vendor/gonum.org/v1/gonum/blas/testblas/zgeru.go new file mode 100644 index 00000000..09c66e71 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zgeru.go @@ -0,0 +1,257 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "testing" +) + +type Zgeruer interface { + Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) +} + +func ZgeruTest(t *testing.T, impl Zgeruer) { + for tc, test := range []struct { + alpha complex128 + x []complex128 + incX int + y []complex128 + incY int + a []complex128 + + want []complex128 + }{ + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + }, + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: 7, + incY: 13, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: 1, + incY: 13, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: 1, + incY: -13, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{19 + 12i, 5 + 16i, 4 + 8i, 15 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: 7, + incY: 1, + alpha: 1 + 2i, + x: []complex128{1 + 13i, 18 + 15i, 10 + 18i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: -7, + incY: 1, + alpha: 1 + 2i, + x: []complex128{10 + 18i, 18 + 15i, 1 + 13i}, + y: []complex128{15 + 12i, 4 + 8i, 5 + 16i, 19 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: -7, + incY: -13, + alpha: 1 + 2i, + x: []complex128{10 + 18i, 18 + 15i, 1 + 13i}, + y: []complex128{19 + 12i, 5 + 16i, 4 + 8i, 15 + 12i}, + a: []complex128{ + 4 + 7i, 4 + 7i, 12 + 3i, 9 + 10i, + 3 + 3i, 1 + 2i, 17 + 17i, 9 + 18i, + 14 + 12i, 9 + 16i, 1 + 1i, 9 + 1i, + }, + want: []complex128{ + -551 - 68i, -216 - 133i, -353 - 322i, -646 - 5i, + -789 + 624i, -455 + 110i, -859 + 80i, -831 + 843i, + -832 + 270i, -399 - 40i, -737 - 225i, -941 + 411i, + }, + }, + { + incX: 1, + incY: 1, + alpha: 1 + 2i, + x: []complex128{5 + 16i, 12 + 19i, 9 + 7i, 2 + 4i}, + y: []complex128{18 + 7i, 20 + 15i, 12 + 14i}, + a: []complex128{ + 8 + 17i, 2 + 2i, 8 + 17i, + 1 + 10i, 10 + 15i, 4 + 18i, + 11 + 3i, 15 + 7i, 12 + 15i, + 20 + 10i, 8 + 13i, 19 + 10i, + }, + want: []complex128{ + -660 + 296i, -928 + 117i, -680 - 49i, + -768 + 602i, -1155 + 485i, -910 + 170i, + -254 + 418i, -460 + 432i, -398 + 245i, + -144 + 112i, -232 + 83i, -165 + 22i, + }, + }, + { + incX: 7, + incY: 13, + alpha: 1 + 2i, + x: []complex128{5 + 16i, 12 + 19i, 9 + 7i, 2 + 4i}, + y: []complex128{18 + 7i, 20 + 15i, 12 + 14i}, + a: []complex128{ + 8 + 17i, 2 + 2i, 8 + 17i, + 1 + 10i, 10 + 15i, 4 + 18i, + 11 + 3i, 15 + 7i, 12 + 15i, + 20 + 10i, 8 + 13i, 19 + 10i, + }, + want: []complex128{ + -660 + 296i, -928 + 117i, -680 - 49i, + -768 + 602i, -1155 + 485i, -910 + 170i, + -254 + 418i, -460 + 432i, -398 + 245i, + -144 + 112i, -232 + 83i, -165 + 22i, + }, + }, + { + incX: -7, + incY: -13, + alpha: 1 + 2i, + x: []complex128{2 + 4i, 9 + 7i, 12 + 19i, 5 + 16i}, + y: []complex128{12 + 14i, 20 + 15i, 18 + 7i}, + a: []complex128{ + 8 + 17i, 2 + 2i, 8 + 17i, + 1 + 10i, 10 + 15i, 4 + 18i, + 11 + 3i, 15 + 7i, 12 + 15i, + 20 + 10i, 8 + 13i, 19 + 10i, + }, + want: []complex128{ + -660 + 296i, -928 + 117i, -680 - 49i, + -768 + 602i, -1155 + 485i, -910 + 170i, + -254 + 418i, -460 + 432i, -398 + 245i, + -144 + 112i, -232 + 83i, -165 + 22i, + }, + }, + { + incX: -7, + incY: -13, + alpha: 0, + x: []complex128{5 + 16i, 12 + 19i, 9 + 7i, 2 + 4i}, + y: []complex128{18 + 7i, 20 + 15i, 12 + 14i}, + a: []complex128{ + 8 + 17i, 2 + 2i, 8 + 17i, + 1 + 10i, 10 + 15i, 4 + 18i, + 11 + 3i, 15 + 7i, 12 + 15i, + 20 + 10i, 8 + 13i, 19 + 10i, + }, + want: []complex128{ + 8 + 17i, 2 + 2i, 8 + 17i, + 1 + 10i, 10 + 15i, 4 + 18i, + 11 + 3i, 15 + 7i, 12 + 15i, + 20 + 10i, 8 + 13i, 19 + 10i, + }, + }, + } { + m := len(test.x) + n := len(test.y) + incX := test.incX + incY := test.incY + + for _, lda := range []int{max(1, n), n + 20} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + yCopy := make([]complex128, len(y)) + copy(yCopy, y) + + a := makeZGeneral(test.a, m, n, lda) + want := makeZGeneral(test.want, m, n, lda) + + impl.Zgeru(m, n, test.alpha, x, incX, y, incY, a, lda) + + if !zsame(x, xCopy) { + t.Errorf("Case %v: unexpected modification of x", tc) + } + if !zsame(y, yCopy) { + t.Errorf("Case %v: unexpected modification of y", tc) + } + if !zsame(want, a) { + t.Errorf("Case %v: unexpected result\nwant %v\ngot %v", tc, want, a) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zher.go b/vendor/gonum.org/v1/gonum/blas/testblas/zher.go new file mode 100644 index 00000000..fbd14b65 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zher.go @@ -0,0 +1,155 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "math" + "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Zherer interface { + Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) +} + +func ZherTest(t *testing.T, impl Zherer) { + for tc, test := range []struct { + alpha float64 + x []complex128 + a []complex128 + + want []complex128 + wantRev []complex128 // Result when incX is negative. + }{ + { + alpha: 1, + }, + { + alpha: 3, + x: []complex128{ + 0 - 3i, + 6 + 10i, + -2 - 7i, + }, + a: []complex128{ + -2 + 0i, -3 - 11i, 0 + 4i, + -3 + 11i, -6 + 0i, 7 + 2i, + 0 - 4i, 7 - 2i, 18 + 0i, + }, + want: []complex128{ + 25 + 0i, -93 - 65i, 63 + 22i, + -93 + 65i, 402 + 0i, -239 + 68i, + 63 - 22i, -239 - 68i, 177 + 0i}, + wantRev: []complex128{ + 157 + 0i, -249 - 77i, 63 - 14i, + -249 + 77i, 402 + 0i, -83 + 56i, + 63 + 14i, -83 - 56i, 45 + 0i, + }, + }, + { + alpha: 3, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 122 + 0i, 3 - 77i, 3 + 11i, 52 + 125i, + 3 + 77i, 76 + 0i, -5 + 2i, -91 + 37i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 52 - 125i, -91 - 37i, 2 + 1i, 165 + 0i, + }, + wantRev: []complex128{ + 149 + 0i, -9 + 7i, -81 - 31i, 52 - 127i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + -81 + 31i, -5 - 2i, 74 + 0i, 14 + 83i, + 52 + 127i, -7 + 5i, 14 - 83i, 138 + 0i, + }, + }, + { + alpha: 0, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + wantRev: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + }, + } { + n := len(test.x) + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, incX := range []int{-11, -2, -1, 1, 2, 7} { + for _, lda := range []int{max(1, n), n + 11} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + a := makeZGeneral(test.a, n, n, lda) + + var want []complex128 + if incX > 0 { + want = makeZGeneral(test.want, n, n, lda) + } else { + want = makeZGeneral(test.wantRev, n, n, lda) + } + + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = cmplx.NaN() + want[i*lda+j] = cmplx.NaN() + } + a[i*lda+i] = complex(real(a[i*lda+i]), math.NaN()) + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = cmplx.NaN() + want[i*lda+j] = cmplx.NaN() + } + a[i*lda+i] = complex(real(a[i*lda+i]), math.NaN()) + } + } + + impl.Zher(uplo, n, test.alpha, x, incX, a, lda) + + if !zsame(x, xCopy) { + t.Errorf("Case %v (uplo=%v,incX=%v,lda=%v: unexpected modification of x", tc, uplo, incX, lda) + } + if !zsame(want, a) { + t.Errorf("Case %v (uplo=%v,incX=%v,lda=%v: unexpected result\nwant: %v\ngot: %v", tc, uplo, incX, lda, want, a) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zher2.go b/vendor/gonum.org/v1/gonum/blas/testblas/zher2.go new file mode 100644 index 00000000..0a4c2435 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zher2.go @@ -0,0 +1,257 @@ +// Copyright ©2017 The Gonum 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 testblas + +import ( + "math" + "math/cmplx" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Zher2er interface { + Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) +} + +func Zher2Test(t *testing.T, impl Zher2er) { + for tc, test := range []struct { + alpha complex128 + incX, incY int + x []complex128 + y []complex128 + a []complex128 + + want []complex128 + }{ + { + alpha: 1 + 2i, + incX: 1, + incY: 1, + }, + { + alpha: 1 + 2i, + incX: 1, + incY: 1, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + y: []complex128{ + 2 - 5i, + 0 + 0i, + -8 - 9i, + 6 + 6i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 62 + 0i, 43 - 7i, 173 + 1i, -173 + 55i, + 43 + 7i, 16 + 0i, 19 + 120i, -19 - 89i, + 173 - 1i, 19 - 120i, 14 + 0i, 51 + 181i, + -173 - 55i, -19 + 89i, 51 - 181i, -66 + 0i, + }, + }, + { + alpha: 1 + 2i, + incX: 3, + incY: 7, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + y: []complex128{ + 2 - 5i, + 0 + 0i, + -8 - 9i, + 6 + 6i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 62 + 0i, 43 - 7i, 173 + 1i, -173 + 55i, + 43 + 7i, 16 + 0i, 19 + 120i, -19 - 89i, + 173 - 1i, 19 - 120i, 14 + 0i, 51 + 181i, + -173 - 55i, -19 + 89i, 51 - 181i, -66 + 0i, + }, + }, + { + alpha: 1 + 2i, + incX: -3, + incY: 7, + x: []complex128{ + 0 + 7i, + 0 + 0i, + -2 - 4i, + -6 + 2i, + }, + y: []complex128{ + 2 - 5i, + 0 + 0i, + -8 - 9i, + 6 + 6i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 62 + 0i, 43 - 7i, 173 + 1i, -173 + 55i, + 43 + 7i, 16 + 0i, 19 + 120i, -19 - 89i, + 173 - 1i, 19 - 120i, 14 + 0i, 51 + 181i, + -173 - 55i, -19 + 89i, 51 - 181i, -66 + 0i, + }, + }, + { + alpha: 1 + 2i, + incX: 3, + incY: -7, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + y: []complex128{ + 6 + 6i, + -8 - 9i, + 0 + 0i, + 2 - 5i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 62 + 0i, 43 - 7i, 173 + 1i, -173 + 55i, + 43 + 7i, 16 + 0i, 19 + 120i, -19 - 89i, + 173 - 1i, 19 - 120i, 14 + 0i, 51 + 181i, + -173 - 55i, -19 + 89i, 51 - 181i, -66 + 0i, + }, + }, + { + alpha: 1 + 2i, + incX: -3, + incY: -7, + x: []complex128{ + 0 + 7i, + 0 + 0i, + -2 - 4i, + -6 + 2i, + }, + y: []complex128{ + 6 + 6i, + -8 - 9i, + 0 + 0i, + 2 - 5i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 62 + 0i, 43 - 7i, 173 + 1i, -173 + 55i, + 43 + 7i, 16 + 0i, 19 + 120i, -19 - 89i, + 173 - 1i, 19 - 120i, 14 + 0i, 51 + 181i, + -173 - 55i, -19 + 89i, 51 - 181i, -66 + 0i, + }, + }, + { + alpha: 0, + incX: 1, + incY: 1, + x: []complex128{ + -6 + 2i, + -2 - 4i, + 0 + 0i, + 0 + 7i, + }, + y: []complex128{ + 2 - 5i, + 0 + 0i, + -8 - 9i, + 6 + 6i, + }, + a: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + want: []complex128{ + 2 + 0i, -9 + 7i, 3 + 11i, 10 - 1i, + -9 - 7i, 16 + 0i, -5 + 2i, -7 - 5i, + 3 - 11i, -5 - 2i, 14 + 0i, 2 - 1i, + 10 + 1i, -7 + 5i, 2 + 1i, 18 + 0i, + }, + }, + } { + n := len(test.x) + incX := test.incX + incY := test.incY + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, lda := range []int{max(1, n), n + 11} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + y := makeZVector(test.y, incY) + yCopy := make([]complex128, len(y)) + copy(yCopy, y) + + a := makeZGeneral(test.a, n, n, lda) + want := makeZGeneral(test.want, n, n, lda) + + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = cmplx.NaN() + want[i*lda+j] = cmplx.NaN() + } + a[i*lda+i] = complex(real(a[i*lda+i]), math.NaN()) + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = cmplx.NaN() + want[i*lda+j] = cmplx.NaN() + } + a[i*lda+i] = complex(real(a[i*lda+i]), math.NaN()) + } + } + + impl.Zher2(uplo, n, test.alpha, x, incX, y, incY, a, lda) + + if !zsame(x, xCopy) { + t.Errorf("Case %v (uplo=%v,incX=%v,incY=%v,lda=%v: unexpected modification of x", tc, uplo, incX, incY, lda) + } + if !zsame(y, yCopy) { + t.Errorf("Case %v (uplo=%v,incX=%v,incY=%v,lda=%v: unexpected modification of y", tc, uplo, incX, incY, lda) + } + if !zsame(want, a) { + t.Errorf("Case %v (uplo=%v,incX=%v,incY=%v,lda=%v: unexpected result\nwant: %v\ngot: %v", tc, uplo, incX, incY, lda, want, a) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zscal.go b/vendor/gonum.org/v1/gonum/blas/testblas/zscal.go new file mode 100644 index 00000000..67210e1b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zscal.go @@ -0,0 +1,119 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "testing" +) + +type Zscaler interface { + Zscal(n int, alpha complex128, x []complex128, incX int) +} + +func ZscalTest(t *testing.T, impl Zscaler) { + for tc, test := range []struct { + alpha complex128 + x []complex128 + want []complex128 + }{ + { + alpha: 2 + 5i, + x: nil, + want: nil, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i}, + want: []complex128{-8 + 9i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i}, + want: []complex128{-8 + 9i, -14 + 23i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i, -50 + 107i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i, -50 + 107i, -56 + 121i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i, -50 + 107i, -56 + 121i, -62 + 135i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i, -50 + 107i, -56 + 121i, -62 + 135i, -68 + 149i}, + }, + { + alpha: 2 + 5i, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + want: []complex128{-8 + 9i, -14 + 23i, -20 + 37i, -26 + 51i, -32 + 65i, -38 + 79i, -44 + 93i, -50 + 107i, -56 + 121i, -62 + 135i, -68 + 149i, -74 + 163i}, + }, + { + alpha: 0, + x: []complex128{1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i, 9 + 10i, 11 + 12i, 13 + 14i, 15 + 16i, 17 + 18i, 19 + 20i, 21 + 22i, 23 + 24i}, + want: []complex128{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + } { + n := len(test.x) + if len(test.want) != n { + panic("bad test") + } + for _, incX := range []int{-3, -1, 1, 2, 4, 7, 10} { + x := makeZVector(test.x, incX) + xCopy := make([]complex128, len(x)) + copy(xCopy, x) + + want := makeZVector(test.want, incX) + + impl.Zscal(n, test.alpha, x, incX) + + prefix := fmt.Sprintf("Case %v (n=%v,incX=%v):", tc, n, incX) + + if incX < 0 { + if !zsame(x, xCopy) { + t.Errorf("%v: unexpected modification of x\nwant %v\ngot %v", prefix, want, x) + } + continue + } + if !zsame(x, want) { + t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, want, x) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/testblas/zswap.go b/vendor/gonum.org/v1/gonum/blas/testblas/zswap.go new file mode 100644 index 00000000..1be1037e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/testblas/zswap.go @@ -0,0 +1,68 @@ +// Copyright ©2017 The gonum 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 testblas + +import ( + "fmt" + "math/cmplx" + "math/rand" + "testing" +) + +type Zswaper interface { + Zswap(n int, x []complex128, incX int, y []complex128, incY int) +} + +func ZswapTest(t *testing.T, impl Zswaper) { + rnd := rand.New(rand.NewSource(1)) + for n := 0; n < 20; n++ { + for _, inc := range allPairs([]int{-5, -1, 1, 2, 5, 10}, []int{-3, -1, 1, 3, 7, 12}) { + incX := inc[0] + incY := inc[1] + aincX := abs(incX) + aincY := abs(incY) + + var x, y []complex128 + if n > 0 { + x = make([]complex128, (n-1)*aincX+1) + y = make([]complex128, (n-1)*aincY+1) + } + for i := range x { + x[i] = cmplx.NaN() + } + for i := range y { + y[i] = cmplx.NaN() + } + for i := 0; i < n; i++ { + x[i*aincX] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + y[i*aincY] = complex(rnd.NormFloat64(), rnd.NormFloat64()) + } + + xWant := make([]complex128, len(x)) + yWant := make([]complex128, len(y)) + if incX*incY > 0 { + for i := 0; i < n; i++ { + xWant[i*aincX] = y[i*aincY] + yWant[i*aincY] = x[i*aincX] + } + } else { + for i := 0; i < n; i++ { + xWant[(n-i-1)*aincX] = y[i*aincY] + yWant[(n-i-1)*aincY] = x[i*aincX] + } + } + + impl.Zswap(n, x, incX, y, incY) + + prefix := fmt.Sprintf("Case n=%v,incX=%v,incY=%v:", n, incX, incY) + if !zsame(x, xWant) { + t.Errorf("%v: unexpected x:\nwant %v\ngot %v", prefix, xWant, x) + } + if !zsame(y, yWant) { + t.Errorf("%v: unexpected y:\nwant %v\ngot %v", prefix, yWant, y) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/README.md b/vendor/gonum.org/v1/gonum/diff/README.md new file mode 100644 index 00000000..6fbcf725 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/README.md @@ -0,0 +1,3 @@ +# Gonum diff [![GoDoc](https://godoc.org/gonum.org/v1/gonum/diff?status.svg)](https://godoc.org/gonum.org/v1/gonum/diff) + +Package diff is a package for computing derivatives of functions for the Go language. diff --git a/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian.go b/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian.go new file mode 100644 index 00000000..9b2f1d1f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian.go @@ -0,0 +1,186 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "math" + "sync" +) + +// CrossLaplacian computes a Laplacian-like quantity for a function of two vectors +// at the locations x and y. +// It computes +// ∇_y · ∇_x f(x,y) = \sum_i ∂^2 f(x,y)/∂x_i ∂y_i +// The two input vector lengths must be the same. +// +// Finite difference formula and other options are specified by settings. If +// settings is nil, CrossLaplacian will be estimated using the Forward formula and +// a default step size. +// +// CrossLaplacian panics if the two input vectors are not the same length, or if +// the derivative order of the formula is not 1. +func CrossLaplacian(f func(x, y []float64) float64, x, y []float64, settings *Settings) float64 { + n := len(x) + if n == 0 { + panic("crosslaplacian: x has zero length") + } + if len(x) != len(y) { + panic("crosslaplacian: input vector length mismatch") + } + + // Default settings. + formula := Forward + step := math.Sqrt(formula.Step) // Use the sqrt because taking derivatives of derivatives. + var originValue float64 + var originKnown, concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = math.Sqrt(formula.Step) + checkFormula(formula) + if formula.Derivative != 1 { + panic(badDerivOrder) + } + } + if settings.Step != 0 { + if settings.Step < 0 { + panic(negativeStep) + } + step = settings.Step + } + originKnown = settings.OriginKnown + originValue = settings.OriginValue + concurrent = settings.Concurrent + } + + evals := n * len(formula.Stencil) * len(formula.Stencil) + if usesOrigin(formula.Stencil) { + evals -= n + } + + nWorkers := computeWorkers(concurrent, evals) + if nWorkers == 1 { + return crossLaplacianSerial(f, x, y, formula.Stencil, step, originKnown, originValue) + } + return crossLaplacianConcurrent(nWorkers, evals, f, x, y, formula.Stencil, step, originKnown, originValue) +} + +func crossLaplacianSerial(f func(x, y []float64) float64, x, y []float64, stencil []Point, step float64, originKnown bool, originValue float64) float64 { + n := len(x) + xCopy := make([]float64, len(x)) + yCopy := make([]float64, len(y)) + fo := func() float64 { + // Copy x and y in case they are modified during the call. + copy(xCopy, x) + copy(yCopy, y) + return f(x, y) + } + origin := getOrigin(originKnown, originValue, fo, stencil) + + is2 := 1 / (step * step) + var laplacian float64 + for i := 0; i < n; i++ { + for _, pty := range stencil { + for _, ptx := range stencil { + var v float64 + if ptx.Loc == 0 && pty.Loc == 0 { + v = origin + } else { + // Copying the data anew has two benefits. First, it + // avoids floating point issues where adding and then + // subtracting the step don't return to the exact same + // location. Secondly, it protects against the function + // modifying the input data. + copy(yCopy, y) + copy(xCopy, x) + yCopy[i] += pty.Loc * step + xCopy[i] += ptx.Loc * step + v = f(xCopy, yCopy) + } + laplacian += v * ptx.Coeff * pty.Coeff * is2 + } + } + } + return laplacian +} + +func crossLaplacianConcurrent(nWorkers, evals int, f func(x, y []float64) float64, x, y []float64, stencil []Point, step float64, originKnown bool, originValue float64) float64 { + n := len(x) + type run struct { + i int + xIdx, yIdx int + result float64 + } + + send := make(chan run, evals) + ans := make(chan run, evals) + + var originWG sync.WaitGroup + hasOrigin := usesOrigin(stencil) + if hasOrigin { + originWG.Add(1) + // Launch worker to compute the origin. + go func() { + defer originWG.Done() + xCopy := make([]float64, len(x)) + yCopy := make([]float64, len(y)) + copy(xCopy, x) + copy(yCopy, y) + originValue = f(xCopy, yCopy) + }() + } + + var workerWG sync.WaitGroup + // Launch workers. + for i := 0; i < nWorkers; i++ { + workerWG.Add(1) + go func(send <-chan run, ans chan<- run) { + defer workerWG.Done() + xCopy := make([]float64, len(x)) + yCopy := make([]float64, len(y)) + for r := range send { + if stencil[r.xIdx].Loc == 0 && stencil[r.yIdx].Loc == 0 { + originWG.Wait() + r.result = originValue + } else { + // See crossLaplacianSerial for comment on the copy. + copy(xCopy, x) + copy(yCopy, y) + xCopy[r.i] += stencil[r.xIdx].Loc * step + yCopy[r.i] += stencil[r.yIdx].Loc * step + r.result = f(xCopy, yCopy) + } + ans <- r + } + }(send, ans) + } + + // Launch the distributor, which sends all of runs. + go func(send chan<- run) { + for i := 0; i < n; i++ { + for xIdx := range stencil { + for yIdx := range stencil { + send <- run{ + i: i, xIdx: xIdx, yIdx: yIdx, + } + } + } + } + close(send) + // Wait for all the workers to quit, then close the ans channel. + workerWG.Wait() + close(ans) + }(send) + + // Read in the results. + is2 := 1 / (step * step) + var laplacian float64 + for r := range ans { + laplacian += r.result * stencil[r.xIdx].Coeff * stencil[r.yIdx].Coeff * is2 + } + return laplacian +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian_test.go b/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian_test.go new file mode 100644 index 00000000..e27a83fa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/crosslaplacian_test.go @@ -0,0 +1,111 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +type CrossLaplacianTester interface { + Func(x, y []float64) float64 + CrossLaplacian(x, y []float64) float64 +} + +type WrapperCL struct { + Tester HessianTester +} + +func (WrapperCL) constructZ(x, y []float64) []float64 { + z := make([]float64, len(x)+len(y)) + copy(z, x) + copy(z[len(x):], y) + return z +} + +func (w WrapperCL) Func(x, y []float64) float64 { + z := w.constructZ(x, y) + return w.Tester.Func(z) +} + +func (w WrapperCL) CrossLaplacian(x, y []float64) float64 { + z := w.constructZ(x, y) + hess := mat.NewSymDense(len(z), nil) + w.Tester.Hess(hess, z) + // The CrossLaplacian is the trace of the off-diagonal block of the Hessian. + var l float64 + for i := 0; i < len(x); i++ { + l += hess.At(i, i+len(x)) + } + return l +} + +func TestCrossLaplacian(t *testing.T) { + for cas, test := range []struct { + l CrossLaplacianTester + x, y []float64 + settings *Settings + tol float64 + }{ + { + l: WrapperCL{Watson{}}, + x: []float64{0.2, 0.3}, + y: []float64{0.1, 0.4}, + tol: 1e-3, + }, + { + l: WrapperCL{Watson{}}, + x: []float64{2, 3, 1}, + y: []float64{1, 4, 1}, + tol: 1e-3, + }, + { + l: WrapperCL{ConstFunc(6)}, + x: []float64{2, -3, 1}, + y: []float64{1, 4, -5}, + tol: 1e-6, + }, + { + l: WrapperCL{LinearFunc{w: []float64{10, 6, -1, 5}, c: 5}}, + x: []float64{3, 1}, + y: []float64{8, 6}, + tol: 1e-6, + }, + { + l: WrapperCL{QuadFunc{ + a: mat.NewSymDense(4, []float64{ + 10, 2, 1, 9, + 2, 5, -3, 4, + 1, -3, 6, 2, + 9, 4, 2, -14, + }), + b: mat.NewVecDense(4, []float64{3, -2, -1, 4}), + c: 5, + }}, + x: []float64{-1.6, -3}, + y: []float64{1.8, 3.4}, + tol: 1e-6, + }, + } { + got := CrossLaplacian(test.l.Func, test.x, test.y, test.settings) + want := test.l.CrossLaplacian(test.x, test.y) + if !floats.EqualWithinAbsOrRel(got, want, test.tol, test.tol) { + t.Errorf("Cas %d: CrossLaplacian mismatch serial. got %v, want %v", cas, got, want) + } + + // Test that concurrency works. + settings := test.settings + if settings == nil { + settings = &Settings{} + } + settings.Concurrent = true + got2 := CrossLaplacian(test.l.Func, test.x, test.y, settings) + if !floats.EqualWithinAbsOrRel(got, got2, 1e-6, 1e-6) { + t.Errorf("Cas %d: Laplacian mismatch. got %v, want %v", cas, got2, got) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/derivative.go b/vendor/gonum.org/v1/gonum/diff/fd/derivative.go new file mode 100644 index 00000000..e5aa9af3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/derivative.go @@ -0,0 +1,71 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "math" + "runtime" + "sync" +) + +// Derivative estimates the derivative of the function f at the given location. +// The finite difference formula, the step size, and other options are +// specified by settings. If settings is nil, the first derivative will be +// estimated using the Forward formula and a default step size. +func Derivative(f func(float64) float64, x float64, settings *Settings) float64 { + // Default settings. + formula := Forward + step := formula.Step + var originValue float64 + var originKnown, concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = formula.Step + checkFormula(formula) + } + if settings.Step != 0 { + step = settings.Step + } + originKnown = settings.OriginKnown + originValue = settings.OriginValue + concurrent = settings.Concurrent + } + + var deriv float64 + if !concurrent || runtime.GOMAXPROCS(0) == 1 { + for _, pt := range formula.Stencil { + if originKnown && pt.Loc == 0 { + deriv += pt.Coeff * originValue + continue + } + deriv += pt.Coeff * f(x+step*pt.Loc) + } + return deriv / math.Pow(step, float64(formula.Derivative)) + } + + wg := &sync.WaitGroup{} + mux := &sync.Mutex{} + for _, pt := range formula.Stencil { + if originKnown && pt.Loc == 0 { + mux.Lock() + deriv += pt.Coeff * originValue + mux.Unlock() + continue + } + wg.Add(1) + go func(pt Point) { + defer wg.Done() + fofx := f(x + step*pt.Loc) + mux.Lock() + defer mux.Unlock() + deriv += pt.Coeff * fofx + }(pt) + } + wg.Wait() + return deriv / math.Pow(step, float64(formula.Derivative)) +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/derivative_test.go b/vendor/gonum.org/v1/gonum/diff/fd/derivative_test.go new file mode 100644 index 00000000..35d4f0f3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/derivative_test.go @@ -0,0 +1,145 @@ +// Copyright ©2014 The gonum 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 fd + +import ( + "math" + "testing" +) + +var xSquared = func(x float64) float64 { return x * x } + +type testPoint struct { + f func(float64) float64 + loc float64 + fofx float64 + ans float64 +} + +var testsFirst = []testPoint{ + { + f: xSquared, + loc: 0, + fofx: 0, + ans: 0, + }, + { + f: xSquared, + loc: 5, + fofx: 25, + ans: 10, + }, + { + f: xSquared, + loc: 2, + fofx: 4, + ans: 4, + }, + { + f: xSquared, + loc: -5, + fofx: 25, + ans: -10, + }, +} + +var testsSecond = []testPoint{ + { + f: xSquared, + loc: 0, + fofx: 0, + ans: 2, + }, + { + f: xSquared, + loc: 5, + fofx: 25, + ans: 2, + }, + { + f: xSquared, + loc: 2, + fofx: 4, + ans: 2, + }, + { + f: xSquared, + loc: -5, + fofx: 25, + ans: 2, + }, +} + +func testDerivative(t *testing.T, formula Formula, tol float64, tests []testPoint) { + for i, test := range tests { + + ans := Derivative(test.f, test.loc, &Settings{ + Formula: formula, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch serial: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + OriginKnown: true, + OriginValue: test.fofx, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch serial origin known: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + Concurrent: true, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch concurrent: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + OriginKnown: true, + OriginValue: test.fofx, + Concurrent: true, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch concurrent: expected %v, found %v", i, test.ans, ans) + } + } +} + +func TestForward(t *testing.T) { + testDerivative(t, Forward, 2e-4, testsFirst) +} + +func TestBackward(t *testing.T) { + testDerivative(t, Backward, 2e-4, testsFirst) +} + +func TestCentral(t *testing.T) { + testDerivative(t, Central, 1e-6, testsFirst) +} + +func TestCentralSecond(t *testing.T) { + testDerivative(t, Central2nd, 1e-3, testsSecond) +} + +// TestDerivativeDefault checks that the derivative works when settings is nil +// or zero value. +func TestDerivativeDefault(t *testing.T) { + tol := 1e-6 + for i, test := range testsFirst { + ans := Derivative(test.f, test.loc, nil) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch default: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{}) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch zero value: expected %v, found %v", i, test.ans, ans) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/diff.go b/vendor/gonum.org/v1/gonum/diff/fd/diff.go new file mode 100644 index 00000000..3bde48d9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/diff.go @@ -0,0 +1,148 @@ +// Copyright ©2014 The gonum 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 fd + +import ( + "math" + "runtime" +) + +// A Point is a stencil location in a finite difference formula. +type Point struct { + Loc float64 + Coeff float64 +} + +// Formula represents a finite difference formula on a regularly spaced grid +// that approximates the derivative of order k of a function f at x as +// d^k f(x) ≈ (1 / Step^k) * \sum_i Coeff_i * f(x + Step * Loc_i). +// Step must be positive, or the finite difference formula will panic. +type Formula struct { + // Stencil is the set of sampling Points which are used to estimate the + // derivative. The locations will be scaled by Step and are relative to x. + Stencil []Point + Derivative int // The order of the approximated derivative. + Step float64 // Default step size for the formula. +} + +func (f Formula) isZero() bool { + return f.Stencil == nil && f.Derivative == 0 && f.Step == 0 +} + +// Settings is the settings structure for computing finite differences. +type Settings struct { + // Formula is the finite difference formula used + // for approximating the derivative. + // Zero value indicates a default formula. + Formula Formula + // Step is the distance between points of the stencil. + // If equal to 0, formula's default step will be used. + Step float64 + + OriginKnown bool // Flag that the value at the origin x is known. + OriginValue float64 // Value at the origin (only used if OriginKnown is true). + + Concurrent bool // Should the function calls be executed concurrently. +} + +// Forward represents a first-order accurate forward approximation +// to the first derivative. +var Forward = Formula{ + Stencil: []Point{{Loc: 0, Coeff: -1}, {Loc: 1, Coeff: 1}}, + Derivative: 1, + Step: 2e-8, +} + +// Forward2nd represents a first-order accurate forward approximation +// to the second derivative. +var Forward2nd = Formula{ + Stencil: []Point{{Loc: 0, Coeff: 1}, {Loc: 1, Coeff: -2}, {Loc: 2, Coeff: 1}}, + Derivative: 2, + Step: 1e-4, +} + +// Backward represents a first-order accurate backward approximation +// to the first derivative. +var Backward = Formula{ + Stencil: []Point{{Loc: -1, Coeff: -1}, {Loc: 0, Coeff: 1}}, + Derivative: 1, + Step: 2e-8, +} + +// Backward2nd represents a first-order accurate forward approximation +// to the second derivative. +var Backward2nd = Formula{ + Stencil: []Point{{Loc: 0, Coeff: 1}, {Loc: -1, Coeff: -2}, {Loc: -2, Coeff: 1}}, + Derivative: 2, + Step: 1e-4, +} + +// Central represents a second-order accurate centered approximation +// to the first derivative. +var Central = Formula{ + Stencil: []Point{{Loc: -1, Coeff: -0.5}, {Loc: 1, Coeff: 0.5}}, + Derivative: 1, + Step: 6e-6, +} + +// Central2nd represents a secord-order accurate centered approximation +// to the second derivative. +var Central2nd = Formula{ + Stencil: []Point{{Loc: -1, Coeff: 1}, {Loc: 0, Coeff: -2}, {Loc: 1, Coeff: 1}}, + Derivative: 2, + Step: 1e-4, +} + +var negativeStep = "fd: negative step" + +// checkFormula checks if the formula is valid, and panics otherwise. +func checkFormula(formula Formula) { + if formula.Derivative == 0 || formula.Stencil == nil || formula.Step <= 0 { + panic("fd: bad formula") + } +} + +// computeWorkers returns the desired number of workers given the concurrency +// level and number of evaluations. +func computeWorkers(concurrent bool, evals int) int { + if !concurrent { + return 1 + } + nWorkers := runtime.GOMAXPROCS(0) + if nWorkers > evals { + nWorkers = evals + } + return nWorkers +} + +// usesOrigin returns whether the stencil uses the origin, which is true iff +// one of the locations in the stencil equals 0. +func usesOrigin(stencil []Point) bool { + for _, pt := range stencil { + if pt.Loc == 0 { + return true + } + } + return false +} + +// getOrigin returns the value at the origin. It returns originValue if originKnown +// is true. It returns the value returned by f if stencil contains a point with +// zero location, and NaN otherwise. +func getOrigin(originKnown bool, originValue float64, f func() float64, stencil []Point) float64 { + if originKnown { + return originValue + } + for _, pt := range stencil { + if pt.Loc == 0 { + return f() + } + } + return math.NaN() +} + +const ( + badDerivOrder = "fd: invalid derivative order" +) diff --git a/vendor/gonum.org/v1/gonum/diff/fd/doc.go b/vendor/gonum.org/v1/gonum/diff/fd/doc.go new file mode 100644 index 00000000..ec6fbb10 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 fd provides functions to approximate derivatives using finite differences. +package fd // import "gonum.org/v1/gonum/diff/fd" diff --git a/vendor/gonum.org/v1/gonum/diff/fd/example_test.go b/vendor/gonum.org/v1/gonum/diff/fd/example_test.go new file mode 100644 index 00000000..adc9db0f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/example_test.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum 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 fd_test + +import ( + "fmt" + "math" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/mat" +) + +func ExampleDerivative() { + f := func(x float64) float64 { + return math.Sin(x) + } + // Compute the first derivative of f at 0 using the default settings. + fmt.Println("f'(0) ≈", fd.Derivative(f, 0, nil)) + // Compute the first derivative of f at 0 using the forward approximation + // with a custom step size. + df := fd.Derivative(f, 0, &fd.Settings{ + Formula: fd.Forward, + Step: 1e-3, + }) + fmt.Println("f'(0) ≈", df) + + f = func(x float64) float64 { + return math.Pow(math.Cos(x), 3) + } + // Compute the second derivative of f at 0 using + // the centered approximation, concurrent evaluation, + // and a known function value at x. + df = fd.Derivative(f, 0, &fd.Settings{ + Formula: fd.Central2nd, + Concurrent: true, + OriginKnown: true, + OriginValue: f(0), + }) + fmt.Println("f''(0) ≈", df) + + // Output: + // f'(0) ≈ 1 + // f'(0) ≈ 0.9999998333333416 + // f''(0) ≈ -2.999999981767587 +} + +func ExampleJacobian() { + f := func(dst, x []float64) { + dst[0] = x[0] + 1 + dst[1] = 5 * x[2] + dst[2] = 4*x[1]*x[1] - 2*x[2] + dst[3] = x[2] * math.Sin(x[0]) + } + jac := mat.NewDense(4, 3, nil) + fd.Jacobian(jac, f, []float64{1, 2, 3}, &fd.JacobianSettings{ + Formula: fd.Central, + Concurrent: true, + }) + fmt.Printf("J ≈ %.6v\n", mat.Formatted(jac, mat.Prefix(" "))) + + // Output: + // J ≈ ⎡ 1 0 0⎤ + // ⎢ 0 0 5⎥ + // ⎢ 0 16 -2⎥ + // ⎣ 1.62091 0 0.841471⎦ +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/gradient.go b/vendor/gonum.org/v1/gonum/diff/fd/gradient.go new file mode 100644 index 00000000..79bb3d1a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/gradient.go @@ -0,0 +1,145 @@ +// Copyright ©2017 The gonum 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 fd + +import "gonum.org/v1/gonum/floats" + +// Gradient estimates the gradient of the multivariate function f at the +// location x. If dst is not nil, the result will be stored in-place into dst +// and returned, otherwise a new slice will be allocated first. Finite +// difference formula and other options are specified by settings. If settings is +// nil, the gradient will be estimated using the Forward formula and a default +// step size. +// +// Gradient panics if the length of dst and x is not equal, or if the derivative +// order of the formula is not 1. +func Gradient(dst []float64, f func([]float64) float64, x []float64, settings *Settings) []float64 { + if dst == nil { + dst = make([]float64, len(x)) + } + if len(dst) != len(x) { + panic("fd: slice length mismatch") + } + + // Default settings. + formula := Forward + step := formula.Step + var originValue float64 + var originKnown, concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = formula.Step + checkFormula(formula) + if formula.Derivative != 1 { + panic(badDerivOrder) + } + } + if settings.Step != 0 { + step = settings.Step + } + originKnown = settings.OriginKnown + originValue = settings.OriginValue + concurrent = settings.Concurrent + } + + evals := len(formula.Stencil) * len(x) + nWorkers := computeWorkers(concurrent, evals) + + hasOrigin := usesOrigin(formula.Stencil) + // Copy x in case it is modified during the call. + xcopy := make([]float64, len(x)) + if hasOrigin && !originKnown { + copy(xcopy, x) + originValue = f(xcopy) + } + + if nWorkers == 1 { + for i := range xcopy { + var deriv float64 + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + deriv += pt.Coeff * originValue + continue + } + // Copying the data anew has two benefits. First, it + // avoids floating point issues where adding and then + // subtracting the step don't return to the exact same + // location. Secondly, it protects against the function + // modifying the input data. + copy(xcopy, x) + xcopy[i] += pt.Loc * step + deriv += pt.Coeff * f(xcopy) + } + dst[i] = deriv / step + } + return dst + } + + sendChan := make(chan fdrun, evals) + ansChan := make(chan fdrun, evals) + quit := make(chan struct{}) + defer close(quit) + + // Launch workers. Workers receive an index and a step, and compute the answer. + for i := 0; i < nWorkers; i++ { + go func(sendChan <-chan fdrun, ansChan chan<- fdrun, quit <-chan struct{}) { + xcopy := make([]float64, len(x)) + for { + select { + case <-quit: + return + case run := <-sendChan: + // See above comment on the copy. + copy(xcopy, x) + xcopy[run.idx] += run.pt.Loc * step + run.result = f(xcopy) + ansChan <- run + } + } + }(sendChan, ansChan, quit) + } + + // Launch the distributor. Distributor sends the cases to be computed. + go func(sendChan chan<- fdrun, ansChan chan<- fdrun) { + for i := range x { + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + // Answer already known. Send the answer on the answer channel. + ansChan <- fdrun{ + idx: i, + pt: pt, + result: originValue, + } + continue + } + // Answer not known, send the answer to be computed. + sendChan <- fdrun{ + idx: i, + pt: pt, + } + } + } + }(sendChan, ansChan) + + for i := range dst { + dst[i] = 0 + } + // Read in all of the results. + for i := 0; i < evals; i++ { + run := <-ansChan + dst[run.idx] += run.pt.Coeff * run.result + } + floats.Scale(1/step, dst) + return dst +} + +type fdrun struct { + idx int + pt Point + result float64 +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/gradient_test.go b/vendor/gonum.org/v1/gonum/diff/fd/gradient_test.go new file mode 100644 index 00000000..0774ad73 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/gradient_test.go @@ -0,0 +1,187 @@ +// Copyright ©2014 The gonum 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 fd + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Rosenbrock struct { + nDim int +} + +func (r Rosenbrock) F(x []float64) (sum float64) { + deriv := make([]float64, len(x)) + return r.FDf(x, deriv) +} + +func (r Rosenbrock) FDf(x []float64, deriv []float64) (sum float64) { + for i := range deriv { + deriv[i] = 0 + } + + for i := 0; i < len(x)-1; i++ { + sum += math.Pow(1-x[i], 2) + 100*math.Pow(x[i+1]-math.Pow(x[i], 2), 2) + } + for i := 0; i < len(x)-1; i++ { + deriv[i] += -1 * 2 * (1 - x[i]) + deriv[i] += 2 * 100 * (x[i+1] - math.Pow(x[i], 2)) * (-2 * x[i]) + } + for i := 1; i < len(x); i++ { + deriv[i] += 2 * 100 * (x[i] - math.Pow(x[i-1], 2)) + } + + return sum +} + +func TestGradient(t *testing.T) { + rand.Seed(1) + for i, test := range []struct { + nDim int + tol float64 + formula Formula + }{ + { + nDim: 2, + tol: 2e-4, + formula: Forward, + }, + { + nDim: 2, + tol: 1e-6, + formula: Central, + }, + { + nDim: 40, + tol: 2e-4, + formula: Forward, + }, + { + nDim: 40, + tol: 1e-6, + formula: Central, + }, + } { + x := make([]float64, test.nDim) + for i := range x { + x[i] = rand.Float64() + } + xcopy := make([]float64, len(x)) + copy(xcopy, x) + + r := Rosenbrock{len(x)} + trueGradient := make([]float64, len(x)) + r.FDf(x, trueGradient) + + // Try with gradient nil. + gradient := Gradient(nil, r.F, x, &Settings{ + Formula: test.formula, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch in serial with nil. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in serial with nil.", i) + } + + // Try with provided gradient. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch in serial. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in serial with non-nil.", i) + } + + // Try with known value. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + OriginKnown: true, + OriginValue: r.F(x), + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with known origin in serial. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with concurrent evaluation. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + Concurrent: true, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with unknown origin in parallel. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in parallel", i) + } + + // Try with concurrent evaluation with origin known. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + Concurrent: true, + OriginKnown: true, + OriginValue: r.F(x), + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with known origin in parallel. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with nil settings. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, nil) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with default settings. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with zero-valued settings. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{}) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with zero settings. Want: %v, Got: %v.", i, trueGradient, gradient) + } + } +} + +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestGradientPanics(t *testing.T) { + // Test that it panics + if !Panics(func() { + Gradient([]float64{0.0}, func(x []float64) float64 { return x[0] * x[0] }, []float64{0.0, 0.0}, nil) + }) { + t.Errorf("Gradient did not panic with length mismatch") + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/hessian.go b/vendor/gonum.org/v1/gonum/diff/fd/hessian.go new file mode 100644 index 00000000..871097ce --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/hessian.go @@ -0,0 +1,193 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "math" + "sync" + + "gonum.org/v1/gonum/mat" +) + +// Hessian approximates the Hessian matrix of the multivariate function f +// at the location x. That is +// H_{i,j} = ∂^2 f(x)/∂x_i ∂x_j +// If dst is not nil, the resulting H will be stored in-place into dst +// and returned, otherwise a new matrix will be allocated first. Finite difference +// formula and other options are specified by settings. If settings is nil, +// the Hessian will be estimated using the Forward formula and a default step size. +// +// Hessian panics if the size of dst and x is not equal, or if the derivative +// order of the formula is not 1. +func Hessian(dst *mat.SymDense, f func(x []float64) float64, x []float64, settings *Settings) *mat.SymDense { + n := len(x) + if dst == nil { + dst = mat.NewSymDense(n, nil) + } else { + if n2 := dst.Symmetric(); n2 != n { + panic("hessian: dst size mismatch") + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dst.SetSym(i, j, 0) + } + } + } + + // Default settings. + formula := Forward + step := math.Sqrt(formula.Step) // Use the sqrt because taking derivatives of derivatives. + var originValue float64 + var originKnown, concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = math.Sqrt(formula.Step) + checkFormula(formula) + if formula.Derivative != 1 { + panic(badDerivOrder) + } + } + if settings.Step != 0 { + if settings.Step < 0 { + panic(negativeStep) + } + step = settings.Step + } + originKnown = settings.OriginKnown + originValue = settings.OriginValue + concurrent = settings.Concurrent + } + + evals := n * (n + 1) / 2 * len(formula.Stencil) * len(formula.Stencil) + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + evals -= n * (n + 1) / 2 + break + } + } + + nWorkers := computeWorkers(concurrent, evals) + if nWorkers == 1 { + hessianSerial(dst, f, x, formula.Stencil, step, originKnown, originValue) + return dst + } + hessianConcurrent(dst, nWorkers, evals, f, x, formula.Stencil, step, originKnown, originValue) + return dst +} + +func hessianSerial(dst *mat.SymDense, f func(x []float64) float64, x []float64, stencil []Point, step float64, originKnown bool, originValue float64) { + n := len(x) + xCopy := make([]float64, n) + fo := func() float64 { + // Copy x in case it is modified during the call. + copy(xCopy, x) + return f(x) + } + is2 := 1 / (step * step) + origin := getOrigin(originKnown, originValue, fo, stencil) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + var hess float64 + for _, pti := range stencil { + for _, ptj := range stencil { + var v float64 + if pti.Loc == 0 && ptj.Loc == 0 { + v = origin + } else { + // Copying the data anew has two benefits. First, it + // avoids floating point issues where adding and then + // subtracting the step don't return to the exact same + // location. Secondly, it protects against the function + // modifying the input data. + copy(xCopy, x) + xCopy[i] += pti.Loc * step + xCopy[j] += ptj.Loc * step + v = f(xCopy) + } + hess += v * pti.Coeff * ptj.Coeff * is2 + } + } + dst.SetSym(i, j, hess) + } + } +} + +func hessianConcurrent(dst *mat.SymDense, nWorkers, evals int, f func(x []float64) float64, x []float64, stencil []Point, step float64, originKnown bool, originValue float64) { + n := dst.Symmetric() + type run struct { + i, j int + iIdx, jIdx int + result float64 + } + + send := make(chan run, evals) + ans := make(chan run, evals) + + var originWG sync.WaitGroup + hasOrigin := usesOrigin(stencil) + if hasOrigin { + originWG.Add(1) + // Launch worker to compute the origin. + go func() { + defer originWG.Done() + xCopy := make([]float64, len(x)) + copy(xCopy, x) + originValue = f(xCopy) + }() + } + + var workerWG sync.WaitGroup + // Launch workers. + for i := 0; i < nWorkers; i++ { + workerWG.Add(1) + go func(send <-chan run, ans chan<- run) { + defer workerWG.Done() + xCopy := make([]float64, len(x)) + for r := range send { + if stencil[r.iIdx].Loc == 0 && stencil[r.jIdx].Loc == 0 { + originWG.Wait() + r.result = originValue + } else { + // See hessianSerial for comment on the copy. + copy(xCopy, x) + xCopy[r.i] += stencil[r.iIdx].Loc * step + xCopy[r.j] += stencil[r.jIdx].Loc * step + r.result = f(xCopy) + } + ans <- r + } + }(send, ans) + } + + // Launch the distributor, which sends all of runs. + go func(send chan<- run) { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + for iIdx := range stencil { + for jIdx := range stencil { + send <- run{ + i: i, j: j, iIdx: iIdx, jIdx: jIdx, + } + } + } + } + } + close(send) + // Wait for all the workers to quit, then close the ans channel. + workerWG.Wait() + close(ans) + }(send) + + is2 := 1 / (step * step) + // Read in the results. + for r := range ans { + v := r.result * stencil[r.iIdx].Coeff * stencil[r.jIdx].Coeff * is2 + v += dst.At(r.i, r.j) + dst.SetSym(r.i, r.j, v) + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/hessian_test.go b/vendor/gonum.org/v1/gonum/diff/fd/hessian_test.go new file mode 100644 index 00000000..f9ae8736 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/hessian_test.go @@ -0,0 +1,94 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "testing" + + "gonum.org/v1/gonum/mat" +) + +type HessianTester interface { + Func(x []float64) float64 + Grad(grad, x []float64) + Hess(dst mat.MutableSymmetric, x []float64) +} + +var hessianTestCases = []struct { + h HessianTester + x []float64 + settings *Settings + tol float64 +}{ + { + h: Watson{}, + x: []float64{0.2, 0.3, 0.1, 0.4}, + tol: 1e-3, + }, + { + h: Watson{}, + x: []float64{2, 3, 1, 4}, + tol: 1e-3, + settings: &Settings{ + Step: 1e-5, + Formula: Central, + }, + }, + { + h: Watson{}, + x: []float64{2, 3, 1}, + tol: 1e-3, + settings: &Settings{ + OriginKnown: true, + OriginValue: 7606.529501201192, + }, + }, + { + h: ConstFunc(5), + x: []float64{1, 9}, + tol: 1e-16, + }, + { + h: LinearFunc{w: []float64{10, 6, -1}, c: 5}, + x: []float64{3, 1, 8}, + tol: 1e-6, + }, + { + h: QuadFunc{ + a: mat.NewSymDense(3, []float64{ + 10, 2, 1, + 2, 5, -3, + 1, -3, 6, + }), + b: mat.NewVecDense(3, []float64{3, -2, -1}), + c: 5, + }, + x: []float64{-1.6, -3, 2}, + tol: 1e-6, + }, +} + +func TestHessian(t *testing.T) { + for cas, test := range hessianTestCases { + n := len(test.x) + got := Hessian(nil, test.h.Func, test.x, test.settings) + want := mat.NewSymDense(n, nil) + test.h.Hess(want, test.x) + if !mat.EqualApprox(got, want, test.tol) { + t.Errorf("Cas %d: Hessian mismatch\ngot=\n%0.4v\nwant=\n%0.4v\n", cas, mat.Formatted(got), mat.Formatted(want)) + } + + // Test that concurrency works. + settings := test.settings + if settings == nil { + settings = &Settings{} + } + settings.Concurrent = true + got2 := Hessian(nil, test.h.Func, test.x, settings) + if !mat.EqualApprox(got, got2, 1e-5) { + t.Errorf("Cas %d: Hessian mismatch concurrent\ngot=\n%0.6v\nwant=\n%0.6v\n", cas, mat.Formatted(got2), mat.Formatted(got)) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/jacobian.go b/vendor/gonum.org/v1/gonum/diff/fd/jacobian.go new file mode 100644 index 00000000..658d1183 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/jacobian.go @@ -0,0 +1,200 @@ +// Copyright ©2016 The gonum 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 fd + +import ( + "sync" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +type JacobianSettings struct { + Formula Formula + OriginValue []float64 + Step float64 + Concurrent bool +} + +// Jacobian approximates the Jacobian matrix of a vector-valued function f at +// the location x and stores the result in-place into dst. +// +// Finite difference formula and other options are specified by settings. If +// settings is nil, the Jacobian will be estimated using the Forward formula and +// a default step size. +// +// The Jacobian matrix J is the matrix of all first-order partial derivatives of f. +// If f maps an n-dimensional vector x to an m-dimensional vector y = f(x), J is +// an m×n matrix whose elements are given as +// J_{i,j} = ∂f_i/∂x_j, +// or expanded out +// [ ∂f_1/∂x_1 ... ∂f_1/∂x_n ] +// [ . . . ] +// J = [ . . . ] +// [ . . . ] +// [ ∂f_m/∂x_1 ... ∂f_m/∂x_n ] +// +// dst must be non-nil, the number of its columns must equal the length of x, and +// the derivative order of the formula must be 1, otherwise Jacobian will panic. +func Jacobian(dst *mat.Dense, f func(y, x []float64), x []float64, settings *JacobianSettings) { + n := len(x) + if n == 0 { + panic("jacobian: x has zero length") + } + m, c := dst.Dims() + if c != n { + panic("jacobian: mismatched matrix size") + } + + // Default settings. + formula := Forward + step := formula.Step + var originValue []float64 + var concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = formula.Step + checkFormula(formula) + if formula.Derivative != 1 { + panic(badDerivOrder) + } + } + if settings.Step != 0 { + step = settings.Step + } + originValue = settings.OriginValue + if originValue != nil && len(originValue) != m { + panic("jacobian: mismatched OriginValue slice length") + } + concurrent = settings.Concurrent + } + + evals := n * len(formula.Stencil) + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + evals -= n - 1 + break + } + } + + nWorkers := computeWorkers(concurrent, evals) + if nWorkers == 1 { + jacobianSerial(dst, f, x, originValue, formula, step) + return + } + jacobianConcurrent(dst, f, x, originValue, formula, step, nWorkers) +} + +func jacobianSerial(dst *mat.Dense, f func([]float64, []float64), x, origin []float64, formula Formula, step float64) { + m, n := dst.Dims() + xcopy := make([]float64, n) + y := make([]float64, m) + col := make([]float64, m) + for j := 0; j < n; j++ { + for i := range col { + col[i] = 0 + } + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + if origin == nil { + origin = make([]float64, m) + copy(xcopy, x) + f(origin, xcopy) + } + floats.AddScaled(col, pt.Coeff, origin) + } else { + copy(xcopy, x) + xcopy[j] += pt.Loc * step + f(y, xcopy) + floats.AddScaled(col, pt.Coeff, y) + } + } + dst.SetCol(j, col) + } + dst.Scale(1/step, dst) +} + +func jacobianConcurrent(dst *mat.Dense, f func([]float64, []float64), x, origin []float64, formula Formula, step float64, nWorkers int) { + m, n := dst.Dims() + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + dst.Set(i, j, 0) + } + } + + var ( + wg sync.WaitGroup + mu = make([]sync.Mutex, n) // Guard access to individual columns. + ) + worker := func(jobs <-chan jacJob) { + defer wg.Done() + xcopy := make([]float64, n) + y := make([]float64, m) + yVec := mat.NewVecDense(m, y) + for job := range jobs { + copy(xcopy, x) + xcopy[job.j] += job.pt.Loc * step + f(y, xcopy) + col := dst.ColView(job.j) + mu[job.j].Lock() + col.AddScaledVec(col, job.pt.Coeff, yVec) + mu[job.j].Unlock() + } + } + jobs := make(chan jacJob, nWorkers) + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go worker(jobs) + } + var hasOrigin bool + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + hasOrigin = true + continue + } + for j := 0; j < n; j++ { + jobs <- jacJob{j, pt} + } + } + close(jobs) + if hasOrigin && origin == nil { + wg.Add(1) + go func() { + defer wg.Done() + origin = make([]float64, m) + xcopy := make([]float64, n) + copy(xcopy, x) + f(origin, xcopy) + }() + } + wg.Wait() + + if hasOrigin { + // The formula evaluated at x, we need to add scaled origin to + // all columns of dst. Iterate again over all Formula points + // because we don't forbid repeated locations. + + originVec := mat.NewVecDense(m, origin) + for _, pt := range formula.Stencil { + if pt.Loc != 0 { + continue + } + for j := 0; j < n; j++ { + col := dst.ColView(j) + col.AddScaledVec(col, pt.Coeff, originVec) + } + } + } + + dst.Scale(1/step, dst) +} + +type jacJob struct { + j int + pt Point +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/jacobian_test.go b/vendor/gonum.org/v1/gonum/diff/fd/jacobian_test.go new file mode 100644 index 00000000..020f2c1b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/jacobian_test.go @@ -0,0 +1,268 @@ +// Copyright ©2016 The gonum 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 fd + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func vecFunc13(y, x []float64) { + y[0] = 5*x[0] + x[2]*math.Sin(x[1]) + 1 +} +func vecFunc13Jac(jac *mat.Dense, x []float64) { + jac.Set(0, 0, 5) + jac.Set(0, 1, x[2]*math.Cos(x[1])) + jac.Set(0, 2, math.Sin(x[1])) +} + +func vecFunc22(y, x []float64) { + y[0] = x[0]*x[0]*x[1] + 1 + y[1] = 5*x[0] + math.Sin(x[1]) + 1 +} +func vecFunc22Jac(jac *mat.Dense, x []float64) { + jac.Set(0, 0, 2*x[0]*x[1]) + jac.Set(0, 1, x[0]*x[0]) + jac.Set(1, 0, 5) + jac.Set(1, 1, math.Cos(x[1])) +} + +func vecFunc43(y, x []float64) { + y[0] = x[0] + 1 + y[1] = 5*x[2] + 1 + y[2] = 4*x[1]*x[1] - 2*x[2] + 1 + y[3] = x[2]*math.Sin(x[0]) + 1 +} +func vecFunc43Jac(jac *mat.Dense, x []float64) { + jac.Set(0, 0, 1) + jac.Set(0, 1, 0) + jac.Set(0, 2, 0) + jac.Set(1, 0, 0) + jac.Set(1, 1, 0) + jac.Set(1, 2, 5) + jac.Set(2, 0, 0) + jac.Set(2, 1, 8*x[1]) + jac.Set(2, 2, -2) + jac.Set(3, 0, x[2]*math.Cos(x[0])) + jac.Set(3, 1, 0) + jac.Set(3, 2, math.Sin(x[0])) +} + +func TestJacobian(t *testing.T) { + rand.Seed(1) + + // Test with default settings. + for tc, test := range []struct { + m, n int + f func([]float64, []float64) + jac func(*mat.Dense, []float64) + }{ + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + }, + } { + const tol = 1e-6 + + x := randomSlice(test.n, 10) + xcopy := make([]float64, test.n) + copy(xcopy, x) + + want := mat.NewDense(test.m, test.n, nil) + test.jac(want, x) + + got := mat.NewDense(test.m, test.n, nil) + fillNaNDense(got) + Jacobian(got, test.f, x, nil) + if !mat.EqualApprox(want, got, tol) { + t.Errorf("Case %d (default settings): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat.Formatted(want, mat.Prefix(" ")), mat.Formatted(got, mat.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (default settings): x modified", tc) + } + } + + // Test with non-default settings. + for tc, test := range []struct { + m, n int + f func([]float64, []float64) + jac func(*mat.Dense, []float64) + tol float64 + formula Formula + }{ + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-9, + formula: Central, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-9, + formula: Central, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-9, + formula: Central, + }, + } { + x := randomSlice(test.n, 10) + xcopy := make([]float64, test.n) + copy(xcopy, x) + + want := mat.NewDense(test.m, test.n, nil) + test.jac(want, x) + + got := mat.NewDense(test.m, test.n, nil) + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + }) + if !mat.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d: unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat.Formatted(want, mat.Prefix(" ")), mat.Formatted(got, mat.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d: x modified", tc) + } + + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + Concurrent: true, + }) + if !mat.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (concurrent): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat.Formatted(want, mat.Prefix(" ")), mat.Formatted(got, mat.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (concurrent): x modified", tc) + } + + fillNaNDense(got) + origin := make([]float64, test.m) + test.f(origin, x) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + OriginValue: origin, + }) + if !mat.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (origin): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat.Formatted(want, mat.Prefix(" ")), mat.Formatted(got, mat.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (origin): x modified", tc) + } + + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + OriginValue: origin, + Concurrent: true, + }) + if !mat.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (concurrent, origin): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat.Formatted(want, mat.Prefix(" ")), mat.Formatted(got, mat.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (concurrent, origin): x modified", tc) + } + } +} + +// randomSlice returns a slice of n elements from the interval [-bound,bound). +func randomSlice(n int, bound float64) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = 2*bound*rand.Float64() - bound + } + return x +} + +// fillNaNDense fills the matrix m with NaN values. +func fillNaNDense(m *mat.Dense) { + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m.Set(i, j, math.NaN()) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/laplacian.go b/vendor/gonum.org/v1/gonum/diff/fd/laplacian.go new file mode 100644 index 00000000..e5a8ca15 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/laplacian.go @@ -0,0 +1,158 @@ +// Copyright ©2017 The gonum 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 fd + +import "sync" + +// Laplacian computes the Laplacian of the multivariate function f at the location +// x. That is, Laplacian returns +// ∆ f(x) = ∇ · ∇ f(x) = \sum_i ∂^2 f(x)/∂x_i^2 +// The finite difference formula and other options are specified by settings. +// The order of the difference formula must be 2 or Laplacian will panic. +func Laplacian(f func(x []float64) float64, x []float64, settings *Settings) float64 { + n := len(x) + if n == 0 { + panic("laplacian: x has zero length") + } + + // Default settings. + formula := Central2nd + step := formula.Step + var originValue float64 + var originKnown, concurrent bool + + // Use user settings if provided. + if settings != nil { + if !settings.Formula.isZero() { + formula = settings.Formula + step = formula.Step + checkFormula(formula) + if formula.Derivative != 2 { + panic(badDerivOrder) + } + } + if settings.Step != 0 { + if settings.Step < 0 { + panic(negativeStep) + } + step = settings.Step + } + originKnown = settings.OriginKnown + originValue = settings.OriginValue + concurrent = settings.Concurrent + } + + evals := n * len(formula.Stencil) + if usesOrigin(formula.Stencil) { + evals -= n + } + + nWorkers := computeWorkers(concurrent, evals) + if nWorkers == 1 { + return laplacianSerial(f, x, formula.Stencil, step, originKnown, originValue) + } + return laplacianConcurrent(nWorkers, evals, f, x, formula.Stencil, step, originKnown, originValue) +} + +func laplacianSerial(f func(x []float64) float64, x []float64, stencil []Point, step float64, originKnown bool, originValue float64) float64 { + n := len(x) + xCopy := make([]float64, n) + fo := func() float64 { + // Copy x in case it is modified during the call. + copy(xCopy, x) + return f(x) + } + is2 := 1 / (step * step) + origin := getOrigin(originKnown, originValue, fo, stencil) + var laplacian float64 + for i := 0; i < n; i++ { + for _, pt := range stencil { + var v float64 + if pt.Loc == 0 { + v = origin + } else { + // Copying the data anew has two benefits. First, it + // avoids floating point issues where adding and then + // subtracting the step don't return to the exact same + // location. Secondly, it protects against the function + // modifying the input data. + copy(xCopy, x) + xCopy[i] += pt.Loc * step + v = f(xCopy) + } + laplacian += v * pt.Coeff * is2 + } + } + return laplacian +} + +func laplacianConcurrent(nWorkers, evals int, f func(x []float64) float64, x []float64, stencil []Point, step float64, originKnown bool, originValue float64) float64 { + type run struct { + i int + idx int + result float64 + } + n := len(x) + send := make(chan run, evals) + ans := make(chan run, evals) + + var originWG sync.WaitGroup + hasOrigin := usesOrigin(stencil) + if hasOrigin { + originWG.Add(1) + // Launch worker to compute the origin. + go func() { + defer originWG.Done() + xCopy := make([]float64, len(x)) + copy(xCopy, x) + originValue = f(xCopy) + }() + } + + var workerWG sync.WaitGroup + // Launch workers. + for i := 0; i < nWorkers; i++ { + workerWG.Add(1) + go func(send <-chan run, ans chan<- run) { + defer workerWG.Done() + xCopy := make([]float64, len(x)) + for r := range send { + if stencil[r.idx].Loc == 0 { + originWG.Wait() + r.result = originValue + } else { + // See laplacianSerial for comment on the copy. + copy(xCopy, x) + xCopy[r.i] += stencil[r.idx].Loc * step + r.result = f(xCopy) + } + ans <- r + } + }(send, ans) + } + + // Launch the distributor, which sends all of runs. + go func(send chan<- run) { + for i := 0; i < n; i++ { + for idx := range stencil { + send <- run{ + i: i, idx: idx, + } + } + } + close(send) + // Wait for all the workers to quit, then close the ans channel. + workerWG.Wait() + close(ans) + }(send) + + // Read in the results. + is2 := 1 / (step * step) + var laplacian float64 + for r := range ans { + laplacian += r.result * stencil[r.idx].Coeff * is2 + } + return laplacian +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/laplacian_test.go b/vendor/gonum.org/v1/gonum/diff/fd/laplacian_test.go new file mode 100644 index 00000000..75949d4a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/laplacian_test.go @@ -0,0 +1,44 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func TestLaplacian(t *testing.T) { + for cas, test := range hessianTestCases { + // Modify the test cases where the forumla is set. + settings := test.settings + if settings != nil && !settings.Formula.isZero() { + settings.Formula = Forward2nd + } + + n := len(test.x) + got := Laplacian(test.h.Func, test.x, test.settings) + hess := mat.NewSymDense(n, nil) + test.h.Hess(hess, test.x) + var want float64 + for i := 0; i < n; i++ { + want += hess.At(i, i) + } + if !floats.EqualWithinAbsOrRel(got, want, test.tol, test.tol) { + t.Errorf("Cas %d: Laplacian mismatch. got %v, want %v", cas, got, want) + } + + // Test that concurrency works. + if settings == nil { + settings = &Settings{} + } + settings.Concurrent = true + got2 := Laplacian(test.h.Func, test.x, settings) + if !floats.EqualWithinAbsOrRel(got, got2, 1e-5, 1e-5) { + t.Errorf("Cas %d: Laplacian mismatch. got %v, want %v", cas, got2, got) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/simplefunctions_test.go b/vendor/gonum.org/v1/gonum/diff/fd/simplefunctions_test.go new file mode 100644 index 00000000..1c1dd42e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/simplefunctions_test.go @@ -0,0 +1,87 @@ +// Copyright ©2017 The gonum 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 fd + +import ( + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// ConstFunc is a constant function returning the value held by the type. +type ConstFunc float64 + +func (c ConstFunc) Func(x []float64) float64 { + return float64(c) +} + +func (c ConstFunc) Grad(grad, x []float64) { + for i := range grad { + grad[i] = 0 + } +} + +func (c ConstFunc) Hess(dst mat.MutableSymmetric, x []float64) { + n := len(x) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dst.SetSym(i, j, 0) + } + } +} + +// LinearFunc is a linear function returning w*x+c. +type LinearFunc struct { + w []float64 + c float64 +} + +func (l LinearFunc) Func(x []float64) float64 { + return floats.Dot(l.w, x) + l.c +} + +func (l LinearFunc) Grad(grad, x []float64) { + copy(grad, l.w) +} + +func (l LinearFunc) Hess(dst mat.MutableSymmetric, x []float64) { + n := len(x) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dst.SetSym(i, j, 0) + } + } +} + +// QuadFunc is a quadratic function returning 0.5*x'*a*x + b*x + c. +type QuadFunc struct { + a *mat.SymDense + b *mat.VecDense + c float64 +} + +func (q QuadFunc) Func(x []float64) float64 { + v := mat.NewVecDense(len(x), x) + var tmp mat.VecDense + tmp.MulVec(q.a, v) + return 0.5*mat.Dot(&tmp, v) + mat.Dot(q.b, v) + q.c +} + +func (q QuadFunc) Grad(grad, x []float64) { + var tmp mat.VecDense + v := mat.NewVecDense(len(x), x) + tmp.MulVec(q.a, v) + for i := range grad { + grad[i] = tmp.At(i, 0) + q.b.At(i, 0) + } +} + +func (q QuadFunc) Hess(dst mat.MutableSymmetric, x []float64) { + n := len(x) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dst.SetSym(i, j, q.a.At(i, j)) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/diff/fd/watson_test.go b/vendor/gonum.org/v1/gonum/diff/fd/watson_test.go new file mode 100644 index 00000000..62095e21 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/diff/fd/watson_test.go @@ -0,0 +1,132 @@ +// Copyright ©2017 The gonum 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 fd + +import "gonum.org/v1/gonum/mat" + +// Watson implements the Watson's function. +// Dimension of the problem should be 2 <= dim <= 31. For dim == 9, the problem +// of minimizing the function is very ill conditioned. +// +// This is copied from gonum.org/v1/optimize/functions for testing Hessian-like +// derivative methods. +// +// References: +// - Kowalik, J.S., Osborne, M.R.: Methods for Unconstrained Optimization +// Problems. Elsevier North-Holland, New York, 1968 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Watson struct{} + +func (Watson) Func(x []float64) (sum float64) { + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + sum += t * t + } + t := x[1] - x[0]*x[0] - 1 + sum += x[0]*x[0] + t*t + return sum +} + +func (Watson) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + for j := range x { + grad[j] += d2 * (float64(j) - s3) * t + d2 *= d1 + } + } + t := x[1] - x[0]*x[0] - 1 + grad[0] += x[0] * (2 - 4*t) + grad[1] += 2 * t +} + +func (Watson) Hess(hess mat.MutableSymmetric, x []float64) { + dim := len(x) + if dim != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + for j := 0; j < dim; j++ { + for k := j; k < dim; k++ { + hess.SetSym(j, k, 0) + } + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + d2 := 1.0 + var s1 float64 + for j := 1; j < dim; j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + th := 2 * d1 * d1 * t + for j := 0; j < dim; j++ { + v := float64(j) - s3 + d3 := 1 / d1 + for k := 0; k <= j; k++ { + hess.SetSym(k, j, hess.At(k, j)+d2*d3*(v*(float64(k)-s3)-th)) + d3 *= d1 + } + d2 *= d1 + } + } + t1 := x[1] - x[0]*x[0] - 1 + hess.SetSym(0, 0, hess.At(0, 0)+8*x[0]*x[0]+2-4*t1) + hess.SetSym(0, 1, hess.At(0, 1)-4*x[0]) + hess.SetSym(1, 1, hess.At(1, 1)+2) +} diff --git a/vendor/gonum.org/v1/gonum/floats/README.md b/vendor/gonum.org/v1/gonum/floats/README.md new file mode 100644 index 00000000..ee867bb7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/README.md @@ -0,0 +1,4 @@ +# Gonum floats [![GoDoc](https://godoc.org/gonum.org/v1/gonum/floats?status.svg)](https://godoc.org/gonum.org/v1/gonum/floats) + +Package floats provides a set of helper routines for dealing with slices of float64. +The functions avoid allocations to allow for use within tight loops without garbage collection overhead. diff --git a/vendor/gonum.org/v1/gonum/floats/doc.go b/vendor/gonum.org/v1/gonum/floats/doc.go new file mode 100644 index 00000000..a9bd5742 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/doc.go @@ -0,0 +1,11 @@ +// Copyright ©2017 The gonum 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 floats provides a set of helper routines for dealing with slices +// of float64. The functions avoid allocations to allow for use within tight +// loops without garbage collection overhead. +// +// The convention used is that when a slice is being modified in place, it has +// the name dst. +package floats // import "gonum.org/v1/gonum/floats" diff --git a/vendor/gonum.org/v1/gonum/floats/examples_test.go b/vendor/gonum.org/v1/gonum/floats/examples_test.go new file mode 100644 index 00000000..3bc59ad1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/examples_test.go @@ -0,0 +1,104 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats + +import ( + "fmt" +) + +// Set of examples for all the functions + +func ExampleAdd_simple() { + // Adding three slices together. Note that + // the result is stored in the first slice + s1 := []float64{1, 2, 3, 4} + s2 := []float64{5, 6, 7, 8} + s3 := []float64{1, 1, 1, 1} + Add(s1, s2) + Add(s1, s3) + + fmt.Println("s1 =", s1) + fmt.Println("s2 =", s2) + fmt.Println("s3 =", s3) + // Output: + // s1 = [7 9 11 13] + // s2 = [5 6 7 8] + // s3 = [1 1 1 1] +} + +func ExampleAdd_newslice() { + // If one wants to store the result in a + // new container, just make a new slice + s1 := []float64{1, 2, 3, 4} + s2 := []float64{5, 6, 7, 8} + s3 := []float64{1, 1, 1, 1} + dst := make([]float64, len(s1)) + + AddTo(dst, s1, s2) + Add(dst, s3) + + fmt.Println("dst =", dst) + fmt.Println("s1 =", s1) + fmt.Println("s2 =", s2) + fmt.Println("s3 =", s3) + // Output: + // dst = [7 9 11 13] + // s1 = [1 2 3 4] + // s2 = [5 6 7 8] + // s3 = [1 1 1 1] +} + +func ExampleAdd_unequallengths() { + // If the lengths of the slices are unknown, + // use Eqlen to check + s1 := []float64{1, 2, 3} + s2 := []float64{5, 6, 7, 8} + + eq := EqualLengths(s1, s2) + if eq { + Add(s1, s2) + } else { + fmt.Println("Unequal lengths") + } + // Output: + // Unequal lengths +} + +func ExampleAddConst() { + s := []float64{1, -2, 3, -4} + c := 5.0 + + AddConst(c, s) + + fmt.Println("s =", s) + // Output: + // s = [6 3 8 1] +} + +func ExampleCumProd() { + s := []float64{1, -2, 3, -4} + dst := make([]float64, len(s)) + + CumProd(dst, s) + + fmt.Println("dst =", dst) + fmt.Println("s =", s) + // Output: + // dst = [1 -2 -6 24] + // s = [1 -2 3 -4] +} + +func ExampleCumSum() { + s := []float64{1, -2, 3, -4} + dst := make([]float64, len(s)) + + CumSum(dst, s) + + fmt.Println("dst =", dst) + fmt.Println("s =", s) + // Output: + // dst = [1 -1 2 -2] + // s = [1 -2 3 -4] +} diff --git a/vendor/gonum.org/v1/gonum/floats/floats.go b/vendor/gonum.org/v1/gonum/floats/floats.go new file mode 100644 index 00000000..6a582b70 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/floats.go @@ -0,0 +1,771 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats + +import ( + "errors" + "math" + "sort" + "strconv" + + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Add adds, element-wise, the elements of s and dst, and stores in dst. +// Panics if the lengths of dst and s do not match. +func Add(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: length of the slices do not match") + } + f64.AxpyUnitaryTo(dst, 1, s, dst) +} + +// AddTo adds, element-wise, the elements of s and t and +// stores the result in dst. Panics if the lengths of s, t and dst do not match. +func AddTo(dst, s, t []float64) []float64 { + if len(s) != len(t) { + panic("floats: length of adders do not match") + } + if len(dst) != len(s) { + panic("floats: length of destination does not match length of adder") + } + f64.AxpyUnitaryTo(dst, 1, s, t) + return dst +} + +// AddConst adds the scalar c to all of the values in dst. +func AddConst(c float64, dst []float64) { + for i := range dst { + dst[i] += c + } +} + +// AddScaled performs dst = dst + alpha * s. +// It panics if the lengths of dst and s are not equal. +func AddScaled(dst []float64, alpha float64, s []float64) { + if len(dst) != len(s) { + panic("floats: length of destination and source to not match") + } + f64.AxpyUnitaryTo(dst, alpha, s, dst) +} + +// AddScaledTo performs dst = y + alpha * s, where alpha is a scalar, +// and dst, y and s are all slices. +// It panics if the lengths of dst, y, and s are not equal. +// +// At the return of the function, dst[i] = y[i] + alpha * s[i] +func AddScaledTo(dst, y []float64, alpha float64, s []float64) []float64 { + if len(dst) != len(s) || len(dst) != len(y) { + panic("floats: lengths of slices do not match") + } + f64.AxpyUnitaryTo(dst, alpha, s, y) + return dst +} + +// argsort is a helper that implements sort.Interface, as used by +// Argsort. +type argsort struct { + s []float64 + inds []int +} + +func (a argsort) Len() int { + return len(a.s) +} + +func (a argsort) Less(i, j int) bool { + return a.s[i] < a.s[j] +} + +func (a argsort) Swap(i, j int) { + a.s[i], a.s[j] = a.s[j], a.s[i] + a.inds[i], a.inds[j] = a.inds[j], a.inds[i] +} + +// Argsort sorts the elements of s while tracking their original order. +// At the conclusion of Argsort, s will contain the original elements of s +// but sorted in increasing order, and inds will contain the original position +// of the elements in the slice such that dst[i] = origDst[inds[i]]. +// It panics if the lengths of dst and inds do not match. +func Argsort(dst []float64, inds []int) { + if len(dst) != len(inds) { + panic("floats: length of inds does not match length of slice") + } + for i := range dst { + inds[i] = i + } + + a := argsort{s: dst, inds: inds} + sort.Sort(a) +} + +// Count applies the function f to every element of s and returns the number +// of times the function returned true. +func Count(f func(float64) bool, s []float64) int { + var n int + for _, val := range s { + if f(val) { + n++ + } + } + return n +} + +// CumProd finds the cumulative product of the first i elements in +// s and puts them in place into the ith element of the +// destination dst. A panic will occur if the lengths of arguments +// do not match. +// +// At the return of the function, dst[i] = s[i] * s[i-1] * s[i-2] * ... +func CumProd(dst, s []float64) []float64 { + if len(dst) != len(s) { + panic("floats: length of destination does not match length of the source") + } + if len(dst) == 0 { + return dst + } + return f64.CumProd(dst, s) +} + +// CumSum finds the cumulative sum of the first i elements in +// s and puts them in place into the ith element of the +// destination dst. A panic will occur if the lengths of arguments +// do not match. +// +// At the return of the function, dst[i] = s[i] + s[i-1] + s[i-2] + ... +func CumSum(dst, s []float64) []float64 { + if len(dst) != len(s) { + panic("floats: length of destination does not match length of the source") + } + if len(dst) == 0 { + return dst + } + return f64.CumSum(dst, s) +} + +// Distance computes the L-norm of s - t. See Norm for special cases. +// A panic will occur if the lengths of s and t do not match. +func Distance(s, t []float64, L float64) float64 { + if len(s) != len(t) { + panic("floats: slice lengths do not match") + } + if len(s) == 0 { + return 0 + } + var norm float64 + if L == 2 { + for i, v := range s { + diff := t[i] - v + norm = math.Hypot(norm, diff) + } + return norm + } + if L == 1 { + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm + } + if math.IsInf(L, 1) { + for i, v := range s { + absDiff := math.Abs(t[i] - v) + if absDiff > norm { + norm = absDiff + } + } + return norm + } + for i, v := range s { + norm += math.Pow(math.Abs(t[i]-v), L) + } + return math.Pow(norm, 1/L) +} + +// Div performs element-wise division dst / s +// and stores the value in dst. It panics if the +// lengths of s and t are not equal. +func Div(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: slice lengths do not match") + } + f64.Div(dst, s) +} + +// DivTo performs element-wise division s / t +// and stores the value in dst. It panics if the +// lengths of s, t, and dst are not equal. +func DivTo(dst, s, t []float64) []float64 { + if len(s) != len(t) || len(dst) != len(t) { + panic("floats: slice lengths do not match") + } + return f64.DivTo(dst, s, t) +} + +// Dot computes the dot product of s1 and s2, i.e. +// sum_{i = 1}^N s1[i]*s2[i]. +// A panic will occur if lengths of arguments do not match. +func Dot(s1, s2 []float64) float64 { + if len(s1) != len(s2) { + panic("floats: lengths of the slices do not match") + } + return f64.DotUnitary(s1, s2) +} + +// Equal returns true if the slices have equal lengths and +// all elements are numerically identical. +func Equal(s1, s2 []float64) bool { + if len(s1) != len(s2) { + return false + } + for i, val := range s1 { + if s2[i] != val { + return false + } + } + return true +} + +// EqualApprox returns true if the slices have equal lengths and +// all element pairs have an absolute tolerance less than tol or a +// relative tolerance less than tol. +func EqualApprox(s1, s2 []float64, tol float64) bool { + if len(s1) != len(s2) { + return false + } + for i, a := range s1 { + if !EqualWithinAbsOrRel(a, s2[i], tol, tol) { + return false + } + } + return true +} + +// EqualFunc returns true if the slices have the same lengths +// and the function returns true for all element pairs. +func EqualFunc(s1, s2 []float64, f func(float64, float64) bool) bool { + if len(s1) != len(s2) { + return false + } + for i, val := range s1 { + if !f(val, s2[i]) { + return false + } + } + return true +} + +// EqualWithinAbs returns true if a and b have an absolute +// difference of less than tol. +func EqualWithinAbs(a, b, tol float64) bool { + return a == b || math.Abs(a-b) <= tol +} + +const minNormalFloat64 = 2.2250738585072014e-308 + +// EqualWithinRel returns true if the difference between a and b +// is not greater than tol times the greater value. +func EqualWithinRel(a, b, tol float64) bool { + if a == b { + return true + } + delta := math.Abs(a - b) + if delta <= minNormalFloat64 { + return delta <= tol*minNormalFloat64 + } + // We depend on the division in this relationship to identify + // infinities (we rely on the NaN to fail the test) otherwise + // we compare Infs of the same sign and evaluate Infs as equal + // independent of sign. + return delta/math.Max(math.Abs(a), math.Abs(b)) <= tol +} + +// EqualWithinAbsOrRel returns true if a and b are equal to within +// the absolute tolerance. +func EqualWithinAbsOrRel(a, b, absTol, relTol float64) bool { + if EqualWithinAbs(a, b, absTol) { + return true + } + return EqualWithinRel(a, b, relTol) +} + +// EqualWithinULP returns true if a and b are equal to within +// the specified number of floating point units in the last place. +func EqualWithinULP(a, b float64, ulp uint) bool { + if a == b { + return true + } + if math.IsNaN(a) || math.IsNaN(b) { + return false + } + if math.Signbit(a) != math.Signbit(b) { + return math.Float64bits(math.Abs(a))+math.Float64bits(math.Abs(b)) <= uint64(ulp) + } + return ulpDiff(math.Float64bits(a), math.Float64bits(b)) <= uint64(ulp) +} + +func ulpDiff(a, b uint64) uint64 { + if a > b { + return a - b + } + return b - a +} + +// EqualLengths returns true if all of the slices have equal length, +// and false otherwise. Returns true if there are no input slices. +func EqualLengths(slices ...[]float64) bool { + // This length check is needed: http://play.golang.org/p/sdty6YiLhM + if len(slices) == 0 { + return true + } + l := len(slices[0]) + for i := 1; i < len(slices); i++ { + if len(slices[i]) != l { + return false + } + } + return true +} + +// Find applies f to every element of s and returns the indices of the first +// k elements for which the f returns true, or all such elements +// if k < 0. +// Find will reslice inds to have 0 length, and will append +// found indices to inds. +// If k > 0 and there are fewer than k elements in s satisfying f, +// all of the found elements will be returned along with an error. +// At the return of the function, the input inds will be in an undetermined state. +func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) { + + // inds is also returned to allow for calling with nil + + // Reslice inds to have zero length + inds = inds[:0] + + // If zero elements requested, can just return + if k == 0 { + return inds, nil + } + + // If k < 0, return all of the found indices + if k < 0 { + for i, val := range s { + if f(val) { + inds = append(inds, i) + } + } + return inds, nil + } + + // Otherwise, find the first k elements + nFound := 0 + for i, val := range s { + if f(val) { + inds = append(inds, i) + nFound++ + if nFound == k { + return inds, nil + } + } + } + // Finished iterating over the loop, which means k elements were not found + return inds, errors.New("floats: insufficient elements found") +} + +// HasNaN returns true if the slice s has any values that are NaN and false +// otherwise. +func HasNaN(s []float64) bool { + for _, v := range s { + if math.IsNaN(v) { + return true + } + } + return false +} + +// LogSpan returns a set of n equally spaced points in log space between, +// l and u where N is equal to len(dst). The first element of the +// resulting dst will be l and the final element of dst will be u. +// Panics if len(dst) < 2 +// Note that this call will return NaNs if either l or u are negative, and +// will return all zeros if l or u is zero. +// Also returns the mutated slice dst, so that it can be used in range, like: +// +// for i, x := range LogSpan(dst, l, u) { ... } +func LogSpan(dst []float64, l, u float64) []float64 { + Span(dst, math.Log(l), math.Log(u)) + for i := range dst { + dst[i] = math.Exp(dst[i]) + } + return dst +} + +// LogSumExp returns the log of the sum of the exponentials of the values in s. +// Panics if s is an empty slice. +func LogSumExp(s []float64) float64 { + // Want to do this in a numerically stable way which avoids + // overflow and underflow + // First, find the maximum value in the slice. + maxval := Max(s) + if math.IsInf(maxval, 0) { + // If it's infinity either way, the logsumexp will be infinity as well + // returning now avoids NaNs + return maxval + } + var lse float64 + // Compute the sumexp part + for _, val := range s { + lse += math.Exp(val - maxval) + } + // Take the log and add back on the constant taken out + return math.Log(lse) + maxval +} + +// Max returns the maximum value in the input slice. If the slice is empty, Max will panic. +func Max(s []float64) float64 { + return s[MaxIdx(s)] +} + +// MaxIdx returns the index of the maximum value in the input slice. If several +// entries have the maximum value, the first such index is returned. If the slice +// is empty, MaxIdx will panic. +func MaxIdx(s []float64) int { + if len(s) == 0 { + panic("floats: zero slice length") + } + max := s[0] + var ind int + for i, v := range s { + if v > max { + max = v + ind = i + } + } + return ind +} + +// Min returns the maximum value in the input slice. If the slice is empty, Min will panic. +func Min(s []float64) float64 { + return s[MinIdx(s)] +} + +// MinIdx returns the index of the minimum value in the input slice. If several +// entries have the maximum value, the first such index is returned. If the slice +// is empty, MinIdx will panic. +func MinIdx(s []float64) int { + min := s[0] + var ind int + for i, v := range s { + if v < min { + min = v + ind = i + } + } + return ind +} + +// Mul performs element-wise multiplication between dst +// and s and stores the value in dst. Panics if the +// lengths of s and t are not equal. +func Mul(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: slice lengths do not match") + } + for i, val := range s { + dst[i] *= val + } +} + +// MulTo performs element-wise multiplication between s +// and t and stores the value in dst. Panics if the +// lengths of s, t, and dst are not equal. +func MulTo(dst, s, t []float64) []float64 { + if len(s) != len(t) || len(dst) != len(t) { + panic("floats: slice lengths do not match") + } + for i, val := range t { + dst[i] = val * s[i] + } + return dst +} + +// Nearest returns the index of the element in s +// whose value is nearest to v. If several such +// elements exist, the lowest index is returned. +// Panics if len(s) == 0. +func Nearest(s []float64, v float64) int { + var ind int + dist := math.Abs(v - s[0]) + for i, val := range s { + newDist := math.Abs(v - val) + if newDist < dist { + dist = newDist + ind = i + } + } + return ind +} + +// NearestWithinSpan return the index of a hypothetical vector created +// by Span with length n and bounds l and u whose value is closest +// to v. NearestWithinSpan panics if u < l. If the value is greater than u or +// less than l, the function returns -1. +func NearestWithinSpan(n int, l, u float64, v float64) int { + if u < l { + panic("floats: upper bound greater than lower bound") + } + if v < l || v > u { + return -1 + } + // Can't guarantee anything about exactly halfway between + // because of floating point weirdness. + return int((float64(n)-1)/(u-l)*(v-l) + 0.5) +} + +// Norm returns the L norm of the slice S, defined as +// (sum_{i=1}^N s[i]^L)^{1/L} +// Special cases: +// L = math.Inf(1) gives the maximum absolute value. +// Does not correctly compute the zero norm (use Count). +func Norm(s []float64, L float64) float64 { + // Should this complain if L is not positive? + // Should this be done in log space for better numerical stability? + // would be more cost + // maybe only if L is high? + if len(s) == 0 { + return 0 + } + if L == 2 { + twoNorm := math.Abs(s[0]) + for i := 1; i < len(s); i++ { + twoNorm = math.Hypot(twoNorm, s[i]) + } + return twoNorm + } + var norm float64 + if L == 1 { + for _, val := range s { + norm += math.Abs(val) + } + return norm + } + if math.IsInf(L, 1) { + for _, val := range s { + norm = math.Max(norm, math.Abs(val)) + } + return norm + } + for _, val := range s { + norm += math.Pow(math.Abs(val), L) + } + return math.Pow(norm, 1/L) +} + +// ParseWithNA converts the string s to a float64 in v. +// If s equals missing, w is returned as 0, otherwise 1. +func ParseWithNA(s, missing string) (v, w float64, err error) { + if s == missing { + return 0, 0, nil + } + v, err = strconv.ParseFloat(s, 64) + if err == nil { + w = 1 + } + return v, w, err +} + +// Prod returns the product of the elements of the slice. +// Returns 1 if len(s) = 0. +func Prod(s []float64) float64 { + prod := 1.0 + for _, val := range s { + prod *= val + } + return prod +} + +// Reverse reverses the order of elements in the slice. +func Reverse(s []float64) { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } +} + +// Round returns the half away from zero rounded value of x with prec precision. +// +// Special cases are: +// Round(±0) = +0 +// Round(±Inf) = ±Inf +// Round(NaN) = NaN +func Round(x float64, prec int) float64 { + if x == 0 { + // Make sure zero is returned + // without the negative bit set. + return 0 + } + // Fast path for positive precision on integers. + if prec >= 0 && x == math.Trunc(x) { + return x + } + pow := math.Pow10(prec) + intermed := x * pow + if math.IsInf(intermed, 0) { + return x + } + if x < 0 { + x = math.Ceil(intermed - 0.5) + } else { + x = math.Floor(intermed + 0.5) + } + + if x == 0 { + return 0 + } + + return x / pow +} + +// RoundEven returns the half even rounded value of x with prec precision. +// +// Special cases are: +// RoundEven(±0) = +0 +// RoundEven(±Inf) = ±Inf +// RoundEven(NaN) = NaN +func RoundEven(x float64, prec int) float64 { + if x == 0 { + // Make sure zero is returned + // without the negative bit set. + return 0 + } + // Fast path for positive precision on integers. + if prec >= 0 && x == math.Trunc(x) { + return x + } + pow := math.Pow10(prec) + intermed := x * pow + if math.IsInf(intermed, 0) { + return x + } + if isHalfway(intermed) { + correction, _ := math.Modf(math.Mod(intermed, 2)) + intermed += correction + if intermed > 0 { + x = math.Floor(intermed) + } else { + x = math.Ceil(intermed) + } + } else { + if x < 0 { + x = math.Ceil(intermed - 0.5) + } else { + x = math.Floor(intermed + 0.5) + } + } + + if x == 0 { + return 0 + } + + return x / pow +} + +func isHalfway(x float64) bool { + _, frac := math.Modf(x) + frac = math.Abs(frac) + return frac == 0.5 || (math.Nextafter(frac, math.Inf(-1)) < 0.5 && math.Nextafter(frac, math.Inf(1)) > 0.5) +} + +// Same returns true if the input slices have the same length and the all elements +// have the same value with NaN treated as the same. +func Same(s, t []float64) bool { + if len(s) != len(t) { + return false + } + for i, v := range s { + w := t[i] + if v != w && !math.IsNaN(v) && !math.IsNaN(w) { + return false + } + } + return true +} + +// Scale multiplies every element in dst by the scalar c. +func Scale(c float64, dst []float64) { + if len(dst) > 0 { + f64.ScalUnitary(c, dst) + } +} + +// Span returns a set of N equally spaced points between l and u, where N +// is equal to the length of the destination. The first element of the destination +// is l, the final element of the destination is u. +// Panics if len(dst) < 2. +// +// Also returns the mutated slice dst, so that it can be used in range expressions, like: +// +// for i, x := range Span(dst, l, u) { ... } +func Span(dst []float64, l, u float64) []float64 { + n := len(dst) + if n < 2 { + panic("floats: destination must have length >1") + } + step := (u - l) / float64(n-1) + for i := range dst { + dst[i] = l + step*float64(i) + } + return dst +} + +// Sub subtracts, element-wise, the elements of s from dst. Panics if +// the lengths of dst and s do not match. +func Sub(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: length of the slices do not match") + } + f64.AxpyUnitaryTo(dst, -1, s, dst) +} + +// SubTo subtracts, element-wise, the elements of t from s and +// stores the result in dst. Panics if the lengths of s, t and dst do not match. +func SubTo(dst, s, t []float64) []float64 { + if len(s) != len(t) { + panic("floats: length of subtractor and subtractee do not match") + } + if len(dst) != len(s) { + panic("floats: length of destination does not match length of subtractor") + } + f64.AxpyUnitaryTo(dst, -1, t, s) + return dst +} + +// Sum returns the sum of the elements of the slice. +func Sum(s []float64) float64 { + var sum float64 + for _, val := range s { + sum += val + } + return sum +} + +// Within returns the first index i where s[i] <= v < s[i+1]. Within panics if: +// - len(s) < 2 +// - s is not sorted +func Within(s []float64, v float64) int { + if len(s) < 2 { + panic("floats: slice length less than 2") + } + if !sort.Float64sAreSorted(s) { + panic("floats: input slice not sorted") + } + if v < s[0] || v >= s[len(s)-1] || math.IsNaN(v) { + return -1 + } + for i, f := range s[1:] { + if v < f { + return i + } + } + return -1 +} diff --git a/vendor/gonum.org/v1/gonum/floats/floats_test.go b/vendor/gonum.org/v1/gonum/floats/floats_test.go new file mode 100644 index 00000000..32e4a392 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/floats_test.go @@ -0,0 +1,1403 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats + +import ( + "math" + "math/rand" + "strconv" + "testing" +) + +const ( + EqTolerance = 1E-14 + Small = 10 + Medium = 1000 + Large = 100000 + Huge = 10000000 +) + +func AreSlicesEqual(t *testing.T, truth, comp []float64, str string) { + if !EqualApprox(comp, truth, EqTolerance) { + t.Errorf(str+". Expected %v, returned %v", truth, comp) + } +} + +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestAdd(t *testing.T) { + a := []float64{1, 2, 3} + b := []float64{4, 5, 6} + c := []float64{7, 8, 9} + truth := []float64{12, 15, 18} + n := make([]float64, len(a)) + + Add(n, a) + Add(n, b) + Add(n, c) + AreSlicesEqual(t, truth, n, "Wrong addition of slices new receiver") + Add(a, b) + Add(a, c) + AreSlicesEqual(t, truth, n, "Wrong addition of slices for no new receiver") + + // Test that it panics + if !Panics(func() { Add(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestAddTo(t *testing.T) { + a := []float64{1, 2, 3} + b := []float64{4, 5, 6} + truth := []float64{5, 7, 9} + n1 := make([]float64, len(a)) + + n2 := AddTo(n1, a, b) + AreSlicesEqual(t, truth, n1, "Bad addition from mutator") + AreSlicesEqual(t, truth, n2, "Bad addition from returned slice") + + // Test that it panics + if !Panics(func() { AddTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + if !Panics(func() { AddTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Did not panic with length mismatch") + } + +} + +func TestAddConst(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + c := 6.0 + truth := []float64{9, 10, 7, 13, 11} + AddConst(c, s) + AreSlicesEqual(t, truth, s, "Wrong addition of constant") +} + +func TestAddScaled(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + alpha := 6.0 + dst := []float64{1, 2, 3, 4, 5} + ans := []float64{19, 26, 9, 46, 35} + AddScaled(dst, alpha, s) + if !EqualApprox(dst, ans, EqTolerance) { + t.Errorf("Adding scaled did not match") + } + short := []float64{1} + if !Panics(func() { AddScaled(dst, alpha, short) }) { + t.Errorf("Doesn't panic if s is smaller than dst") + } + if !Panics(func() { AddScaled(short, alpha, s) }) { + t.Errorf("Doesn't panic if dst is smaller than s") + } +} + +func TestAddScaledTo(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + alpha := 6.0 + y := []float64{1, 2, 3, 4, 5} + dst1 := make([]float64, 5) + ans := []float64{19, 26, 9, 46, 35} + dst2 := AddScaledTo(dst1, y, alpha, s) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("AddScaledTo did not match for mutator") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("AddScaledTo did not match for returned slice") + } + AddScaledTo(dst1, y, alpha, s) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("Reusing dst did not match") + } + short := []float64{1} + if !Panics(func() { AddScaledTo(dst1, y, alpha, short) }) { + t.Errorf("Doesn't panic if s is smaller than dst") + } + if !Panics(func() { AddScaledTo(short, y, alpha, s) }) { + t.Errorf("Doesn't panic if dst is smaller than s") + } + if !Panics(func() { AddScaledTo(dst1, short, alpha, s) }) { + t.Errorf("Doesn't panic if y is smaller than dst") + } +} + +func TestArgsort(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + inds := make([]int, len(s)) + + Argsort(s, inds) + + sortedS := []float64{1, 3, 4, 5, 7} + trueInds := []int{2, 0, 1, 4, 3} + + if !Equal(s, sortedS) { + t.Error("elements not sorted correctly") + } + for i := range trueInds { + if trueInds[i] != inds[i] { + t.Error("inds not correct") + } + } + + inds = []int{1, 2} + if !Panics(func() { Argsort(s, inds) }) { + t.Error("does not panic if lengths do not match") + } +} + +func TestCount(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + f := func(v float64) bool { return v > 3.5 } + truth := 3 + n := Count(f, s) + if n != truth { + t.Errorf("Wrong number of elements counted") + } +} + +func TestCumProd(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + receiver := make([]float64, len(s)) + result := CumProd(receiver, s) + truth := []float64{3, 12, 12, 84, 420} + AreSlicesEqual(t, truth, receiver, "Wrong cumprod mutated with new receiver") + AreSlicesEqual(t, truth, result, "Wrong cumprod result with new receiver") + CumProd(receiver, s) + AreSlicesEqual(t, truth, receiver, "Wrong cumprod returned with reused receiver") + + // Test that it panics + if !Panics(func() { CumProd(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + + // Test empty CumProd + emptyReceiver := make([]float64, 0) + truth = []float64{} + CumProd(emptyReceiver, emptyReceiver) + AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with empty receiver") + +} + +func TestCumSum(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + receiver := make([]float64, len(s)) + result := CumSum(receiver, s) + truth := []float64{3, 7, 8, 15, 20} + AreSlicesEqual(t, truth, receiver, "Wrong cumsum mutated with new receiver") + AreSlicesEqual(t, truth, result, "Wrong cumsum returned with new receiver") + CumSum(receiver, s) + AreSlicesEqual(t, truth, receiver, "Wrong cumsum returned with reused receiver") + + // Test that it panics + if !Panics(func() { CumSum(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + + // Test empty CumSum + emptyReceiver := make([]float64, 0) + truth = []float64{} + CumSum(emptyReceiver, emptyReceiver) + AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumsum returned with empty receiver") + +} + +func TestDistance(t *testing.T) { + norms := []float64{1, 2, 4, math.Inf(1)} + slices := []struct { + s []float64 + t []float64 + }{ + { + nil, + nil, + }, + { + []float64{8, 9, 10, -12}, + []float64{8, 9, 10, -12}, + }, + { + []float64{1, 2, 3, -4, -5, 8}, + []float64{-9.2, -6.8, 9, -3, -2, 1}, + }, + } + + for j, test := range slices { + tmp := make([]float64, len(test.s)) + for i, L := range norms { + dist := Distance(test.s, test.t, L) + copy(tmp, test.s) + Sub(tmp, test.t) + norm := Norm(tmp, L) + if dist != norm { // Use equality because they should be identical + t.Errorf("Distance does not match norm for case %v, %v. Expected %v, Found %v.", i, j, norm, dist) + } + } + } + + if !Panics(func() { Distance([]float64{}, norms, 1) }) { + t.Errorf("Did not panic with unequal lengths") + } + +} + +func TestDiv(t *testing.T) { + s1 := []float64{5, 12, 27} + s2 := []float64{1, 2, 3} + ans := []float64{5, 6, 9} + Div(s1, s2) + if !EqualApprox(s1, ans, EqTolerance) { + t.Errorf("Mul doesn't give correct answer") + } + s1short := []float64{1} + if !Panics(func() { Div(s1short, s2) }) { + t.Errorf("Did not panic with unequal lengths") + } + s2short := []float64{1} + if !Panics(func() { Div(s1, s2short) }) { + t.Errorf("Did not panic with unequal lengths") + } +} + +func TestDivTo(t *testing.T) { + s1 := []float64{5, 12, 27} + s1orig := []float64{5, 12, 27} + s2 := []float64{1, 2, 3} + s2orig := []float64{1, 2, 3} + dst1 := make([]float64, 3) + ans := []float64{5, 6, 9} + dst2 := DivTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer in mutated slice") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer in returned slice") + } + if !EqualApprox(s1, s1orig, EqTolerance) { + t.Errorf("S1 changes during multo") + } + if !EqualApprox(s2, s2orig, EqTolerance) { + t.Errorf("s2 changes during multo") + } + DivTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer reusing dst") + } + dstShort := []float64{1} + if !Panics(func() { DivTo(dstShort, s1, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s1short := []float64{1} + if !Panics(func() { DivTo(dst1, s1short, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s2short := []float64{1} + if !Panics(func() { DivTo(dst1, s1, s2short) }) { + t.Errorf("Did not panic with s2 wrong length") + } +} + +func TestDot(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{-3, 4, 5, -6} + truth := -4.0 + ans := Dot(s1, s2) + if ans != truth { + t.Errorf("Dot product computed incorrectly") + } + + // Test that it panics + if !Panics(func() { Dot(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestEquals(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + if !Equal(s1, s2) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if Equal(s1, s2) { + t.Errorf("Unequal slices returned as equal") + } + if Equal(s1, []float64{}) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualApprox(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4 + 1e-10} + if EqualApprox(s1, s2, 1e-13) { + t.Errorf("Unequal slices returned as equal for absolute") + } + if !EqualApprox(s1, s2, 1e-5) { + t.Errorf("Equal slices returned as unequal for absolute") + } + s1 = []float64{1, 2, 3, 1000} + s2 = []float64{1, 2, 3, 1000 * (1 + 1e-7)} + if EqualApprox(s1, s2, 1e-8) { + t.Errorf("Unequal slices returned as equal for relative") + } + if !EqualApprox(s1, s2, 1e-5) { + t.Errorf("Equal slices returned as unequal for relative") + } + if EqualApprox(s1, []float64{}, 1e-5) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualFunc(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + eq := func(x, y float64) bool { return x == y } + if !EqualFunc(s1, s2, eq) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if EqualFunc(s1, s2, eq) { + t.Errorf("Unequal slices returned as equal") + } + if EqualFunc(s1, []float64{}, eq) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualsRelative(t *testing.T) { + var equalityTests = []struct { + a, b float64 + tol float64 + equal bool + }{ + {1000000, 1000001, 0, true}, + {1000001, 1000000, 0, true}, + {10000, 10001, 0, false}, + {10001, 10000, 0, false}, + {-1000000, -1000001, 0, true}, + {-1000001, -1000000, 0, true}, + {-10000, -10001, 0, false}, + {-10001, -10000, 0, false}, + {1.0000001, 1.0000002, 0, true}, + {1.0000002, 1.0000001, 0, true}, + {1.0002, 1.0001, 0, false}, + {1.0001, 1.0002, 0, false}, + {-1.000001, -1.000002, 0, true}, + {-1.000002, -1.000001, 0, true}, + {-1.0001, -1.0002, 0, false}, + {-1.0002, -1.0001, 0, false}, + {0.000000001000001, 0.000000001000002, 0, true}, + {0.000000001000002, 0.000000001000001, 0, true}, + {0.000000000001002, 0.000000000001001, 0, false}, + {0.000000000001001, 0.000000000001002, 0, false}, + {-0.000000001000001, -0.000000001000002, 0, true}, + {-0.000000001000002, -0.000000001000001, 0, true}, + {-0.000000000001002, -0.000000000001001, 0, false}, + {-0.000000000001001, -0.000000000001002, 0, false}, + {0, 0, 0, true}, + {0, -0, 0, true}, + {-0, -0, 0, true}, + {0.00000001, 0, 0, false}, + {0, 0.00000001, 0, false}, + {-0.00000001, 0, 0, false}, + {0, -0.00000001, 0, false}, + {0, 1e-310, 0.01, true}, + {1e-310, 0, 0.01, true}, + {1e-310, 0, 0.000001, false}, + {0, 1e-310, 0.000001, false}, + {0, -1e-310, 0.1, true}, + {-1e-310, 0, 0.1, true}, + {-1e-310, 0, 0.00000001, false}, + {0, -1e-310, 0.00000001, false}, + {math.Inf(1), math.Inf(1), 0, true}, + {math.Inf(-1), math.Inf(-1), 0, true}, + {math.Inf(-1), math.Inf(1), 0, false}, + {math.Inf(1), math.MaxFloat64, 0, false}, + {math.Inf(-1), -math.MaxFloat64, 0, false}, + {math.NaN(), math.NaN(), 0, false}, + {math.NaN(), 0, 0, false}, + {-0, math.NaN(), 0, false}, + {math.NaN(), -0, 0, false}, + {0, math.NaN(), 0, false}, + {math.NaN(), math.Inf(1), 0, false}, + {math.Inf(1), math.NaN(), 0, false}, + {math.NaN(), math.Inf(-1), 0, false}, + {math.Inf(-1), math.NaN(), 0, false}, + {math.NaN(), math.MaxFloat64, 0, false}, + {math.MaxFloat64, math.NaN(), 0, false}, + {math.NaN(), -math.MaxFloat64, 0, false}, + {-math.MaxFloat64, math.NaN(), 0, false}, + {math.NaN(), math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, math.NaN(), 0, false}, + {math.NaN(), -math.SmallestNonzeroFloat64, 0, false}, + {-math.SmallestNonzeroFloat64, math.NaN(), 0, false}, + {1.000000001, -1.0, 0, false}, + {-1.0, 1.000000001, 0, false}, + {-1.000000001, 1.0, 0, false}, + {1.0, -1.000000001, 0, false}, + {10 * math.SmallestNonzeroFloat64, 10 * -math.SmallestNonzeroFloat64, 0, true}, + {1e11 * math.SmallestNonzeroFloat64, 1e11 * -math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, -math.SmallestNonzeroFloat64, 0, true}, + {-math.SmallestNonzeroFloat64, math.SmallestNonzeroFloat64, 0, true}, + {math.SmallestNonzeroFloat64, 0, 0, true}, + {0, math.SmallestNonzeroFloat64, 0, true}, + {-math.SmallestNonzeroFloat64, 0, 0, true}, + {0, -math.SmallestNonzeroFloat64, 0, true}, + {0.000000001, -math.SmallestNonzeroFloat64, 0, false}, + {0.000000001, math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, 0.000000001, 0, false}, + {-math.SmallestNonzeroFloat64, 0.000000001, 0, false}, + } + for _, ts := range equalityTests { + if ts.tol == 0 { + ts.tol = 1e-5 + } + if equal := EqualWithinRel(ts.a, ts.b, ts.tol); equal != ts.equal { + t.Errorf("Relative equality of %g and %g with tolerance %g returned: %v. Expected: %v", + ts.a, ts.b, ts.tol, equal, ts.equal) + } + } +} + +func nextAfterN(x, y float64, n int) float64 { + for i := 0; i < n; i++ { + x = math.Nextafter(x, y) + } + return x +} + +func TestEqualsULP(t *testing.T) { + if f := 67329.242; !EqualWithinULP(f, nextAfterN(f, math.Inf(1), 10), 10) { + t.Errorf("Equal values returned as unequal") + } + if f := 67329.242; EqualWithinULP(f, nextAfterN(f, math.Inf(1), 5), 1) { + t.Errorf("Unequal values returned as equal") + } + if f := 67329.242; EqualWithinULP(nextAfterN(f, math.Inf(1), 5), f, 1) { + t.Errorf("Unequal values returned as equal") + } + if f := nextAfterN(0, math.Inf(1), 2); !EqualWithinULP(f, nextAfterN(f, math.Inf(-1), 5), 10) { + t.Errorf("Equal values returned as unequal") + } + if !EqualWithinULP(67329.242, 67329.242, 10) { + t.Errorf("Equal float64s not returned as equal") + } + if EqualWithinULP(1, math.NaN(), 10) { + t.Errorf("NaN returned as equal") + } + +} + +func TestEqualLengths(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + s3 := []float64{1, 2, 3} + if !EqualLengths(s1, s2) { + t.Errorf("Equal lengths returned as unequal") + } + if EqualLengths(s1, s3) { + t.Errorf("Unequal lengths returned as equal") + } + if !EqualLengths(s1) { + t.Errorf("Single slice returned as unequal") + } + if !EqualLengths() { + t.Errorf("No slices returned as unequal") + } +} + +func eqIntSlice(one, two []int) string { + if len(one) != len(two) { + return "Length mismatch" + } + for i, val := range one { + if val != two[i] { + return "Index " + strconv.Itoa(i) + " mismatch" + } + } + return "" +} + +func TestFind(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + f := func(v float64) bool { return v > 3.5 } + allTrueInds := []int{1, 3, 4} + + // Test finding first two elements + inds, err := Find(nil, f, s, 2) + if err != nil { + t.Errorf("Find first two: Improper error return") + } + trueInds := allTrueInds[:2] + str := eqIntSlice(inds, trueInds) + if str != "" { + t.Errorf("Find first two: " + str) + } + + // Test finding no elements with non nil slice + inds = []int{1, 2, 3, 4, 5, 6} + inds, err = Find(inds, f, s, 0) + if err != nil { + t.Errorf("Find no elements: Improper error return") + } + str = eqIntSlice(inds, []int{}) + if str != "" { + t.Errorf("Find no non-nil: " + str) + } + + // Test finding first two elements with non nil slice + inds = []int{1, 2, 3, 4, 5, 6} + inds, err = Find(inds, f, s, 2) + if err != nil { + t.Errorf("Find first two non-nil: Improper error return") + } + str = eqIntSlice(inds, trueInds) + if str != "" { + t.Errorf("Find first two non-nil: " + str) + } + + // Test finding too many elements + inds, err = Find(inds, f, s, 4) + if err == nil { + t.Errorf("Request too many: No error returned") + } + str = eqIntSlice(inds, allTrueInds) + if str != "" { + t.Errorf("Request too many: Does not match all of the inds: " + str) + } + + // Test finding all elements + inds, err = Find(nil, f, s, -1) + if err != nil { + t.Errorf("Find all: Improper error returned") + } + str = eqIntSlice(inds, allTrueInds) + if str != "" { + t.Errorf("Find all: Does not match all of the inds: " + str) + } +} + +func TestHasNaN(t *testing.T) { + for i, test := range []struct { + s []float64 + ans bool + }{ + {}, + { + s: []float64{1, 2, 3, 4}, + }, + { + s: []float64{1, math.NaN(), 3, 4}, + ans: true, + }, + { + s: []float64{1, 2, 3, math.NaN()}, + ans: true, + }, + } { + b := HasNaN(test.s) + if b != test.ans { + t.Errorf("HasNaN mismatch case %d. Expected %v, Found %v", i, test.ans, b) + } + } +} + +func TestLogSpan(t *testing.T) { + receiver1 := make([]float64, 6) + truth := []float64{0.001, 0.01, 0.1, 1, 10, 100} + receiver2 := LogSpan(receiver1, 0.001, 100) + tst := make([]float64, 6) + for i := range truth { + tst[i] = receiver1[i] / truth[i] + } + comp := make([]float64, 6) + for i := range comp { + comp[i] = 1 + } + AreSlicesEqual(t, comp, tst, "Improper logspace from mutator") + + for i := range truth { + tst[i] = receiver2[i] / truth[i] + } + AreSlicesEqual(t, comp, tst, "Improper logspace from returned slice") + + if !Panics(func() { LogSpan(nil, 1, 5) }) { + t.Errorf("Span accepts nil argument") + } + if !Panics(func() { LogSpan(make([]float64, 1), 1, 5) }) { + t.Errorf("Span accepts argument of len = 1") + } +} + +func TestLogSumExp(t *testing.T) { + s := []float64{1, 2, 3, 4, 5} + val := LogSumExp(s) + // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29+%2B+exp%283%29+%2B+exp%284%29+%2B+exp%285%29%29 + truth := 5.4519143959375933331957225109748087179338972737576824 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for many values") + } + s = []float64{1, 2} + // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29%29 + truth = 2.3132616875182228340489954949678556419152800856703483 + val = LogSumExp(s) + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for two values. %v expected, %v found", truth, val) + } + // This case would normally underflow + s = []float64{-1001, -1002, -1003, -1004, -1005} + // http://www.wolframalpha.com/input/?i=log%28exp%28-1001%29%2Bexp%28-1002%29%2Bexp%28-1003%29%2Bexp%28-1004%29%2Bexp%28-1005%29%29 + truth = -1000.54808560406240666680427748902519128206610272624 + val = LogSumExp(s) + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for underflow case. %v expected, %v found", truth, val) + } + // positive infinite case + s = []float64{1, 2, 3, 4, 5, math.Inf(1)} + val = LogSumExp(s) + truth = math.Inf(1) + if val != truth { + t.Errorf("Doesn't match for pos Infinity case. %v expected, %v found", truth, val) + } + // negative infinite case + s = []float64{1, 2, 3, 4, 5, math.Inf(-1)} + val = LogSumExp(s) + truth = 5.4519143959375933331957225109748087179338972737576824 // same as first case + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for values with negative infinity") + } + +} + +func TestMaxAndIdx(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + ind := MaxIdx(s) + val := Max(s) + if val != 7 { + t.Errorf("Wrong value returned") + } + if ind != 3 { + t.Errorf("Wrong index returned") + } +} + +func TestMinAndIdx(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + ind := MinIdx(s) + val := Min(s) + if val != 1 { + t.Errorf("Wrong value returned") + } + if ind != 2 { + t.Errorf("Wrong index returned") + } +} + +func TestMul(t *testing.T) { + s1 := []float64{1, 2, 3} + s2 := []float64{1, 2, 3} + ans := []float64{1, 4, 9} + Mul(s1, s2) + if !EqualApprox(s1, ans, EqTolerance) { + t.Errorf("Mul doesn't give correct answer") + } + s1short := []float64{1} + if !Panics(func() { Mul(s1short, s2) }) { + t.Errorf("Did not panic with unequal lengths") + } + s2short := []float64{1} + if !Panics(func() { Mul(s1, s2short) }) { + t.Errorf("Did not panic with unequal lengths") + } +} + +func TestMulTo(t *testing.T) { + s1 := []float64{1, 2, 3} + s1orig := []float64{1, 2, 3} + s2 := []float64{1, 2, 3} + s2orig := []float64{1, 2, 3} + dst1 := make([]float64, 3) + ans := []float64{1, 4, 9} + dst2 := MulTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer in mutated slice") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer in returned slice") + } + if !EqualApprox(s1, s1orig, EqTolerance) { + t.Errorf("S1 changes during multo") + } + if !EqualApprox(s2, s2orig, EqTolerance) { + t.Errorf("s2 changes during multo") + } + MulTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer reusing dst") + } + dstShort := []float64{1} + if !Panics(func() { MulTo(dstShort, s1, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s1short := []float64{1} + if !Panics(func() { MulTo(dst1, s1short, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s2short := []float64{1} + if !Panics(func() { MulTo(dst1, s1, s2short) }) { + t.Errorf("Did not panic with s2 wrong length") + } +} + +func TestNearest(t *testing.T) { + s := []float64{6.2, 3, 5, 6.2, 8} + ind := Nearest(s, 2.0) + if ind != 1 { + t.Errorf("Wrong index returned when value is less than all of elements") + } + ind = Nearest(s, 9.0) + if ind != 4 { + t.Errorf("Wrong index returned when value is greater than all of elements") + } + ind = Nearest(s, 3.1) + if ind != 1 { + t.Errorf("Wrong index returned when value is greater than closest element") + } + ind = Nearest(s, 3.1) + if ind != 1 { + t.Errorf("Wrong index returned when value is greater than closest element") + } + ind = Nearest(s, 2.9) + if ind != 1 { + t.Errorf("Wrong index returned when value is less than closest element") + } + ind = Nearest(s, 3) + if ind != 1 { + t.Errorf("Wrong index returned when value is equal to element") + } + ind = Nearest(s, 6.2) + if ind != 0 { + t.Errorf("Wrong index returned when value is equal to several elements") + } + ind = Nearest(s, 4) + if ind != 1 { + t.Errorf("Wrong index returned when value is exactly between two closest elements") + } +} + +func TestNearestWithinSpan(t *testing.T) { + if !Panics(func() { NearestWithinSpan(10, 8, 2, 4.5) }) { + t.Errorf("Did not panic when upper bound is lower than greater bound") + } + for i, test := range []struct { + length int + lower float64 + upper float64 + value float64 + idx int + }{ + { + length: 13, + lower: 7, + upper: 8.2, + value: 6, + idx: -1, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 10, + idx: -1, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.19, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.21, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.2, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.151, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.249, + idx: 2, + }, + } { + if idx := NearestWithinSpan(test.length, test.lower, test.upper, test.value); test.idx != idx { + t.Errorf("Case %v mismatch: Want: %v, Got: %v", i, test.idx, idx) + } + } +} + +func TestNorm(t *testing.T) { + s := []float64{-1, -3.4, 5, -6} + val := Norm(s, math.Inf(1)) + truth := 6.0 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + // http://www.wolframalpha.com/input/?i=%28%28-1%29%5E2+%2B++%28-3.4%29%5E2+%2B+5%5E2%2B++6%5E2%29%5E%281%2F2%29 + val = Norm(s, 2) + truth = 8.5767126569566267590651614132751986658027271236078592 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + // http://www.wolframalpha.com/input/?i=%28%28%7C-1%7C%29%5E3+%2B++%28%7C-3.4%7C%29%5E3+%2B+%7C5%7C%5E3%2B++%7C6%7C%5E3%29%5E%281%2F3%29 + val = Norm(s, 3) + truth = 7.2514321388020228478109121239004816430071237369356233 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + + //http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C + val = Norm(s, 1) + truth = 15.4 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } +} + +func TestProd(t *testing.T) { + s := []float64{} + val := Prod(s) + if val != 1 { + t.Errorf("Val not returned as default when slice length is zero") + } + s = []float64{3, 4, 1, 7, 5} + val = Prod(s) + if val != 420 { + t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val) + } +} + +func TestReverse(t *testing.T) { + for _, s := range [][]float64{ + {0}, + {1, 0}, + {2, 1, 0}, + {3, 2, 1, 0}, + {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + } { + Reverse(s) + for i, v := range s { + if v != float64(i) { + t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i) + } + } + } +} + +func TestRound(t *testing.T) { + for _, test := range []struct { + x float64 + prec int + want float64 + }{ + {x: 0, prec: 1, want: 0}, + {x: math.Inf(1), prec: 1, want: math.Inf(1)}, + {x: math.NaN(), prec: 1, want: math.NaN()}, + {x: func() float64 { var f float64; return -f }(), prec: 1, want: 0}, + {x: math.MaxFloat64 / 2, prec: 1, want: math.MaxFloat64 / 2}, + {x: 1 << 64, prec: 1, want: 1 << 64}, + {x: 454.4445, prec: 3, want: 454.445}, + {x: 454.44445, prec: 4, want: 454.4445}, + {x: 0.42499, prec: 4, want: 0.425}, + {x: 0.42599, prec: 4, want: 0.426}, + {x: 0.424999999999993, prec: 2, want: 0.42}, + {x: 0.425, prec: 2, want: 0.43}, + {x: 0.425000000000001, prec: 2, want: 0.43}, + {x: 123.4244999999999, prec: 3, want: 123.424}, + {x: 123.4245, prec: 3, want: 123.425}, + {x: 123.4245000000001, prec: 3, want: 123.425}, + + {x: 454.45, prec: 0, want: 454}, + {x: 454.45, prec: 1, want: 454.5}, + {x: 454.45, prec: 2, want: 454.45}, + {x: 454.45, prec: 3, want: 454.45}, + {x: 454.445, prec: 0, want: 454}, + {x: 454.445, prec: 1, want: 454.4}, + {x: 454.445, prec: 2, want: 454.45}, + {x: 454.445, prec: 3, want: 454.445}, + {x: 454.445, prec: 4, want: 454.445}, + {x: 454.55, prec: 0, want: 455}, + {x: 454.55, prec: 1, want: 454.6}, + {x: 454.55, prec: 2, want: 454.55}, + {x: 454.55, prec: 3, want: 454.55}, + {x: 454.455, prec: 0, want: 454}, + {x: 454.455, prec: 1, want: 454.5}, + {x: 454.455, prec: 2, want: 454.46}, + {x: 454.455, prec: 3, want: 454.455}, + {x: 454.455, prec: 4, want: 454.455}, + + // Negative precision. + {x: 454.45, prec: -1, want: 450}, + {x: 454.45, prec: -2, want: 500}, + {x: 500, prec: -3, want: 1000}, + {x: 500, prec: -4, want: 0}, + {x: 1500, prec: -3, want: 2000}, + {x: 1500, prec: -4, want: 0}, + } { + for _, sign := range []float64{1, -1} { + got := Round(sign*test.x, test.prec) + want := sign * test.want + if want == 0 { + want = 0 + } + if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) { + t.Errorf("unexpected result for Round(%g, %d): got: %g, want: %g", sign*test.x, test.prec, got, want) + } + } + } +} + +func TestRoundEven(t *testing.T) { + for _, test := range []struct { + x float64 + prec int + want float64 + }{ + {x: 0, prec: 1, want: 0}, + {x: math.Inf(1), prec: 1, want: math.Inf(1)}, + {x: math.NaN(), prec: 1, want: math.NaN()}, + {x: func() float64 { var f float64; return -f }(), prec: 1, want: 0}, + {x: math.MaxFloat64 / 2, prec: 1, want: math.MaxFloat64 / 2}, + {x: 1 << 64, prec: 1, want: 1 << 64}, + {x: 454.4445, prec: 3, want: 454.444}, + {x: 454.44445, prec: 4, want: 454.4444}, + {x: 0.42499, prec: 4, want: 0.425}, + {x: 0.42599, prec: 4, want: 0.426}, + {x: 0.424999999999993, prec: 2, want: 0.42}, + {x: 0.425, prec: 2, want: 0.42}, + {x: 0.425000000000001, prec: 2, want: 0.43}, + {x: 123.4244999999999, prec: 3, want: 123.424}, + {x: 123.4245, prec: 3, want: 123.424}, + {x: 123.4245000000001, prec: 3, want: 123.425}, + + {x: 454.45, prec: 0, want: 454}, + {x: 454.45, prec: 1, want: 454.4}, + {x: 454.45, prec: 2, want: 454.45}, + {x: 454.45, prec: 3, want: 454.45}, + {x: 454.445, prec: 0, want: 454}, + {x: 454.445, prec: 1, want: 454.4}, + {x: 454.445, prec: 2, want: 454.44}, + {x: 454.445, prec: 3, want: 454.445}, + {x: 454.445, prec: 4, want: 454.445}, + {x: 454.55, prec: 0, want: 455}, + {x: 454.55, prec: 1, want: 454.6}, + {x: 454.55, prec: 2, want: 454.55}, + {x: 454.55, prec: 3, want: 454.55}, + {x: 454.455, prec: 0, want: 454}, + {x: 454.455, prec: 1, want: 454.5}, + {x: 454.455, prec: 2, want: 454.46}, + {x: 454.455, prec: 3, want: 454.455}, + {x: 454.455, prec: 4, want: 454.455}, + + // Negative precision. + {x: 454.45, prec: -1, want: 450}, + {x: 454.45, prec: -2, want: 500}, + {x: 500, prec: -3, want: 0}, + {x: 500, prec: -4, want: 0}, + {x: 1500, prec: -3, want: 2000}, + {x: 1500, prec: -4, want: 0}, + } { + for _, sign := range []float64{1, -1} { + got := RoundEven(sign*test.x, test.prec) + want := sign * test.want + if want == 0 { + want = 0 + } + if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) { + t.Errorf("unexpected result for RoundEven(%g, %d): got: %g, want: %g", sign*test.x, test.prec, got, want) + } + } + } +} + +func TestSame(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + if !Same(s1, s2) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if Same(s1, s2) { + t.Errorf("Unequal slices returned as equal") + } + if Same(s1, []float64{}) { + t.Errorf("Unequal slice lengths returned as equal") + } + s1 = []float64{1, 2, math.NaN(), 4} + s2 = []float64{1, 2, math.NaN(), 4} + if !Same(s1, s2) { + t.Errorf("Slices with matching NaN values returned as unequal") + } + s1 = []float64{1, 2, math.NaN(), 4} + s2 = []float64{1, math.NaN(), 3, 4} + if !Same(s1, s2) { + t.Errorf("Slices with unmatching NaN values returned as equal") + } +} + +func TestScale(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + c := 5.0 + truth := []float64{15, 20, 5, 35, 25} + Scale(c, s) + AreSlicesEqual(t, truth, s, "Bad scaling") +} + +func TestSpan(t *testing.T) { + receiver1 := make([]float64, 5) + truth := []float64{1, 2, 3, 4, 5} + receiver2 := Span(receiver1, 1, 5) + AreSlicesEqual(t, truth, receiver1, "Improper linspace from mutator") + AreSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice") + receiver1 = make([]float64, 6) + truth = []float64{0, 0.2, 0.4, 0.6, 0.8, 1.0} + Span(receiver1, 0, 1) + AreSlicesEqual(t, truth, receiver1, "Improper linspace") + if !Panics(func() { Span(nil, 1, 5) }) { + t.Errorf("Span accepts nil argument") + } + if !Panics(func() { Span(make([]float64, 1), 1, 5) }) { + t.Errorf("Span accepts argument of len = 1") + } +} + +func TestSub(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + v := []float64{1, 2, 3, 4, 5} + truth := []float64{2, 2, -2, 3, 0} + Sub(s, v) + AreSlicesEqual(t, truth, s, "Bad subtract") + // Test that it panics + if !Panics(func() { Sub(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestSubTo(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + v := []float64{1, 2, 3, 4, 5} + truth := []float64{2, 2, -2, 3, 0} + dst1 := make([]float64, len(s)) + dst2 := SubTo(dst1, s, v) + AreSlicesEqual(t, truth, dst1, "Bad subtract from mutator") + AreSlicesEqual(t, truth, dst2, "Bad subtract from returned slice") + // Test that all mismatch combinations panic + if !Panics(func() { SubTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Did not panic with dst different length") + } + if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with subtractor different length") + } + if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Did not panic with subtractee different length") + } +} + +func TestSum(t *testing.T) { + s := []float64{} + val := Sum(s) + if val != 0 { + t.Errorf("Val not returned as default when slice length is zero") + } + s = []float64{3, 4, 1, 7, 5} + val = Sum(s) + if val != 20 { + t.Errorf("Wrong sum returned") + } +} + +func TestWithin(t *testing.T) { + for i, test := range []struct { + s []float64 + v float64 + idx int + panics bool + }{ + { + s: []float64{1, 2, 5, 9}, + v: 1, + idx: 0, + }, + { + s: []float64{1, 2, 5, 9}, + v: 9, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 1.5, + idx: 0, + }, + { + s: []float64{1, 2, 5, 9}, + v: 2, + idx: 1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 2.5, + idx: 1, + }, + { + s: []float64{1, 2, 5, 9}, + v: -3, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 15, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: math.NaN(), + idx: -1, + }, + { + s: []float64{5, 2, 6}, + panics: true, + }, + { + panics: true, + }, + { + s: []float64{1}, + panics: true, + }, + } { + var idx int + panics := Panics(func() { idx = Within(test.s, test.v) }) + if panics { + if !test.panics { + t.Errorf("Case %v: bad panic", i) + } + continue + } + if test.panics { + if !panics { + t.Errorf("Case %v: did not panic when it should", i) + } + continue + } + if idx != test.idx { + t.Errorf("Case %v: Idx mismatch. Want: %v, got: %v", i, test.idx, idx) + } + } + +} + +func randomSlice(l int) []float64 { + s := make([]float64, l) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkMin(b *testing.B, size int) { + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Min(s) + } +} +func BenchmarkMinSmall(b *testing.B) { benchmarkMin(b, Small) } +func BenchmarkMinMed(b *testing.B) { benchmarkMin(b, Medium) } +func BenchmarkMinLarge(b *testing.B) { benchmarkMin(b, Large) } +func BenchmarkMinHuge(b *testing.B) { benchmarkMin(b, Huge) } + +func benchmarkAdd(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Add(s1, s2) + } +} +func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) } +func BenchmarkAddMed(b *testing.B) { benchmarkAdd(b, Medium) } +func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) } +func BenchmarkAddHuge(b *testing.B) { benchmarkAdd(b, Huge) } + +func benchmarkAddTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + AddTo(dst, s1, s2) + } +} +func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) } +func BenchmarkAddToMed(b *testing.B) { benchmarkAddTo(b, Medium) } +func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) } +func BenchmarkAddToHuge(b *testing.B) { benchmarkAddTo(b, Huge) } + +func benchmarkCumProd(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CumProd(dst, s) + } +} +func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) } +func BenchmarkCumProdMed(b *testing.B) { benchmarkCumProd(b, Medium) } +func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) } +func BenchmarkCumProdHuge(b *testing.B) { benchmarkCumProd(b, Huge) } + +func benchmarkCumSum(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CumSum(dst, s) + } +} +func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) } +func BenchmarkCumSumMed(b *testing.B) { benchmarkCumSum(b, Medium) } +func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) } +func BenchmarkCumSumHuge(b *testing.B) { benchmarkCumSum(b, Huge) } + +func benchmarkDiv(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Div(dst, s) + } +} +func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) } +func BenchmarkDivMed(b *testing.B) { benchmarkDiv(b, Medium) } +func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) } +func BenchmarkDivHuge(b *testing.B) { benchmarkDiv(b, Huge) } + +func benchmarkDivTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + DivTo(dst, s1, s2) + } +} +func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) } +func BenchmarkDivToMed(b *testing.B) { benchmarkDivTo(b, Medium) } +func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) } +func BenchmarkDivToHuge(b *testing.B) { benchmarkDivTo(b, Huge) } + +func benchmarkSub(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sub(s1, s2) + } +} +func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) } +func BenchmarkSubMed(b *testing.B) { benchmarkSub(b, Medium) } +func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) } +func BenchmarkSubHuge(b *testing.B) { benchmarkSub(b, Huge) } + +func benchmarkSubTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + SubTo(dst, s1, s2) + } +} +func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) } +func BenchmarkSubToMed(b *testing.B) { benchmarkSubTo(b, Medium) } +func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) } +func BenchmarkSubToHuge(b *testing.B) { benchmarkSubTo(b, Huge) } + +func benchmarkLogSumExp(b *testing.B, size int) { + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + LogSumExp(s) + } +} +func BenchmarkLogSumExpSmall(b *testing.B) { benchmarkLogSumExp(b, Small) } +func BenchmarkLogSumExpMed(b *testing.B) { benchmarkLogSumExp(b, Medium) } +func BenchmarkLogSumExpLarge(b *testing.B) { benchmarkLogSumExp(b, Large) } +func BenchmarkLogSumExpHuge(b *testing.B) { benchmarkLogSumExp(b, Huge) } + +func benchmarkDot(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Dot(s1, s2) + } +} +func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) } +func BenchmarkDotMed(b *testing.B) { benchmarkDot(b, Medium) } +func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) } +func BenchmarkDotHuge(b *testing.B) { benchmarkDot(b, Huge) } + +func benchmarkAddScaledTo(b *testing.B, size int) { + dst := randomSlice(size) + y := randomSlice(size) + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + AddScaledTo(dst, y, 2.3, s) + } +} +func BenchmarkAddScaledToSmall(b *testing.B) { benchmarkAddScaledTo(b, Small) } +func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) } +func BenchmarkAddScaledToLarge(b *testing.B) { benchmarkAddScaledTo(b, Large) } +func BenchmarkAddScaledToHuge(b *testing.B) { benchmarkAddScaledTo(b, Huge) } + +func benchmarkScale(b *testing.B, size int) { + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + Scale(2.0, dst) + Scale(0.5, dst) + } +} +func BenchmarkScaleSmall(b *testing.B) { benchmarkScale(b, Small) } +func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) } +func BenchmarkScaleLarge(b *testing.B) { benchmarkScale(b, Large) } +func BenchmarkScaleHuge(b *testing.B) { benchmarkScale(b, Huge) } diff --git a/vendor/gonum.org/v1/gonum/floats/parse_example_test.go b/vendor/gonum.org/v1/gonum/floats/parse_example_test.go new file mode 100644 index 00000000..cb8c4e51 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/floats/parse_example_test.go @@ -0,0 +1,43 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats_test + +import ( + "bufio" + "fmt" + "log" + "strings" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat" +) + +func ExampleParseWithNA() { + // Calculate the mean of a list of numbers + // ignoring missing values. + const data = `6 +missing +4 +` + + var vals, weights []float64 + sc := bufio.NewScanner(strings.NewReader(data)) + for sc.Scan() { + v, w, err := floats.ParseWithNA(sc.Text(), "missing") + if err != nil { + log.Fatal(err) + } + vals = append(vals, v) + weights = append(weights, w) + } + err := sc.Err() + if err != nil { + log.Fatal(err) + } + fmt.Println(stat.Mean(vals, weights)) + + // Output: + // 5 +} diff --git a/vendor/gonum.org/v1/gonum/graph/.gitignore b/vendor/gonum.org/v1/gonum/graph/.gitignore new file mode 100644 index 00000000..86e0d240 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/.gitignore @@ -0,0 +1 @@ +test.out \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/graph/README.md b/vendor/gonum.org/v1/gonum/graph/README.md new file mode 100644 index 00000000..f0a9505e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/README.md @@ -0,0 +1,3 @@ +# Gonum graph [![GoDoc](https://godoc.org/gonum.org/v1/gonum/graph?status.svg)](https://godoc.org/gonum.org/v1/gonum/graph) + +This is a generalized graph package for the Go language. diff --git a/vendor/gonum.org/v1/gonum/graph/community/bisect.go b/vendor/gonum.org/v1/gonum/graph/community/bisect.go new file mode 100644 index 00000000..ddfdb0a9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/bisect.go @@ -0,0 +1,248 @@ +// Copyright ©2016 The gonum 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 community + +import ( + "errors" + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" +) + +// Interval is an interval of resolutions with a common score. +type Interval struct { + // Low and High delimit the interval + // such that the interval is [low, high). + Low, High float64 + + // Score is the score of the interval. + Score float64 + + // Reduced is the best scoring + // community membership found for the + // interval. + Reduced +} + +// Reduced is a graph reduction. +type Reduced interface { + // Communities returns the community + // structure of the reduction. + Communities() [][]graph.Node +} + +// Size is a score function that is the reciprocal of the number of communities. +func Size(g ReducedGraph) float64 { return 1 / float64(len(g.Structure())) } + +// Weight is a score function that is the sum of community weights. The concrete +// type of g must be a pointer to a ReducedUndirected or a ReducedDirected, otherwise +// Weight will panic. +func Weight(g ReducedGraph) float64 { + var w float64 + switch g := g.(type) { + case *ReducedUndirected: + for _, n := range g.nodes { + w += n.weight + } + case *ReducedDirected: + for _, n := range g.nodes { + w += n.weight + } + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } + return w +} + +// ModularScore returns a modularized scoring function for Profile based on the +// graph g and the given score function. The effort parameter determines how +// many attempts will be made to get an improved score for any given resolution. +func ModularScore(g graph.Graph, score func(ReducedGraph) float64, effort int, src *rand.Rand) func(float64) (float64, Reduced) { + return func(resolution float64) (float64, Reduced) { + max := math.Inf(-1) + var best Reduced + for i := 0; i < effort; i++ { + r := Modularize(g, resolution, src) + s := score(r) + if s > max { + max = s + best = r + } + } + return max, best + } +} + +// SizeMultiplex is a score function that is the reciprocal of the number of communities. +func SizeMultiplex(g ReducedMultiplex) float64 { return 1 / float64(len(g.Structure())) } + +// WeightMultiplex is a score function that is the sum of community weights. The concrete +// type of g must be pointer to a ReducedUndirectedMultiplex or a ReducedDirectedMultiplex, +// otherwise WeightMultiplex will panic. +func WeightMultiplex(g ReducedMultiplex) float64 { + var w float64 + switch g := g.(type) { + case *ReducedUndirectedMultiplex: + for _, n := range g.nodes { + for _, lw := range n.weights { + w += lw + } + } + case *ReducedDirectedMultiplex: + for _, n := range g.nodes { + for _, lw := range n.weights { + w += lw + } + } + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } + return w +} + +// ModularMultiplexScore returns a modularized scoring function for Profile based +// on the graph g and the given score function. The effort parameter determines how +// many attempts will be made to get an improved score for any given resolution. +func ModularMultiplexScore(g Multiplex, weights []float64, all bool, score func(ReducedMultiplex) float64, effort int, src *rand.Rand) func(float64) (float64, Reduced) { + return func(resolution float64) (float64, Reduced) { + max := math.Inf(-1) + var best Reduced + for i := 0; i < effort; i++ { + r := ModularizeMultiplex(g, weights, []float64{resolution}, all, src) + s := score(r) + if s > max { + max = s + best = r + } + } + return max, best + } +} + +// Profile returns an approximate profile of score values in the resolution domain [low,high) +// at the given granularity. The score is calculated by bisecting calls to fn. If log is true, +// log space bisection is used, otherwise bisection is linear. The function fn should be +// monotonically decreasing in at least 1/grain evaluations. Profile will attempt to detect +// non-monotonicity during the bisection. +// +// Since exact modularity optimization is known to be NP-hard and Profile calls modularization +// routines repeatedly, it is unlikely to return the exact resolution profile. +func Profile(fn func(float64) (float64, Reduced), log bool, grain, low, high float64) (profile []Interval, err error) { + if low >= high { + return nil, errors.New("community: zero or negative width domain") + } + + defer func() { + r := recover() + e, ok := r.(nonDecreasing) + if ok { + err = e + return + } + if r != nil { + panic(r) + } + }() + left, comm := fn(low) + right, _ := fn(high) + for i := 1; i < int(1/grain); i++ { + rt, _ := fn(high) + right = math.Max(right, rt) + } + profile = bisect(fn, log, grain, low, left, high, right, comm) + + // We may have missed some non-monotonicity, + // so merge low score discordant domains into + // their lower resolution neighbours. + return fixUp(profile), nil +} + +type nonDecreasing int + +func (n nonDecreasing) Error() string { + return fmt.Sprintf("community: profile does not reliably monotonically decrease: tried %d times", n) +} + +func bisect(fn func(float64) (float64, Reduced), log bool, grain, low, scoreLow, high, scoreHigh float64, comm Reduced) []Interval { + if low >= high { + panic("community: zero or negative width domain") + } + if math.IsNaN(scoreLow) || math.IsNaN(scoreHigh) { + return nil + } + + // Heuristically determine a reasonable number + // of times to try to get a higher value. + maxIter := int(1 / grain) + + lowComm := comm + for n := 0; scoreLow < scoreHigh; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + scoreLow, lowComm = fn(low) + } + + if scoreLow == scoreHigh || tooSmall(low, high, grain, log) { + return []Interval{{Low: low, High: high, Score: scoreLow, Reduced: lowComm}} + } + + var mid float64 + if log { + mid = math.Sqrt(low * high) + } else { + mid = (low + high) / 2 + } + + scoreMid := math.Inf(-1) + var midComm Reduced + for n := 0; scoreMid < scoreHigh; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + scoreMid, midComm = fn(mid) + } + + lower := bisect(fn, log, grain, low, scoreLow, mid, scoreMid, lowComm) + higher := bisect(fn, log, grain, mid, scoreMid, high, scoreHigh, midComm) + for n := 0; lower[len(lower)-1].Score < higher[0].Score; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + lower[len(lower)-1].Score, lower[len(lower)-1].Reduced = fn(low) + } + + if lower[len(lower)-1].Score == higher[0].Score { + higher[0].Low = lower[len(lower)-1].Low + lower = lower[:len(lower)-1] + if len(lower) == 0 { + return higher + } + } + return append(lower, higher...) +} + +// fixUp non-monotonically decreasing interval scores. +func fixUp(profile []Interval) []Interval { + max := profile[len(profile)-1].Score + for i := len(profile) - 2; i >= 0; i-- { + if profile[i].Score > max { + max = profile[i].Score + continue + } + profile[i+1].Low = profile[i].Low + profile = append(profile[:i], profile[i+1:]...) + } + return profile +} + +func tooSmall(low, high, grain float64, log bool) bool { + if log { + return math.Log(high/low) < grain + } + return high-low < grain +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/bisect_test.go b/vendor/gonum.org/v1/gonum/graph/community/bisect_test.go new file mode 100644 index 00000000..5a225d7e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/bisect_test.go @@ -0,0 +1,311 @@ +// Copyright ©2016 The gonum 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 community + +import ( + "fmt" + "log" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +func ExampleProfile_simple() { + // Create dumbell graph: + // + // 0 4 + // |\ /| + // | 2 - 3 | + // |/ \| + // 1 5 + // + g := simple.NewUndirectedGraph() + for u, e := range smallDumbell { + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + // Get the profile of internal node weight for resolutions + // between 0.1 and 10 using logarithmic bisection. + p, err := Profile(ModularScore(g, Weight, 10, nil), true, 1e-3, 0.1, 10) + if err != nil { + log.Fatal(err) + } + + // Print out each step with communities ordered. + for _, d := range p { + comm := d.Communities() + for _, c := range comm { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(comm)) + fmt.Printf("Low:%.2v High:%.2v Score:%v Communities:%v Q=%.3v\n", + d.Low, d.High, d.Score, comm, Q(g, comm, d.Low)) + } + + // Output: + // Low:0.1 High:0.29 Score:14 Communities:[[0 1 2 3 4 5]] Q=0.9 + // Low:0.29 High:2.3 Score:12 Communities:[[0 1 2] [3 4 5]] Q=0.714 + // Low:2.3 High:3.5 Score:4 Communities:[[0 1] [2] [3] [4 5]] Q=-0.31 + // Low:3.5 High:10 Score:0 Communities:[[0] [1] [2] [3] [4] [5]] Q=-0.607 +} + +var friends, enemies *simple.WeightedUndirectedGraph + +func init() { + friends = simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range middleEast.friends { + // Ensure unconnected nodes are included. + if !friends.Has(simple.Node(u)) { + friends.AddNode(simple.Node(u)) + } + for v := range e { + friends.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + enemies = simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range middleEast.enemies { + // Ensure unconnected nodes are included. + if !enemies.Has(simple.Node(u)) { + enemies.AddNode(simple.Node(u)) + } + for v := range e { + enemies.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: -1}) + } + } +} + +func ExampleProfile_multiplex() { + // The undirected graphs, friends and enemies, are the political relationships + // in the Middle East as described in the Slate article: + // http://www.slate.com/blogs/the_world_/2014/07/17/the_middle_east_friendship_chart.html + g, err := NewUndirectedLayers(friends, enemies) + if err != nil { + log.Fatal(err) + } + weights := []float64{1, -1} + + // Get the profile of internal node weight for resolutions + // between 0.1 and 10 using logarithmic bisection. + p, err := Profile(ModularMultiplexScore(g, weights, true, WeightMultiplex, 10, nil), true, 1e-3, 0.1, 10) + if err != nil { + log.Fatal(err) + } + + // Print out each step with communities ordered. + for _, d := range p { + comm := d.Communities() + for _, c := range comm { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(comm)) + fmt.Printf("Low:%.2v High:%.2v Score:%v Communities:%v Q=%.3v\n", + d.Low, d.High, d.Score, comm, QMultiplex(g, comm, weights, []float64{d.Low})) + } + + // Output: + // Low:0.1 High:0.72 Score:26 Communities:[[0] [1 7 9 12] [2 8 11] [3 4 5 10] [6]] Q=[24.7 1.97] + // Low:0.72 High:1.1 Score:24 Communities:[[0 6] [1 7 9 12] [2 8 11] [3 4 5 10]] Q=[16.9 14.1] + // Low:1.1 High:1.1 Score:18 Communities:[[0 2 6 11] [1 7 9 12] [3 4 5 8 10]] Q=[9.16 25.1] + // Low:1.1 High:1.6 Score:10 Communities:[[0 3 4 5 6 10] [1 7 9 12] [2 8 11]] Q=[11.5 23.9] + // Low:1.6 High:1.6 Score:8 Communities:[[0 1 6 7 9 12] [2 8 11] [3 4 5 10]] Q=[5.56 39.8] + // Low:1.6 High:1.8 Score:2 Communities:[[0 2 3 4 5 6 10] [1 7 8 9 11 12]] Q=[-1.82 48.6] + // Low:1.8 High:2.3 Score:-6 Communities:[[0 2 3 4 5 6 8 10 11] [1 7 9 12]] Q=[-5 57.5] + // Low:2.3 High:2.4 Score:-10 Communities:[[0 1 2 6 7 8 9 11 12] [3 4 5 10]] Q=[-11.2 79] + // Low:2.4 High:4.3 Score:-52 Communities:[[0 1 2 3 4 5 6 7 8 9 10 11 12]] Q=[-46.1 117] + // Low:4.3 High:10 Score:-54 Communities:[[0 1 2 3 4 6 7 8 9 10 11 12] [5]] Q=[-82 254] +} + +func TestProfileUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testProfileUndirected(t, test, g) + } +} + +func TestProfileWeightedUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testProfileUndirected(t, test, g) + } +} + +func testProfileUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) { + fn := ModularScore(g, Weight, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d) + } + } +} + +func TestProfileDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testProfileDirected(t, test, g) + } +} + +func TestProfileWeightedDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testProfileDirected(t, test, g) + } +} + +func testProfileDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) { + fn := ModularScore(g, Weight, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d) + } + } +} + +func TestProfileUndirectedMultiplex(t *testing.T) { + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + const all = true + + fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d) + } + } + } +} + +func TestProfileDirectedMultiplex(t *testing.T) { + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + const all = true + + fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/doc.go b/vendor/gonum.org/v1/gonum/graph/community/doc.go new file mode 100644 index 00000000..2509606b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 community provides graph community detection functions. +package community // import "gonum.org/v1/gonum/graph/community" diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain.tex b/vendor/gonum.org/v1/gonum/graph/community/louvain.tex new file mode 100644 index 00000000..046c02ba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain.tex @@ -0,0 +1,466 @@ +% Copyright ©2015 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +\documentclass{article} + +\usepackage{amsmath,amsfonts} +\usepackage[margin=4cm]{geometry} + +\title{Louvain algorithm for undirected and directed graphs} +\author{The {\tt gonum} Authors} + +\begin{document} + +\maketitle + +The algorithm attempts to find communities (highly connected sub-graphs), +and it does this by minimising the modularity function +\begin{equation} + Q(c) = \frac{1}{2m}\sum_i\sum_j\left[ A_{ij} - \gamma \frac{k_ik_j}{2m} \right] \delta_{ij}(c), +\end{equation} +where $c$ is a partition of nodes into subsets or communities, +$A_{ij}$ is the edge weight between nodes $i$ and $j$, +$\gamma$ is a tuning parameter, +\begin{equation} +m = \frac{1}{2}\sum_i\sum_jA_{ij}, +\end{equation} +\begin{equation} +k_i = \sum_j{A_{ij}}, +\end{equation} +and +\begin{equation} + \delta_{ij}(c) = \left \{ \begin{array}{ll} + 1 & \text{if} \quad c(i) = c(j) \\ + 0 & \text{otherwise} \end{array} \right .. +\end{equation} +Here $c(i)$ denotes the community to which node $i$ belongs +in the partitioning $c$. + +The algorithm finds a hierarchical community structure by iterating +between two phases: +\begin{enumerate} + \item Find a set of communities that minimise $Q$. + \item Construct a new graph, whose nodes are the communities + found in the preceding phase one step. +\end{enumerate} +Each iteration of these two phases is called a `pass'. +In this way, the algorithm obtains a nested community structure, +where at each level $Q$ is minimised for the relevant graph. +We consider this process in more detail, in particular looking +at phase one first in the first pass, when each node is a single +node, and then how this generalises to later passes when each node +is a community. + +\section{Undirected Graphs} + +\subsection{Initial Pass} +\label{sec:initialPass} + +The initial pass is simple as the initial pass uses the original graph, +and in all following passes graphs constructed in the previous pass's +phase two are used. +Here we will consider this initial simple formulation for phase one, and +in Section~\ref{sec:laterPasses} we consider how this generalises for +passes two and onwards. +Phase one works by initially allocating each node to a separate community, +and then iterating through each node $a$ and checking if moving it into +a different community $\beta$ will reduce $Q$. +If there are possible moves that will reduce $Q$, $a$ is moved into the +the community which will generate the largest reduction in $Q$. +This process is continued until there are no moves left to reduce $Q$ +further, meaning a local minimum for $Q$ has been achieved. +Then the algorithm moves to phase two (constructing a new graph where +each node in the new graph is a community in the old graph). + +Note that we assume the original graph to be simple and undirected. +First, we introduce some notation that will be useful: +Let $c(i)$ denote the community to which node $i$ belongs, +and let $\alpha$ be the community that the node $a$ mentioned above +belongs to, i.e., $\alpha = c_a$. +Then we define +\newcommand{\Stot}[1]{\Sigma_{\text{tot}}^{#1}} +\begin{equation} + \Stot{\alpha} = \sum_{i \in \alpha}\sum_{j}A_{ij} = \sum_{i \in \alpha}k_i, +\end{equation} +\newcommand{\kin}[2]{k_{#1}^{#2}} +\begin{equation} + \kin{i}{\alpha} = \sum_{j \in \alpha}A_{ij}, +\end{equation} +and +\newcommand{\Sin}[1]{\Sigma_{\text{in}}^{#1}} +\begin{equation} + \Sin{\alpha} = \sum_{i \in \alpha}\sum_{j \in \alpha}A_{ij} = \sum_{i \in \alpha}\kin{i}{\alpha}. +\end{equation} + +We are interested in how $Q$ will change if we move a node $a$ from its +current community $\alpha$, to a new community $\beta$. +This will have two effects, it will remove the terms from $Q$ +related to $a$ in $\alpha$, which we will call $Q^-$ and it will add terms +related to $a$ in $\beta$, which we will call $Q^+$. +The total change in $Q$ caused by the movement of $a$ from $\alpha$ to $\beta$ is +\begin{equation} + \Delta Q = Q^{+} - Q^{-}, +\end{equation} +where +\begin{align*} +Q^- &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\sum_{i \in \alpha, \, i \neq a} \left( A_{ia} - \gamma \frac{k_ik_a}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\sum_{i \in \alpha, \, i \neq a} k_i \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\left( \Stot{\alpha} - k_a \right) \right], \\ +\end{align*} +and +\begin{align*} +Q^+ &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\sum_{i \in \beta} \left( A_{ia} - \gamma \frac{k_ik_a}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\kin{a}{\beta} - \gamma \frac{2k_a}{2m}\sum_{i \in \beta} k_i \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\kin{a}{\beta} - \gamma \frac{2k_a\Stot{\beta}}{2m} \right]. \\ +\end{align*} +The first term in both these expressions ($Q^-$ and $Q^+$) is the same, and so cancels: +\begin{equation} +\Delta Q = \frac{1}{2m}\left[ \left( 2\kin{a}{\beta} - \gamma \frac{2k_a\Stot{\beta}}{2m} \right) + - \left( 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\left( \Stot{\alpha} - k_a \right) \right) \right]. +\end{equation} + +\subsection{Later Passes} +\label{sec:laterPasses} + +In phase two a `meta-graph' is constructed where nodes correspond to +the communities found in the preceding phase one step, and edge weight +between two such communities (nodes, in the meta-graph) +$\alpha$ and $\beta$ are defined to be +\begin{equation} + A_{\alpha \beta}^* = \sum_{i \in \alpha}\sum_{j \in \beta}A_{ij}. + \label{eqn:Aij*} +\end{equation} +Note that $i$ and $j$ refer to nodes in the original graph, not nodes +in the previous graph, and so holds any meta-graph, not just the first. +Also note that this definition of $A^*_{\alpha \beta}$ allows for +$A^*_{\alpha \alpha}$ to be non-zero as +\begin{equation} +A_{\alpha \alpha}^* = \sum_{i \in \alpha}\sum_{j \in \alpha}A_{ij} = \Sin{\alpha}. +\end{equation} + +In this newly constructed graph, $\alpha$ and $\beta$ are nodes, but +also refer to communities (sets of nodes) in the original graph, and I +use these two interpretations interchangeably. +This should be the only ambiguous bit of notation in this document, I hope. + +The results of Section~\ref{sec:initialPass} generalise to these meta-graphs, +and the generalised results mirror those of Section~\ref{sec:initialPass} closely +-- I distinguish the new results from those of Section~\ref{sec:initialPass} by a +superscript $*$. +I use $i$ and $j$ to denote nodes of the original graph as in Section~\ref{sec:initialPass}, +and use $z$ and $w$ to denote nodes of the meta-graph (communities of the original). +I use analogous notation to Section~\ref{sec:initialPass}, $c^*(z)$, to +denote the community to which node $z$ of the meta-graph belongs, +and let $\mathfrak{a}$ be the community that the node $\alpha$ belongs to +($c^*(\alpha) = \mathfrak{a}$), i.e. +\begin{equation} + \mathfrak{a} = \{z | c^*(z) = c^*(\alpha) \}. +\end{equation} + +Given this notation, we can observe that +\begin{equation} +m^* = \frac{1}{2}\sum_{z}\sum_{w}{A_{zw}^*} = \frac{1}{2}\sum_{z}\sum_{w}{\sum_{i \in z}\sum_{j \in w}A_{ij}} = \frac{1}{2}\sum_i\sum_jA_{ij} = m, +\end{equation} +\begin{equation} +k_{z}^* = \sum_{w}{A_{zw}^*} = \sum_{w}{\sum_{i \in z}\sum_{j \in w}A_{ij}} = \sum_{i \in z}\sum_{j}A_{ij} = \Stot{z}, +\end{equation} +\begin{equation} + \Stot{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w}A_{zw}^* = \sum_{z \in \mathfrak{a}}k_z^* = \sum_{z \in \mathfrak{a}}\Stot{z}, +\end{equation} +\begin{equation} + \kin{z}{\mathfrak{a} *} = \sum_{w \in \mathfrak{a}}{A_{zw}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}, +\end{equation} +and +\begin{equation} +\Sin{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}A_{zw}^* = \sum_{z \in \mathfrak{a}}\kin{z}{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}. + %\label{eqn:Sin} +\end{equation} + +If we let $\mathfrak{b}$ denote the community to which we are considering moving $\alpha$, +then the expression for $\Delta Q$ from Section~\ref{sec:initialPass} trivially generalises to +\begin{equation} +\Delta Q = \frac{1}{2m}\left[ \left( 2 \kin{\alpha}{\mathfrak{b} *} - \gamma \frac{2k_{\alpha}^*\Stot{\mathfrak{b} *}}{2m} \right) + - \left( 2\left( \kin{\alpha}{\mathfrak{a} *} - A_{\alpha \alpha}^* \right) - \gamma \frac{2k_{\alpha}^*}{2m} \left( \Stot{\mathfrak{a} *} - k_{\alpha}^* \right ) \right) \right] \\ +\end{equation} + +\section{Directed Graphs} +\label{sec:directedGraphs} + +It is of interest to consider how this generalises to directed graphs. +If we are to treat incoming and outgoing nodes equally, there are several +thoughts on how to extend the algorithm to directed graphs, of which we +will explore three: +\begin{itemize} + \item Construct an undirected graph first, and then use the undirected case. + \item Generalise the expressions from the undirected case to the directed case, + we will consider two different suggestions for such generalisations. +\end{itemize} +We will show that one of the two `generalisation of expressions' approaches is +equivalent to constructing an undirected graph, and the other is not. + +\subsection{Construction of an undirected graph} +A simple approach to generalising to directed graphs is to construct +an undirected graph with edge weights +\begin{equation} +A_{ij} = B_{ij} + B_{ji}, +\label{eqn:undirectedAB} +\end{equation} +and simply use the undirected algorithm. +Another suggestion is to average the directed edges to make +an undirected graph, i.e. to use a directed graph with edge weights +\begin{equation} +A_{ij} = \frac{B_{ij} + B_{ji}}{2}. +\end{equation} +This raises an important question: does scaling all edge weights across +the entire graph by a constant affect the results of the algorithm? +Hopefully not, but worth checking. +We can follow this through the results for the undirected graph by +substituting $A_{ij}^{(1)} = pA_{ij}$, $p \in \mathbb{R}$, and +distinguishing the new expressions by a superscript ${(1)}$. These +new expressions are: +\begin{equation} +m^{(1)} = \frac{1}{2}\sum_i\sum_jpA_{ij} = p\frac{1}{2}\sum_i\sum_j A_{ij} = pm , +\end{equation} +\begin{equation} +k_i^{(1)} = \sum_j{pA_{ij}} = p\sum_j{A_{ij}} = pk_i, +\end{equation} +and so +\begin{align*} + Q^{(1)}(c) &= \frac{1}{2pm}\sum_i\sum_j\left[ pA_{ij} - \gamma \frac{pk_ipk_j}{2pm} \right] \delta_{ij}(c) \\ + &= \frac{1}{2m}\sum_i\sum_j\left[ A_{ij} - \gamma \frac{k_ik_j}{2m} \right] \delta_{ij}(c) \\ + &= Q(c) +\end{align*} +Note that as we have shown $Q^{(1)} = Q$ there is no need to go into the remainder of the terms +involved in the algorithm, as they all derive from $Q$. + +\subsection{First generalisation of expressions approach} + +One suggested extension to directed graphs is to modify the expressions +involved by adding the `from' case and the `to' case for each term. +If we let $B_{ij}$ be the edge weight between nodes $i$ and $j$ in +the directed graph, and distinguishing these extended expressions by +a superscript $(2)$, the extended expressions become: +\begin{equation} +m^{(2)} = \frac{1}{2}\left ( \sum_i\sum_jB_{ij} + \sum_i\sum_jB_{ji}\right) = \frac{1}{2}\sum_i\sum_j \left( B_{ij} + B_{ji} \right) , +\end{equation} +\begin{equation} +k_i^{(2)} = \sum_jB_{ij} + \sum_jB_{ji} = \sum_j{\left( B_{ij} + B_{ji} \right)}, +\end{equation} +and similarly +\begin{equation} + Q^{(2)}(c) = \frac{1}{2m}\sum_i\sum_j\left[ \left( B_{ij} + B_{ji} \right) - \gamma \frac{k_i^{(2)}k_j^{(2)}}{2m} \right] \delta_{ij}(c). +\end{equation} + +Note how this is equivalent to the construction of an undirected graph as +per Equation~(\ref{eqn:undirectedAB}). Similarly to above, +there is no need to go into the remainder of the terms +involved in the algorithm, as they all derive from $Q$. + + +\subsection{Second generalisation of expressions approach} + +Another approach to generalising the expressions to the +directed case, that still treats incoming and outgoing edges +as equally important, is to propose an alternative modularity +expression: +\newcommand{\dkin}[1]{k_{#1}^{\text{in}}} +\newcommand{\dkout}[1]{k_{#1}^{\text{out}}} +\begin{equation} +Q^{(3)}(c) = \frac{1}{2m}\sum_i\sum_j\left[ 2B_{ij} - 2\gamma \frac{\dkin{i}\dkout{j}}{2m} \right] \delta_{ij}(c), \\ +\end{equation} +where +\begin{equation} +\dkout{i} = \sum_j{B_{ij}} +\quad \quad \text{and} \quad \quad +\dkin{i} = \sum_j{B_{ji}}, +\end{equation} +so $k_i^{(2)} = \dkin{i} + \dkout{i}$. +Note I leave the factor of two in the expression for $Q^{(3)}$ so that it +remains as comparable to that for $Q^{(2)}$ as possible. +There is no need for alternative $m$, as it will still be the same as above. +$Q^{(3)}$ will differ from $Q^{(2)}$ in two ways. +Firstly, as $k_i^{(2)} = \dkin{i} + \dkout{i}$, +\begin{align*} +\sum_i\sum_j k_i^{(2)} k_j^{(2)} \delta_{ij}(c) &= \sum_i\sum_j (\dkin{i} + \dkout{i}) (\dkin{j} + \dkout{j}) \delta_{ij}(c) \\ + &= \sum_i\sum_j \left[ (\dkin{i}\dkin{j} + \dkout{i}\dkout{j}) + (\dkin{i}\dkout{j} + \dkin{j}\dkout{i}) \right] \delta_{ij}(c). \\ + &= \sum_i\sum_j \left[ (\dkin{i}\dkin{j} + \dkout{i}\dkout{j}) + 2\dkin{i}\dkout{j} \right] \delta_{ij}(c), \\ +\end{align*} +and similarly, +\begin{equation} +\sum_i\sum_j \left( B_{ij} + B_{ji} \right) \delta_{ij}(c) = 2\sum_i\sum_j B_{ij} \delta_{ij}(c). +\end{equation} +From these two expressions, we can see that +\begin{equation} +Q^{(3)} - Q^{(2)} = \frac{1}{2m}\sum_i\sum_j \gamma \frac{\dkin{i}\dkin{j} + \dkout{i}\dkout{j}}{2m} \delta_{ij}(c). +\end{equation} + + +\section{Directed Graphs in more detail} +\label{sec:directedGraphsDetail} + +In Section \ref{sec:directedGraphs} we essentially showed three +things: +\begin{itemize} + \item How an undirected graph could be constructed from a directed + graph, thereby allowing the undirected algorithm to be used for + directed graphs. + \item How scaling all edge weights by a non-zero constant would not + affect the modularity function. + \item An alternative approach to extending the algorithm to + directed graphs that is not equivalent to first reducing it + to an undirected graph. +\end{itemize} +It is this third point that we will explore here. +Analogously to Sections \ref{sec:initialPass} and \ref{sec:laterPasses} we will +break this up into the initial pass and the later passes. + +\subsection{Initial pass} +\label{sec:initialPassDirected} + +Continuing with the notation of Section \ref{sec:initialPass}, in which +$c(i)$ denotes the community to which node $i$ belongs, +and $\alpha = c(a)$, we define +\newcommand{\dinStot}[1]{\Sigma_{\text{tot}}^{\text{in}(#1)}} +\newcommand{\doutStot}[1]{\Sigma_{\text{tot}}^{\text{out}(#1)}} +\begin{equation} + \doutStot{\alpha} = \sum_{i \in \alpha}\sum_{j}B_{ij} = \sum_{i \in \alpha}\dkout{i} + \quad \quad \text{and} \quad \quad + \dinStot{\alpha} = \sum_{i \in \alpha}\sum_{j}B_{ji} = \sum_{i \in \alpha}\dkin{i}, +\end{equation} +\newcommand{\dinkin}[2]{k_{#1}^{\text{in}(#2)}} +\newcommand{\doutkin}[2]{k_{#1}^{\text{out}(#2)}} +\begin{equation} + \doutkin{i}{\alpha} = \sum_{j \in \alpha}B_{ij} + \quad \quad \text{and} \quad \quad + \dinkin{i}{\alpha} = \sum_{j \in \alpha}B_{ji}, +\end{equation} +and we will entertain one more ambiguous notation choice: +%\newcommand{\Sin}[1]{\Sigma_{\text{in}}^{#1}} +\begin{equation} + \Sin{\alpha} = \sum_{i \in \alpha}\sum_{j \in \alpha}B_{ij} = \sum_{i \in \alpha}\doutkin{i}{\alpha} = \sum_{i \in \alpha}\dinkin{i}{\alpha}. +\end{equation} + +Analogously to Section \ref{sec:initialPass}, we are interested in how +$Q^{(3)}$ will change if we move a node $a$ from its +current community $\alpha$, to a new community $\beta$, +and analogously this will have two effects -- it will remove the terms +from $Q^{(3)}$ related to $a$ in $\alpha$, which we will call $Q^{-(3)}$ +and it will add terms related to $a$ in $\beta$, which we will call $Q^{+(3)}$. +The total change in $Q^{(3)}$ caused by the movement of $a$ from $\alpha$ to $\beta$ is +\begin{equation} + \Delta Q^{(3)} = Q^{+(3)} - Q^{-(3)}, +\end{equation} +where +\begin{align*} +Q^{-(3)} &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ \sum_{i \in \alpha, \, i \neq a} \left( 2B_{ia} + 2B_{ai} - 2\gamma \frac{\dkin{i}\dkout{a}}{2m} - 2\gamma \frac{\dkin{a}\dkout{i}}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ 2(\dinkin{a}{\alpha} - B_{aa}) + 2(\doutkin{a}{\alpha} - B_{aa}) \hdots \right . \\ + & \quad \quad \quad \quad \quad \quad \left . +- \frac{2\gamma\dkout{a}}{2m} (\dinStot{\alpha} - \dkin{a}) - \frac{2\gamma\dkin{a}}{2m} (\doutStot{\alpha} - \dkout{a}) \right] \\ +\end{align*} +and +\begin{align*} +Q^{+(3)} &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ \sum_{i \in \beta} \left( 2B_{ia} + 2B_{ai} - 2\gamma \frac{\dkin{i}\dkout{a}}{2m} - 2\gamma \frac{\dkin{a}\dkout{i}}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ 2\dinkin{a}{\beta} + 2\doutkin{a}{\beta} - \frac{2\gamma\dkout{a}}{2m} \dinStot{\beta} - \frac{2\gamma\dkin{a}}{2m} \doutStot{\beta} \right] \\ +\end{align*} +Similarly to Section \ref{sec:initialPass}, the first term in both these expressions is the same, and so cancels, leaving: +\begin{align*} +\Delta Q^{(3)} &= \frac{2}{2m}\left[ +\left( \dinkin{a}{\beta} + \doutkin{a}{\beta} - \frac{\gamma\dkout{a}}{2m} \dinStot{\beta} - \frac{\gamma\dkin{a}}{2m} \doutStot{\beta} \right) \right. \\ +& \hspace{-1cm} +- \left. \left( (\dinkin{a}{\alpha} - B_{aa}) + (\doutkin{a}{\alpha} - B_{aa}) - \frac{\gamma\dkout{a}}{2m} (\dinStot{\alpha} - \dkin{a}) - \frac{\gamma\dkin{a}}{2m} (\doutStot{\alpha} - \dkout{a}) \right) \right] \\ + &= \frac{2}{2m}\left[ (\dinkin{a}{\beta}-\dinkin{a}{\alpha}) + (\doutkin{a}{\beta}-\doutkin{a}{\alpha}) + 2B_{aa} \right. \\ +& \hspace{-1cm} \left. +- \frac{\gamma\dkout{a}}{2m} (\dinStot{\beta}-\dinStot{\alpha}) - \frac{\gamma\dkin{a}}{2m} (\doutStot{\beta} - \doutStot{\alpha}) - \frac{2\gamma\dkin{a}\dkout{a}}{2m} \right] +\end{align*} + + + +\subsection{Later passes} +\label{sec:laterPassesDirected} + +In phase two a `meta-graph' is constructed where nodes correspond to +the communities found in the preceding phase one step, and edge weight +between two such communities (nodes, in the meta-graph) +$\alpha$ and $\beta$ are defined to be +\begin{equation} + B_{\alpha \beta}^* = \sum_{i \in \alpha}\sum_{j \in \beta}B_{ij}. + \label{eqn:Bij*} +\end{equation} +Note that $i$ and $j$ refer to nodes in the original graph, not nodes +in the previous graph, and so holds any meta-graph, not just the first. +Also note that this definition of $B^*_{\alpha \beta}$ allows for +$B^*_{\alpha \alpha}$ to be non-zero, in fact +\begin{equation} +B_{\alpha \alpha}^* = \sum_{i \in \alpha}\sum_{j \in \alpha}B_{ij} = \Sin{\alpha}. +\end{equation} + +In this newly constructed graph, $\alpha$ and $\beta$ are nodes, but +also refer to communities (sets of nodes) in the original graph, and I +use these two interpretations interchangeably, completely analogously to +Section \ref{sec:laterPasses}. + +The results of Section~\ref{sec:initialPassDirected} generalise to these meta-graphs, +and the generalised results mirror those of Section~\ref{sec:initialPassDirected} closely +-- I distinguish the new results from those of Section~\ref{sec:initialPassDirected} by a +superscript $*$. +I use $i$ and $j$ to denote nodes of the original graph as in Sections~\ref{sec:initialPass} +and \ref{sec:initialPassDirected}, +and use $z$ and $w$ to denote nodes of the meta-graph (communities of the original). +I use analogous notation to Section~\ref{sec:initialPass}, $c^*(z)$, to +denote the community to which node $z$ of the meta-graph belongs, +and let $\mathfrak{a}$ be the community that the node $\alpha$ belongs to, +i.e., $\mathfrak{a} = c^*(\alpha) $. + +Given this notation, we get all the same results as in \ref{sec:laterPasses}, but +each split into two cases `out' and `in', separating by direction, essentially, so +\newcommand{\dkinStar}[1]{k_{#1}^{\text{in} *}} +\newcommand{\dkoutStar}[1]{k_{#1}^{\text{out} *}} +\begin{equation} +\dkoutStar{z} = \sum_w{B_{zw}^*} = \sum_w\sum_{i \in z}\sum_{j \in w}B_{ij} = \sum_{i \in z}\sum_jB_{ij} = \doutStot{z}, +\end{equation} +\begin{equation} +\dkinStar{z} = \sum_w{B_{wz}^*} = \sum_w\sum_{i \in z}\sum_{j \in w}B_{ji} = \sum_{i \in z}\sum_jB_{ji} = \dinStot{z}, +\end{equation} +\newcommand{\dinStotStar}[1]{\Sigma_{\text{tot}}^{\text{in}(#1) *}} +\newcommand{\doutStotStar}[1]{\Sigma_{\text{tot}}^{\text{out}(#1) *}} +\begin{equation} + \doutStotStar{\mathfrak{a}} = \sum_{z \in \mathfrak{a}}\sum_{w}B_{zw}^* = \sum_{z \in \mathfrak{a}}\dkoutStar{z} = \sum_{z \in \mathfrak{a}}\doutStot{z}, +\end{equation} +\begin{equation} + \dinStotStar{\mathfrak{a}} = \sum_{z \in \mathfrak{a}}\sum_{w}B_{wz}^* = \sum_{z \in \mathfrak{a}}\dkinStar{z} = \sum_{z \in \mathfrak{a}}\dinStot{z}, +\end{equation} +\newcommand{\dinkinStar}[2]{k_{#1}^{\text{in}(#2) *}} +\newcommand{\doutkinStar}[2]{k_{#1}^{\text{out}(#2) *}} +\begin{equation} + \doutkinStar{z}{\mathfrak{a}} = \sum_{w \in \mathfrak{a}}{B_{zw}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}B_{ij}}, +\end{equation} +\begin{equation} + \dinkinStar{z}{\mathfrak{a}} = \sum_{w \in \mathfrak{a}}{B_{wz}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}B_{ji}}, +\end{equation} +and +\begin{equation} +\Sin{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}A_{zw}^* = \sum_{z \in \mathfrak{a}}\kin{z}{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}. + %\label{eqn:Sin} +\end{equation} + +If we let $\mathfrak{b}$ denote the community to which we are considering moving $\alpha$, +then the expression for $\Delta Q$ from Section~\ref{sec:initialPassDirected} simply generalises as +\begin{align*} +\Delta Q^{(3)} &= \frac{2}{2m}\left[ (\dinkinStar{\alpha}{\mathfrak{b}}-\dinkinStar{\alpha}{\mathfrak{a}}) + (\doutkinStar{\alpha}{\mathfrak{b}}-\doutkinStar{\alpha}{\mathfrak{a}}) + 2B_{\alpha\alpha}^* \right. \\ +& \hspace{-1cm} \left. +- \frac{\gamma\dkoutStar{\alpha}}{2m} (\dinStotStar{\mathfrak{b}}-\dinStotStar{\mathfrak{a}}) - \frac{\gamma\dkinStar{\alpha}}{2m} (\doutStotStar{\mathfrak{b}} - \doutStotStar{\mathfrak{a}}) - \frac{2\gamma\dkinStar{\alpha}\dkoutStar{\alpha}}{2m} \right] +\end{align*} + + +\end{document} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_common.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_common.go new file mode 100644 index 00000000..987776c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_common.go @@ -0,0 +1,415 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "fmt" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// Q returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// Q will panic if g has any edge with negative edge weight. +// +// If g is undirected, Q is calculated according to +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j), +// If g is directed, it is calculated according to +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j). +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs with the undirected modularity function. +func Q(g graph.Graph, communities [][]graph.Node, resolution float64) float64 { + switch g := g.(type) { + case graph.Undirected: + return qUndirected(g, communities, resolution) + case graph.Directed: + return qDirected(g, communities, resolution) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// ReducedGraph is a modularised graph. +type ReducedGraph interface { + graph.Graph + + // Communities returns the community memberships + // of the nodes in the graph used to generate + // the reduced graph. + Communities() [][]graph.Node + + // Structure returns the community structure of + // the current level of the module clustering. + // Each slice in the returned value recursively + // describes the membership of a community at + // the current level by indexing via the node + // ID into the structure of the non-nil + // ReducedGraph returned by Expanded, or when the + // ReducedGraph is nil, by containing nodes + // from the original input graph. + // + // The returned value should not be mutated. + Structure() [][]graph.Node + + // Expanded returns the next lower level of the + // module clustering or nil if at the lowest level. + // + // The returned ReducedGraph will be the same + // concrete type as the receiver. + Expanded() ReducedGraph +} + +// Modularize returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If src is nil, rand.Intn is used as the random +// generator. Modularize will panic if g has any edge with negative edge weight. +// +// If g is undirected it is modularised to minimise +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j), +// If g is directed it is modularised to minimise +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j). +// +// The concrete type of the ReducedGraph will be a pointer to either a +// ReducedUndirected or a ReducedDirected depending on the type of g. +// +// graph.Undirect may be used as a shim to allow modularization of +// directed graphs with the undirected modularity function. +func Modularize(g graph.Graph, resolution float64, src *rand.Rand) ReducedGraph { + switch g := g.(type) { + case graph.Undirected: + return louvainUndirected(g, resolution, src) + case graph.Directed: + return louvainDirected(g, resolution, src) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// Multiplex is a multiplex graph. +type Multiplex interface { + // Nodes returns the slice of nodes + // for the multiplex graph. + // All layers must refer to the same + // set of nodes. + Nodes() []graph.Node + + // Depth returns the number of layers + // in the multiplex graph. + Depth() int +} + +// QMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// QMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// If g is undirected, Q is calculated according to +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m_{layer} ] \delta(c_i,c_j), +// If g is directed, it is calculated according to +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i^in k_j^out)/m_{layer} ] \delta(c_i,c_j). +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func QMultiplex(g Multiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + switch g := g.(type) { + case UndirectedMultiplex: + return qUndirectedMultiplex(g, communities, weights, resolutions) + case DirectedMultiplex: + return qDirectedMultiplex(g, communities, weights, resolutions) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// ReducedMultiplex is a modularised multiplex graph. +type ReducedMultiplex interface { + Multiplex + + // Communities returns the community memberships + // of the nodes in the graph used to generate + // the reduced graph. + Communities() [][]graph.Node + + // Structure returns the community structure of + // the current level of the module clustering. + // Each slice in the returned value recursively + // describes the membership of a community at + // the current level by indexing via the node + // ID into the structure of the non-nil + // ReducedGraph returned by Expanded, or when the + // ReducedGraph is nil, by containing nodes + // from the original input graph. + // + // The returned value should not be mutated. + Structure() [][]graph.Node + + // Expanded returns the next lower level of the + // module clustering or nil if at the lowest level. + // + // The returned ReducedGraph will be the same + // concrete type as the receiver. + Expanded() ReducedMultiplex +} + +// ModularizeMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g have negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. ModularizeMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// If g is undirected it is modularised to minimise +// Q = \sum w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j). +// If g is directed it is modularised to minimise +// Q = \sum w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i^in k_j^out)/m_{layer} ] \delta(c_i,c_j). +// +// The concrete type of the ReducedMultiplex will be a pointer to a +// ReducedUndirectedMultiplex. +// +// graph.Undirect may be used as a shim to allow modularization of +// directed graphs with the undirected modularity function. +func ModularizeMultiplex(g Multiplex, weights, resolutions []float64, all bool, src *rand.Rand) ReducedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + switch g := g.(type) { + case UndirectedMultiplex: + return louvainUndirectedMultiplex(g, weights, resolutions, all, src) + case DirectedMultiplex: + return louvainDirectedMultiplex(g, weights, resolutions, all, src) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// undirectedEdges is the edge structure of a reduced undirected graph. +type undirectedEdges struct { + // edges and weights is the set + // of edges between nodes. + // weights is keyed such that + // the first element of the key + // is less than the second. + edges [][]int + weights map[[2]int]float64 +} + +// directedEdges is the edge structure of a reduced directed graph. +type directedEdges struct { + // edgesFrom, edgesTo and weights + // is the set of edges between nodes. + edgesFrom [][]int + edgesTo [][]int + weights map[[2]int]float64 +} + +// isValidID returns whether id is a valid ID for a community, +// multiplexCommunity or node. These are all graph.Node types +// stored in []T with a mapping between their index and their ID +// so IDs must be positive and fit within the int type. +func isValidID(id int64) bool { + return id == int64(int(id)) && id >= 0 +} + +// community is a reduced graph node describing its membership. +type community struct { + // community graphs are internal, in-memory + // with dense IDs, so id is always an int. + id int + + nodes []graph.Node + + weight float64 +} + +func (n community) ID() int64 { return int64(n.id) } + +// edge is a reduced graph edge. +type edge struct { + from, to community + weight float64 +} + +func (e edge) From() graph.Node { return e.from } +func (e edge) To() graph.Node { return e.to } +func (e edge) Weight() float64 { return e.weight } + +// multiplexCommunity is a reduced multiplex graph node describing its membership. +type multiplexCommunity struct { + // community graphs are internal, in-memory + // with dense IDs, so id is always an int. + id int + + nodes []graph.Node + + weights []float64 +} + +func (n multiplexCommunity) ID() int64 { return int64(n.id) } + +// multiplexEdge is a reduced graph edge for a multiplex graph. +type multiplexEdge struct { + from, to multiplexCommunity + weight float64 +} + +func (e multiplexEdge) From() graph.Node { return e.from } +func (e multiplexEdge) To() graph.Node { return e.to } +func (e multiplexEdge) Weight() float64 { return e.weight } + +// commIdx is an index of a node in a community held by a localMover. +type commIdx struct { + community int + node int +} + +// node is defined to avoid an import of .../graph/simple. node is +// used in in-memory, dense ID graphs and so is always an int. +type node int + +func (n node) ID() int64 { return int64(n) } + +// minTaker is a set iterator. +type minTaker interface { + TakeMin(p *int) bool +} + +// dense is a dense integer set iterator. +type dense struct { + pos int + n int +} + +// TakeMin mimics intsets.Sparse TakeMin for dense sets. If the dense +// iterator position is less than the iterator size, TakeMin sets *p +// to the the iterator position and increments the position and returns +// true. +// Otherwise, it returns false and *p is undefined. +func (d *dense) TakeMin(p *int) bool { + if d.pos >= d.n { + return false + } + *p = d.pos + d.pos++ + return true +} + +// slice is a sparse integer set iterator. +type slice struct { + pos int + elems []int +} + +// newSlice returns a new slice of elements from s, sorted ascending. +func newSlice(s set.Ints) *slice { + elems := make([]int, 0, len(s)) + for i := range s { + elems = append(elems, i) + } + sort.Ints(elems) + return &slice{elems: elems} +} + +// TakeMin mimics intsets.Sparse TakeMin for a sorted set. If the set +// iterator position is less than the iterator size, TakeMin sets *p +// to the the iterator position's element and increments the position +// and returns true. +// Otherwise, it returns false and *p is undefined. +func (s *slice) TakeMin(p *int) bool { + if s.pos >= len(s.elems) { + return false + } + *p = s.elems[s.pos] + s.pos++ + return true +} + +const ( + negativeWeight = "community: unexpected negative edge weight" + positiveWeight = "community: unexpected positive edge weight" +) + +// positiveWeightFuncFor returns a constructed weight function for the +// positively weighted g. Unweighted graphs have unit weight for existing +// edges. +func positiveWeightFuncFor(g graph.Graph) func(x, y graph.Node) float64 { + if wg, ok := g.(graph.Weighted); ok { + return func(x, y graph.Node) float64 { + w, ok := wg.Weight(x, y) + if !ok { + return 0 + } + if w < 0 { + panic(negativeWeight) + } + return w + } + } + return func(x, y graph.Node) float64 { + e := g.Edge(x, y) + if e == nil { + return 0 + } + return 1 + } +} + +// negativeWeightFuncFor returns a constructed weight function for the +// negatively weighted g. Unweighted graphs have unit weight for existing +// edges. +func negativeWeightFuncFor(g graph.Graph) func(x, y graph.Node) float64 { + if wg, ok := g.(graph.Weighted); ok { + return func(x, y graph.Node) float64 { + w, ok := wg.Weight(x, y) + if !ok { + return 0 + } + if w > 0 { + panic(positiveWeight) + } + return -w + } + } + return func(x, y graph.Node) float64 { + e := g.Edge(x, y) + if e == nil { + return 0 + } + return 1 + } +} + +// depth returns max(1, len(weights)). It is used to ensure +// that multiplex community weights are properly initialised. +func depth(weights []float64) int { + if weights == nil { + return 1 + } + return len(weights) +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_directed.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed.go new file mode 100644 index 00000000..3bd5a319 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed.go @@ -0,0 +1,650 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// qDirected returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// qDirected will panic if g has any edge with negative edge weight. +// +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j) +// +func qDirected(g graph.Directed, communities [][]graph.Node, resolution float64) float64 { + nodes := g.Nodes() + weight := positiveWeightFuncFor(g) + + // Calculate the total edge weight of the graph + // and the table of penetrating edge weight sums. + var m float64 + k := make(map[int64]directedWeights, len(nodes)) + for _, n := range nodes { + var wOut float64 + u := n + for _, v := range g.From(u) { + wOut += weight(u, v) + } + var wIn float64 + v := n + for _, u := range g.To(v) { + wIn += weight(u, v) + } + w := weight(n, n) + m += w + wOut // We only need to count edges once. + k[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + } + + if communities == nil { + var q float64 + for _, u := range nodes { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU.out*kU.in/m + } + return q / m + } + + var q float64 + for _, c := range communities { + for _, u := range c { + kU := k[u.ID()] + for _, v := range c { + kV := k[v.ID()] + q += weight(u, v) - resolution*kU.out*kV.in/m + } + } + } + return q / m +} + +// louvainDirected returns the hierarchical modularization of g at the given +// resolution using the Louvain algorithm. If src is nil, rand.Intn is used +// as the random generator. louvainDirected will panic if g has any edge with negative +// edge weight. +func louvainDirected(g graph.Directed, resolution float64, src *rand.Rand) ReducedGraph { + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceDirected(g, nil) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newDirectedLocalMover(c, c.communities, resolution) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceDirected(c, l.communities) + } +} + +// ReducedDirected is a directed graph of communities derived from a +// parent graph by reduction. +type ReducedDirected struct { + // nodes is the set of nodes held + // by the graph. In a ReducedDirected + // the node ID is the index into + // nodes. + nodes []community + directedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedDirected +} + +var ( + reducedDirected = (*ReducedDirected)(nil) + + _ graph.WeightedDirected = reducedDirected + _ ReducedGraph = reducedDirected +) + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedDirected) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedDirected) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedDirected) Expanded() ReducedGraph { + return g.parent +} + +// reduceDirected returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceDirected. If communities is nil and g is a +// ReducedDirected, it is returned unaltered. +func reduceDirected(g graph.Directed, communities [][]graph.Node) *ReducedDirected { + if communities == nil { + if r, ok := g.(*ReducedDirected); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + weight := positiveWeightFuncFor(g) + r := ReducedDirected{ + nodes: make([]community, len(nodes)), + directedEdges: directedEdges{ + edgesFrom: make([][]int, len(nodes)), + edgesTo: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + }, + communities: communities, + } + communityOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = community{id: i, nodes: []graph.Node{n}} + communityOf[n.ID()] = i + } + for _, n := range nodes { + id := communityOf[n.ID()] + + var out []int + u := n + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + if vid != id { + out = append(out, vid) + } + r.weights[[2]int{id, vid}] = weight(u, v) + } + r.edgesFrom[id] = out + + var in []int + v := n + for _, u := range g.To(v) { + uid := communityOf[u.ID()] + if uid != id { + in = append(in, uid) + } + r.weights[[2]int{uid, id}] = weight(u, v) + } + r.edgesTo[id] = in + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedDirected{ + nodes: make([]community, len(communities)), + directedEdges: directedEdges{ + edgesFrom: make([][]int, len(communities)), + edgesTo: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + }, + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedDirected); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + weight := positiveWeightFuncFor(g) + communityOf := make(map[int64]int, commNodes) + for i, comm := range communities { + r.nodes[i] = community{id: i, nodes: comm} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for id, comm := range communities { + var out, in []int + for _, n := range comm { + u := n + for _, v := range comm { + r.nodes[id].weight += weight(u, v) + } + + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != id { + out = append(out, vid) + } + // Add half weights because the other + // ends of edges are also counted. + r.weights[[2]int{id, vid}] += weight(u, v) / 2 + } + + v := n + for _, u := range g.To(v) { + uid := communityOf[u.ID()] + found := false + for _, e := range in { + if e == uid { + found = true + break + } + } + if !found && uid != id { + in = append(in, uid) + } + // Add half weights because the other + // ends of edges are also counted. + r.weights[[2]int{uid, id}] += weight(u, v) / 2 + } + } + r.edgesFrom[id] = out + r.edgesTo[id] = in + } + return &r +} + +// Has returns whether the node exists within the graph. +func (g *ReducedDirected) Has(n graph.Node) bool { + id := n.ID() + return 0 <= id && id < int64(len(g.nodes)) +} + +// Nodes returns all the nodes in the graph. +func (g *ReducedDirected) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g *ReducedDirected) From(u graph.Node) []graph.Node { + out := g.edgesFrom[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.nodes[vid] + } + return nodes +} + +// To returns all nodes in g that can reach directly to v. +func (g *ReducedDirected) To(v graph.Node) []graph.Node { + in := g.edgesTo[v.ID()] + nodes := make([]graph.Node, len(in)) + for i, uid := range in { + nodes[i] = g.nodes[uid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *ReducedDirected) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return false + } + _, ok := g.weights[[2]int{int(xid), int(yid)}] + if ok { + return true + } + _, ok = g.weights[[2]int{int(yid), int(xid)}] + return ok +} + +// HasEdgeFromTo returns whether an edge exists from node u to v. +func (g *ReducedDirected) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + vid := v.ID() + if uid == vid || !isValidID(uid) || !isValidID(vid) { + return false + } + _, ok := g.weights[[2]int{int(uid), int(vid)}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedDirected) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdge(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedDirected) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + uid := u.ID() + vid := v.ID() + if uid == vid || !isValidID(uid) || !isValidID(vid) { + return nil + } + w, ok := g.weights[[2]int{int(uid), int(vid)}] + if !ok { + return nil + } + return edge{from: g.nodes[uid], to: g.nodes[vid], weight: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *ReducedDirected) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if !isValidID(xid) || !isValidID(yid) { + return 0, false + } + if xid == yid { + return g.nodes[xid].weight, true + } + w, ok = g.weights[[2]int{int(xid), int(yid)}] + return w, ok +} + +// directedLocalMover is a step in graph modularity optimization. +type directedLocalMover struct { + g *ReducedDirected + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightsOf is the weighted degree + // of each node indexed by ID. + edgeWeightsOf []directedWeights + + // m is the total sum of edge + // weights in g. + m float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolution float64 + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +type directedWeights struct { + out, in float64 +} + +// newDirectedLocalMover returns a new directedLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. +// The node IDs of g must be contiguous in [0,n) where n is the number of +// nodes. +// If g has a zero edge weight sum, nil is returned. +func newDirectedLocalMover(g *ReducedDirected, communities [][]graph.Node, resolution float64) *directedLocalMover { + nodes := g.Nodes() + l := directedLocalMover{ + g: g, + nodes: nodes, + edgeWeightsOf: make([]directedWeights, len(nodes)), + communities: communities, + memberships: make([]int, len(nodes)), + resolution: resolution, + weight: positiveWeightFuncFor(g), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + for _, n := range l.nodes { + u := n + var wOut float64 + for _, v := range g.From(u) { + wOut += l.weight(u, v) + } + + v := n + var wIn float64 + for _, u := range g.To(v) { + wIn += l.weight(u, v) + } + + w := l.weight(n, n) + l.edgeWeightsOf[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + l.m += w + wOut + } + + // Assign membership mappings. + for i, c := range communities { + for _, n := range c { + l.memberships[n.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// directedLocalMover has not made any improvement to the community structure and +// so the Louvain algorithm is done. +func (l *directedLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// directedLocalMover using the random source rnd which should return an +// integer in the range [0,n). +func (l *directedLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *directedLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the directedLocalMover's +// communities field is returned in src if n is in communities. +func (l *directedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + a_aa := l.weight(n, n) + k_a := l.edgeWeightsOf[id] + m := l.m + gamma := l.resolution + + // Find communities connected to n. + connected := make(set.Ints) + // The following for loop is equivalent to: + // + // for _, v := range l.g.From(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // for _, v := range l.g.To(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // + // This is done to avoid two allocations. + for _, vid := range l.g.edgesFrom[id] { + connected.Add(l.memberships[vid]) + } + for _, vid := range l.g.edgesTo[id] { + connected.Add(l.memberships[vid]) + } + // Insert the node's own community. + connected.Add(l.memberships[id]) + + candidates := make([]int, 0, len(connected)) + for i := range connected { + candidates = append(candidates, i) + } + sort.Ints(candidates) + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + for _, i := range candidates { + c := l.communities[i] + var k_aC, sigma_totC directedWeights // C is a substitution for ^𝛼 or ^𝛽. + var removal bool + for j, u := range c { + uid := u.ID() + if uid == id { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + removal = true + } + + k_aC.in += l.weight(u, n) + k_aC.out += l.weight(n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + w := l.edgeWeightsOf[uid] + sigma_totC.in += w.in + sigma_totC.out += w.out + } + + // See louvain.tex for a derivation of these equations. + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove = (k_aC.in /*^𝛼*/ - a_aa) + (k_aC.out /*^𝛼*/ - a_aa) - + gamma*(k_a.in*(sigma_totC.out /*^𝛼*/ -k_a.out)+k_a.out*(sigma_totC.in /*^𝛼*/ -k_a.in))/m + + default: + // Otherwise calculate the change due to an addition + // to c and retain if it is the current best. + dQ := k_aC.in /*^𝛽*/ + k_aC.out /*^𝛽*/ - + gamma*(k_a.in*sigma_totC.out /*^𝛽*/ +k_a.out*sigma_totC.in /*^𝛽*/)/m + + if dQ > dQadd { + dQadd = dQ + dst = i + } + } + } + + return (dQadd - dQremove) / m, dst, src +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex.go new file mode 100644 index 00000000..967ba758 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex.go @@ -0,0 +1,888 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// DirectedMultiplex is a directed multiplex graph. +type DirectedMultiplex interface { + Multiplex + + // Layer returns the lth layer of the + // multiplex graph. + Layer(l int) graph.Directed +} + +// qDirectedMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// qUndirectedMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j) +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +func qDirectedMultiplex(g DirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + q := make([]float64, g.Depth()) + nodes := g.Nodes() + layerWeight := 1.0 + layerResolution := 1.0 + if len(resolutions) == 1 { + layerResolution = resolutions[0] + } + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + + if weights != nil { + layerWeight = weights[l] + } + if layerWeight == 0 { + continue + } + + if len(resolutions) > 1 { + layerResolution = resolutions[l] + } + + var weight func(x, y graph.Node) float64 + if layerWeight < 0 { + weight = negativeWeightFuncFor(layer) + } else { + weight = positiveWeightFuncFor(layer) + } + + // Calculate the total edge weight of the layer + // and the table of penetrating edge weight sums. + var m float64 + k := make(map[int64]directedWeights, len(nodes)) + for _, n := range nodes { + var wOut float64 + u := n + for _, v := range layer.From(u) { + wOut += weight(u, v) + } + var wIn float64 + v := n + for _, u := range layer.To(v) { + wIn += weight(u, v) + } + w := weight(n, n) + m += w + wOut // We only need to count edges once. + k[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + } + + if communities == nil { + var qLayer float64 + for _, u := range nodes { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU.out*kU.in/m + } + q[l] = layerWeight * qLayer + continue + } + + var qLayer float64 + for _, c := range communities { + for _, u := range c { + kU := k[u.ID()] + for _, v := range c { + kV := k[v.ID()] + qLayer += weight(u, v) - layerResolution*kU.out*kV.in/m + } + } + } + q[l] = layerWeight * qLayer + } + + return q +} + +// DirectedLayers implements DirectedMultiplex. +type DirectedLayers []graph.Directed + +// NewDirectedLayers returns a DirectedLayers using the provided layers +// ensuring there is a match between IDs for each layer. +func NewDirectedLayers(layers ...graph.Directed) (DirectedLayers, error) { + if len(layers) == 0 { + return nil, nil + } + base := make(set.Int64s) + for _, n := range layers[0].Nodes() { + base.Add(n.ID()) + } + for i, l := range layers[1:] { + next := make(set.Int64s) + for _, n := range l.Nodes() { + next.Add(n.ID()) + } + if !set.Int64sEqual(base, next) { + return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1) + } + } + return layers, nil +} + +// Nodes returns the nodes of the receiver. +func (g DirectedLayers) Nodes() []graph.Node { + if len(g) == 0 { + return nil + } + return g[0].Nodes() +} + +// Depth returns the depth of the multiplex graph. +func (g DirectedLayers) Depth() int { return len(g) } + +// Layer returns the lth layer of the multiplex graph. +func (g DirectedLayers) Layer(l int) graph.Directed { return g[l] } + +// louvainDirectedMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g has negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. louvainDirectedMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainDirectedMultiplex(g DirectedMultiplex, weights, resolutions []float64, all bool, src *rand.Rand) *ReducedDirectedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceDirectedMultiplex(g, nil, weights) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newDirectedMultiplexLocalMover(c, c.communities, weights, resolutions, all) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceDirectedMultiplex(c, l.communities, weights) + } +} + +// ReducedDirectedMultiplex is a directed graph of communities derived from a +// parent graph by reduction. +type ReducedDirectedMultiplex struct { + // nodes is the set of nodes held + // by the graph. In a ReducedDirectedMultiplex + // the node ID is the index into + // nodes. + nodes []multiplexCommunity + layers []directedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedDirectedMultiplex +} + +var ( + _ DirectedMultiplex = (*ReducedDirectedMultiplex)(nil) + _ graph.WeightedDirected = (*directedLayerHandle)(nil) +) + +// Nodes returns all the nodes in the graph. +func (g *ReducedDirectedMultiplex) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// Depth returns the number of layers in the multiplex graph. +func (g *ReducedDirectedMultiplex) Depth() int { return len(g.layers) } + +// Layer returns the lth layer of the multiplex graph. +func (g *ReducedDirectedMultiplex) Layer(l int) graph.Directed { + return directedLayerHandle{multiplex: g, layer: l} +} + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedDirectedMultiplex) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedDirectedMultiplex) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedDirectedMultiplex) Expanded() ReducedMultiplex { + return g.parent +} + +// reduceDirectedMultiplex returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceDirectedMultiplex. If communities is nil and g is a +// ReducedDirectedMultiplex, it is returned unaltered. +func reduceDirectedMultiplex(g DirectedMultiplex, communities [][]graph.Node, weights []float64) *ReducedDirectedMultiplex { + if communities == nil { + if r, ok := g.(*ReducedDirectedMultiplex); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + r := ReducedDirectedMultiplex{ + nodes: make([]multiplexCommunity, len(nodes)), + layers: make([]directedEdges, g.Depth()), + communities: communities, + } + communityOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = multiplexCommunity{id: i, nodes: []graph.Node{n}, weights: make([]float64, depth(weights))} + communityOf[n.ID()] = i + } + for i := range r.layers { + r.layers[i] = directedEdges{ + edgesFrom: make([][]int, len(nodes)), + edgesTo: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + } + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for _, n := range nodes { + id := communityOf[n.ID()] + + var out []int + u := n + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + if vid != id { + out = append(out, vid) + } + r.layers[l].weights[[2]int{id, vid}] = sign * weight(u, v) + } + r.layers[l].edgesFrom[id] = out + + var in []int + v := n + for _, u := range layer.To(v) { + uid := communityOf[u.ID()] + if uid != id { + in = append(in, uid) + } + r.layers[l].weights[[2]int{uid, id}] = sign * weight(u, v) + } + r.layers[l].edgesTo[id] = in + } + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedDirectedMultiplex{ + nodes: make([]multiplexCommunity, len(communities)), + layers: make([]directedEdges, g.Depth()), + } + communityOf := make(map[int64]int, commNodes) + for i, comm := range communities { + r.nodes[i] = multiplexCommunity{id: i, nodes: comm, weights: make([]float64, depth(weights))} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for i := range r.layers { + r.layers[i] = directedEdges{ + edgesFrom: make([][]int, len(communities)), + edgesTo: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + } + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedDirectedMultiplex); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for id, comm := range communities { + var out, in []int + for _, n := range comm { + u := n + for _, v := range comm { + r.nodes[id].weights[l] += sign * weight(u, v) + } + + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != id { + out = append(out, vid) + } + // Add half weights because the other + // ends of edges are also counted. + r.layers[l].weights[[2]int{id, vid}] += sign * weight(u, v) / 2 + } + + v := n + for _, u := range layer.To(v) { + uid := communityOf[u.ID()] + found := false + for _, e := range in { + if e == uid { + found = true + break + } + } + if !found && uid != id { + in = append(in, uid) + } + // Add half weights because the other + // ends of edges are also counted. + r.layers[l].weights[[2]int{uid, id}] += sign * weight(u, v) / 2 + } + + } + r.layers[l].edgesFrom[id] = out + r.layers[l].edgesTo[id] = in + } + } + return &r +} + +// directedLayerHandle is a handle to a multiplex graph layer. +type directedLayerHandle struct { + // multiplex is the complete + // multiplex graph. + multiplex *ReducedDirectedMultiplex + + // layer is an index into the + // multiplex for the current + // layer. + layer int +} + +// Has returns whether the node exists within the graph. +func (g directedLayerHandle) Has(n graph.Node) bool { + id := n.ID() + return 0 <= id && id < int64(len(g.multiplex.nodes)) +} + +// Nodes returns all the nodes in the graph. +func (g directedLayerHandle) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.multiplex.nodes)) + for i := range g.multiplex.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g directedLayerHandle) From(u graph.Node) []graph.Node { + out := g.multiplex.layers[g.layer].edgesFrom[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.multiplex.nodes[vid] + } + return nodes +} + +// To returns all nodes in g that can reach directly to v. +func (g directedLayerHandle) To(v graph.Node) []graph.Node { + in := g.multiplex.layers[g.layer].edgesTo[v.ID()] + nodes := make([]graph.Node, len(in)) + for i, uid := range in { + nodes[i] = g.multiplex.nodes[uid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g directedLayerHandle) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid { + return false + } + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return false + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{int(xid), int(yid)}] + if ok { + return true + } + _, ok = g.multiplex.layers[g.layer].weights[[2]int{int(yid), int(xid)}] + return ok +} + +// HasEdgeFromTo returns whether an edge exists from node u to v. +func (g directedLayerHandle) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + vid := v.ID() + if uid == vid || !isValidID(uid) || !isValidID(vid) { + return false + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{int(uid), int(vid)}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g directedLayerHandle) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdge(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g directedLayerHandle) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + uid := u.ID() + vid := v.ID() + if uid == vid || !isValidID(uid) || !isValidID(vid) { + return nil + } + w, ok := g.multiplex.layers[g.layer].weights[[2]int{int(uid), int(vid)}] + if !ok { + return nil + } + return multiplexEdge{from: g.multiplex.nodes[u.ID()], to: g.multiplex.nodes[v.ID()], weight: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g directedLayerHandle) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if !isValidID(xid) || !isValidID(yid) { + return 0, false + } + if xid == yid { + return g.multiplex.nodes[xid].weights[g.layer], true + } + w, ok = g.multiplex.layers[g.layer].weights[[2]int{int(xid), int(yid)}] + return w, ok +} + +// directedMultiplexLocalMover is a step in graph modularity optimization. +type directedMultiplexLocalMover struct { + g *ReducedDirectedMultiplex + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightsOf is the weighted degree + // of each node indexed by ID. + edgeWeightsOf [][]directedWeights + + // m is the total sum of + // edge weights in g. + m []float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight []func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolutions []float64 + + // weights is the layer weights for + // the modularisation. + weights []float64 + + // searchAll specifies whether the local + // mover should consider non-connected + // communities during the local moving + // heuristic. + searchAll bool + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newDirectedMultiplexLocalMover returns a new directedMultiplexLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newDirectedMultiplexLocalMover(g *ReducedDirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64, all bool) *directedMultiplexLocalMover { + nodes := g.Nodes() + l := directedMultiplexLocalMover{ + g: g, + nodes: nodes, + edgeWeightsOf: make([][]directedWeights, g.Depth()), + m: make([]float64, g.Depth()), + communities: communities, + memberships: make([]int, len(nodes)), + resolutions: resolutions, + weights: weights, + weight: make([]func(x, y graph.Node) float64, g.Depth()), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + var zero int + for i := 0; i < g.Depth(); i++ { + l.edgeWeightsOf[i] = make([]directedWeights, len(nodes)) + var weight func(x, y graph.Node) float64 + + if weights != nil { + if weights[i] == 0 { + zero++ + continue + } + if weights[i] < 0 { + weight = negativeWeightFuncFor(g.Layer(i)) + l.searchAll = all + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + + l.weight[i] = weight + layer := g.Layer(i) + for _, n := range l.nodes { + u := n + var wOut float64 + for _, v := range layer.From(u) { + wOut += weight(u, v) + } + + v := n + var wIn float64 + for _, u := range layer.To(v) { + wIn += weight(u, v) + } + + w := weight(n, n) + l.edgeWeightsOf[i][u.ID()] = directedWeights{out: w + wOut, in: w + wIn} + l.m[i] += w + wOut + } + if l.m[i] == 0 { + zero++ + } + } + if zero == g.Depth() { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, n := range c { + l.memberships[n.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// directedMultiplexLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *directedMultiplexLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// directedMultiplexLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *directedMultiplexLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *directedMultiplexLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// directedMultiplexLocalMover's communities field is returned in src if n +// is in communities. +func (l *directedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + var iterator minTaker + if l.searchAll { + iterator = &dense{n: len(l.communities)} + } else { + // Find communities connected to n. + connected := make(set.Ints) + // The following for loop is equivalent to: + // + // for i := 0; i < l.g.Depth(); i++ { + // for _, v := range l.g.Layer(i).From(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // for _, v := range l.g.Layer(i).To(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // } + // + // This is done to avoid an allocation for + // each layer. + for _, layer := range l.g.layers { + for _, vid := range layer.edgesFrom[id] { + connected.Add(l.memberships[vid]) + } + for _, vid := range layer.edgesTo[id] { + connected.Add(l.memberships[vid]) + } + } + // Insert the node's own community. + connected.Add(l.memberships[id]) + iterator = newSlice(connected) + } + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for iterator.TakeMin(&i) { + c := l.communities[i] + var removal bool + var _dQadd float64 + for layer := 0; layer < l.g.Depth(); layer++ { + m := l.m[layer] + if m == 0 { + // Do not consider layers with zero sum edge weight. + continue + } + w := 1.0 + if l.weights != nil { + w = l.weights[layer] + } + if w == 0 { + // Do not consider layers with zero weighting. + continue + } + + var k_aC, sigma_totC directedWeights // C is a substitution for ^𝛼 or ^𝛽. + removal = false + for j, u := range c { + uid := u.ID() + if uid == id { + // Only mark and check src community on the first layer. + if layer == 0 { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + } + removal = true + } + + k_aC.in += l.weight[layer](n, u) + k_aC.out += l.weight[layer](u, n) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + w := l.edgeWeightsOf[layer][uid] + sigma_totC.in += w.in + sigma_totC.out += w.out + } + + a_aa := l.weight[layer](n, n) + k_a := l.edgeWeightsOf[layer][id] + gamma := 1.0 + if l.resolutions != nil { + if len(l.resolutions) == 1 { + gamma = l.resolutions[0] + } else { + gamma = l.resolutions[layer] + } + } + + // See louvain.tex for a derivation of these equations. + // The weighting term, w, is described in V Traag, + // "Algorithms and dynamical models for communities and + // reputation in social networks", chapter 5. + // http://www.traag.net/wp/wp-content/papercite-data/pdf/traag_algorithms_2013.pdf + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove += w * ((k_aC.in /*^𝛼*/ - a_aa) + (k_aC.out /*^𝛼*/ - a_aa) - + gamma*(k_a.in*(sigma_totC.out /*^𝛼*/ -k_a.out)+k_a.out*(sigma_totC.in /*^𝛼*/ -k_a.in))/m) + + default: + // Otherwise calculate the change due to an addition + // to c. + _dQadd += w * (k_aC.in /*^𝛽*/ + k_aC.out /*^𝛽*/ - + gamma*(k_a.in*sigma_totC.out /*^𝛽*/ +k_a.out*sigma_totC.in /*^𝛽*/)/m) + } + } + if !removal && _dQadd > dQadd { + dQadd = _dQadd + dst = i + } + } + + return dQadd - dQremove, dst, src +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex_test.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex_test.go new file mode 100644 index 00000000..896c6122 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_multiplex_test.go @@ -0,0 +1,722 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityDirectedMultiplexQTests = []struct { + name string + layers []layer + structures []structure + + wantLevels []level +}{ + { + name: "unconnected", + layers: []layer{{g: unconnected, weight: 1}}, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "simple_directed", + layers: []layer{{g: simpleDirected, weight: 1}}, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + q: 0.5714285714285716, + }, + { + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + q: -1.2857142857142856, + }, + }, + }, + { + name: "simple_directed_twice", + layers: []layer{ + {g: simpleDirected, weight: 0.5}, + {g: simpleDirected, weight: 0.5}, + }, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + q: 0.5714285714285716, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + }, + { + q: -1.2857142857142856, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + }, + }, + }, + { + name: "small_dumbell", + layers: []layer{ + {g: smallDumbell, edgeWeight: 1, weight: 1}, + {g: dumbellRepulsion, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 2.5714285714285716, tol: 1e-10, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 2.5714285714285716, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.857142857142857, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "repulsion", + layers: []layer{{g: repulsion, edgeWeight: -1, weight: -1}}, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 9.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: 3, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 9.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: 3.0, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "middle_east", + layers: []layer{ + {g: middleEast.friends, edgeWeight: 1, weight: 1}, + {g: middleEast.enemies, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 6), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(2, 8, 11), + 3: linksTo(3, 4, 5, 10), + }, + want: 33.818057455540355, tol: 1e-9, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 2, 3, 4, 5, 10), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(6), + 3: linksTo(8, 11), + }, + want: 30.92749658, tol: 1e-7, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 33.818057455540355, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(6)}, + {simple.Node(1), simple.Node(7), simple.Node(9), simple.Node(12)}, + {simple.Node(2), simple.Node(8), simple.Node(11)}, + {simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(10)}, + }, + }, + { + q: 3.8071135430916545, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + }, + }, + }, + }, +} + +func TestCommunityQDirectedMultiplex(t *testing.T) { + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + q := QMultiplex(g, communities, weights, []float64{structure.resolution}) + got := floats.Sum(q) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v %.3v want: %v", + test.name, communities, got, q, structure.want) + } + } + } +} + +func TestCommunityDeltaQDirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int64]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + resolution := []float64{structure.resolution} + + before := QMultiplex(g, communities, weights, resolution) + + // We test exhaustively. + const all = true + + l := newDirectedMultiplexLocalMover( + reduceDirectedMultiplex(g, nil, weights), + communities, weights, resolution, all) + if l == nil { + if !math.IsNaN(floats.Sum(before)) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + if !(all && hasNegative(weights)) { + connected := false + search: + for l := 0; l < g.Depth(); l++ { + if weights[l] < 0 { + connected = true + break search + } + layer := g.Layer(l) + for n := range c { + if layer.HasEdgeBetween(simple.Node(n), target) { + connected = true + break search + } + } + } + if !connected { + continue + } + } + migrated[i] = append(migrated[i], target) + after := QMultiplex(g, migrated, weights, resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if delta := floats.Sum(after) - floats.Sum(before); delta > want { + want = delta + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyDirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := QMultiplex(g, communities, weights, []float64{structure.resolution}) + gQnull := QMultiplex(g, nil, weights, nil) + + cg0 := reduceDirectedMultiplex(g, nil, weights) + cg0Qnull := QMultiplex(cg0, cg0.Structure(), weights, nil) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQnull), floats.Sum(cg0Qnull), structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := QMultiplex(cg0, communities, weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg0Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceDirectedMultiplex(cg0, communities, weights) + cg1Q := QMultiplex(cg1, cg1.Structure(), weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg1Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localDirectedMultiplexMoveTests = []struct { + name string + layers []layer + structures []moveStructures +}{ + { + name: "blondel", + layers: []layer{{g: blondel, weight: 1}, {g: blondel, weight: 0.5}}, + structures: []moveStructures{ + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalDirectedMultiplex(t *testing.T) { + for _, test := range localDirectedMultiplexMoveTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceDirectedMultiplex(reduceDirectedMultiplex(g, nil, weights), communities, weights) + + l := newDirectedMultiplexLocalMover(r, r.communities, weights, []float64{structure.resolution}, true) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + l.move(dst, src) + after := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestLouvainDirectedMultiplex(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedDirectedMultiplex + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := ModularizeMultiplex(g, weights, nil, true, src).(*ReducedDirectedMultiplex) + if q := floats.Sum(QMultiplex(r, nil, weights, nil)); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedDirectedMultiplex) { + qs = append(qs, floats.Sum(QMultiplex(p, nil, weights, nil))) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedDirectedMultiplex) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceDirectedMultiplex(g, nil, weights).Communities() + } + q := floats.Sum(QMultiplex(p, nil, weights, nil)) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousDirectedMultiplex(t *testing.T) { + g := simple.NewDirectedGraph() + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1)}, + {F: simple.Node(4), T: simple.Node(5)}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(DirectedLayers{g}, nil, nil, true, nil) + }() +} + +func TestNonContiguousWeightedDirectedMultiplex(t *testing.T) { + g := simple.NewWeightedDirectedGraph(0, 0) + for _, e := range []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetWeightedEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(DirectedLayers{g}, nil, nil, true, nil) + }() +} + +func BenchmarkLouvainDirectedMultiplex(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + ModularizeMultiplex(DirectedLayers{dupGraphDirected}, nil, nil, true, src) + } +} + +func directedMultiplexFrom(raw []layer) (DirectedLayers, []float64, error) { + var layers []graph.Directed + var weights []float64 + for _, l := range raw { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range l.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + w := 1.0 + if l.edgeWeight != 0 { + w = l.edgeWeight + } + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: w}) + } + } + layers = append(layers, g) + weights = append(weights, l.weight) + } + g, err := NewDirectedLayers(layers...) + if err != nil { + return nil, nil, err + } + return g, weights, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_test.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_test.go new file mode 100644 index 00000000..5810ffb7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_directed_test.go @@ -0,0 +1,719 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +type communityDirectedQTest struct { + name string + g []intset + structures []structure + + wantLevels []level +} + +var communityDirectedQTests = []communityDirectedQTest{ + { + name: "simple_directed", + g: simpleDirected, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716 / 7, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + q: 0.5714285714285716 / 7, + }, + { + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + q: -1.2857142857142856 / 7, + }, + }, + }, + { + name: "zachary", + g: zachary, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21), + 1: linksTo(4, 5, 6, 10, 16), + 2: linksTo(8, 9, 14, 15, 18, 20, 22, 26, 29, 30, 32, 33), + 3: linksTo(23, 24, 25, 27, 28, 31), + }, + want: 34.3417721519 / 79 /* 5->6 and 6->5 because of co-equal rank */, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.43470597660631316, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(10), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: 0.3911232174331037, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(10)}, + {simple.Node(5), simple.Node(6), simple.Node(16)}, + {simple.Node(8), simple.Node(30)}, + {simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + {simple.Node(26), simple.Node(29)}, + }, + }, + { + q: -0.014580996635154624, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + {simple.Node(16)}, + {simple.Node(17)}, + {simple.Node(18)}, + {simple.Node(19)}, + {simple.Node(20)}, + {simple.Node(21)}, + {simple.Node(22)}, + {simple.Node(23)}, + {simple.Node(24)}, + {simple.Node(25)}, + {simple.Node(26)}, + {simple.Node(27)}, + {simple.Node(28)}, + {simple.Node(29)}, + {simple.Node(30)}, + {simple.Node(31)}, + {simple.Node(32)}, + {simple.Node(33)}, + }, + }, + }, + }, + { + name: "blondel", + g: blondel, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7), + 1: linksTo(8, 9, 10, 11, 12, 13, 14, 15), + }, + want: 11.1428571429 / 28, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.3979591836734694, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(14), simple.Node(15)}, + }, + }, + { + q: 0.32525510204081637, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(3), simple.Node(5), simple.Node(7)}, + {simple.Node(1), simple.Node(2), simple.Node(4), simple.Node(6)}, + {simple.Node(8), simple.Node(10), simple.Node(11), simple.Node(13), simple.Node(15)}, + {simple.Node(9), simple.Node(12), simple.Node(14)}, + }, + }, + { + q: -0.022959183673469385, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + }, + }, + }, + }, +} + +func TestCommunityQDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testCommunityQDirected(t, test, g) + } +} + +func TestCommunityQWeightedDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testCommunityQDirected(t, test, g) + } +} + +func testCommunityQDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) { + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + got := Q(g, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v want: %v", + test.name, communities, got, structure.want) + } + } +} + +func TestCommunityDeltaQDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testCommunityDeltaQDirected(t, test, g) + } +} + +func TestCommunityDeltaQWeightedDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testCommunityDeltaQDirected(t, test, g) + } +} + +func testCommunityDeltaQDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) { + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int64]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + before := Q(g, communities, structure.resolution) + + l := newDirectedLocalMover(reduceDirected(g, nil), communities, structure.resolution) + if l == nil { + if !math.IsNaN(before) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + return + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + connected := false + for n := range c { + if g.HasEdgeBetween(simple.Node(n), target) { + connected = true + break + } + } + if !connected { + continue + } + migrated[i] = append(migrated[i], target) + after := Q(g, migrated, structure.resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if after-before > want { + want = after - before + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } +} + +func TestReduceQConsistencyDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testReduceQConsistencyDirected(t, test, g) + } +} + +func TestReduceQConsistencyWeightedDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testReduceQConsistencyDirected(t, test, g) + } +} + +func testReduceQConsistencyDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) { + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + return + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := Q(g, communities, structure.resolution) + gQnull := Q(g, nil, 1) + + cg0 := reduceDirected(g, nil) + cg0Qnull := Q(cg0, cg0.Structure(), 1) + if !floats.EqualWithinAbsOrRel(gQnull, cg0Qnull, structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := Q(cg0, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg0Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceDirected(cg0, communities) + cg1Q := Q(cg1, cg1.Structure(), structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg1Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } +} + +type localDirectedMoveTest struct { + name string + g []intset + structures []moveStructures +} + +var localDirectedMoveTests = []localDirectedMoveTest{ + { + name: "blondel", + g: blondel, + structures: []moveStructures{ + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalDirected(t *testing.T) { + for _, test := range localDirectedMoveTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testMoveLocalDirected(t, test, g) + } +} + +func TestMoveLocalWeightedDirected(t *testing.T) { + for _, test := range localDirectedMoveTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testMoveLocalDirected(t, test, g) + } +} + +func testMoveLocalDirected(t *testing.T, test localDirectedMoveTest, g graph.Directed) { + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceDirected(reduceDirected(g, nil), communities) + + l := newDirectedLocalMover(r, r.communities, structure.resolution) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := Q(r, l.communities, structure.resolution) + l.move(dst, src) + after := Q(r, l.communities, structure.resolution) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } +} + +func TestModularizeDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testModularizeDirected(t, test, g) + } +} + +func TestModularizeWeightedDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewWeightedDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testModularizeDirected(t, test, g) + } +} + +func testModularizeDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) { + const louvainIterations = 20 + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedDirected + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := Modularize(g, 1, src).(*ReducedDirected) + if q := Q(r, nil, 1); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedDirected) { + qs = append(qs, Q(p, nil, 1)) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + return + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedDirected) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceDirected(g, nil).Communities() + } + q := Q(p, nil, 1) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } +} + +func TestNonContiguousDirected(t *testing.T) { + g := simple.NewDirectedGraph() + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1)}, + {F: simple.Node(4), T: simple.Node(5)}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func TestNonContiguousWeightedDirected(t *testing.T) { + g := simple.NewWeightedDirectedGraph(0, 0) + for _, e := range []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetWeightedEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func BenchmarkLouvainDirected(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + Modularize(dupGraphDirected, 1, src) + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_test.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_test.go new file mode 100644 index 00000000..32631404 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_test.go @@ -0,0 +1,277 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "fmt" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +// intset is an integer set. +type intset map[int]struct{} + +func linksTo(i ...int) intset { + if len(i) == 0 { + return nil + } + s := make(intset) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +type layer struct { + g []intset + edgeWeight float64 // Zero edge weight is interpreted as 1.0. + weight float64 +} + +var ( + unconnected = []intset{ /* Nodes 0-4 are implicit .*/ 5: nil} + + smallDumbell = []intset{ + 0: linksTo(1, 2), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: linksTo(5), + 5: nil, + } + dumbellRepulsion = []intset{ + 0: linksTo(4), + 1: linksTo(5), + 2: nil, + 3: nil, + 4: nil, + 5: nil, + } + + repulsion = []intset{ + 0: linksTo(3, 4, 5), + 1: linksTo(3, 4, 5), + 2: linksTo(3, 4, 5), + 3: linksTo(0, 1, 2), + 4: linksTo(0, 1, 2), + 5: linksTo(0, 1, 2), + } + + simpleDirected = []intset{ + 0: linksTo(1), + 1: linksTo(0, 4), + 2: linksTo(1), + 3: linksTo(0, 4), + 4: linksTo(2), + } + + // http://www.slate.com/blogs/the_world_/2014/07/17/the_middle_east_friendship_chart.html + middleEast = struct{ friends, complicated, enemies []intset }{ + // green cells + friends: []intset{ + 0: nil, + 1: linksTo(5, 7, 9, 12), + 2: linksTo(11), + 3: linksTo(4, 5, 10), + 4: linksTo(3, 5, 10), + 5: linksTo(1, 3, 4, 8, 10, 12), + 6: nil, + 7: linksTo(1, 12), + 8: linksTo(5, 9, 11), + 9: linksTo(1, 8, 12), + 10: linksTo(3, 4, 5), + 11: linksTo(2, 8), + 12: linksTo(1, 5, 7, 9), + }, + + // yellow cells + complicated: []intset{ + 0: linksTo(2, 4), + 1: linksTo(4, 8), + 2: linksTo(0, 3, 4, 5, 8, 9), + 3: linksTo(2, 8, 11), + 4: linksTo(0, 1, 2, 8), + 5: linksTo(2), + 6: nil, + 7: linksTo(9, 11), + 8: linksTo(1, 2, 3, 4, 10, 12), + 9: linksTo(2, 7, 11), + 10: linksTo(8), + 11: linksTo(3, 7, 9, 12), + 12: linksTo(8, 11), + }, + + // red cells + enemies: []intset{ + 0: linksTo(1, 3, 5, 6, 7, 8, 9, 10, 11, 12), + 1: linksTo(0, 2, 3, 6, 10, 11), + 2: linksTo(1, 6, 7, 10, 12), + 3: linksTo(0, 1, 6, 7, 9, 12), + 4: linksTo(6, 7, 9, 11, 12), + 5: linksTo(0, 6, 7, 9, 11), + 6: linksTo(0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12), + 7: linksTo(0, 2, 3, 4, 5, 6, 8, 10), + 8: linksTo(0, 6, 7), + 9: linksTo(0, 3, 4, 5, 6, 10), + 10: linksTo(0, 1, 2, 6, 7, 9, 11, 12), + 11: linksTo(0, 1, 4, 5, 6, 10), + 12: linksTo(0, 2, 3, 4, 6, 10), + }, + } + + // W. W. Zachary, An information flow model for conflict and fission in small groups, + // Journal of Anthropological Research 33, 452-473 (1977). + // + // The edge list here is constructed such that all link descriptions + // head from a node with lower Page Rank to a node with higher Page + // Rank. This has no impact on undirected tests, but allows a sensible + // view for directed tests. + zachary = []intset{ + 0: nil, // rank=0.097 + 1: linksTo(0, 2), // rank=0.05288 + 2: linksTo(0, 32), // rank=0.05708 + 3: linksTo(0, 1, 2), // rank=0.03586 + 4: linksTo(0, 6, 10), // rank=0.02198 + 5: linksTo(0, 6), // rank=0.02911 + 6: linksTo(0, 5), // rank=0.02911 + 7: linksTo(0, 1, 2, 3), // rank=0.02449 + 8: linksTo(0, 2, 32, 33), // rank=0.02977 + 9: linksTo(2, 33), // rank=0.01431 + 10: linksTo(0, 5), // rank=0.02198 + 11: linksTo(0), // rank=0.009565 + 12: linksTo(0, 3), // rank=0.01464 + 13: linksTo(0, 1, 2, 3, 33), // rank=0.02954 + 14: linksTo(32, 33), // rank=0.01454 + 15: linksTo(32, 33), // rank=0.01454 + 16: linksTo(5, 6), // rank=0.01678 + 17: linksTo(0, 1), // rank=0.01456 + 18: linksTo(32, 33), // rank=0.01454 + 19: linksTo(0, 1, 33), // rank=0.0196 + 20: linksTo(32, 33), // rank=0.01454 + 21: linksTo(0, 1), // rank=0.01456 + 22: linksTo(32, 33), // rank=0.01454 + 23: linksTo(32, 33), // rank=0.03152 + 24: linksTo(27, 31), // rank=0.02108 + 25: linksTo(23, 24, 31), // rank=0.02101 + 26: linksTo(29, 33), // rank=0.01504 + 27: linksTo(2, 23, 33), // rank=0.02564 + 28: linksTo(2, 31, 33), // rank=0.01957 + 29: linksTo(23, 32, 33), // rank=0.02629 + 30: linksTo(1, 8, 32, 33), // rank=0.02459 + 31: linksTo(0, 32, 33), // rank=0.03716 + 32: linksTo(33), // rank=0.07169 + 33: nil, // rank=0.1009 + } + + // doi:10.1088/1742-5468/2008/10/P10008 figure 1 + // + // The edge list here is constructed such that all link descriptions + // head from a node with lower Page Rank to a node with higher Page + // Rank. This has no impact on undirected tests, but allows a sensible + // view for directed tests. + blondel = []intset{ + 0: linksTo(2), // rank=0.06858 + 1: linksTo(2, 4, 7), // rank=0.05264 + 2: nil, // rank=0.08249 + 3: linksTo(0, 7), // rank=0.03884 + 4: linksTo(0, 2, 10), // rank=0.06754 + 5: linksTo(0, 2, 7, 11), // rank=0.06738 + 6: linksTo(2, 7, 11), // rank=0.0528 + 7: nil, // rank=0.07008 + 8: linksTo(10), // rank=0.09226 + 9: linksTo(8), // rank=0.05821 + 10: nil, // rank=0.1035 + 11: linksTo(8, 10), // rank=0.08538 + 12: linksTo(9, 10), // rank=0.04052 + 13: linksTo(10, 11), // rank=0.03855 + 14: linksTo(8, 9, 10), // rank=0.05621 + 15: linksTo(8), // rank=0.02506 + } +) + +type structure struct { + resolution float64 + memberships []intset + want, tol float64 +} + +type level struct { + q float64 + communities [][]graph.Node +} + +type moveStructures struct { + memberships []intset + targetNodes []graph.Node + + resolution float64 + tol float64 +} + +func reverse(f []float64) { + for i, j := 0, len(f)-1; i < j; i, j = i+1, j-1 { + f[i], f[j] = f[j], f[i] + } +} + +func hasNegative(f []float64) bool { + for _, v := range f { + if v < 0 { + return true + } + } + return false +} + +var ( + dupGraph = simple.NewUndirectedGraph() + dupGraphDirected = simple.NewDirectedGraph() +) + +func init() { + err := gen.Duplication(dupGraph, 1000, 0.8, 0.1, 0.5, rand.New(rand.NewSource(1))) + if err != nil { + panic(err) + } + + // Construct a directed graph from dupGraph + // such that every edge dupGraph is replaced + // with an edge that flows from the low node + // ID to the high node ID. + for _, e := range dupGraph.Edges() { + if e.To().ID() < e.From().ID() { + se := e.(simple.Edge) + se.F, se.T = se.T, se.F + e = se + } + dupGraphDirected.SetEdge(e) + } +} + +// This init function checks the Middle East relationship data. +func init() { + world := make([]intset, len(middleEast.friends)) + for i := range world { + world[i] = make(intset) + } + for _, relationships := range [][]intset{middleEast.friends, middleEast.complicated, middleEast.enemies} { + for i, rel := range relationships { + for inter := range rel { + if _, ok := world[i][inter]; ok { + panic(fmt.Sprintf("unexpected relationship: %v--%v", i, inter)) + } + world[i][inter] = struct{}{} + } + } + } + for i := range world { + if len(world[i]) != len(middleEast.friends)-1 { + panic(fmt.Sprintf("missing relationship in %v: %v", i, world[i])) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected.go new file mode 100644 index 00000000..450a438c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected.go @@ -0,0 +1,590 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// qUndirected returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// qUndirected will panic if g has any edge with negative edge weight. +// +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j) +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func qUndirected(g graph.Undirected, communities [][]graph.Node, resolution float64) float64 { + nodes := g.Nodes() + weight := positiveWeightFuncFor(g) + + // Calculate the total edge weight of the graph + // and the table of penetrating edge weight sums. + var m2 float64 + k := make(map[int64]float64, len(nodes)) + for _, u := range nodes { + w := weight(u, u) + for _, v := range g.From(u) { + w += weight(u, v) + } + m2 += w + k[u.ID()] = w + } + + if communities == nil { + var q float64 + for _, u := range nodes { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU*kU/m2 + } + return q / m2 + } + + // Iterate over the communities, calculating + // the non-self edge weights for the upper + // triangle and adjust the diagonal. + var q float64 + for _, c := range communities { + for i, u := range c { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU*kU/m2 + for _, v := range c[i+1:] { + q += 2 * (weight(u, v) - resolution*kU*k[v.ID()]/m2) + } + } + } + return q / m2 +} + +// louvainUndirected returns the hierarchical modularization of g at the given +// resolution using the Louvain algorithm. If src is nil, rand.Intn is used as +// the random generator. louvainUndirected will panic if g has any edge with negative edge +// weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainUndirected(g graph.Undirected, resolution float64, src *rand.Rand) *ReducedUndirected { + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceUndirected(g, nil) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newUndirectedLocalMover(c, c.communities, resolution) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceUndirected(c, l.communities) + } +} + +// ReducedUndirected is an undirected graph of communities derived from a +// parent graph by reduction. +type ReducedUndirected struct { + // nodes is the set of nodes held + // by the graph. In a ReducedUndirected + // the node ID is the index into + // nodes. + nodes []community + undirectedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedUndirected +} + +var ( + reducedUndirected = (*ReducedUndirected)(nil) + + _ graph.WeightedUndirected = reducedUndirected + _ ReducedGraph = reducedUndirected +) + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedUndirected) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedUndirected) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedUndirected) Expanded() ReducedGraph { + return g.parent +} + +// reduceUndirected returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceUndirected. If communities is nil and g is a +// ReducedUndirected, it is returned unaltered. +func reduceUndirected(g graph.Undirected, communities [][]graph.Node) *ReducedUndirected { + if communities == nil { + if r, ok := g.(*ReducedUndirected); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + weight := positiveWeightFuncFor(g) + r := ReducedUndirected{ + nodes: make([]community, len(nodes)), + undirectedEdges: undirectedEdges{ + edges: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + }, + communities: communities, + } + communityOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = community{id: i, nodes: []graph.Node{n}} + communityOf[n.ID()] = i + } + for _, u := range nodes { + var out []int + uid := communityOf[u.ID()] + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + if vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.weights[[2]int{uid, vid}] = weight(u, v) + } + } + r.edges[uid] = out + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedUndirected{ + nodes: make([]community, len(communities)), + undirectedEdges: undirectedEdges{ + edges: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + }, + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedUndirected); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + weight := positiveWeightFuncFor(g) + communityOf := make(map[int64]int, commNodes) + for i, comm := range communities { + r.nodes[i] = community{id: i, nodes: comm} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for uid, comm := range communities { + var out []int + for i, u := range comm { + r.nodes[uid].weight += weight(u, u) + for _, v := range comm[i+1:] { + r.nodes[uid].weight += 2 * weight(u, v) + } + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.weights[[2]int{uid, vid}] += weight(u, v) + } + } + } + r.edges[uid] = out + } + return &r +} + +// Has returns whether the node exists within the graph. +func (g *ReducedUndirected) Has(n graph.Node) bool { + id := n.ID() + return 0 <= id || id < int64(len(g.nodes)) +} + +// Nodes returns all the nodes in the graph. +func (g *ReducedUndirected) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g *ReducedUndirected) From(u graph.Node) []graph.Node { + out := g.edges[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.nodes[vid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *ReducedUndirected) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return false + } + if xid > yid { + xid, yid = yid, xid + } + _, ok := g.weights[[2]int{int(xid), int(yid)}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedUndirected) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedUndirected) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return g.WeightedEdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *ReducedUndirected) EdgeBetween(x, y graph.Node) graph.Edge { + return g.WeightedEdgeBetween(x, y) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g *ReducedUndirected) WeightedEdgeBetween(x, y graph.Node) graph.WeightedEdge { + xid := x.ID() + yid := y.ID() + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return nil + } + if yid < xid { + xid, yid = yid, xid + } + w, ok := g.weights[[2]int{int(xid), int(yid)}] + if !ok { + return nil + } + return edge{from: g.nodes[x.ID()], to: g.nodes[y.ID()], weight: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *ReducedUndirected) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if !isValidID(xid) || !isValidID(yid) { + return 0, false + } + if xid == yid { + return g.nodes[xid].weight, true + } + if xid > yid { + xid, yid = yid, xid + } + w, ok = g.weights[[2]int{int(xid), int(yid)}] + return w, ok +} + +// undirectedLocalMover is a step in graph modularity optimization. +type undirectedLocalMover struct { + g *ReducedUndirected + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightOf is the weighted degree + // of each node indexed by ID. + edgeWeightOf []float64 + + // m2 is the total sum of + // edge weights in g. + m2 float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolution float64 + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newUndirectedLocalMover returns a new undirectedLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newUndirectedLocalMover(g *ReducedUndirected, communities [][]graph.Node, resolution float64) *undirectedLocalMover { + nodes := g.Nodes() + l := undirectedLocalMover{ + g: g, + nodes: nodes, + edgeWeightOf: make([]float64, len(nodes)), + communities: communities, + memberships: make([]int, len(nodes)), + resolution: resolution, + weight: positiveWeightFuncFor(g), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + for _, u := range l.nodes { + w := l.weight(u, u) + for _, v := range g.From(u) { + w += l.weight(u, v) + } + l.edgeWeightOf[u.ID()] = w + l.m2 += w + } + if l.m2 == 0 { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, u := range c { + l.memberships[u.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// undirectedLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *undirectedLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// undirectedLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *undirectedLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *undirectedLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// undirectedLocalMover's communities field is returned in src if n +// is in communities. +func (l *undirectedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + a_aa := l.weight(n, n) + k_a := l.edgeWeightOf[id] + m2 := l.m2 + gamma := l.resolution + + // Find communities connected to n. + connected := make(set.Ints) + // The following for loop is equivalent to: + // + // for _, v := range l.g.From(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // + // This is done to avoid an allocation. + for _, vid := range l.g.edges[id] { + connected.Add(l.memberships[vid]) + } + // Insert the node's own community. + connected.Add(l.memberships[id]) + + candidates := make([]int, 0, len(connected)) + for i := range connected { + candidates = append(candidates, i) + } + sort.Ints(candidates) + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + for _, i := range candidates { + c := l.communities[i] + var k_aC, sigma_totC float64 // C is a substitution for ^𝛼 or ^𝛽. + var removal bool + for j, u := range c { + uid := u.ID() + if uid == id { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + removal = true + } + + k_aC += l.weight(n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + sigma_totC += l.edgeWeightOf[uid] + } + + // See louvain.tex for a derivation of these equations. + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove = k_aC /*^𝛼*/ - a_aa - gamma*k_a*(sigma_totC /*^𝛼*/ -k_a)/m2 + + default: + // Otherwise calculate the change due to an addition + // to c and retain if it is the current best. + dQ := k_aC /*^𝛽*/ - gamma*k_a*sigma_totC /*^𝛽*/ /m2 + if dQ > dQadd { + dQadd = dQ + dst = i + } + } + } + + return 2 * (dQadd - dQremove) / m2, dst, src +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex.go new file mode 100644 index 00000000..23799522 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex.go @@ -0,0 +1,826 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// UndirectedMultiplex is an undirected multiplex graph. +type UndirectedMultiplex interface { + Multiplex + + // Layer returns the lth layer of the + // multiplex graph. + Layer(l int) graph.Undirected +} + +// qUndirectedMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// qUndirectedMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j) +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func qUndirectedMultiplex(g UndirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + q := make([]float64, g.Depth()) + nodes := g.Nodes() + layerWeight := 1.0 + layerResolution := 1.0 + if len(resolutions) == 1 { + layerResolution = resolutions[0] + } + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + + if weights != nil { + layerWeight = weights[l] + } + if layerWeight == 0 { + continue + } + + if len(resolutions) > 1 { + layerResolution = resolutions[l] + } + + var weight func(x, y graph.Node) float64 + if layerWeight < 0 { + weight = negativeWeightFuncFor(layer) + } else { + weight = positiveWeightFuncFor(layer) + } + + // Calculate the total edge weight of the layer + // and the table of penetrating edge weight sums. + var m2 float64 + k := make(map[int64]float64, len(nodes)) + for _, u := range nodes { + w := weight(u, u) + for _, v := range layer.From(u) { + w += weight(u, v) + } + m2 += w + k[u.ID()] = w + } + + if communities == nil { + var qLayer float64 + for _, u := range nodes { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU*kU/m2 + } + q[l] = layerWeight * qLayer + continue + } + + // Iterate over the communities, calculating + // the non-self edge weights for the upper + // triangle and adjust the diagonal. + var qLayer float64 + for _, c := range communities { + for i, u := range c { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU*kU/m2 + for _, v := range c[i+1:] { + qLayer += 2 * (weight(u, v) - layerResolution*kU*k[v.ID()]/m2) + } + } + } + q[l] = layerWeight * qLayer + } + + return q +} + +// UndirectedLayers implements UndirectedMultiplex. +type UndirectedLayers []graph.Undirected + +// NewUndirectedLayers returns an UndirectedLayers using the provided layers +// ensuring there is a match between IDs for each layer. +func NewUndirectedLayers(layers ...graph.Undirected) (UndirectedLayers, error) { + if len(layers) == 0 { + return nil, nil + } + base := make(set.Int64s) + for _, n := range layers[0].Nodes() { + base.Add(n.ID()) + } + for i, l := range layers[1:] { + next := make(set.Int64s) + for _, n := range l.Nodes() { + next.Add(n.ID()) + } + if !set.Int64sEqual(next, base) { + return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1) + } + } + return layers, nil +} + +// Nodes returns the nodes of the receiver. +func (g UndirectedLayers) Nodes() []graph.Node { + if len(g) == 0 { + return nil + } + return g[0].Nodes() +} + +// Depth returns the depth of the multiplex graph. +func (g UndirectedLayers) Depth() int { return len(g) } + +// Layer returns the lth layer of the multiplex graph. +func (g UndirectedLayers) Layer(l int) graph.Undirected { return g[l] } + +// louvainUndirectedMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g has negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. louvainUndirectedMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainUndirectedMultiplex(g UndirectedMultiplex, weights, resolutions []float64, all bool, src *rand.Rand) *ReducedUndirectedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceUndirectedMultiplex(g, nil, weights) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newUndirectedMultiplexLocalMover(c, c.communities, weights, resolutions, all) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceUndirectedMultiplex(c, l.communities, weights) + } +} + +// ReducedUndirectedMultiplex is an undirected graph of communities derived from a +// parent graph by reduction. +type ReducedUndirectedMultiplex struct { + // nodes is the set of nodes held + // by the graph. In a ReducedUndirectedMultiplex + // the node ID is the index into + // nodes. + nodes []multiplexCommunity + layers []undirectedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedUndirectedMultiplex +} + +var ( + _ UndirectedMultiplex = (*ReducedUndirectedMultiplex)(nil) + _ graph.WeightedUndirected = (*undirectedLayerHandle)(nil) +) + +// Nodes returns all the nodes in the graph. +func (g *ReducedUndirectedMultiplex) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// Depth returns the number of layers in the multiplex graph. +func (g *ReducedUndirectedMultiplex) Depth() int { return len(g.layers) } + +// Layer returns the lth layer of the multiplex graph. +func (g *ReducedUndirectedMultiplex) Layer(l int) graph.Undirected { + return undirectedLayerHandle{multiplex: g, layer: l} +} + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedUndirectedMultiplex) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedUndirectedMultiplex) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedUndirectedMultiplex) Expanded() ReducedMultiplex { + return g.parent +} + +// reduceUndirectedMultiplex returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceUndirectedMultiplex. If communities is nil and g is a +// ReducedUndirectedMultiplex, it is returned unaltered. +func reduceUndirectedMultiplex(g UndirectedMultiplex, communities [][]graph.Node, weights []float64) *ReducedUndirectedMultiplex { + if communities == nil { + if r, ok := g.(*ReducedUndirectedMultiplex); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + r := ReducedUndirectedMultiplex{ + nodes: make([]multiplexCommunity, len(nodes)), + layers: make([]undirectedEdges, g.Depth()), + communities: communities, + } + communityOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = multiplexCommunity{id: i, nodes: []graph.Node{n}, weights: make([]float64, depth(weights))} + communityOf[n.ID()] = i + } + for i := range r.layers { + r.layers[i] = undirectedEdges{ + edges: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + } + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for _, u := range nodes { + var out []int + uid := communityOf[u.ID()] + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + if vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.layers[l].weights[[2]int{uid, vid}] = sign * weight(u, v) + } + } + r.layers[l].edges[uid] = out + } + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedUndirectedMultiplex{ + nodes: make([]multiplexCommunity, len(communities)), + layers: make([]undirectedEdges, g.Depth()), + } + communityOf := make(map[int64]int, commNodes) + for i, comm := range communities { + r.nodes[i] = multiplexCommunity{id: i, nodes: comm, weights: make([]float64, depth(weights))} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for i := range r.layers { + r.layers[i] = undirectedEdges{ + edges: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + } + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedUndirectedMultiplex); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for uid, comm := range communities { + var out []int + for i, u := range comm { + r.nodes[uid].weights[l] += sign * weight(u, u) + for _, v := range comm[i+1:] { + r.nodes[uid].weights[l] += 2 * sign * weight(u, v) + } + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.layers[l].weights[[2]int{uid, vid}] += sign * weight(u, v) + } + } + } + r.layers[l].edges[uid] = out + } + } + return &r +} + +// undirectedLayerHandle is a handle to a multiplex graph layer. +type undirectedLayerHandle struct { + // multiplex is the complete + // multiplex graph. + multiplex *ReducedUndirectedMultiplex + + // layer is an index into the + // multiplex for the current + // layer. + layer int +} + +// Has returns whether the node exists within the graph. +func (g undirectedLayerHandle) Has(n graph.Node) bool { + id := n.ID() + return 0 <= id && id < int64(len(g.multiplex.nodes)) +} + +// Nodes returns all the nodes in the graph. +func (g undirectedLayerHandle) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.multiplex.nodes)) + for i := range g.multiplex.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g undirectedLayerHandle) From(u graph.Node) []graph.Node { + out := g.multiplex.layers[g.layer].edges[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.multiplex.nodes[vid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g undirectedLayerHandle) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return false + } + if xid > yid { + xid, yid = yid, xid + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{int(xid), int(yid)}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g undirectedLayerHandle) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g undirectedLayerHandle) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return g.WeightedEdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g undirectedLayerHandle) EdgeBetween(x, y graph.Node) graph.Edge { + return g.WeightedEdgeBetween(x, y) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g undirectedLayerHandle) WeightedEdgeBetween(x, y graph.Node) graph.WeightedEdge { + xid := x.ID() + yid := y.ID() + if xid == yid || !isValidID(xid) || !isValidID(yid) { + return nil + } + if yid < xid { + xid, yid = yid, xid + } + w, ok := g.multiplex.layers[g.layer].weights[[2]int{int(xid), int(yid)}] + if !ok { + return nil + } + return multiplexEdge{from: g.multiplex.nodes[x.ID()], to: g.multiplex.nodes[y.ID()], weight: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g undirectedLayerHandle) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if !isValidID(xid) || !isValidID(yid) { + return 0, false + } + if xid == yid { + return g.multiplex.nodes[xid].weights[g.layer], true + } + if xid > yid { + xid, yid = yid, xid + } + w, ok = g.multiplex.layers[g.layer].weights[[2]int{int(xid), int(yid)}] + return w, ok +} + +// undirectedMultiplexLocalMover is a step in graph modularity optimization. +type undirectedMultiplexLocalMover struct { + g *ReducedUndirectedMultiplex + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightOf is the weighted degree + // of each node indexed by ID. + edgeWeightOf [][]float64 + + // m2 is the total sum of + // edge weights in g. + m2 []float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight []func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolutions []float64 + + // weights is the layer weights for + // the modularisation. + weights []float64 + + // searchAll specifies whether the local + // mover should consider non-connected + // communities during the local moving + // heuristic. + searchAll bool + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newUndirectedMultiplexLocalMover returns a new undirectedMultiplexLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newUndirectedMultiplexLocalMover(g *ReducedUndirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64, all bool) *undirectedMultiplexLocalMover { + nodes := g.Nodes() + l := undirectedMultiplexLocalMover{ + g: g, + nodes: nodes, + edgeWeightOf: make([][]float64, g.Depth()), + m2: make([]float64, g.Depth()), + communities: communities, + memberships: make([]int, len(nodes)), + resolutions: resolutions, + weights: weights, + weight: make([]func(x, y graph.Node) float64, g.Depth()), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + var zero int + for i := 0; i < g.Depth(); i++ { + l.edgeWeightOf[i] = make([]float64, len(nodes)) + var weight func(x, y graph.Node) float64 + + if weights != nil { + if weights[i] == 0 { + zero++ + continue + } + if weights[i] < 0 { + weight = negativeWeightFuncFor(g.Layer(i)) + l.searchAll = all + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + + l.weight[i] = weight + layer := g.Layer(i) + for _, u := range l.nodes { + w := weight(u, u) + for _, v := range layer.From(u) { + w += weight(u, v) + } + l.edgeWeightOf[i][u.ID()] = w + l.m2[i] += w + } + if l.m2[i] == 0 { + zero++ + } + } + if zero == g.Depth() { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, u := range c { + l.memberships[u.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// undirectedMultiplexLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *undirectedMultiplexLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// undirectedMultiplexLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *undirectedMultiplexLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *undirectedMultiplexLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// undirectedMultiplexLocalMover's communities field is returned in src if n +// is in communities. +func (l *undirectedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + var iterator minTaker + if l.searchAll { + iterator = &dense{n: len(l.communities)} + } else { + // Find communities connected to n. + connected := make(set.Ints) + // The following for loop is equivalent to: + // + // for i := 0; i < l.g.Depth(); i++ { + // for _, v := range l.g.Layer(i).From(n) { + // connected.Add(l.memberships[v.ID()]) + // } + // } + // + // This is done to avoid an allocation for + // each layer. + for _, layer := range l.g.layers { + for _, vid := range layer.edges[id] { + connected.Add(l.memberships[vid]) + } + } + // Insert the node's own community. + connected.Add(l.memberships[id]) + iterator = newSlice(connected) + } + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for iterator.TakeMin(&i) { + c := l.communities[i] + var removal bool + var _dQadd float64 + for layer := 0; layer < l.g.Depth(); layer++ { + m2 := l.m2[layer] + if m2 == 0 { + // Do not consider layers with zero sum edge weight. + continue + } + w := 1.0 + if l.weights != nil { + w = l.weights[layer] + } + if w == 0 { + // Do not consider layers with zero weighting. + continue + } + + var k_aC, sigma_totC float64 // C is a substitution for ^𝛼 or ^𝛽. + removal = false + for j, u := range c { + uid := u.ID() + if uid == id { + // Only mark and check src community on the first layer. + if layer == 0 { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + } + removal = true + } + + k_aC += l.weight[layer](n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + sigma_totC += l.edgeWeightOf[layer][uid] + } + + a_aa := l.weight[layer](n, n) + k_a := l.edgeWeightOf[layer][id] + gamma := 1.0 + if l.resolutions != nil { + if len(l.resolutions) == 1 { + gamma = l.resolutions[0] + } else { + gamma = l.resolutions[layer] + } + } + + // See louvain.tex for a derivation of these equations. + // The weighting term, w, is described in V Traag, + // "Algorithms and dynamical models for communities and + // reputation in social networks", chapter 5. + // http://www.traag.net/wp/wp-content/papercite-data/pdf/traag_algorithms_2013.pdf + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove += w * (k_aC /*^𝛼*/ - a_aa - gamma*k_a*(sigma_totC /*^𝛼*/ -k_a)/m2) + + default: + // Otherwise calculate the change due to an addition + // to c. + _dQadd += w * (k_aC /*^𝛽*/ - gamma*k_a*sigma_totC /*^𝛽*/ /m2) + } + } + if !removal && _dQadd > dQadd { + dQadd = _dQadd + dst = i + } + } + + return 2 * (dQadd - dQremove), dst, src +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex_test.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex_test.go new file mode 100644 index 00000000..6f593777 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_multiplex_test.go @@ -0,0 +1,691 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityUndirectedMultiplexQTests = []struct { + name string + layers []layer + structures []structure + + wantLevels []level +}{ + { + name: "unconnected", + layers: []layer{{g: unconnected, weight: 1}}, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell", + layers: []layer{ + {g: smallDumbell, edgeWeight: 1, weight: 1}, + {g: dumbellRepulsion, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 7.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 7.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -1.4285714285714284, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell_twice", + layers: []layer{ + {g: smallDumbell, weight: 0.5}, + {g: smallDumbell, weight: 0.5}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 5, tol: 1e-10, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 0.35714285714285715 * 14, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.17346938775510204 * 14, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "repulsion", + layers: []layer{{g: repulsion, edgeWeight: -1, weight: -1}}, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 9.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: 3, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 9.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: 3.0, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "middle_east", + layers: []layer{ + {g: middleEast.friends, edgeWeight: 1, weight: 1}, + {g: middleEast.enemies, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 6), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(2, 8, 11), + 3: linksTo(3, 4, 5, 10), + }, + want: 33.8180574555, tol: 1e-9, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 2, 3, 4, 5, 10), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(6), + 3: linksTo(8, 11), + }, + want: 30.92749658, tol: 1e-7, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 33.818057455540355, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(6)}, + {simple.Node(1), simple.Node(7), simple.Node(9), simple.Node(12)}, + {simple.Node(2), simple.Node(8), simple.Node(11)}, + {simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(10)}, + }, + }, + { + q: 3.8071135430916545, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + }, + }, + }, + }, +} + +func TestCommunityQUndirectedMultiplex(t *testing.T) { + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + q := QMultiplex(g, communities, weights, []float64{structure.resolution}) + got := floats.Sum(q) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v %.3v want: %v", + test.name, communities, got, q, structure.want) + } + } + } +} + +func TestCommunityDeltaQUndirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int64]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + resolution := []float64{structure.resolution} + + before := QMultiplex(g, communities, weights, resolution) + + // We test exhaustively. + const all = true + + l := newUndirectedMultiplexLocalMover( + reduceUndirectedMultiplex(g, nil, weights), + communities, weights, resolution, all) + if l == nil { + if !math.IsNaN(floats.Sum(before)) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + if !(all && hasNegative(weights)) { + connected := false + search: + for l := 0; l < g.Depth(); l++ { + if weights[l] < 0 { + connected = true + break search + } + layer := g.Layer(l) + for n := range c { + if layer.HasEdgeBetween(simple.Node(n), target) { + connected = true + break search + } + } + } + if !connected { + continue + } + } + migrated[i] = append(migrated[i], target) + after := QMultiplex(g, migrated, weights, resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if delta := floats.Sum(after) - floats.Sum(before); delta > want { + want = delta + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyUndirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := QMultiplex(g, communities, weights, []float64{structure.resolution}) + gQnull := QMultiplex(g, nil, weights, nil) + + cg0 := reduceUndirectedMultiplex(g, nil, weights) + cg0Qnull := QMultiplex(cg0, cg0.Structure(), weights, nil) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQnull), floats.Sum(cg0Qnull), structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := QMultiplex(cg0, communities, weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg0Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceUndirectedMultiplex(cg0, communities, weights) + cg1Q := QMultiplex(cg1, cg1.Structure(), weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg1Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localUndirectedMultiplexMoveTests = []struct { + name string + layers []layer + structures []moveStructures +}{ + { + name: "blondel", + layers: []layer{{g: blondel, weight: 1}, {g: blondel, weight: 0.5}}, + structures: []moveStructures{ + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalUndirectedMultiplex(t *testing.T) { + for _, test := range localUndirectedMultiplexMoveTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceUndirectedMultiplex(reduceUndirectedMultiplex(g, nil, weights), communities, weights) + + l := newUndirectedMultiplexLocalMover(r, r.communities, weights, []float64{structure.resolution}, true) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + l.move(dst, src) + after := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestLouvainMultiplex(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedUndirectedMultiplex + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := ModularizeMultiplex(g, weights, nil, true, src).(*ReducedUndirectedMultiplex) + if q := floats.Sum(QMultiplex(r, nil, weights, nil)); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedUndirectedMultiplex) { + qs = append(qs, floats.Sum(QMultiplex(p, nil, weights, nil))) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedUndirectedMultiplex) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceUndirectedMultiplex(g, nil, weights).Communities() + } + q := floats.Sum(QMultiplex(p, nil, weights, nil)) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousUndirectedMultiplex(t *testing.T) { + g := simple.NewUndirectedGraph() + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1)}, + {F: simple.Node(4), T: simple.Node(5)}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(UndirectedLayers{g}, nil, nil, true, nil) + }() +} + +func TestNonContiguousWeightedUndirectedMultiplex(t *testing.T) { + g := simple.NewWeightedUndirectedGraph(0, 0) + for _, e := range []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetWeightedEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(UndirectedLayers{g}, nil, nil, true, nil) + }() +} + +func BenchmarkLouvainMultiplex(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + ModularizeMultiplex(UndirectedLayers{dupGraph}, nil, nil, true, src) + } +} + +func undirectedMultiplexFrom(raw []layer) (UndirectedLayers, []float64, error) { + var layers []graph.Undirected + var weights []float64 + for _, l := range raw { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range l.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + w := 1.0 + if l.edgeWeight != 0 { + w = l.edgeWeight + } + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: w}) + } + } + layers = append(layers, g) + weights = append(weights, l.weight) + } + g, err := NewUndirectedLayers(layers...) + if err != nil { + return nil, nil, err + } + return g, weights, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_test.go b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_test.go new file mode 100644 index 00000000..b9a87722 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/louvain_undirected_test.go @@ -0,0 +1,778 @@ +// Copyright ©2015 The gonum 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 community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +type communityUndirectedQTest struct { + name string + g []intset + structures []structure + + wantLevels []level +} + +var communityUndirectedQTests = []communityUndirectedQTest{ + // The java reference implementation is available from http://www.ludowaltman.nl/slm/. + { + name: "unconnected", + g: unconnected, + structures: []structure{ + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell", + g: smallDumbell, + structures: []structure{ + { + resolution: 1, + // community structure and modularity calculated by java reference implementation. + memberships: []intset{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 0.357, tol: 1e-3, + }, + { + resolution: 1, + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + // theoretical expectation. + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 0.35714285714285715, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.17346938775510204, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "zachary", + g: zachary, + structures: []structure{ + { + resolution: 1, + // community structure and modularity from doi: 10.1140/epjb/e2013-40829-0 + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21), + 1: linksTo(4, 5, 6, 10, 16), + 2: linksTo(8, 9, 14, 15, 18, 20, 22, 26, 29, 30, 32, 33), + 3: linksTo(23, 24, 25, 27, 28, 31), + }, + // Noted to be the optimal modularisation in the paper above. + want: 0.4198, tol: 1e-4, + }, + { + resolution: 0.5, + // community structure and modularity calculated by java reference implementation. + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 16, 17, 19, 21), + 1: linksTo(8, 14, 15, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33), + }, + want: 0.6218, tol: 1e-3, + }, + { + resolution: 2, + // community structure and modularity calculated by java reference implementation. + memberships: []intset{ + 0: linksTo(14, 18, 20, 22, 32, 33, 15), + 1: linksTo(0, 1, 11, 17, 19, 21), + 2: linksTo(2, 3, 7, 9, 12, 13), + 3: linksTo(4, 5, 6, 10, 16), + 4: linksTo(24, 25, 28, 31), + 5: linksTo(23, 26, 27, 29), + 6: linksTo(8, 30), + }, + want: 0.1645, tol: 1e-3, + }, + }, + wantLevels: []level{ + { + q: 0.4197896120973044, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(10), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: 0.39907955292570674, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(10)}, + {simple.Node(5), simple.Node(6), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: -0.04980276134122286, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + {simple.Node(16)}, + {simple.Node(17)}, + {simple.Node(18)}, + {simple.Node(19)}, + {simple.Node(20)}, + {simple.Node(21)}, + {simple.Node(22)}, + {simple.Node(23)}, + {simple.Node(24)}, + {simple.Node(25)}, + {simple.Node(26)}, + {simple.Node(27)}, + {simple.Node(28)}, + {simple.Node(29)}, + {simple.Node(30)}, + {simple.Node(31)}, + {simple.Node(32)}, + {simple.Node(33)}, + }, + }, + }, + }, + { + name: "blondel", + g: blondel, + structures: []structure{ + { + resolution: 1, + // community structure and modularity calculated by java reference implementation. + memberships: []intset{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7), + 1: linksTo(8, 9, 10, 11, 12, 13, 14, 15), + }, + want: 0.3922, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.39221938775510207, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(14), simple.Node(15)}, + }, + }, + { + q: 0.34630102040816324, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(4), simple.Node(5)}, + {simple.Node(3), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(12), simple.Node(14), simple.Node(15)}, + {simple.Node(11), simple.Node(13)}, + }, + }, + { + q: -0.07142857142857144, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + }, + }, + }, + }, +} + +func TestCommunityQUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testCommunityQUndirected(t, test, g) + } +} + +func TestCommunityQWeightedUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testCommunityQUndirected(t, test, g) + } +} + +func testCommunityQUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) { + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + got := Q(g, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v want: %v", + test.name, communities, got, structure.want) + } + } +} + +func TestCommunityDeltaQUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testCommunityDeltaQUndirected(t, test, g) + } +} + +func TestCommunityDeltaQWeightedUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testCommunityDeltaQUndirected(t, test, g) + } +} + +func testCommunityDeltaQUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) { + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int64]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + before := Q(g, communities, structure.resolution) + + l := newUndirectedLocalMover(reduceUndirected(g, nil), communities, structure.resolution) + if l == nil { + if !math.IsNaN(before) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + return + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + n := int64(n) + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + connected := false + for n := range c { + if g.HasEdgeBetween(simple.Node(n), target) { + connected = true + break + } + } + if !connected { + continue + } + migrated[i] = append(migrated[i], target) + after := Q(g, migrated, structure.resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if after-before > want { + want = after - before + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } +} + +func TestReduceQConsistencyUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testReduceQConsistencyUndirected(t, test, g) + } +} + +func TestReduceQConsistencyWeightedUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testReduceQConsistencyUndirected(t, test, g) + } +} + +func testReduceQConsistencyUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) { + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + return + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := Q(g, communities, structure.resolution) + gQnull := Q(g, nil, 1) + + cg0 := reduceUndirected(g, nil) + cg0Qnull := Q(cg0, cg0.Structure(), 1) + if !floats.EqualWithinAbsOrRel(gQnull, cg0Qnull, structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := Q(cg0, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg0Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceUndirected(cg0, communities) + cg1Q := Q(cg1, cg1.Structure(), structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg1Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } +} + +type localUndirectedMoveTest struct { + name string + g []intset + structures []moveStructures +} + +var localUndirectedMoveTests = []localUndirectedMoveTest{ + { + name: "blondel", + g: blondel, + structures: []moveStructures{ + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []intset{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalUndirected(t *testing.T) { + for _, test := range localUndirectedMoveTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testMoveLocalUndirected(t, test, g) + } +} + +func TestMoveLocalWeightedUndirected(t *testing.T) { + for _, test := range localUndirectedMoveTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testMoveLocalUndirected(t, test, g) + } +} + +func testMoveLocalUndirected(t *testing.T, test localUndirectedMoveTest, g graph.Undirected) { + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceUndirected(reduceUndirected(g, nil), communities) + + l := newUndirectedLocalMover(r, r.communities, structure.resolution) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := Q(r, l.communities, structure.resolution) + l.move(dst, src) + after := Q(r, l.communities, structure.resolution) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } +} + +func TestModularizeUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + testModularizeUndirected(t, test, g) + } +} + +func TestModularizeWeightedUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewWeightedUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + testModularizeUndirected(t, test, g) + } +} + +func testModularizeUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) { + const louvainIterations = 20 + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedUndirected + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := Modularize(g, 1, src).(*ReducedUndirected) + if q := Q(r, nil, 1); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedUndirected) { + qs = append(qs, Q(p, nil, 1)) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + return + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedUndirected) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceUndirected(g, nil).Communities() + } + q := Q(p, nil, 1) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } +} + +func TestNonContiguousUndirected(t *testing.T) { + g := simple.NewUndirectedGraph() + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1)}, + {F: simple.Node(4), T: simple.Node(5)}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func TestNonContiguousWeightedUndirected(t *testing.T) { + g := simple.NewWeightedUndirectedGraph(0, 0) + for _, e := range []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetWeightedEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func BenchmarkLouvain(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + Modularize(dupGraph, 1, src) + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/community/printgraphs.go b/vendor/gonum.org/v1/gonum/graph/community/printgraphs.go new file mode 100644 index 00000000..9d8eb1b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/community/printgraphs.go @@ -0,0 +1,142 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// printgraphs allows us to generate a consistent directed view of +// a set of edges that follows a reasonably real-world-meaningful +// graph. The interpretation of the links in the resulting directed +// graphs are either "suggests" in the context of a Page Ranking or +// possibly "looks up to" in the Zachary graph. +package main + +import ( + "fmt" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/network" + "gonum.org/v1/gonum/graph/simple" +) + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + zachary = []set{ + 0: linksTo(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 17, 19, 21, 31), + 1: linksTo(2, 3, 7, 13, 17, 19, 21, 30), + 2: linksTo(3, 7, 8, 9, 13, 27, 28, 32), + 3: linksTo(7, 12, 13), + 4: linksTo(6, 10), + 5: linksTo(6, 10, 16), + 6: linksTo(16), + 8: linksTo(30, 32, 33), + 9: linksTo(33), + 13: linksTo(33), + 14: linksTo(32, 33), + 15: linksTo(32, 33), + 18: linksTo(32, 33), + 19: linksTo(33), + 20: linksTo(32, 33), + 22: linksTo(32, 33), + 23: linksTo(25, 27, 29, 32, 33), + 24: linksTo(25, 27, 31), + 25: linksTo(31), + 26: linksTo(29, 33), + 27: linksTo(33), + 28: linksTo(31, 33), + 29: linksTo(32, 33), + 30: linksTo(32, 33), + 31: linksTo(32, 33), + 32: linksTo(33), + 33: nil, + } + + blondel = []set{ + 0: linksTo(2, 3, 4, 5), + 1: linksTo(2, 4, 7), + 2: linksTo(4, 5, 6), + 3: linksTo(7), + 4: linksTo(10), + 5: linksTo(7, 11), + 6: linksTo(7, 11), + 8: linksTo(9, 10, 11, 14, 15), + 9: linksTo(12, 14), + 10: linksTo(11, 12, 13, 14), + 11: linksTo(13), + 15: nil, + } +) + +func main() { + for _, raw := range []struct { + name string + set []set + }{ + {"zachary", zachary}, + {"blondel", blondel}, + } { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range raw.set { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + + fmt.Printf("%s = []set{\n", raw.name) + rank := network.PageRank(asDirected{g}, 0.85, 1e-8) + for _, u := range nodes { + to := g.From(nodes[u.ID()]) + sort.Sort(ordered.ByID(to)) + var links []int + for _, v := range to { + if rank[u.ID()] <= rank[v.ID()] { + links = append(links, v.ID()) + } + } + + if links == nil { + fmt.Printf("\t%d: nil, // rank=%.4v\n", u.ID(), rank[u.ID()]) + continue + } + + fmt.Printf("\t%d: linksTo(", u.ID()) + for i, v := range links { + if i != 0 { + fmt.Print(", ") + } + fmt.Print(v) + } + fmt.Printf("), // rank=%.4v\n", rank[u.ID()]) + } + fmt.Println("}") + } +} + +type asDirected struct{ *simple.UndirectedGraph } + +func (g asDirected) HasEdgeFromTo(u, v graph.Node) bool { + return g.UndirectedGraph.HasEdgeBetween(u, v) +} +func (g asDirected) To(v graph.Node) []graph.Node { return g.From(v) } diff --git a/vendor/gonum.org/v1/gonum/graph/doc.go b/vendor/gonum.org/v1/gonum/graph/doc.go new file mode 100644 index 00000000..74477274 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/doc.go @@ -0,0 +1,38 @@ +// Copyright ©2014 The gonum 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 graph implements functions and interfaces to deal with formal discrete graphs. It aims to +be first and foremost flexible, with speed as a strong second priority. + +In this package, graphs are taken to be directed, and undirected graphs are considered to be a +special case of directed graphs that happen to have reciprocal edges. Graphs are, by default, +unweighted, but functions that require weighted edges have several methods of dealing with this. +In order of precedence: + +1. These functions have an argument called Cost (and in some cases, HeuristicCost). If this is +present, it will always be used to determine the cost between two nodes. + +2. These functions will check if your graph implements the Coster (and/or HeuristicCoster) +interface. If this is present, and the Cost (or HeuristicCost) argument is nil, these functions +will be used. + +3. Finally, if no user data is supplied, it will use the functions UniformCost (always returns 1) +and/or NulLHeuristic (always returns 0). + +For information on the specification for Cost functions, please see the Coster interface. + +Finally, although the functions take in a Graph -- they will always use the correct behavior. +If your graph implements DirectedGraph, it will use Successors and To where applicable, +if undirected, it will use From instead. If it implements neither, it will scan the edge list +for successors and predecessors where applicable. (This is slow, you should always implement either +Directed or Undirected) + +This package will never modify a graph that is not Mutable (and the interface does not allow it to +do so). However, return values are free to be modified, so never pass a reference to your own edge +list or node list. It also guarantees that any nodes passed back to the user will be the same +nodes returned to it -- that is, it will never take a Node's ID and then wrap the ID in a new +struct and return that. You'll always get back your original data. +*/ +package graph // import "gonum.org/v1/gonum/graph" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/doc.go b/vendor/gonum.org/v1/gonum/graph/encoding/doc.go new file mode 100644 index 00000000..1f51390f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 encoding provides a common graph encoding API. +package encoding // import "gonum.org/v1/gonum/graph/encoding" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go new file mode 100644 index 00000000..ccc2868d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go @@ -0,0 +1,278 @@ +// Copyright ©2017 The gonum 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 dot + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/formats/dot" + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/internal/set" +) + +// AttributeSetters is implemented by graph values that can set global +// DOT attributes. +type AttributeSetters interface { + // DOTAttributeSetters returns the global attribute setters. + DOTAttributeSetters() (graph, node, edge encoding.AttributeSetter) +} + +// DOTIDSetter is implemented by types that can set a DOT ID. +type DOTIDSetter interface { + SetDOTID(id string) +} + +// Unmarshal parses the Graphviz DOT-encoded data and stores the result in dst. +func Unmarshal(data []byte, dst encoding.Builder) error { + file, err := dot.ParseBytes(data) + if err != nil { + return err + } + if len(file.Graphs) != 1 { + return fmt.Errorf("invalid number of graphs; expected 1, got %d", len(file.Graphs)) + } + return copyGraph(dst, file.Graphs[0]) +} + +// copyGraph copies the nodes and edges from the Graphviz AST source graph to +// the destination graph. Edge direction is maintained if present. +func copyGraph(dst encoding.Builder, src *ast.Graph) (err error) { + defer func() { + switch e := recover().(type) { + case nil: + case error: + err = e + default: + panic(e) + } + }() + gen := &generator{ + directed: src.Directed, + ids: make(map[string]graph.Node), + } + if a, ok := dst.(AttributeSetters); ok { + gen.graphAttr, gen.nodeAttr, gen.edgeAttr = a.DOTAttributeSetters() + } + for _, stmt := range src.Stmts { + gen.addStmt(dst, stmt) + } + return err +} + +// A generator keeps track of the information required for generating a gonum +// graph from a dot AST graph. +type generator struct { + // Directed graph. + directed bool + // Map from dot AST node ID to gonum node. + ids map[string]graph.Node + // Nodes processed within the context of a subgraph, that is to be used as a + // vertex of an edge. + subNodes []graph.Node + // Stack of start indices into the subgraph node slice. The top element + // corresponds to the start index of the active (or inner-most) subgraph. + subStart []int + // graphAttr, nodeAttr and edgeAttr are global graph attributes. + graphAttr, nodeAttr, edgeAttr encoding.AttributeSetter +} + +// node returns the gonum node corresponding to the given dot AST node ID, +// generating a new such node if none exist. +func (gen *generator) node(dst encoding.Builder, id string) graph.Node { + if n, ok := gen.ids[id]; ok { + return n + } + n := dst.NewNode() + dst.AddNode(n) + if n, ok := n.(DOTIDSetter); ok { + n.SetDOTID(id) + } + gen.ids[id] = n + // Check if within the context of a subgraph, that is to be used as a vertex + // of an edge. + if gen.isInSubgraph() { + // Append node processed within the context of a subgraph, that is to be + // used as a vertex of an edge + gen.appendSubgraphNode(n) + } + return n +} + +// addStmt adds the given statement to the graph. +func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.NodeStmt: + n, ok := gen.node(dst, stmt.Node.ID).(encoding.AttributeSetter) + if !ok { + return + } + for _, attr := range stmt.Attrs { + a := encoding.Attribute{ + Key: attr.Key, + Value: attr.Val, + } + if err := n.SetAttribute(a); err != nil { + panic(fmt.Errorf("unable to unmarshal node DOT attribute (%s=%s)", a.Key, a.Value)) + } + } + case *ast.EdgeStmt: + gen.addEdgeStmt(dst, stmt) + case *ast.AttrStmt: + var n encoding.AttributeSetter + var dst string + switch stmt.Kind { + case ast.GraphKind: + if gen.graphAttr == nil { + return + } + n = gen.graphAttr + dst = "graph" + case ast.NodeKind: + if gen.nodeAttr == nil { + return + } + n = gen.nodeAttr + dst = "node" + case ast.EdgeKind: + if gen.edgeAttr == nil { + return + } + n = gen.edgeAttr + dst = "edge" + default: + panic("unreachable") + } + for _, attr := range stmt.Attrs { + a := encoding.Attribute{ + Key: attr.Key, + Value: attr.Val, + } + if err := n.SetAttribute(a); err != nil { + panic(fmt.Errorf("unable to unmarshal global %s DOT attribute (%s=%s)", dst, a.Key, a.Value)) + } + } + case *ast.Attr: + // ignore. + case *ast.Subgraph: + for _, stmt := range stmt.Stmts { + gen.addStmt(dst, stmt) + } + default: + panic(fmt.Sprintf("unknown statement type %T", stmt)) + } +} + +// addEdgeStmt adds the given edge statement to the graph. +func (gen *generator) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) { + fs := gen.addVertex(dst, stmt.From) + ts := gen.addEdge(dst, stmt.To) + for _, f := range fs { + for _, t := range ts { + edge := dst.NewEdge(f, t) + dst.SetEdge(edge) + e, ok := edge.(encoding.AttributeSetter) + if !ok { + continue + } + for _, attr := range stmt.Attrs { + a := encoding.Attribute{ + Key: attr.Key, + Value: attr.Val, + } + if err := e.SetAttribute(a); err != nil { + panic(fmt.Errorf("unable to unmarshal edge DOT attribute (%s=%s)", a.Key, a.Value)) + } + } + } + } +} + +// addVertex adds the given vertex to the graph, and returns its set of nodes. +func (gen *generator) addVertex(dst encoding.Builder, v ast.Vertex) []graph.Node { + switch v := v.(type) { + case *ast.Node: + n := gen.node(dst, v.ID) + return []graph.Node{n} + case *ast.Subgraph: + gen.pushSubgraph() + for _, stmt := range v.Stmts { + gen.addStmt(dst, stmt) + } + return gen.popSubgraph() + default: + panic(fmt.Sprintf("unknown vertex type %T", v)) + } +} + +// addEdge adds the given edge to the graph, and returns its set of nodes. +func (gen *generator) addEdge(dst encoding.Builder, to *ast.Edge) []graph.Node { + if !gen.directed && to.Directed { + panic(fmt.Errorf("directed edge to %v in undirected graph", to.Vertex)) + } + fs := gen.addVertex(dst, to.Vertex) + if to.To != nil { + ts := gen.addEdge(dst, to.To) + for _, f := range fs { + for _, t := range ts { + edge := dst.NewEdge(f, t) + dst.SetEdge(edge) + } + } + } + return fs +} + +// pushSubgraph pushes the node start index of the active subgraph onto the +// stack. +func (gen *generator) pushSubgraph() { + gen.subStart = append(gen.subStart, len(gen.subNodes)) +} + +// popSubgraph pops the node start index of the active subgraph from the stack, +// and returns the nodes processed since. +func (gen *generator) popSubgraph() []graph.Node { + // Get nodes processed since the subgraph became active. + start := gen.subStart[len(gen.subStart)-1] + // TODO: Figure out a better way to store subgraph nodes, so that duplicates + // may not occur. + nodes := unique(gen.subNodes[start:]) + // Remove subgraph from stack. + gen.subStart = gen.subStart[:len(gen.subStart)-1] + if len(gen.subStart) == 0 { + // Remove subgraph nodes when the bottom-most subgraph has been processed. + gen.subNodes = gen.subNodes[:0] + } + return nodes +} + +// unique returns the set of unique nodes contained within ns. +func unique(ns []graph.Node) []graph.Node { + var nodes []graph.Node + seen := make(set.Int64s) + for _, n := range ns { + id := n.ID() + if seen.Has(id) { + // skip duplicate node + continue + } + seen.Add(id) + nodes = append(nodes, n) + } + return nodes +} + +// isInSubgraph reports whether the active context is within a subgraph, that is +// to be used as a vertex of an edge. +func (gen *generator) isInSubgraph() bool { + return len(gen.subStart) > 0 +} + +// appendSubgraphNode appends the given node to the slice of nodes processed +// within the context of a subgraph. +func (gen *generator) appendSubgraphNode(n graph.Node) { + gen.subNodes = append(gen.subNodes, n) +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode_test.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode_test.go new file mode 100644 index 00000000..d05b0507 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode_test.go @@ -0,0 +1,247 @@ +// Copyright ©2017 The gonum 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 dot + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/simple" +) + +func TestRoundTrip(t *testing.T) { + golden := []struct { + want string + directed bool + }{ + { + want: directed, + directed: true, + }, + { + want: undirected, + directed: false, + }, + } + for i, g := range golden { + var dst encoding.Builder + if g.directed { + dst = newDotDirectedGraph() + } else { + dst = newDotUndirectedGraph() + } + data := []byte(g.want) + if err := Unmarshal(data, dst); err != nil { + t.Errorf("i=%d: unable to unmarshal DOT graph; %v", i, err) + continue + } + buf, err := Marshal(dst, "", "", "\t", false) + if err != nil { + t.Errorf("i=%d: unable to marshal graph; %v", i, dst) + continue + } + got := string(buf) + if got != g.want { + t.Errorf("i=%d: graph content mismatch; want:\n%s\n\ngot:\n%s", i, g.want, got) + continue + } + } +} + +const directed = `digraph { + graph [ + outputorder=edgesfirst + ]; + node [ + shape=circle + style=filled + ]; + edge [ + penwidth=5 + color=gray + ]; + + // Node definitions. + A [label="foo 2"]; + B [label="bar 2"]; + + // Edge definitions. + A -> B [label="baz 2"]; +}` + +const undirected = `graph { + graph [ + outputorder=edgesfirst + ]; + node [ + shape=circle + style=filled + ]; + edge [ + penwidth=5 + color=gray + ]; + + // Node definitions. + A [label="foo 2"]; + B [label="bar 2"]; + + // Edge definitions. + A -- B [label="baz 2"]; +}` + +// Below follows a minimal implementation of a graph capable of validating the +// round-trip encoding and decoding of DOT graphs with nodes and edges +// containing DOT attributes. + +// dotDirectedGraph extends simple.DirectedGraph to add NewNode and NewEdge +// methods for creating user-defined nodes and edges. +// +// dotDirectedGraph implements the dot.Builder interface. +type dotDirectedGraph struct { + *simple.DirectedGraph + graph, node, edge attributes +} + +// newDotDirectedGraph returns a new directed capable of creating user-defined +// nodes and edges. +func newDotDirectedGraph() *dotDirectedGraph { + return &dotDirectedGraph{DirectedGraph: simple.NewDirectedGraph()} +} + +// NewNode returns a new node with a unique node ID for the graph. +func (g *dotDirectedGraph) NewNode() graph.Node { + return &dotNode{Node: g.DirectedGraph.NewNode()} +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *dotDirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &dotEdge{Edge: g.DirectedGraph.NewEdge(from, to)} +} + +// DOTAttributers implements the dot.Attributers interface. +func (g *dotDirectedGraph) DOTAttributers() (graph, node, edge encoding.Attributer) { + return g.graph, g.node, g.edge +} + +// DOTAttributeSetters implements the dot.AttributeSetters interface. +func (g *dotDirectedGraph) DOTAttributeSetters() (graph, node, edge encoding.AttributeSetter) { + return &g.graph, &g.node, &g.edge +} + +// dotUndirectedGraph extends simple.UndirectedGraph to add NewNode and NewEdge +// methods for creating user-defined nodes and edges. +// +// dotUndirectedGraph implements the dot.Builder interface. +type dotUndirectedGraph struct { + *simple.UndirectedGraph + graph, node, edge attributes +} + +// newDotUndirectedGraph returns a new undirected capable of creating user- +// defined nodes and edges. +func newDotUndirectedGraph() *dotUndirectedGraph { + return &dotUndirectedGraph{UndirectedGraph: simple.NewUndirectedGraph()} +} + +// NewNode adds a new node with a unique node ID to the graph. +func (g *dotUndirectedGraph) NewNode() graph.Node { + return &dotNode{Node: g.UndirectedGraph.NewNode()} +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *dotUndirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &dotEdge{Edge: g.UndirectedGraph.NewEdge(from, to)} +} + +// DOTAttributers implements the dot.Attributers interface. +func (g *dotUndirectedGraph) DOTAttributers() (graph, node, edge encoding.Attributer) { + return g.graph, g.node, g.edge +} + +// DOTUnmarshalerAttrs implements the dot.UnmarshalerAttrs interface. +func (g *dotUndirectedGraph) DOTAttributeSetters() (graph, node, edge encoding.AttributeSetter) { + return &g.graph, &g.node, &g.edge +} + +// dotNode extends simple.Node with a label field to test round-trip encoding +// and decoding of node DOT label attributes. +type dotNode struct { + graph.Node + dotID string + // Node label. + Label string +} + +// DOTID returns the node's DOT ID. +func (n *dotNode) DOTID() string { + return n.dotID +} + +// SetDOTID sets a DOT ID. +func (n *dotNode) SetDOTID(id string) { + n.dotID = id +} + +// SetAttribute sets a DOT attribute. +func (n *dotNode) SetAttribute(attr encoding.Attribute) error { + if attr.Key != "label" { + return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key) + } + n.Label = attr.Value + return nil +} + +// Attributes returns the DOT attributes of the node. +func (n *dotNode) Attributes() []encoding.Attribute { + if len(n.Label) == 0 { + return nil + } + return []encoding.Attribute{{ + Key: "label", + Value: n.Label, + }} +} + +// dotEdge extends simple.Edge with a label field to test round-trip encoding and +// decoding of edge DOT label attributes. +type dotEdge struct { + graph.Edge + // Edge label. + Label string +} + +// SetAttribute sets a DOT attribute. +func (e *dotEdge) SetAttribute(attr encoding.Attribute) error { + if attr.Key != "label" { + return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key) + } + e.Label = attr.Value + return nil +} + +// Attributes returns the DOT attributes of the edge. +func (e *dotEdge) Attributes() []encoding.Attribute { + if len(e.Label) == 0 { + return nil + } + return []encoding.Attribute{{ + Key: "label", + Value: e.Label, + }} +} + +// attributes is a helper for global attributes. +type attributes []encoding.Attribute + +func (a attributes) Attributes() []encoding.Attribute { + return []encoding.Attribute(a) +} +func (a *attributes) SetAttribute(attr encoding.Attribute) error { + *a = append(*a, attr) + return nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go new file mode 100644 index 00000000..6a4a6675 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go @@ -0,0 +1,14 @@ +// Copyright ©2017 The gonum 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 dot implements GraphViz DOT marshaling and unmarshaling of graphs. +// +// See the GraphViz DOT Guide and the DOT grammar for more information +// on using specific aspects of the DOT language: +// +// DOT Guide: http://www.graphviz.org/Documentation/dotguide.pdf +// +// DOT grammar: http://www.graphviz.org/doc/info/lang.html +// +package dot // import "gonum.org/v1/gonum/graph/encoding/dot" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go new file mode 100644 index 00000000..2272d7ae --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go @@ -0,0 +1,5 @@ +// Copyright ©2015 The gonum 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 dot diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go new file mode 100644 index 00000000..a7a15493 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go @@ -0,0 +1,359 @@ +// Copyright ©2015 The gonum 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 dot + +import ( + "bytes" + "errors" + "fmt" + "sort" + "strings" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// Node is a DOT graph node. +type Node interface { + // DOTID returns a DOT node ID. + // + // An ID is one of the following: + // + // - a string of alphabetic ([a-zA-Z\x80-\xff]) characters, underscores ('_'). + // digits ([0-9]), not beginning with a digit. + // - a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)?). + // - a double-quoted string ("...") possibly containing escaped quotes (\"). + // - an HTML string (<...>). + DOTID() string +} + +// Attributers are graph.Graph values that specify top-level DOT +// attributes. +type Attributers interface { + DOTAttributers() (graph, node, edge encoding.Attributer) +} + +// Porter defines the behavior of graph.Edge values that can specify +// connection ports for their end points. The returned port corresponds +// to the the DOT node port to be used by the edge, compass corresponds +// to DOT compass point to which the edge will be aimed. +type Porter interface { + FromPort() (port, compass string) + ToPort() (port, compass string) +} + +// Structurer represents a graph.Graph that can define subgraphs. +type Structurer interface { + Structure() []Graph +} + +// Graph wraps named graph.Graph values. +type Graph interface { + graph.Graph + DOTID() string +} + +// Subgrapher wraps graph.Node values that represent subgraphs. +type Subgrapher interface { + Subgraph() graph.Graph +} + +// Marshal returns the DOT encoding for the graph g, applying the prefix +// and indent to the encoding. Name is used to specify the graph name. If +// name is empty and g implements Graph, the returned string from DOTID +// will be used. If strict is true the output bytes will be prefixed with +// the DOT "strict" keyword. +// +// Graph serialization will work for a graph.Graph without modification, +// however, advanced GraphViz DOT features provided by Marshal depend on +// implementation of the Node, Attributer, Porter, Attributers, Structurer, +// Subgrapher and Graph interfaces. +func Marshal(g graph.Graph, name, prefix, indent string, strict bool) ([]byte, error) { + var p printer + p.indent = indent + p.prefix = prefix + p.visited = make(map[edge]bool) + if strict { + p.buf.WriteString("strict ") + } + err := p.print(g, name, false, false) + if err != nil { + return nil, err + } + return p.buf.Bytes(), nil +} + +type printer struct { + buf bytes.Buffer + + prefix string + indent string + depth int + + visited map[edge]bool + + err error +} + +type edge struct { + inGraph string + from, to int64 +} + +func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool) error { + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + + p.buf.WriteString(p.prefix) + if needsIndent { + for i := 0; i < p.depth; i++ { + p.buf.WriteString(p.indent) + } + } + _, isDirected := g.(graph.Directed) + if isSubgraph { + p.buf.WriteString("sub") + } else if isDirected { + p.buf.WriteString("di") + } + p.buf.WriteString("graph") + + if name == "" { + if g, ok := g.(Graph); ok { + name = g.DOTID() + } + } + if name != "" { + p.buf.WriteByte(' ') + p.buf.WriteString(name) + } + + p.openBlock(" {") + if a, ok := g.(Attributers); ok { + p.writeAttributeComplex(a) + } + if s, ok := g.(Structurer); ok { + for _, g := range s.Structure() { + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.buf.WriteByte('\n') + p.print(g, g.DOTID(), true, true) + } + } + + havePrintedNodeHeader := false + for _, n := range nodes { + if s, ok := n.(Subgrapher); ok { + // If the node is not linked to any other node + // the graph needs to be written now. + if len(g.From(n)) == 0 { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + if !havePrintedNodeHeader { + p.newline() + p.buf.WriteString("// Node definitions.") + havePrintedNodeHeader = true + } + p.newline() + p.print(g, graphID(g, n), false, true) + } + continue + } + if !havePrintedNodeHeader { + p.newline() + p.buf.WriteString("// Node definitions.") + havePrintedNodeHeader = true + } + p.newline() + p.writeNode(n) + if a, ok := n.(encoding.Attributer); ok { + p.writeAttributeList(a) + } + p.buf.WriteByte(';') + } + + havePrintedEdgeHeader := false + for _, n := range nodes { + to := g.From(n) + sort.Sort(ordered.ByID(to)) + for _, t := range to { + if isDirected { + if p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] { + continue + } + p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] = true + } else { + if p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] { + continue + } + p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] = true + p.visited[edge{inGraph: name, from: t.ID(), to: n.ID()}] = true + } + + if !havePrintedEdgeHeader { + p.buf.WriteByte('\n') + p.buf.WriteString(strings.TrimRight(p.prefix, " \t\n")) // Trim whitespace suffix. + p.newline() + p.buf.WriteString("// Edge definitions.") + havePrintedEdgeHeader = true + } + p.newline() + + if s, ok := n.(Subgrapher); ok { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.print(g, graphID(g, n), false, true) + } else { + p.writeNode(n) + } + e, edgeIsPorter := g.Edge(n, t).(Porter) + if edgeIsPorter { + p.writePorts(e.FromPort()) + } + + if isDirected { + p.buf.WriteString(" -> ") + } else { + p.buf.WriteString(" -- ") + } + + if s, ok := t.(Subgrapher); ok { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.print(g, graphID(g, t), false, true) + } else { + p.writeNode(t) + } + if edgeIsPorter { + p.writePorts(e.ToPort()) + } + + if a, ok := g.Edge(n, t).(encoding.Attributer); ok { + p.writeAttributeList(a) + } + + p.buf.WriteByte(';') + } + } + p.closeBlock("}") + + return nil +} + +func (p *printer) writeNode(n graph.Node) { + p.buf.WriteString(nodeID(n)) +} + +func (p *printer) writePorts(port, cp string) { + if port != "" { + p.buf.WriteByte(':') + p.buf.WriteString(port) + } + if cp != "" { + p.buf.WriteByte(':') + p.buf.WriteString(cp) + } +} + +func nodeID(n graph.Node) string { + switch n := n.(type) { + case Node: + return n.DOTID() + default: + return fmt.Sprint(n.ID()) + } +} + +func graphID(g graph.Graph, n graph.Node) string { + switch g := g.(type) { + case Node: + return g.DOTID() + default: + return nodeID(n) + } +} + +func (p *printer) writeAttributeList(a encoding.Attributer) { + attributes := a.Attributes() + switch len(attributes) { + case 0: + case 1: + p.buf.WriteString(" [") + p.buf.WriteString(attributes[0].Key) + p.buf.WriteByte('=') + p.buf.WriteString(attributes[0].Value) + p.buf.WriteString("]") + default: + p.openBlock(" [") + for _, att := range attributes { + p.newline() + p.buf.WriteString(att.Key) + p.buf.WriteByte('=') + p.buf.WriteString(att.Value) + } + p.closeBlock("]") + } +} + +var attType = []string{"graph", "node", "edge"} + +func (p *printer) writeAttributeComplex(ca Attributers) { + g, n, e := ca.DOTAttributers() + haveWrittenBlock := false + for i, a := range []encoding.Attributer{g, n, e} { + attributes := a.Attributes() + if len(attributes) == 0 { + continue + } + if haveWrittenBlock { + p.buf.WriteByte(';') + } + p.newline() + p.buf.WriteString(attType[i]) + p.openBlock(" [") + for _, att := range attributes { + p.newline() + p.buf.WriteString(att.Key) + p.buf.WriteByte('=') + p.buf.WriteString(att.Value) + } + p.closeBlock("]") + haveWrittenBlock = true + } + if haveWrittenBlock { + p.buf.WriteString(";\n") + } +} + +func (p *printer) newline() { + p.buf.WriteByte('\n') + p.buf.WriteString(p.prefix) + for i := 0; i < p.depth; i++ { + p.buf.WriteString(p.indent) + } +} + +func (p *printer) openBlock(b string) { + p.buf.WriteString(b) + p.depth++ +} + +func (p *printer) closeBlock(b string) { + p.depth-- + p.newline() + p.buf.WriteString(b) +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode_test.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode_test.go new file mode 100644 index 00000000..d4dba18c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode_test.go @@ -0,0 +1,1436 @@ +// Copyright ©2015 The gonum 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 dot + +import ( + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/simple" +) + +// intset is an integer set. +type intset map[int64]struct{} + +func linksTo(i ...int64) intset { + if len(i) == 0 { + return nil + } + s := make(intset) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + // Node identities are rewritten here to use integers from 0 to match with the DOT output. + pageRankGraph = []intset{ + 0: nil, + 1: linksTo(2), + 2: linksTo(1), + 3: linksTo(0, 1), + 4: linksTo(3, 1, 5), + 5: linksTo(1, 4), + 6: linksTo(1, 4), + 7: linksTo(1, 4), + 8: linksTo(1, 4), + 9: linksTo(4), + 10: linksTo(4), + } + + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + powerMethodGraph = []intset{ + 0: linksTo(1, 2), + 1: linksTo(3), + 2: linksTo(3, 4), + 3: linksTo(4), + 4: linksTo(0), + } +) + +func directedGraphFrom(g []intset) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + for v := range e { + dg.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + return dg +} + +func undirectedGraphFrom(g []intset) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + for v := range e { + dg.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + return dg +} + +const alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +type namedNode struct { + id int64 + name string +} + +func (n namedNode) ID() int64 { return n.id } +func (n namedNode) DOTID() string { return n.name } + +func directedNamedIDGraphFrom(g []intset) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + u := int64(u) + nu := namedNode{id: u, name: alpha[u : u+1]} + for v := range e { + nv := namedNode{id: v, name: alpha[v : v+1]} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNamedIDGraphFrom(g []intset) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + nu := namedNode{id: u, name: alpha[u : u+1]} + for v := range e { + nv := namedNode{id: v, name: alpha[v : v+1]} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type attrNode struct { + id int64 + name string + attr []encoding.Attribute +} + +func (n attrNode) ID() int64 { return n.id } +func (n attrNode) Attributes() []encoding.Attribute { return n.attr } + +func directedNodeAttrGraphFrom(g []intset, attr [][]encoding.Attribute) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + nv := attrNode{id: v, attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNodeAttrGraphFrom(g []intset, attr [][]encoding.Attribute) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + nv := attrNode{id: v, attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type namedAttrNode struct { + id int64 + name string + attr []encoding.Attribute +} + +func (n namedAttrNode) ID() int64 { return n.id } +func (n namedAttrNode) DOTID() string { return n.name } +func (n namedAttrNode) Attributes() []encoding.Attribute { return n.attr } + +func directedNamedIDNodeAttrGraphFrom(g []intset, attr [][]encoding.Attribute) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := namedAttrNode{id: u, name: alpha[u : u+1], attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + nv := namedAttrNode{id: v, name: alpha[v : v+1], attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNamedIDNodeAttrGraphFrom(g []intset, attr [][]encoding.Attribute) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := namedAttrNode{id: u, name: alpha[u : u+1], attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + nv := namedAttrNode{id: v, name: alpha[v : v+1], attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type attrEdge struct { + from, to graph.Node + + attr []encoding.Attribute +} + +func (e attrEdge) From() graph.Node { return e.from } +func (e attrEdge) To() graph.Node { return e.to } +func (e attrEdge) Weight() float64 { return 0 } +func (e attrEdge) Attributes() []encoding.Attribute { return e.attr } + +func directedEdgeAttrGraphFrom(g []intset, attr map[edge][]encoding.Attribute) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + u := int64(u) + for v := range e { + dg.SetEdge(attrEdge{from: simple.Node(u), to: simple.Node(v), attr: attr[edge{from: u, to: v}]}) + } + } + return dg +} + +func undirectedEdgeAttrGraphFrom(g []intset, attr map[edge][]encoding.Attribute) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + for v := range e { + dg.SetEdge(attrEdge{from: simple.Node(u), to: simple.Node(v), attr: attr[edge{from: u, to: v}]}) + } + } + return dg +} + +type portedEdge struct { + from, to graph.Node + + directed bool + + fromPort string + fromCompass string + toPort string + toCompass string +} + +func (e portedEdge) From() graph.Node { return e.from } +func (e portedEdge) To() graph.Node { return e.to } +func (e portedEdge) Weight() float64 { return 0 } + +// TODO(kortschak): Figure out a better way to handle the fact that +// headedness is an undefined concept in undirected graphs. We sort +// nodes by ID, so lower ID nodes are always from nodes in undirected +// graphs. We can probably do this in the printer, but I am leaving +// this here as a WARNING. +// Maybe the approach should be to document that for undirected graphs +// the low ID node should be returned by the FromPort and the high ID +// by the ToPort calls. +func (e portedEdge) FromPort() (port, compass string) { + return e.fromPort, e.fromCompass +} +func (e portedEdge) ToPort() (port, compass string) { + return e.toPort, e.toCompass +} + +func directedPortedAttrGraphFrom(g []intset, attr [][]encoding.Attribute, ports map[edge]portedEdge) graph.Directed { + dg := simple.NewDirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + pe := ports[edge{from: u, to: v}] + pe.from = nu + pe.to = attrNode{id: v, attr: at} + dg.SetEdge(pe) + } + } + return dg +} + +func undirectedPortedAttrGraphFrom(g []intset, attr [][]encoding.Attribute, ports map[edge]portedEdge) graph.Graph { + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + var at []encoding.Attribute + if u < int64(len(attr)) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < int64(len(attr)) { + at = attr[v] + } + pe := ports[edge{from: u, to: v}] + pe.from = nu + pe.to = attrNode{id: v, attr: at} + dg.SetEdge(pe) + } + } + return dg +} + +type graphAttributer struct { + graph.Graph + graph attributer + node attributer + edge attributer +} + +type attributer []encoding.Attribute + +func (a attributer) Attributes() []encoding.Attribute { return a } + +func (g graphAttributer) DOTAttributers() (graph, node, edge encoding.Attributer) { + return g.graph, g.node, g.edge +} + +type structuredGraph struct { + *simple.UndirectedGraph + sub []Graph +} + +func undirectedStructuredGraphFrom(c []edge, g ...[]intset) graph.Graph { + s := &structuredGraph{UndirectedGraph: simple.NewUndirectedGraph()} + var base int64 + for i, sg := range g { + sub := simple.NewUndirectedGraph() + for u, e := range sg { + u := int64(u) + for v := range e { + ce := simple.Edge{F: simple.Node(u + base), T: simple.Node(v + base)} + sub.SetEdge(ce) + } + } + s.sub = append(s.sub, namedGraph{id: int64(i), Graph: sub}) + base += int64(len(sg)) + } + for _, e := range c { + s.SetEdge(simple.Edge{F: simple.Node(e.from), T: simple.Node(e.to)}) + } + return s +} + +func (g structuredGraph) Structure() []Graph { + return g.sub +} + +type namedGraph struct { + id int64 + graph.Graph +} + +func (g namedGraph) DOTID() string { return alpha[g.id : g.id+1] } + +type subGraph struct { + id int64 + graph.Graph +} + +func (g subGraph) ID() int64 { return g.id } +func (g subGraph) Subgraph() graph.Graph { + return namedGraph(g) +} + +func undirectedSubGraphFrom(g []intset, s map[int64][]intset) graph.Graph { + var base int64 + subs := make(map[int64]subGraph) + for i, sg := range s { + sub := simple.NewUndirectedGraph() + for u, e := range sg { + u := int64(u) + for v := range e { + ce := simple.Edge{F: simple.Node(u + base), T: simple.Node(v + base)} + sub.SetEdge(ce) + } + } + subs[i] = subGraph{id: int64(i), Graph: sub} + base += int64(len(sg)) + } + + dg := simple.NewUndirectedGraph() + for u, e := range g { + u := int64(u) + var nu graph.Node + if sg, ok := subs[u]; ok { + sg.id += base + nu = sg + } else { + nu = simple.Node(u + base) + } + for v := range e { + var nv graph.Node + if sg, ok := subs[v]; ok { + sg.id += base + nv = sg + } else { + nv = simple.Node(v + base) + } + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +var encodeTests = []struct { + name string + g graph.Graph + strict bool + + prefix string + + want string +}{ + // Basic graph.Graph handling. + { + name: "PageRank", + g: directedGraphFrom(pageRankGraph), + + want: `digraph PageRank { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + 5; + 6; + 7; + 8; + 9; + 10; + + // Edge definitions. + 1 -> 2; + 2 -> 1; + 3 -> 0; + 3 -> 1; + 4 -> 1; + 4 -> 3; + 4 -> 5; + 5 -> 1; + 5 -> 4; + 6 -> 1; + 6 -> 4; + 7 -> 1; + 7 -> 4; + 8 -> 1; + 8 -> 4; + 9 -> 4; + 10 -> 4; +}`, + }, + { + g: undirectedGraphFrom(pageRankGraph), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + 5; + 6; + 7; + 8; + 9; + 10; + + // Edge definitions. + 0 -- 3; + 1 -- 2; + 1 -- 3; + 1 -- 4; + 1 -- 5; + 1 -- 6; + 1 -- 7; + 1 -- 8; + 3 -- 4; + 4 -- 5; + 4 -- 6; + 4 -- 7; + 4 -- 8; + 4 -- 9; + 4 -- 10; +}`, + }, + { + g: directedGraphFrom(powerMethodGraph), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedGraphFrom(powerMethodGraph), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: undirectedGraphFrom(powerMethodGraph), + prefix: "# ", + + want: `# graph { +# // Node definitions. +# 0; +# 1; +# 2; +# 3; +# 4; +# +# // Edge definitions. +# 0 -- 1; +# 0 -- 2; +# 0 -- 4; +# 1 -- 3; +# 2 -- 3; +# 2 -- 4; +# 3 -- 4; +# }`, + }, + + // Names named nodes. + { + name: "PageRank", + g: directedNamedIDGraphFrom(pageRankGraph), + + want: `digraph PageRank { + // Node definitions. + A; + B; + C; + D; + E; + F; + G; + H; + I; + J; + K; + + // Edge definitions. + B -> C; + C -> B; + D -> A; + D -> B; + E -> B; + E -> D; + E -> F; + F -> B; + F -> E; + G -> B; + G -> E; + H -> B; + H -> E; + I -> B; + I -> E; + J -> E; + K -> E; +}`, + }, + { + g: undirectedNamedIDGraphFrom(pageRankGraph), + + want: `graph { + // Node definitions. + A; + B; + C; + D; + E; + F; + G; + H; + I; + J; + K; + + // Edge definitions. + A -- D; + B -- C; + B -- D; + B -- E; + B -- F; + B -- G; + B -- H; + B -- I; + D -- E; + E -- F; + E -- G; + E -- H; + E -- I; + E -- J; + E -- K; +}`, + }, + { + g: directedNamedIDGraphFrom(powerMethodGraph), + + want: `digraph { + // Node definitions. + A; + B; + C; + D; + E; + + // Edge definitions. + A -> B; + A -> C; + B -> D; + C -> D; + C -> E; + D -> E; + E -> A; +}`, + }, + { + g: undirectedNamedIDGraphFrom(powerMethodGraph), + + want: `graph { + // Node definitions. + A; + B; + C; + D; + E; + + // Edge definitions. + A -- B; + A -- C; + A -- E; + B -- D; + C -- D; + C -- E; + D -- E; +}`, + }, + { + g: undirectedNamedIDGraphFrom(powerMethodGraph), + prefix: "# ", + + want: `# graph { +# // Node definitions. +# A; +# B; +# C; +# D; +# E; +# +# // Edge definitions. +# A -- B; +# A -- C; +# A -- E; +# B -- D; +# C -- D; +# C -- E; +# D -- E; +# }`, + }, + + // Handling nodes with attributes. + { + g: directedNodeAttrGraphFrom(powerMethodGraph, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedNodeAttrGraphFrom(powerMethodGraph, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedNodeAttrGraphFrom(powerMethodGraph, [][]encoding.Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `digraph { + // Node definitions. + 0; + 1; + 2 [ + fontsize=16 + shape=ellipse + ]; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedNodeAttrGraphFrom(powerMethodGraph, [][]encoding.Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `graph { + // Node definitions. + 0; + 1; + 2 [ + fontsize=16 + shape=ellipse + ]; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedNamedIDNodeAttrGraphFrom(powerMethodGraph, [][]encoding.Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `digraph { + // Node definitions. + A; + B; + C [ + fontsize=16 + shape=ellipse + ]; + D; + E; + + // Edge definitions. + A -> B; + A -> C; + B -> D; + C -> D; + C -> E; + D -> E; + E -> A; +}`, + }, + { + g: undirectedNamedIDNodeAttrGraphFrom(powerMethodGraph, [][]encoding.Attribute{ + 0: nil, + 1: nil, + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 3: nil, + 4: {}, + }), + + want: `graph { + // Node definitions. + A; + B; + C [ + fontsize=16 + shape=ellipse + ]; + D; + E; + + // Edge definitions. + A -- B; + A -- C; + A -- E; + B -- D; + C -- D; + C -- E; + D -- E; +}`, + }, + + // Handling edge with attributes. + { + g: directedEdgeAttrGraphFrom(powerMethodGraph, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedEdgeAttrGraphFrom(powerMethodGraph, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]encoding.Attribute{ + {from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + {from: 2, to: 4}: {}, + {from: 3, to: 4}: {{"color", "red"}}, + }), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2 [ + label="???" + style=dashed + ]; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4 [color=red]; + 4 -> 0; +}`, + }, + { + g: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]encoding.Attribute{ + {from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + {from: 2, to: 4}: {}, + {from: 3, to: 4}: {{"color", "red"}}, + }), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + + // Handling nodes with ports. + { + g: directedPortedAttrGraphFrom(powerMethodGraph, nil, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedPortedAttrGraphFrom(powerMethodGraph, nil, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedPortedAttrGraphFrom(powerMethodGraph, + [][]encoding.Attribute{ + 2: {{"shape", "record"}, {"label", `"English|German"`}}, + 4: {{"shape", "record"}, {"label", `"English|German"`}}, + }, + map[edge]portedEdge{ + {from: 0, to: 1}: {fromCompass: "s"}, + {from: 0, to: 2}: {fromCompass: "s", toPort: "Zwei", toCompass: "e"}, + {from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"}, + {from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"}, + {from: 3, to: 4}: {toPort: "Four", toCompass: "w"}, + {from: 4, to: 0}: {fromPort: "Four", fromCompass: "_", toCompass: "s"}, + }, + ), + + want: `digraph { + // Node definitions. + 0; + 1; + 2 [ + shape=record + label="English|German" + ]; + 3; + 4 [ + shape=record + label="English|German" + ]; + + // Edge definitions. + 0:s -> 1; + 0:s -> 2:Zwei:e; + 1 -> 3; + 2:Zwei:e -> 3; + 2:Two:w -> 4:Four:w; + 3 -> 4:Four:w; + 4:Four:_ -> 0:s; +}`, + }, + { + g: undirectedPortedAttrGraphFrom(powerMethodGraph, + [][]encoding.Attribute{ + 2: {{"shape", "record"}, {"label", `"English|German"`}}, + 4: {{"shape", "record"}, {"label", `"English|German"`}}, + }, + map[edge]portedEdge{ + {from: 0, to: 1}: {fromCompass: "s"}, + {from: 0, to: 2}: {fromCompass: "s", toPort: "Zwei", toCompass: "e"}, + {from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"}, + {from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"}, + {from: 3, to: 4}: {toPort: "Four", toCompass: "w"}, + + // This definition is reversed (see comment above at portedEdge + // definition) so that 4 gets the from port. This is a result + // of the fact that we sort nodes by ID, so the lower node + // will be always be printed first when the graph is undirected, + // thus becoming the from port, but we define the edges here + // from a directed adjacency list. + {from: 4, to: 0}: {fromCompass: "s", toPort: "Four", toCompass: "_"}, + }, + ), + + want: `graph { + // Node definitions. + 0; + 1; + 2 [ + shape=record + label="English|German" + ]; + 3; + 4 [ + shape=record + label="English|German" + ]; + + // Edge definitions. + 0:s -- 1; + 0:s -- 2:Zwei:e; + 0:s -- 4:Four:_; + 1 -- 3; + 2:Zwei:e -- 3; + 2:Two:w -- 4:Four:w; + 3 -- 4:Four:w; +}`, + }, + + // Handling graph attributes. + { + g: graphAttributer{Graph: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]encoding.Attribute{ + {from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + {from: 2, to: 4}: {}, + {from: 3, to: 4}: {{"color", "red"}}, + })}, + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + { + g: graphAttributer{Graph: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]encoding.Attribute{ + {from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + {from: 2, to: 4}: {}, + {from: 3, to: 4}: {{"color", "red"}}, + }), + graph: []encoding.Attribute{{"rankdir", `"LR"`}}, + node: []encoding.Attribute{{"fontsize", "16"}, {"shape", "ellipse"}}, + }, + + want: `graph { + graph [ + rankdir="LR" + ]; + node [ + fontsize=16 + shape=ellipse + ]; + + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + + // Handling structured graphs. + { + g: undirectedStructuredGraphFrom(nil, powerMethodGraph, pageRankGraph), + + want: `graph { + subgraph A { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } + subgraph B { + // Node definitions. + 5; + 6; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- 7; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; + } +}`, + }, + { + g: undirectedStructuredGraphFrom([]edge{{from: 0, to: 9}}, powerMethodGraph, pageRankGraph), + + want: `graph { + subgraph A { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } + subgraph B { + // Node definitions. + 5; + 6; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- 7; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; + } + // Node definitions. + 0; + 9; + + // Edge definitions. + 0 -- 9; +}`, + }, + + // Handling subgraphs. + { + g: undirectedSubGraphFrom(pageRankGraph, map[int64][]intset{2: powerMethodGraph}), + + want: `graph { + // Node definitions. + 5; + 6; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- subgraph H { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + }; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; +}`, + }, + { + name: "H", + g: undirectedSubGraphFrom(pageRankGraph, map[int64][]intset{1: powerMethodGraph}), + strict: true, + + want: `strict graph H { + // Node definitions. + 5; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } -- 7; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 8; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 9; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 10; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 11; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 12; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; +}`, + }, +} + +func TestEncode(t *testing.T) { + for i, test := range encodeTests { + got, err := Marshal(test.g, test.name, test.prefix, "\t", test.strict) + if err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if string(got) != test.want { + t.Errorf("unexpected DOT result for test %d:\ngot: %s\nwant:%s", i, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go b/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go new file mode 100644 index 00000000..0f99ac73 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go @@ -0,0 +1,30 @@ +// Copyright ©2017 The gonum 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 encoding + +import "gonum.org/v1/gonum/graph" + +// Builder is a graph that can have user-defined nodes and edges added. +type Builder interface { + graph.Graph + graph.Builder +} + +// AttributeSetter is implemented by types that can set an encoded graph +// attribute. +type AttributeSetter interface { + SetAttribute(Attribute) error +} + +// Attributer defines graph.Node or graph.Edge values that can +// specify graph attributes. +type Attributer interface { + Attributes() []Attribute +} + +// Attribute is an encoded key value attribute pair use in graph encoding. +type Attribute struct { + Key, Value string +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode.go b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode.go new file mode 100644 index 00000000..8ad758c1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode.go @@ -0,0 +1,157 @@ +// Copyright ©2017 The gonum 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 graphql + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" +) + +// Unmarshal parses the the JSON-encoded data and stores the result in dst. +// Node IDs are obtained from the JSON fields identified by the uid parameter. +// UIDs obtained from the JSON encoding must map to unique node ID values +// consistently across the JSON-encoded spanning tree. +func Unmarshal(data []byte, uid string, dst encoding.Builder) error { + if uid == "" { + return errors.New("graphql: invalid UID field name") + } + var src json.RawMessage + err := json.Unmarshal(data, &src) + if err != nil { + return err + } + gen := generator{dst: dst, uidName: uid, nodes: make(map[string]graph.Node)} + return gen.walk(src, nil, "") +} + +// StringIDSetter is a graph node that can set its ID based on the given uid string. +type StringIDSetter interface { + SetIDFromString(uid string) error +} + +// LabelSetter is a graph edge that can set its label. +type LabelSetter interface { + SetLabel(string) +} + +type generator struct { + dst encoding.Builder + + // uidName is the name of the UID field in the source JSON. + uidName string + // nodes maps from GraphQL UID string to graph.Node. + nodes map[string]graph.Node +} + +func (g *generator) walk(src json.RawMessage, node graph.Node, attr string) error { + switch src[0] { + case '{': + var val map[string]json.RawMessage + err := json.Unmarshal(src, &val) + if err != nil { + return err + } + if next, ok := val[g.uidName]; !ok { + if node != nil { + var buf bytes.Buffer + err := json.Compact(&buf, src) + if err != nil { + panic(err) + } + return fmt.Errorf("graphql: no UID for node: `%s`", &buf) + } + } else { + var v interface{} + err = json.Unmarshal(next, &v) + if err != nil { + return err + } + value := fmt.Sprint(v) + child, ok := g.nodes[value] + if !ok { + child = g.dst.NewNode() + s, ok := child.(StringIDSetter) + if !ok { + return errors.New("graphql: cannot set UID") + } + err = s.SetIDFromString(value) + if err != nil { + return err + } + g.nodes[value] = child + g.dst.AddNode(child) + } + if node != nil { + e := g.dst.NewEdge(node, child) + if s, ok := e.(LabelSetter); ok { + s.SetLabel(attr) + } + g.dst.SetEdge(e) + } + node = child + } + for attr, src := range val { + if attr == g.uidName { + continue + } + err = g.walk(src, node, attr) + if err != nil { + return err + } + } + + case '[': + var val []json.RawMessage + err := json.Unmarshal(src, &val) + if err != nil { + return err + } + for _, src := range val { + err = g.walk(src, node, attr) + if err != nil { + return err + } + } + + default: + var v interface{} + err := json.Unmarshal(src, &v) + if err != nil { + return err + } + if attr == g.uidName { + value := fmt.Sprint(v) + if s, ok := node.(StringIDSetter); ok { + if _, ok := g.nodes[value]; !ok { + err = s.SetIDFromString(value) + if err != nil { + return err + } + g.nodes[value] = node + } + } else { + return errors.New("graphql: cannot set ID") + } + } else if s, ok := node.(encoding.AttributeSetter); ok { + var value string + if _, ok := v.(float64); ok { + value = string(src) + } else { + value = fmt.Sprint(v) + } + err = s.SetAttribute(encoding.Attribute{Key: attr, Value: value}) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode_test.go b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode_test.go new file mode 100644 index 00000000..4bcc7925 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/decode_test.go @@ -0,0 +1,221 @@ +// Copyright ©2017 The gonum 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 graphql + +import ( + "errors" + "fmt" + "sort" + "strconv" + "strings" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/encoding/dot" + "gonum.org/v1/gonum/graph/simple" +) + +var decodeTests = []struct { + name string + json string + roots map[uint64]bool + wantDOT string + wantErr error +}{ + { + name: "starwars", + json: starwars, + roots: map[uint64]bool{ + 0xa3cff1a4c3ef3bb6: true, + 0xb39aa14d66aedad5: true, + }, + wantDOT: `digraph { + // Node definitions. + 0x8a10d5a2611fd03f [name="Richard Marquand"]; + 0xa3cff1a4c3ef3bb6 [ + name="Star Wars: Episode V - The Empire Strikes Back" + release_date=1980-05-21T00:00:00Z + revenue=534000000 + running_time=124 + ]; + 0xb39aa14d66aedad5 [ + name="Star Wars: Episode VI - Return of the Jedi" + release_date=1983-05-25T00:00:00Z + revenue=572000000 + running_time=131 + ]; + 0x0312de17a7ee89f9 [name="Luke Skywalker"]; + 0x3da8d1dcab1bb381 [name="Han Solo"]; + 0x4a7d0b5fe91e78a4 [name="Irvin Kernshner"]; + 0x718337b9dcbaa7d9 [name="Princess Leia"]; + + // Edge definitions. + 0xa3cff1a4c3ef3bb6 -> 0x0312de17a7ee89f9 [label=starring]; + 0xa3cff1a4c3ef3bb6 -> 0x3da8d1dcab1bb381 [label=starring]; + 0xa3cff1a4c3ef3bb6 -> 0x4a7d0b5fe91e78a4 [label=director]; + 0xa3cff1a4c3ef3bb6 -> 0x718337b9dcbaa7d9 [label=starring]; + 0xb39aa14d66aedad5 -> 0x8a10d5a2611fd03f [label=director]; + 0xb39aa14d66aedad5 -> 0x0312de17a7ee89f9 [label=starring]; + 0xb39aa14d66aedad5 -> 0x3da8d1dcab1bb381 [label=starring]; + 0xb39aa14d66aedad5 -> 0x718337b9dcbaa7d9 [label=starring]; +}`, + }, + { + name: "tutorial", + json: dgraphTutorial, + roots: map[uint64]bool{ + 0xfd90205a458151f: true, + 0x52a80955d40ec819: true, + }, + wantDOT: `digraph { + // Node definitions. + 0x892a6da7ee1fbdec [ + age=55 + name=Sarah + ]; + 0x99b74c1b5ab100ec [ + age=35 + name=Artyom + ]; + 0xb9e12a67e34d6acc [ + age=19 + name=Catalina + ]; + 0xbf104824c777525d [name=Perro]; + 0xf590a923ea1fccaa [name=Goldie]; + 0xf92d7dbe272d680b [name="Hyung Sin"]; + 0x0fd90205a458151f [ + age=39 + name=Michael + ]; + 0x37734fcf0a6fcc69 [name="Rammy the sheep"]; + 0x52a80955d40ec819 [ + age=35 + name=Amit + ]; + 0x5e9ad1cd9466228c [ + age=24 + name="Sang Hyun" + ]; + + // Edge definitions. + 0xb9e12a67e34d6acc -> 0xbf104824c777525d [label=owns_pet]; + 0xb9e12a67e34d6acc -> 0x5e9ad1cd9466228c [label=friend]; + 0xf92d7dbe272d680b -> 0x5e9ad1cd9466228c [label=friend]; + 0x0fd90205a458151f -> 0x892a6da7ee1fbdec [label=friend]; + 0x0fd90205a458151f -> 0x99b74c1b5ab100ec [label=friend]; + 0x0fd90205a458151f -> 0xb9e12a67e34d6acc [label=friend]; + 0x0fd90205a458151f -> 0x37734fcf0a6fcc69 [label=owns_pet]; + 0x0fd90205a458151f -> 0x52a80955d40ec819 [label=friend]; + 0x0fd90205a458151f -> 0x5e9ad1cd9466228c [label=friend]; + 0x52a80955d40ec819 -> 0x99b74c1b5ab100ec [label=friend]; + 0x52a80955d40ec819 -> 0x0fd90205a458151f [label=friend]; + 0x52a80955d40ec819 -> 0x5e9ad1cd9466228c [label=friend]; + 0x5e9ad1cd9466228c -> 0xb9e12a67e34d6acc [label=friend]; + 0x5e9ad1cd9466228c -> 0xf590a923ea1fccaa [label=owns_pet]; + 0x5e9ad1cd9466228c -> 0xf92d7dbe272d680b [label=friend]; + 0x5e9ad1cd9466228c -> 0x52a80955d40ec819 [label=friend]; +}`, + }, + { + name: "tutorial missing IDs", + json: dgraphTutorialMissingIDs, + wantErr: errors.New("graphql: no UID for node"), // Incomplete error string. + }, +} + +func TestDecode(t *testing.T) { + for _, test := range decodeTests { + dst := newDirectedGraph() + err := Unmarshal([]byte(test.json), "_uid_", dst) + if test.wantErr == nil && err != nil { + t.Errorf("failed to unmarshal GraphQL JSON graph for %q: %v", test.name, err) + } else if test.wantErr != nil { + if err == nil { + t.Errorf("expected error for %q: got:%v want:%v", test.name, err, test.wantErr) + } + continue + } + b, err := dot.Marshal(dst, "", "", " ", false) + if err != nil { + t.Fatalf("failed to DOT marshal graph %q: %v", test.name, err) + } + gotDOT := string(b) + if gotDOT != test.wantDOT { + t.Errorf("unexpected DOT encoding for %q:\ngot:\n%s\nwant:\n%s", test.name, gotDOT, test.wantDOT) + } + } +} + +type directedGraph struct { + *simple.DirectedGraph +} + +func newDirectedGraph() *directedGraph { + return &directedGraph{DirectedGraph: simple.NewDirectedGraph()} +} + +func (g *directedGraph) NewNode() graph.Node { + return &node{attributes: make(attributes)} +} + +func (g *directedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &edge{Edge: g.DirectedGraph.NewEdge(from, to)} +} + +type node struct { + id uint64 + attributes +} + +func (n *node) ID() int64 { return int64(n.id) } +func (n *node) DOTID() string { return fmt.Sprintf("0x%016x", uint64(n.id)) } + +func (n *node) SetIDFromString(uid string) error { + if !strings.HasPrefix(uid, "0x") { + return fmt.Errorf("uid is not hex value: %q", uid) + } + var err error + n.id, err = strconv.ParseUint(uid[2:], 16, 64) + return err +} + +type edge struct { + graph.Edge + label string +} + +func (e *edge) SetLabel(l string) { + e.label = l +} + +func (e *edge) Attributes() []encoding.Attribute { + return []encoding.Attribute{{"label", e.label}} +} + +type attributes map[string]encoding.Attribute + +func (a attributes) SetAttribute(attr encoding.Attribute) error { + a[attr.Key] = attr + return nil +} + +func (a attributes) Attributes() []encoding.Attribute { + keys := make([]string, 0, len(a)) + for k := range a { + keys = append(keys, k) + } + sort.Strings(keys) + attr := make([]encoding.Attribute, 0, len(keys)) + for _, k := range keys { + v := a[k] + if strings.Contains(v.Value, " ") { + v.Value = `"` + v.Value + `"` + } + attr = append(attr, v) + } + return attr +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/graphql/doc.go b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/doc.go new file mode 100644 index 00000000..dd405034 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 graphql implements JSON marshaling and unmarshaling of graph as +// used by GraphQL +package graphql // import "gonum.org/v1/gonum/graph/encoding/graphql" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphql.go b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphql.go new file mode 100644 index 00000000..7598cb1a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphql.go @@ -0,0 +1,5 @@ +// Copyright ©2017 The gonum 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 graphql diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphs_test.go b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphs_test.go new file mode 100644 index 00000000..0e90348f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/encoding/graphql/graphs_test.go @@ -0,0 +1,1013 @@ +// Copyright ©2017 The gonum 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 graphql + +const ( + starwars = `{ + "movie": [ + { + "_uid_": "0xa3cff1a4c3ef3bb6", + "director": [ + { + "_uid_": "0x4a7d0b5fe91e78a4", + "name": "Irvin Kernshner" + } + ], + "name": "Star Wars: Episode V - The Empire Strikes Back", + "release_date": "1980-05-21T00:00:00Z", + "revenue": 534000000, + "running_time": 124, + "starring": [ + { + "_uid_": "0x312de17a7ee89f9", + "name": "Luke Skywalker" + }, + { + "_uid_": "0x3da8d1dcab1bb381", + "name": "Han Solo" + }, + { + "_uid_": "0x718337b9dcbaa7d9", + "name": "Princess Leia" + } + ] + }, + { + "_uid_": "0xb39aa14d66aedad5", + "director": [ + { + "_uid_": "0x8a10d5a2611fd03f", + "name": "Richard Marquand" + } + ], + "name": "Star Wars: Episode VI - Return of the Jedi", + "release_date": "1983-05-25T00:00:00Z", + "revenue": 572000000, + "running_time": 131, + "starring": [ + { + "_uid_": "0x312de17a7ee89f9", + "name": "Luke Skywalker" + }, + { + "_uid_": "0x3da8d1dcab1bb381", + "name": "Han Solo" + }, + { + "_uid_": "0x718337b9dcbaa7d9", + "name": "Princess Leia" + } + ] + } + ] +} +` + + dgraphTutorialMissingIDs = `{ + "everyone": [ + { + "_uid_": "0xfd90205a458151f", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "age": 39, + "friend": [ + { + "age": 35, + "name": "Amit" + }, + { + "age": 24, + "name": "Sang Hyun" + }, + { + "age": 55, + "name": "Sarah" + }, + { + "age": 35, + "name": "Artyom" + }, + { + "age": 19, + "name": "Catalina" + } + ], + "name": "Michael", + "owns_pet": [ + { + "name": "Rammy the sheep" + } + ] + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "age": 35, + "name": "Amit" + }, + { + "age": 19, + "name": "Catalina" + }, + { + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "name": "Goldie" + } + ] + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "age": 39, + "name": "Michael" + }, + { + "age": 24, + "name": "Sang Hyun" + }, + { + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "age": 24, + "name": "Sang Hyun" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "name": "Perro" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "age": 24, + "name": "Sang Hyun" + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun" + }, + { + "_uid_": "0x892a6da7ee1fbdec", + "name": "Sarah" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "name": "Artyom" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "age": 35, + "name": "Amit" + }, + { + "age": 19, + "name": "Catalina" + }, + { + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "name": "Goldie" + } + ] + } + ], + "name": "Catalina" + } + ], + "name": "Michael" + }, + { + "_uid_": "0x52a80955d40ec819", + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "age": 39, + "name": "Michael" + }, + { + "age": 24, + "name": "Sang Hyun" + }, + { + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "age": 35, + "name": "Amit" + }, + { + "age": 19, + "name": "Catalina" + }, + { + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "name": "Goldie" + } + ] + }, + { + "_uid_": "0x892a6da7ee1fbdec", + "age": 55, + "name": "Sarah" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "age": 24, + "name": "Sang Hyun" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "name": "Perro" + } + ] + } + ], + "name": "Michael" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "age": 39, + "name": "Michael" + }, + { + "age": 24, + "name": "Sang Hyun" + }, + { + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "age": 24, + "name": "Sang Hyun" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "name": "Perro" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "age": 24, + "name": "Sang Hyun" + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "name": "Artyom" + } + ], + "name": "Amit" + } + ] +} +` + + dgraphTutorial = `{ + "everyone": [ + { + "_uid_": "0xfd90205a458151f", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "age": 39, + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + } + ], + "name": "Amit" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + }, + { + "_uid_": "0x892a6da7ee1fbdec", + "age": 55, + "name": "Sarah" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d" + } + ] + } + ], + "name": "Michael", + "owns_pet": [ + { + "_uid_": "0x37734fcf0a6fcc69", + "name": "Rammy the sheep" + } + ] + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa", + "name": "Goldie" + } + ] + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "age": 39, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x892a6da7ee1fbdec" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + } + ], + "name": "Michael", + "owns_pet": [ + { + "_uid_": "0x37734fcf0a6fcc69" + } + ] + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d", + "name": "Perro" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun" + }, + { + "_uid_": "0x892a6da7ee1fbdec", + "name": "Sarah" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "name": "Artyom" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa", + "name": "Goldie" + } + ] + } + ], + "name": "Catalina" + } + ], + "name": "Michael" + }, + { + "_uid_": "0x52a80955d40ec819", + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "age": 39, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x892a6da7ee1fbdec" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + } + ], + "name": "Michael", + "owns_pet": [ + { + "_uid_": "0x37734fcf0a6fcc69" + } + ] + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c" + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa", + "name": "Goldie" + } + ] + }, + { + "_uid_": "0x892a6da7ee1fbdec", + "age": 55, + "name": "Sarah" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d", + "name": "Perro" + } + ] + } + ], + "name": "Michael" + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "friend": [ + { + "_uid_": "0x52a80955d40ec819", + "age": 35, + "friend": [ + { + "_uid_": "0xfd90205a458151f", + "age": 39, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0x5e9ad1cd9466228c" + }, + { + "_uid_": "0x892a6da7ee1fbdec" + }, + { + "_uid_": "0x99b74c1b5ab100ec" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + } + ], + "name": "Michael", + "owns_pet": [ + { + "_uid_": "0x37734fcf0a6fcc69" + } + ] + }, + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "age": 35, + "name": "Artyom" + } + ], + "name": "Amit" + }, + { + "_uid_": "0xb9e12a67e34d6acc", + "age": 19, + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + } + ], + "name": "Catalina", + "owns_pet": [ + { + "_uid_": "0xbf104824c777525d", + "name": "Perro" + } + ] + }, + { + "_uid_": "0xf92d7dbe272d680b", + "friend": [ + { + "_uid_": "0x5e9ad1cd9466228c", + "age": 24, + "friend": [ + { + "_uid_": "0x52a80955d40ec819" + }, + { + "_uid_": "0xb9e12a67e34d6acc" + }, + { + "_uid_": "0xf92d7dbe272d680b" + } + ], + "name": "Sang Hyun", + "owns_pet": [ + { + "_uid_": "0xf590a923ea1fccaa" + } + ] + } + ], + "name": "Hyung Sin" + } + ], + "name": "Sang Hyun" + }, + { + "_uid_": "0x99b74c1b5ab100ec", + "name": "Artyom" + } + ], + "name": "Amit" + } + ] +} +` +) diff --git a/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/gn.go b/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/gn.go new file mode 100644 index 00000000..bcb1aad1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/gn.go @@ -0,0 +1,278 @@ +package main + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type GraphNode struct { + id int64 + neighbors []graph.Node + roots []*GraphNode +} + +func (g *GraphNode) Has(n graph.Node) bool { + if n.ID() == g.id { + return true + } + + visited := map[int64]struct{}{g.id: {}} + for _, root := range g.roots { + if root.ID() == n.ID() { + return true + } + + if root.has(n, visited) { + return true + } + } + + for _, neigh := range g.neighbors { + if neigh.ID() == n.ID() { + return true + } + + if gn, ok := neigh.(*GraphNode); ok { + if gn.has(n, visited) { + return true + } + } + } + + return false +} + +func (g *GraphNode) has(n graph.Node, visited map[int64]struct{}) bool { + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + + visited[root.ID()] = struct{}{} + if root.ID() == n.ID() { + return true + } + + if root.has(n, visited) { + return true + } + + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + visited[neigh.ID()] = struct{}{} + if neigh.ID() == n.ID() { + return true + } + + if gn, ok := neigh.(*GraphNode); ok { + if gn.has(n, visited) { + return true + } + } + + } + + return false +} + +func (g *GraphNode) Nodes() []graph.Node { + toReturn := []graph.Node{g} + visited := map[int64]struct{}{g.id: {}} + + for _, root := range g.roots { + toReturn = append(toReturn, root) + visited[root.ID()] = struct{}{} + + toReturn = root.nodes(toReturn, visited) + } + + for _, neigh := range g.neighbors { + toReturn = append(toReturn, neigh) + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + toReturn = gn.nodes(toReturn, visited) + } + } + + return toReturn +} + +func (g *GraphNode) nodes(list []graph.Node, visited map[int64]struct{}) []graph.Node { + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + list = append(list, graph.Node(root)) + + list = root.nodes(list, visited) + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + list = append(list, neigh) + if gn, ok := neigh.(*GraphNode); ok { + list = gn.nodes(list, visited) + } + } + + return list +} + +func (g *GraphNode) From(n graph.Node) []graph.Node { + if n.ID() == g.ID() { + return g.neighbors + } + + visited := map[int64]struct{}{g.id: {}} + for _, root := range g.roots { + visited[root.ID()] = struct{}{} + + if result := root.findNeighbors(n, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.findNeighbors(n, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) findNeighbors(n graph.Node, visited map[int64]struct{}) []graph.Node { + if n.ID() == g.ID() { + return g.neighbors + } + + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + + if result := root.findNeighbors(n, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.findNeighbors(n, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) HasEdgeBetween(u, v graph.Node) bool { + return g.EdgeBetween(u, v) != nil +} + +func (g *GraphNode) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +func (g *GraphNode) EdgeBetween(u, v graph.Node) graph.Edge { + if u.ID() == g.id || v.ID() == g.id { + for _, neigh := range g.neighbors { + if neigh.ID() == u.ID() || neigh.ID() == v.ID() { + return simple.Edge{F: g, T: neigh} + } + } + return nil + } + + visited := map[int64]struct{}{g.id: {}} + for _, root := range g.roots { + visited[root.ID()] = struct{}{} + if result := root.edgeBetween(u, v, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + visited[neigh.ID()] = struct{}{} + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.edgeBetween(u, v, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) edgeBetween(u, v graph.Node, visited map[int64]struct{}) graph.Edge { + if u.ID() == g.id || v.ID() == g.id { + for _, neigh := range g.neighbors { + if neigh.ID() == u.ID() || neigh.ID() == v.ID() { + return simple.Edge{F: g, T: neigh} + } + } + return nil + } + + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + if result := root.edgeBetween(u, v, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + visited[neigh.ID()] = struct{}{} + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.edgeBetween(u, v, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) ID() int64 { + return g.id +} + +func (g *GraphNode) AddNeighbor(n *GraphNode) { + g.neighbors = append(g.neighbors, graph.Node(n)) +} + +func (g *GraphNode) AddRoot(n *GraphNode) { + g.roots = append(g.roots, n) +} + +func NewGraphNode(id int64) *GraphNode { + return &GraphNode{id: id} +} diff --git a/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/main.go b/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/main.go new file mode 100644 index 00000000..eb14226a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/ex/fdpclust/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/topo" +) + +func main() { + // graph G { + G := NewGraphNode(0) + // e + e := NewGraphNode(1) + + // subgraph clusterA { + clusterA := NewGraphNode(2) + + // a -- b + a := NewGraphNode(3) + b := NewGraphNode(4) + a.AddNeighbor(b) + b.AddNeighbor(a) + clusterA.AddRoot(a) + clusterA.AddRoot(b) + + // subgraph clusterC { + clusterC := NewGraphNode(5) + // C -- D + C := NewGraphNode(6) + D := NewGraphNode(7) + C.AddNeighbor(D) + D.AddNeighbor(C) + + clusterC.AddRoot(C) + clusterC.AddRoot(D) + // } + clusterA.AddRoot(clusterC) + // } + + // subgraph clusterB { + clusterB := NewGraphNode(8) + + // d -- f + d := NewGraphNode(9) + f := NewGraphNode(10) + d.AddNeighbor(f) + f.AddNeighbor(d) + clusterB.AddRoot(d) + clusterB.AddRoot(f) + // } + + // d -- D + d.AddNeighbor(D) + D.AddNeighbor(d) + + // e -- clusterB + e.AddNeighbor(clusterB) + clusterB.AddNeighbor(e) + + // clusterC -- clusterB + clusterC.AddNeighbor(clusterB) + clusterB.AddNeighbor(clusterC) + + G.AddRoot(e) + G.AddRoot(clusterA) + G.AddRoot(clusterB) + // } + + if !topo.IsPathIn(G, []graph.Node{C, D, d, f}) { + fmt.Println("Not working!") + } else { + fmt.Println("Working!") + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/README.md b/vendor/gonum.org/v1/gonum/graph/formats/dot/README.md new file mode 100644 index 00000000..a26ca902 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/README.md @@ -0,0 +1,9 @@ +# formats/dot + +## License + +The source code and any original content of the formats/dot directory is released under [Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/). + +The source code is also licensed under the gonum license, and users are free to choose the license which suits their needs. + +Please see gonum.org/v1/gonum for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast.go new file mode 100644 index 00000000..8bb961ce --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast.go @@ -0,0 +1,406 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package ast + +import ( + "bytes" + "fmt" +) + +// === [ File ] ================================================================ + +// A File represents a DOT file. +// +// Examples. +// +// digraph G { +// A -> B +// } +// graph H { +// C - D +// } +type File struct { + // Graphs. + Graphs []*Graph +} + +// String returns the string representation of the file. +func (f *File) String() string { + buf := new(bytes.Buffer) + for i, graph := range f.Graphs { + if i != 0 { + buf.WriteString("\n") + } + buf.WriteString(graph.String()) + } + return buf.String() +} + +// === [ Graphs ] ============================================================== + +// A Graph represents a directed or an undirected graph. +// +// Examples. +// +// digraph G { +// A -> {B C} +// B -> C +// } +type Graph struct { + // Strict graph; multi-edges forbidden. + Strict bool + // Directed graph. + Directed bool + // Graph ID; or empty if anonymous. + ID string + // Graph statements. + Stmts []Stmt +} + +// String returns the string representation of the graph. +func (g *Graph) String() string { + buf := new(bytes.Buffer) + if g.Strict { + buf.WriteString("strict ") + } + if g.Directed { + buf.WriteString("digraph ") + } else { + buf.WriteString("graph ") + } + if len(g.ID) > 0 { + fmt.Fprintf(buf, "%s ", g.ID) + } + buf.WriteString("{\n") + for _, stmt := range g.Stmts { + fmt.Fprintf(buf, "\t%s\n", stmt) + } + buf.WriteString("}") + return buf.String() +} + +// === [ Statements ] ========================================================== + +// A Stmt represents a statement, and has one of the following underlying types. +// +// *NodeStmt +// *EdgeStmt +// *AttrStmt +// *Attr +// *Subgraph +type Stmt interface { + fmt.Stringer + // isStmt ensures that only statements can be assigned to the Stmt interface. + isStmt() +} + +// --- [ Node statement ] ------------------------------------------------------ + +// A NodeStmt represents a node statement. +// +// Examples. +// +// A [color=blue] +type NodeStmt struct { + // Node. + Node *Node + // Node attributes. + Attrs []*Attr +} + +// String returns the string representation of the node statement. +func (e *NodeStmt) String() string { + buf := new(bytes.Buffer) + buf.WriteString(e.Node.String()) + if len(e.Attrs) > 0 { + buf.WriteString(" [") + for i, attr := range e.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + } + return buf.String() +} + +// --- [ Edge statement ] ------------------------------------------------------ + +// An EdgeStmt represents an edge statement. +// +// Examples. +// +// A -> B +// A -> {B C} +// A -> B -> C +type EdgeStmt struct { + // Source vertex. + From Vertex + // Outgoing edge. + To *Edge + // Edge attributes. + Attrs []*Attr +} + +// String returns the string representation of the edge statement. +func (e *EdgeStmt) String() string { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s %s", e.From, e.To) + if len(e.Attrs) > 0 { + buf.WriteString(" [") + for i, attr := range e.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + } + return buf.String() +} + +// An Edge represents an edge between two vertices. +type Edge struct { + // Directed edge. + Directed bool + // Destination vertex. + Vertex Vertex + // Outgoing edge; or nil if none. + To *Edge +} + +// String returns the string representation of the edge. +func (e *Edge) String() string { + op := "--" + if e.Directed { + op = "->" + } + if e.To != nil { + return fmt.Sprintf("%s %s %s", op, e.Vertex, e.To) + } + return fmt.Sprintf("%s %s", op, e.Vertex) +} + +// --- [ Attribute statement ] ------------------------------------------------- + +// An AttrStmt represents an attribute statement. +// +// Examples. +// +// graph [rankdir=LR] +// node [color=blue fillcolor=red] +// edge [minlen=1] +type AttrStmt struct { + // Graph component kind to which the attributes are assigned. + Kind Kind + // Attributes. + Attrs []*Attr +} + +// String returns the string representation of the attribute statement. +func (a *AttrStmt) String() string { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s [", a.Kind) + for i, attr := range a.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + return buf.String() +} + +// Kind specifies the set of graph components to which attribute statements may +// be assigned. +type Kind uint + +// Graph component kinds. +const ( + GraphKind Kind = iota // graph + NodeKind // node + EdgeKind // edge +) + +// String returns the string representation of the graph component kind. +func (k Kind) String() string { + switch k { + case GraphKind: + return "graph" + case NodeKind: + return "node" + case EdgeKind: + return "edge" + } + panic(fmt.Sprintf("invalid graph component kind (%d)", k)) +} + +// --- [ Attribute ] ----------------------------------------------------------- + +// An Attr represents an attribute. +// +// Examples. +// +// rank=same +type Attr struct { + // Attribute key. + Key string + // Attribute value. + Val string +} + +// String returns the string representation of the attribute. +func (a *Attr) String() string { + return fmt.Sprintf("%s=%s", a.Key, a.Val) +} + +// --- [ Subgraph ] ------------------------------------------------------------ + +// A Subgraph represents a subgraph vertex. +// +// Examples. +// +// subgraph S {A B C} +type Subgraph struct { + // Subgraph ID; or empty if none. + ID string + // Subgraph statements. + Stmts []Stmt +} + +// String returns the string representation of the subgraph. +func (s *Subgraph) String() string { + buf := new(bytes.Buffer) + if len(s.ID) > 0 { + fmt.Fprintf(buf, "subgraph %s ", s.ID) + } + buf.WriteString("{") + for i, stmt := range s.Stmts { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(stmt.String()) + } + buf.WriteString("}") + return buf.String() +} + +// isStmt ensures that only statements can be assigned to the Stmt interface. +func (*NodeStmt) isStmt() {} +func (*EdgeStmt) isStmt() {} +func (*AttrStmt) isStmt() {} +func (*Attr) isStmt() {} +func (*Subgraph) isStmt() {} + +// === [ Vertices ] ============================================================ + +// A Vertex represents a vertex, and has one of the following underlying types. +// +// *Node +// *Subgraph +type Vertex interface { + fmt.Stringer + // isVertex ensures that only vertices can be assigned to the Vertex + // interface. + isVertex() +} + +// --- [ Node identifier ] ----------------------------------------------------- + +// A Node represents a node vertex. +// +// Examples. +// +// A +// A:nw +type Node struct { + // Node ID. + ID string + // Node port; or nil if none. + Port *Port +} + +// String returns the string representation of the node. +func (n *Node) String() string { + if n.Port != nil { + return fmt.Sprintf("%s%s", n.ID, n.Port) + } + return n.ID +} + +// A Port specifies where on a node an edge should be aimed. +type Port struct { + // Port ID; or empty if none. + ID string + // Compass point. + CompassPoint CompassPoint +} + +// String returns the string representation of the port. +func (p *Port) String() string { + buf := new(bytes.Buffer) + if len(p.ID) > 0 { + fmt.Fprintf(buf, ":%s", p.ID) + } + if p.CompassPoint != CompassPointDefault { + fmt.Fprintf(buf, ":%s", p.CompassPoint) + } + return buf.String() +} + +// CompassPoint specifies the set of compass points. +type CompassPoint uint + +// Compass points. +const ( + CompassPointDefault CompassPoint = iota // _ + CompassPointNorth // n + CompassPointNorthEast // ne + CompassPointEast // e + CompassPointSouthEast // se + CompassPointSouth // s + CompassPointSouthWest // sw + CompassPointWest // w + CompassPointNorthWest // nw + CompassPointCenter // c +) + +// String returns the string representation of the compass point. +func (c CompassPoint) String() string { + switch c { + case CompassPointDefault: + return "_" + case CompassPointNorth: + return "n" + case CompassPointNorthEast: + return "ne" + case CompassPointEast: + return "e" + case CompassPointSouthEast: + return "se" + case CompassPointSouth: + return "s" + case CompassPointSouthWest: + return "sw" + case CompassPointWest: + return "w" + case CompassPointNorthWest: + return "nw" + case CompassPointCenter: + return "c" + } + panic(fmt.Sprintf("invalid compass point (%d)", uint(c))) +} + +// isVertex ensures that only vertices can be assigned to the Vertex interface. +func (*Node) isVertex() {} +func (*Subgraph) isVertex() {} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast_test.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast_test.go new file mode 100644 index 00000000..2417dce5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/ast_test.go @@ -0,0 +1,101 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package ast_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" + "gonum.org/v1/gonum/graph/formats/dot/ast" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../internal/testdata/empty.dot"}, + {in: "../internal/testdata/graph.dot"}, + {in: "../internal/testdata/digraph.dot"}, + {in: "../internal/testdata/strict.dot"}, + {in: "../internal/testdata/multi.dot"}, + {in: "../internal/testdata/named_graph.dot"}, + {in: "../internal/testdata/node_stmt.dot"}, + {in: "../internal/testdata/edge_stmt.dot"}, + {in: "../internal/testdata/attr_stmt.dot"}, + {in: "../internal/testdata/attr.dot"}, + { + in: "../internal/testdata/subgraph.dot", + out: "../internal/testdata/subgraph.golden", + }, + { + in: "../internal/testdata/semi.dot", + out: "../internal/testdata/semi.golden", + }, + { + in: "../internal/testdata/empty_attr.dot", + out: "../internal/testdata/empty_attr.golden", + }, + { + in: "../internal/testdata/attr_lists.dot", + out: "../internal/testdata/attr_lists.golden", + }, + { + in: "../internal/testdata/attr_sep.dot", + out: "../internal/testdata/attr_sep.golden", + }, + {in: "../internal/testdata/subgraph_vertex.dot"}, + { + in: "../internal/testdata/port.dot", + out: "../internal/testdata/port.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected %q, got %q", g.in, want, got) + } + } +} + +// Verify that all statements implement the Stmt interface. +var ( + _ ast.Stmt = (*ast.NodeStmt)(nil) + _ ast.Stmt = (*ast.EdgeStmt)(nil) + _ ast.Stmt = (*ast.AttrStmt)(nil) + _ ast.Stmt = (*ast.Attr)(nil) + _ ast.Stmt = (*ast.Subgraph)(nil) +) + +// Verify that all vertices implement the Vertex interface. +var ( + _ ast.Vertex = (*ast.Node)(nil) + _ ast.Vertex = (*ast.Subgraph)(nil) +) diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/doc.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/doc.go new file mode 100644 index 00000000..2d96617c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/ast/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 ast declares the types used to represent abstract syntax trees of +// Graphviz DOT graphs. +package ast // import "gonum.org/v1/gonum/graph/formats/dot/ast" diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/doc.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/doc.go new file mode 100644 index 00000000..4337ff08 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 dot implements a parser for Graphviz DOT files. +package dot // import "gonum.org/v1/gonum/graph/formats/dot" diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/dot.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/dot.go new file mode 100644 index 00000000..edc44f68 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/dot.go @@ -0,0 +1,64 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +//go:generate ./makeinternal.bash + +package dot + +import ( + "fmt" + "io" + "io/ioutil" + + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/lexer" + "gonum.org/v1/gonum/graph/formats/dot/internal/parser" +) + +// ParseFile parses the given Graphviz DOT file into an AST. +func ParseFile(path string) (*ast.File, error) { + buf, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return ParseBytes(buf) +} + +// Parse parses the given Graphviz DOT file into an AST, reading from r. +func Parse(r io.Reader) (*ast.File, error) { + buf, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + return ParseBytes(buf) +} + +// ParseBytes parses the given Graphviz DOT file into an AST, reading from b. +func ParseBytes(b []byte) (*ast.File, error) { + l := lexer.NewLexer(b) + p := parser.NewParser() + file, err := p.Parse(l) + if err != nil { + return nil, err + } + f, ok := file.(*ast.File) + if !ok { + return nil, fmt.Errorf("invalid file type; expected *ast.File, got %T", file) + } + if err := check(f); err != nil { + return nil, err + } + return f, nil +} + +// ParseString parses the given Graphviz DOT file into an AST, reading from s. +func ParseString(s string) (*ast.File, error) { + return ParseBytes([]byte(s)) +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/Makefile b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/Makefile new file mode 100644 index 00000000..ba04504a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/Makefile @@ -0,0 +1,33 @@ +gen: dot.bnf + gocc $< + ./paste_copyright.bash + +debug_lexer: dot.bnf + gocc -debug_lexer -v -a $< + ./paste_copyright.bash + +debug_parser: dot.bnf + gocc -debug_parser -v -a $< + ./paste_copyright.bash + +clean: + rm -f errors/errors.go + rm -f lexer/acttab.go + rm -f lexer/lexer.go + rm -f lexer/transitiontable.go + rm -f parser/action.go + rm -f parser/actiontable.go + rm -f parser/gototable.go + rm -f parser/parser.go + rm -f parser/productionstable.go + rm -f token/token.go + rm -f util/litconv.go + rm -f util/rune.go + -rmdir --ignore-fail-on-non-empty errors + -rmdir --ignore-fail-on-non-empty lexer + -rmdir --ignore-fail-on-non-empty parser + -rmdir --ignore-fail-on-non-empty token + -rmdir --ignore-fail-on-non-empty util + rm -f terminals.txt LR1_conflicts.txt LR1_sets.txt first.txt lexer_sets.txt + +.PHONY: gen debug_lexer debug_parser clean diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx.go new file mode 100644 index 00000000..1b3bff55 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx.go @@ -0,0 +1,326 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package astx + +import ( + "fmt" + "strings" + + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +// === [ File ] ================================================================ + +// NewFile returns a new file based on the given graph. +func NewFile(graph interface{}) (*ast.File, error) { + g, ok := graph.(*ast.Graph) + if !ok { + return nil, fmt.Errorf("invalid graph type; expected *ast.Graph, got %T", graph) + } + return &ast.File{Graphs: []*ast.Graph{g}}, nil +} + +// AppendGraph appends graph to the given file. +func AppendGraph(file, graph interface{}) (*ast.File, error) { + f, ok := file.(*ast.File) + if !ok { + return nil, fmt.Errorf("invalid file type; expected *ast.File, got %T", file) + } + g, ok := graph.(*ast.Graph) + if !ok { + return nil, fmt.Errorf("invalid graph type; expected *ast.Graph, got %T", graph) + } + f.Graphs = append(f.Graphs, g) + return f, nil +} + +// === [ Graphs ] ============================================================== + +// NewGraph returns a new graph based on the given graph strictness, direction, +// optional ID and optional statements. +func NewGraph(strict, directed, optID, optStmts interface{}) (*ast.Graph, error) { + s, ok := strict.(bool) + if !ok { + return nil, fmt.Errorf("invalid strictness type; expected bool, got %T", strict) + } + d, ok := directed.(bool) + if !ok { + return nil, fmt.Errorf("invalid direction type; expected bool, got %T", directed) + } + id, ok := optID.(string) + if optID != nil && !ok { + return nil, fmt.Errorf("invalid ID type; expected string or nil, got %T", optID) + } + stmts, ok := optStmts.([]ast.Stmt) + if optStmts != nil && !ok { + return nil, fmt.Errorf("invalid statements type; expected []ast.Stmt or nil, got %T", optStmts) + } + return &ast.Graph{Strict: s, Directed: d, ID: id, Stmts: stmts}, nil +} + +// === [ Statements ] ========================================================== + +// NewStmtList returns a new statement list based on the given statement. +func NewStmtList(stmt interface{}) ([]ast.Stmt, error) { + s, ok := stmt.(ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement type; expected ast.Stmt, got %T", stmt) + } + return []ast.Stmt{s}, nil +} + +// AppendStmt appends stmt to the given statement list. +func AppendStmt(list, stmt interface{}) ([]ast.Stmt, error) { + l, ok := list.([]ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement list type; expected []ast.Stmt, got %T", list) + } + s, ok := stmt.(ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement type; expected ast.Stmt, got %T", stmt) + } + return append(l, s), nil +} + +// --- [ Node statement ] ------------------------------------------------------ + +// NewNodeStmt returns a new node statement based on the given node and optional +// attributes. +func NewNodeStmt(node, optAttrs interface{}) (*ast.NodeStmt, error) { + n, ok := node.(*ast.Node) + if !ok { + return nil, fmt.Errorf("invalid node type; expected *ast.Node, got %T", node) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.NodeStmt{Node: n, Attrs: attrs}, nil +} + +// --- [ Edge statement ] ------------------------------------------------------ + +// NewEdgeStmt returns a new edge statement based on the given source vertex, +// outgoing edge and optional attributes. +func NewEdgeStmt(from, to, optAttrs interface{}) (*ast.EdgeStmt, error) { + f, ok := from.(ast.Vertex) + if !ok { + return nil, fmt.Errorf("invalid source vertex type; expected ast.Vertex, got %T", from) + } + t, ok := to.(*ast.Edge) + if !ok { + return nil, fmt.Errorf("invalid outgoing edge type; expected *ast.Edge, got %T", to) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.EdgeStmt{From: f, To: t, Attrs: attrs}, nil +} + +// NewEdge returns a new edge based on the given edge direction, destination +// vertex and optional outgoing edge. +func NewEdge(directed, vertex, optTo interface{}) (*ast.Edge, error) { + d, ok := directed.(bool) + if !ok { + return nil, fmt.Errorf("invalid direction type; expected bool, got %T", directed) + } + v, ok := vertex.(ast.Vertex) + if !ok { + return nil, fmt.Errorf("invalid destination vertex type; expected ast.Vertex, got %T", vertex) + } + to, ok := optTo.(*ast.Edge) + if optTo != nil && !ok { + return nil, fmt.Errorf("invalid outgoing edge type; expected *ast.Edge or nil, got %T", optTo) + } + return &ast.Edge{Directed: d, Vertex: v, To: to}, nil +} + +// --- [ Attribute statement ] ------------------------------------------------- + +// NewAttrStmt returns a new attribute statement based on the given graph +// component kind and attributes. +func NewAttrStmt(kind, optAttrs interface{}) (*ast.AttrStmt, error) { + k, ok := kind.(ast.Kind) + if !ok { + return nil, fmt.Errorf("invalid graph component kind type; expected ast.Kind, got %T", kind) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.AttrStmt{Kind: k, Attrs: attrs}, nil +} + +// NewAttrList returns a new attribute list based on the given attribute. +func NewAttrList(attr interface{}) ([]*ast.Attr, error) { + a, ok := attr.(*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute type; expected *ast.Attr, got %T", attr) + } + return []*ast.Attr{a}, nil +} + +// AppendAttr appends attr to the given attribute list. +func AppendAttr(list, attr interface{}) ([]*ast.Attr, error) { + l, ok := list.([]*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute list type; expected []*ast.Attr, got %T", list) + } + a, ok := attr.(*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute type; expected *ast.Attr, got %T", attr) + } + return append(l, a), nil +} + +// AppendAttrList appends the optional attrs to the given optional attribute +// list. +func AppendAttrList(optList, optAttrs interface{}) ([]*ast.Attr, error) { + list, ok := optList.([]*ast.Attr) + if optList != nil && !ok { + return nil, fmt.Errorf("invalid attribute list type; expected []*ast.Attr or nil, got %T", optList) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return append(list, attrs...), nil +} + +// --- [ Attribute ] ----------------------------------------------------------- + +// NewAttr returns a new attribute based on the given key-value pair. +func NewAttr(key, val interface{}) (*ast.Attr, error) { + k, ok := key.(string) + if !ok { + return nil, fmt.Errorf("invalid key type; expected string, got %T", key) + } + v, ok := val.(string) + if !ok { + return nil, fmt.Errorf("invalid value type; expected string, got %T", val) + } + return &ast.Attr{Key: k, Val: v}, nil +} + +// --- [ Subgraph ] ------------------------------------------------------------ + +// NewSubgraph returns a new subgraph based on the given optional subgraph ID +// and optional statements. +func NewSubgraph(optID, optStmts interface{}) (*ast.Subgraph, error) { + id, ok := optID.(string) + if optID != nil && !ok { + return nil, fmt.Errorf("invalid ID type; expected string or nil, got %T", optID) + } + stmts, ok := optStmts.([]ast.Stmt) + if optStmts != nil && !ok { + return nil, fmt.Errorf("invalid statements type; expected []ast.Stmt or nil, got %T", optStmts) + } + return &ast.Subgraph{ID: id, Stmts: stmts}, nil +} + +// === [ Vertices ] ============================================================ + +// --- [ Node identifier ] ----------------------------------------------------- + +// NewNode returns a new node based on the given node id and optional port. +func NewNode(id, optPort interface{}) (*ast.Node, error) { + i, ok := id.(string) + if !ok { + return nil, fmt.Errorf("invalid ID type; expected string, got %T", id) + } + port, ok := optPort.(*ast.Port) + if optPort != nil && !ok { + return nil, fmt.Errorf("invalid port type; expected *ast.Port or nil, got %T", optPort) + } + return &ast.Node{ID: i, Port: port}, nil +} + +// NewPort returns a new port based on the given id and optional compass point. +func NewPort(id, optCompassPoint interface{}) (*ast.Port, error) { + // Note, if optCompassPoint is nil, id may be either an identifier or a + // compass point. + // + // The following strings are valid compass points: + // + // "n", "ne", "e", "se", "s", "sw", "w", "nw", "c" and "_" + i, ok := id.(string) + if !ok { + return nil, fmt.Errorf("invalid ID type; expected string, got %T", id) + } + + // Early return if optional compass point is absent and ID is a valid compass + // point. + if optCompassPoint == nil { + if compassPoint, ok := getCompassPoint(i); ok { + return &ast.Port{CompassPoint: compassPoint}, nil + } + } + + c, ok := optCompassPoint.(string) + if optCompassPoint != nil && !ok { + return nil, fmt.Errorf("invalid compass point type; expected string or nil, got %T", optCompassPoint) + } + compassPoint, _ := getCompassPoint(c) + return &ast.Port{ID: i, CompassPoint: compassPoint}, nil +} + +// getCompassPoint returns the corresponding compass point to the given string, +// and a boolean value indicating if such a compass point exists. +func getCompassPoint(s string) (ast.CompassPoint, bool) { + switch s { + case "_": + return ast.CompassPointDefault, true + case "n": + return ast.CompassPointNorth, true + case "ne": + return ast.CompassPointNorthEast, true + case "e": + return ast.CompassPointEast, true + case "se": + return ast.CompassPointSouthEast, true + case "s": + return ast.CompassPointSouth, true + case "sw": + return ast.CompassPointSouthWest, true + case "w": + return ast.CompassPointWest, true + case "nw": + return ast.CompassPointNorthWest, true + case "c": + return ast.CompassPointCenter, true + } + return ast.CompassPointDefault, false +} + +// === [ Identifiers ] ========================================================= + +// NewID returns a new identifier based on the given ID token. +func NewID(id interface{}) (string, error) { + i, ok := id.(*token.Token) + if !ok { + return "", fmt.Errorf("invalid identifier type; expected *token.Token, got %T", id) + } + s := string(i.Lit) + + // As another aid for readability, dot allows double-quoted strings to span + // multiple physical lines using the standard C convention of a backslash + // immediately preceding a newline character. + if strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) { + // Strip "\\\n" sequences. + s = strings.Replace(s, "\\\n", "", -1) + } + + // TODO: Add support for concatenated using a '+' operator. + + return s, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx_test.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx_test.go new file mode 100644 index 00000000..4ec55000 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/astx_test.go @@ -0,0 +1,90 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package astx_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../testdata/empty.dot"}, + {in: "../testdata/graph.dot"}, + {in: "../testdata/digraph.dot"}, + {in: "../testdata/strict.dot"}, + {in: "../testdata/multi.dot"}, + {in: "../testdata/named_graph.dot"}, + {in: "../testdata/node_stmt.dot"}, + {in: "../testdata/edge_stmt.dot"}, + {in: "../testdata/attr_stmt.dot"}, + {in: "../testdata/attr.dot"}, + { + in: "../testdata/subgraph.dot", + out: "../testdata/subgraph.golden", + }, + { + in: "../testdata/semi.dot", + out: "../testdata/semi.golden", + }, + { + in: "../testdata/empty_attr.dot", + out: "../testdata/empty_attr.golden", + }, + { + in: "../testdata/attr_lists.dot", + out: "../testdata/attr_lists.golden", + }, + { + in: "../testdata/attr_sep.dot", + out: "../testdata/attr_sep.golden", + }, + {in: "../testdata/subgraph_vertex.dot"}, + { + in: "../testdata/port.dot", + out: "../testdata/port.golden", + }, + {in: "../testdata/quoted_id.dot"}, + { + in: "../testdata/backslash_newline_id.dot", + out: "../testdata/backslash_newline_id.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected `%s`, got `%s`", g.in, want, got) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/doc.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/doc.go new file mode 100644 index 00000000..65fd9011 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/astx/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 astx implements utility functions for generating abstract syntax +// trees of Graphviz DOT graphs. +package astx // import "gonum.org/v1/gonum/graph/formats/dot/internal/astx" diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/dot.bnf b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/dot.bnf new file mode 100644 index 00000000..b2eafb3a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/dot.bnf @@ -0,0 +1,358 @@ +// The DOT Language +// +// http://www.graphviz.org/doc/info/lang.html + +// ### [ Tokens ] ############################################################## + +// The keywords node, edge, graph, digraph, subgraph, and strict are case- +// independent. + +node + : 'n' 'o' 'd' 'e' + | 'N' 'o' 'd' 'e' + | 'N' 'O' 'D' 'E' +; + +edge + : 'e' 'd' 'g' 'e' + | 'E' 'd' 'g' 'e' + | 'E' 'D' 'G' 'E' +; + +// TODO: Rename graphx to graph once gocc#20 is fixed [1]. +// +// [1]: https://github.com/goccmack/gocc/issues/20 + +graphx + : 'g' 'r' 'a' 'p' 'h' + | 'G' 'r' 'a' 'p' 'h' + | 'G' 'R' 'A' 'P' 'H' +; + +digraph + : 'd' 'i' 'g' 'r' 'a' 'p' 'h' + | 'D' 'i' 'g' 'r' 'a' 'p' 'h' + | 'd' 'i' 'G' 'r' 'a' 'p' 'h' + | 'D' 'i' 'G' 'r' 'a' 'p' 'h' + | 'D' 'I' 'G' 'R' 'A' 'P' 'H' +; + +subgraph + : 's' 'u' 'b' 'g' 'r' 'a' 'p' 'h' + | 'S' 'u' 'b' 'g' 'r' 'a' 'p' 'h' + | 's' 'u' 'b' 'G' 'r' 'a' 'p' 'h' + | 'S' 'u' 'b' 'G' 'r' 'a' 'p' 'h' + | 'S' 'U' 'B' 'G' 'R' 'A' 'P' 'H' +; + +strict + : 's' 't' 'r' 'i' 'c' 't' + | 'S' 't' 'r' 'i' 'c' 't' + | 'S' 'T' 'R' 'I' 'C' 'T' +; + +// An arbitrary ASCII character except null (0x00), double quote (0x22) and +// backslash (0x5C). +_ascii_char + // skip null (0x00) + : '\x01' - '\x21' + // skip double quote (0x22) + | '\x23' - '\x5B' + // skip backslash (0x5C) + | '\x5D' - '\x7F' +; + +_ascii_letter + : 'a' - 'z' + | 'A' - 'Z' +; + +_ascii_digit : '0' - '9' ; + +_unicode_char + : _ascii_char + | _unicode_byte +; + +_unicode_byte + : '\u0080' - '\uFFFC' + // skip invalid code point (\uFFFD) + | '\uFFFE' - '\U0010FFFF' +; + +_letter : _ascii_letter | _unicode_byte | '_' ; +_decimal_digit : _ascii_digit ; +_decimals : _decimal_digit { _decimal_digit } ; + +// An ID is one of the following: +// +// 1) Any string of alphabetic ([a-zA-Z\200-\377]) characters, underscores +// ('_') or digits ([0-9]), not beginning with a digit; +// +// 2) a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? ); +// +// 3) any double-quoted string ("...") possibly containing escaped quotes +// (\"); +// +// 4) an HTML string (<...>). + +id + : _letter { _letter | _decimal_digit } + | _int_lit + | _string_lit + | _html_lit +; + +_int_lit + : [ '-' ] '.' _decimals + | [ '-' ] _decimals [ '.' { _decimal_digit } ] +; + +// In quoted strings in DOT, the only escaped character is double-quote ("). +// That is, in quoted strings, the dyad \" is converted to "; all other +// characters are left unchanged. In particular, \\ remains \\. + +// As another aid for readability, dot allows double-quoted strings to span +// multiple physical lines using the standard C convention of a backslash +// immediately preceding a newline character. + +// In addition, double-quoted strings can be concatenated using a '+' operator. + +_escaped_char : '\\' ( _unicode_char | '"' | '\\' ) ; +_char : _unicode_char | _escaped_char ; +_string_lit : '"' { _char } '"' ; + +// An arbitrary HTML character except null (0x00), left angle bracket (0x3C) and +// right angle bracket (0x3E). +_html_char + // skip null (0x00) + : '\x01' - '\x3B' + // skip left angle bracket (0x3C) + | '\x3D' + // skip right angle bracket (0x3E) + | '\x3F' - '\xFF' +; + +_html_chars : { _html_char } ; +_html_tag : '<' _html_chars '>' ; +_html_lit : '<' { _html_chars | _html_tag } '>' ; + +// The language supports C++-style comments: /* */ and //. In addition, a line +// beginning with a '#' character is considered a line output from a C +// preprocessor (e.g., # 34 to indicate line 34 ) and discarded. + +_line_comment + : '/' '/' { . } '\n' + | '#' { . } '\n' +; + +_block_comment : '/' '*' { . | '*' } '*' '/' ; +!comment : _line_comment | _block_comment ; + +!whitespace : ' ' | '\t' | '\r' | '\n' ; + +// ### [ Syntax ] ############################################################## + +<< import ( + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/astx" +) >> + +// === [ Files ] =============================================================== + +File + : Graph << astx.NewFile($0) >> + | File Graph << astx.AppendGraph($0, $1) >> +; + +// === [ Graphs ] ============================================================== + +// Graph : [ "strict" ] ( "graph" | "digraph" ) [ ID ] "{" [ StmtList ] "}" + +Graph + : OptStrict DirectedGraph OptID + "{" OptStmtList "}" << astx.NewGraph($0, $1, $2, $4) >> +; + +OptStrict + : empty << false, nil >> + | strict << true, nil >> +; + +DirectedGraph + : graphx << false, nil >> + | digraph << true, nil >> +; + +// === [ Statements ] ========================================================== + +// StmtList +// : Stmt [ ";" ] +// | StmtList Stmt [ ";" ] + +StmtList + : Stmt OptSemi << astx.NewStmtList($0) >> + | StmtList Stmt OptSemi << astx.AppendStmt($0, $1) >> +; + +OptStmtList + : empty + | StmtList +; + +Stmt + : NodeStmt + | EdgeStmt + | AttrStmt + | Attr + | Subgraph +; + +OptSemi + : empty + | ";" +; + +// --- [ Node statement ] ------------------------------------------------------ + +// NodeStmt : Node [ AttrList ] + +NodeStmt + : Node OptAttrList << astx.NewNodeStmt($0, $1) >> +; + +// --- [ Edge statement ] ------------------------------------------------------ + +// EdgeStmt : ( Node | Subgraph ) Edge [ AttrList ] + +EdgeStmt + : Vertex Edge OptAttrList << astx.NewEdgeStmt($0, $1, $2) >> +; + +// Edge : ( "--" | "-->" ) ( Node | Subgraph ) [ Edge ] + +Edge + : DirectedEdge Vertex OptEdge << astx.NewEdge($0, $1, $2) >> +; + +DirectedEdge + : "--" << false, nil >> + | "->" << true, nil >> +; + +OptEdge + : empty + | Edge +; + +// --- [ Attribute statement ] ------------------------------------------------- + +// AttrStmt : ( "graph" | "node" | "edge" ) AttrList + +AttrStmt + : Component AttrList << astx.NewAttrStmt($0, $1) >> +; + +Component + : graphx << ast.GraphKind, nil >> + | node << ast.NodeKind, nil >> + | edge << ast.EdgeKind, nil >> +; + +// AttrList : "[" [ AList ] "]" [ AttrList ] + +AttrList + : "[" OptAList "]" << $1, nil >> + | AttrList "[" OptAList "]" << astx.AppendAttrList($0, $2) >> +; + +OptAttrList + : empty + | AttrList +; + +// AList +// : Attr [ ( ";" | "," ) ] +// | AList Attr [ ( ";" | "," ) ] + +AList + : Attr OptSep << astx.NewAttrList($0) >> + | AList Attr OptSep << astx.AppendAttr($0, $1) >> +; + +OptAList + : empty + | AList +; + +OptSep + : empty + | ";" + | "," +; + +// --- [ Attribute ] ----------------------------------------------------------- + +Attr + : ID "=" ID << astx.NewAttr($0, $2) >> +; + +// --- [ Subgraph ] ------------------------------------------------------------ + +// Subgraph : [ "subgraph" [ ID ] ] "{" [ StmtList ] "}" + +Subgraph + : OptSubgraphID "{" OptStmtList "}" << astx.NewSubgraph($0, $2) >> +; + +OptSubgraphID + : empty + | subgraph OptID << $1, nil >> +; + +// === [ Vertices ] ============================================================ + +Vertex + : Node + | Subgraph +; + +// --- [ Node identifier ] ----------------------------------------------------- + +// Node : ID [ Port ] + +Node + : ID OptPort << astx.NewNode($0, $1) >> +; + +// Port +// : ":" ID [ ":" CompassPoint ] +// | ":" CompassPoint +// +// CompassPoint +// : "n" | "ne" | "e" | "se" | "s" | "sw" | "w" | "nw" | "c" | "_" + +// Note also that the allowed compass point values are not keywords, so these +// strings can be used elsewhere as ordinary identifiers and, conversely, the +// parser will actually accept any identifier. + +Port + : ":" ID << astx.NewPort($1, nil) >> + | ":" ID ":" ID << astx.NewPort($1, $3) >> +; + +OptPort + : empty + | Port +; + +// === [ Identifiers ] ========================================================= + +ID + : id << astx.NewID($0) >> +; + +OptID + : empty << "", nil >> + | ID +; diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go new file mode 100644 index 00000000..44f8825e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go @@ -0,0 +1,66 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package errors + +import ( + "bytes" + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, e.Err.Error()) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/acttab.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/acttab.go new file mode 100644 index 00000000..34c9d4dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/acttab.go @@ -0,0 +1,597 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +import ( + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1 + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S3 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4 + Accept: 15, + Ignore: "", + }, + ActionRow{ // S5 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S7 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S8 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S9 + Accept: 18, + Ignore: "", + }, + ActionRow{ // S10 + Accept: 8, + Ignore: "", + }, + ActionRow{ // S11 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S12 + Accept: 16, + Ignore: "", + }, + ActionRow{ // S13 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S14 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S15 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S16 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S17 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S18 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S19 + Accept: 13, + Ignore: "", + }, + ActionRow{ // S20 + Accept: 14, + Ignore: "", + }, + ActionRow{ // S21 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S22 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S23 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S24 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S25 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S26 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S27 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S28 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S29 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S30 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S31 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S32 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S33 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S34 + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S35 + Accept: 9, + Ignore: "", + }, + ActionRow{ // S36 + Accept: 10, + Ignore: "", + }, + ActionRow{ // S37 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S38 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S39 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S40 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S41 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S42 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S43 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S44 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S45 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S46 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S47 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S48 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S49 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S50 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S51 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S52 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S53 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S54 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S55 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S56 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S57 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S58 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S59 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S60 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S61 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S62 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S63 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S64 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S65 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S66 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S67 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S68 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S69 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S70 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S71 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S72 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S73 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S74 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S75 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S76 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S77 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S78 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S79 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S80 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S81 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S82 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S83 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S84 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S85 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S86 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S87 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S88 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S89 + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S90 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S91 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S92 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S93 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S94 + Accept: 12, + Ignore: "", + }, + ActionRow{ // S95 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S96 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S97 + Accept: 11, + Ignore: "", + }, + ActionRow{ // S98 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S99 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S100 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S101 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S102 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S103 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S104 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S105 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S106 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S107 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S108 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S109 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S110 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S111 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S112 + Accept: 6, + Ignore: "", + }, + ActionRow{ // S113 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S114 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S115 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S116 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S117 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S118 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S119 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S120 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S121 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S122 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S123 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S124 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S125 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S126 + Accept: 5, + Ignore: "", + }, + ActionRow{ // S127 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S128 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S129 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S130 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S131 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S132 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S133 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S134 + Accept: 7, + Ignore: "", + }, + ActionRow{ // S135 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S136 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S137 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S138 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S139 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S140 + Accept: 17, + Ignore: "", + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer.go new file mode 100644 index 00000000..caa9c461 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer.go @@ -0,0 +1,310 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +import ( + "io/ioutil" + "unicode/utf8" + + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +const ( + NoState = -1 + NumStates = 141 + NumSymbols = 184 +) + +type Lexer struct { + src []byte + pos int + line int + column int +} + +func NewLexer(src []byte) *Lexer { + lexer := &Lexer{ + src: src, + pos: 0, + line: 1, + column: 1, + } + return lexer +} + +func NewLexerFile(fpath string) (*Lexer, error) { + src, err := ioutil.ReadFile(fpath) + if err != nil { + return nil, err + } + return NewLexer(src), nil +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + if l.pos >= len(l.src) { + tok.Type = token.EOF + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column + return + } + start, startLine, startColumn, end := l.pos, l.line, l.column, 0 + tok.Type = token.INVALID + state, rune1, size := 0, rune(-1), 0 + for state != -1 { + if l.pos >= len(l.src) { + rune1 = -1 + } else { + rune1, size = utf8.DecodeRune(l.src[l.pos:]) + l.pos += size + } + + nextState := -1 + if rune1 != -1 { + nextState = TransTab[state](rune1) + } + state = nextState + + if state != -1 { + + switch rune1 { + case '\n': + l.line++ + l.column = 1 + case '\r': + l.column = 1 + case '\t': + l.column += 4 + default: + l.column++ + } + + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + end = l.pos + case ActTab[state].Ignore != "": + start, startLine, startColumn = l.pos, l.line, l.column + state = 0 + if start >= len(l.src) { + tok.Type = token.EOF + } + + } + } else { + if tok.Type == token.INVALID { + end = l.pos + } + } + } + if end > start { + l.pos = end + tok.Lit = l.src[start:end] + } else { + tok.Lit = []byte{} + } + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn + + return +} + +func (l *Lexer) Reset() { + l.pos = 0 +} + +/* +Lexer symbols: +0: 'n' +1: 'o' +2: 'd' +3: 'e' +4: 'N' +5: 'o' +6: 'd' +7: 'e' +8: 'N' +9: 'O' +10: 'D' +11: 'E' +12: 'e' +13: 'd' +14: 'g' +15: 'e' +16: 'E' +17: 'd' +18: 'g' +19: 'e' +20: 'E' +21: 'D' +22: 'G' +23: 'E' +24: 'g' +25: 'r' +26: 'a' +27: 'p' +28: 'h' +29: 'G' +30: 'r' +31: 'a' +32: 'p' +33: 'h' +34: 'G' +35: 'R' +36: 'A' +37: 'P' +38: 'H' +39: 'd' +40: 'i' +41: 'g' +42: 'r' +43: 'a' +44: 'p' +45: 'h' +46: 'D' +47: 'i' +48: 'g' +49: 'r' +50: 'a' +51: 'p' +52: 'h' +53: 'd' +54: 'i' +55: 'G' +56: 'r' +57: 'a' +58: 'p' +59: 'h' +60: 'D' +61: 'i' +62: 'G' +63: 'r' +64: 'a' +65: 'p' +66: 'h' +67: 'D' +68: 'I' +69: 'G' +70: 'R' +71: 'A' +72: 'P' +73: 'H' +74: 's' +75: 'u' +76: 'b' +77: 'g' +78: 'r' +79: 'a' +80: 'p' +81: 'h' +82: 'S' +83: 'u' +84: 'b' +85: 'g' +86: 'r' +87: 'a' +88: 'p' +89: 'h' +90: 's' +91: 'u' +92: 'b' +93: 'G' +94: 'r' +95: 'a' +96: 'p' +97: 'h' +98: 'S' +99: 'u' +100: 'b' +101: 'G' +102: 'r' +103: 'a' +104: 'p' +105: 'h' +106: 'S' +107: 'U' +108: 'B' +109: 'G' +110: 'R' +111: 'A' +112: 'P' +113: 'H' +114: 's' +115: 't' +116: 'r' +117: 'i' +118: 'c' +119: 't' +120: 'S' +121: 't' +122: 'r' +123: 'i' +124: 'c' +125: 't' +126: 'S' +127: 'T' +128: 'R' +129: 'I' +130: 'C' +131: 'T' +132: '{' +133: '}' +134: ';' +135: '-' +136: '-' +137: '-' +138: '>' +139: '[' +140: ']' +141: ',' +142: '=' +143: ':' +144: '_' +145: '-' +146: '.' +147: '-' +148: '.' +149: '\' +150: '"' +151: '\' +152: '"' +153: '"' +154: '=' +155: '<' +156: '>' +157: '<' +158: '>' +159: '/' +160: '/' +161: '\n' +162: '#' +163: '\n' +164: '/' +165: '*' +166: '*' +167: '*' +168: '/' +169: ' ' +170: '\t' +171: '\r' +172: '\n' +173: \u0001-'!' +174: '#'-'[' +175: ']'-\u007f +176: 'a'-'z' +177: 'A'-'Z' +178: '0'-'9' +179: \u0080-\ufffc +180: \ufffe-\U0010ffff +181: \u0001-';' +182: '?'-\u00ff +183: . +*/ diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer_test.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer_test.go new file mode 100644 index 00000000..f90964fc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/lexer_test.go @@ -0,0 +1,54 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + { + in: "testdata/tokens.dot", + out: "testdata/tokens.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected %q, got %q", g.in, want, got) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.dot new file mode 100644 index 00000000..3a161951 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.dot @@ -0,0 +1,39 @@ +# C preprocessing directives act as comments. +/* block comment */ +// keywords are case-insensitive. +graph { + node [] + Node [] + NODE [] + edge [] + Edge [] + EDGE [] + subgraph {} + subGraph {} + Subgraph {} + SubGraph {} + SUBGRAPH S {} + A; B [style=filled, fillcolor=red] + C:nw -- D:se + "foo" + .10 + -20 + 3.14 + F [label=<
foo
>] + _foo + a10 +} +Graph { +} +GRAPH { +} +digraph { +} +Digraph { +} +diGraph { +} +DiGraph { +} +DIGRAPH { +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.golden new file mode 100644 index 00000000..f64bdefc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/testdata/tokens.golden @@ -0,0 +1,37 @@ +graph { + node [] + node [] + node [] + edge [] + edge [] + edge [] + {} + {} + {} + {} + subgraph S {} + A + B [style=filled fillcolor=red] + C:nw -- D:se + "foo" + .10 + -20 + 3.14 + F [label=<
foo
>] + _foo + a10 +} +graph { +} +graph { +} +digraph { +} +digraph { +} +digraph { +} +digraph { +} +digraph { +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/transitiontable.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/transitiontable.go new file mode 100644 index 00000000..8f8f8393 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/lexer/transitiontable.go @@ -0,0 +1,2741 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 34: // ['"','"'] + return 2 + case r == 35: // ['#','#'] + return 3 + case r == 44: // [',',','] + return 4 + case r == 45: // ['-','-'] + return 5 + case r == 46: // ['.','.'] + return 6 + case r == 47: // ['/','/'] + return 7 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 58: // [':',':'] + return 9 + case r == 59: // [';',';'] + return 10 + case r == 60: // ['<','<'] + return 11 + case r == 61: // ['=','='] + return 12 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 14 + case r == 69: // ['E','E'] + return 15 + case r == 70: // ['F','F'] + return 13 + case r == 71: // ['G','G'] + return 16 + case 72 <= r && r <= 77: // ['H','M'] + return 13 + case r == 78: // ['N','N'] + return 17 + case 79 <= r && r <= 82: // ['O','R'] + return 13 + case r == 83: // ['S','S'] + return 18 + case 84 <= r && r <= 90: // ['T','Z'] + return 13 + case r == 91: // ['[','['] + return 19 + case r == 93: // [']',']'] + return 20 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 22 + case r == 101: // ['e','e'] + return 23 + case r == 102: // ['f','f'] + return 13 + case r == 103: // ['g','g'] + return 24 + case 104 <= r && r <= 109: // ['h','m'] + return 13 + case r == 110: // ['n','n'] + return 25 + case 111 <= r && r <= 114: // ['o','r'] + return 13 + case r == 115: // ['s','s'] + return 26 + case 116 <= r && r <= 122: // ['t','z'] + return 13 + case r == 123: // ['{','{'] + return 27 + case r == 125: // ['}','}'] + return 28 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 34 + default: + return 3 + } + }, + // S4 + func(r rune) int { + switch { + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case r == 45: // ['-','-'] + return 35 + case r == 46: // ['.','.'] + return 6 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 62: // ['>','>'] + return 36 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 38 + case r == 47: // ['/','/'] + return 39 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case r == 46: // ['.','.'] + return 40 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + } + return NoState + }, + // S10 + func(r rune) int { + switch { + } + return NoState + }, + // S11 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + } + return NoState + }, + // S12 + func(r rune) int { + switch { + } + return NoState + }, + // S13 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S14 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 72: // ['A','H'] + return 13 + case r == 73: // ['I','I'] + return 45 + case 74 <= r && r <= 90: // ['J','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 46 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S15 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 47 + case 69 <= r && r <= 90: // ['E','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 48 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S16 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 49 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 50 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S17 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 78: // ['A','N'] + return 13 + case r == 79: // ['O','O'] + return 51 + case 80 <= r && r <= 90: // ['P','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 110: // ['a','n'] + return 13 + case r == 111: // ['o','o'] + return 52 + case 112 <= r && r <= 122: // ['p','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S18 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 83: // ['A','S'] + return 13 + case r == 84: // ['T','T'] + return 53 + case r == 85: // ['U','U'] + return 54 + case 86 <= r && r <= 90: // ['V','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 55 + case r == 117: // ['u','u'] + return 56 + case 118 <= r && r <= 122: // ['v','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S19 + func(r rune) int { + switch { + } + return NoState + }, + // S20 + func(r rune) int { + switch { + } + return NoState + }, + // S21 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S22 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 57 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S23 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 58 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S24 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 59 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S25 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 110: // ['a','n'] + return 13 + case r == 111: // ['o','o'] + return 60 + case 112 <= r && r <= 122: // ['p','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S26 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 61 + case r == 117: // ['u','u'] + return 62 + case 118 <= r && r <= 122: // ['v','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S27 + func(r rune) int { + switch { + } + return NoState + }, + // S28 + func(r rune) int { + switch { + } + return NoState + }, + // S29 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S30 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S31 + func(r rune) int { + switch { + } + return NoState + }, + // S32 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 63 + case r == 34: // ['"','"'] + return 64 + case 35 <= r && r <= 91: // ['#','['] + return 63 + case r == 92: // ['\','\'] + return 64 + case 93 <= r && r <= 127: // [']',\u007f] + return 63 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 65 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 65 + } + return NoState + }, + // S33 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S34 + func(r rune) int { + switch { + } + return NoState + }, + // S35 + func(r rune) int { + switch { + } + return NoState + }, + // S36 + func(r rune) int { + switch { + } + return NoState + }, + // S37 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + } + return NoState + }, + // S38 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 66 + default: + return 38 + } + }, + // S39 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 34 + default: + return 39 + } + }, + // S40 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 67 + } + return NoState + }, + // S41 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + } + return NoState + }, + // S42 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 68 + case r == 61: // ['=','='] + return 68 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 68 + } + return NoState + }, + // S43 + func(r rune) int { + switch { + } + return NoState + }, + // S44 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S45 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 69 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S46 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 70 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 71 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S47 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 72 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S48 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 73 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S49 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 74 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S50 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 75 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S51 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 76 + case 69 <= r && r <= 90: // ['E','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S52 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 77 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S53 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 78 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S54 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 13 + case r == 66: // ['B','B'] + return 79 + case 67 <= r && r <= 90: // ['C','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S55 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 80 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S56 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 13 + case r == 98: // ['b','b'] + return 81 + case 99 <= r && r <= 122: // ['c','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S57 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 82 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 83 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S58 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 84 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S59 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 85 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S60 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 86 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S61 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 87 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S62 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 13 + case r == 98: // ['b','b'] + return 88 + case 99 <= r && r <= 122: // ['c','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S63 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S64 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S65 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + } + return NoState + }, + // S66 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 66 + case r == 47: // ['/','/'] + return 89 + default: + return 38 + } + }, + // S67 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 67 + } + return NoState + }, + // S68 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 68 + case r == 61: // ['=','='] + return 68 + case r == 62: // ['>','>'] + return 90 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 68 + } + return NoState + }, + // S69 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 91 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S70 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 92 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S71 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 93 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S72 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 68: // ['A','D'] + return 13 + case r == 69: // ['E','E'] + return 94 + case 70 <= r && r <= 90: // ['F','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S73 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 94 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S74 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 95 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S75 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 96 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S76 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 68: // ['A','D'] + return 13 + case r == 69: // ['E','E'] + return 97 + case 70 <= r && r <= 90: // ['F','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S77 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 97 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S78 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 72: // ['A','H'] + return 13 + case r == 73: // ['I','I'] + return 98 + case 74 <= r && r <= 90: // ['J','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S79 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 99 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S80 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 100 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S81 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 101 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 102 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S82 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 103 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S83 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 104 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S84 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 94 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S85 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 105 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S86 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 97 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S87 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 106 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S88 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 107 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 108 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S89 + func(r rune) int { + switch { + } + return NoState + }, + // S90 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + } + return NoState + }, + // S91 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 109 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S92 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 110 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S93 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 111 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S94 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S95 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 112 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S96 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 112 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S97 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S98 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 66: // ['A','B'] + return 13 + case r == 67: // ['C','C'] + return 113 + case 68 <= r && r <= 90: // ['D','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S99 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 114 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S100 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 98: // ['a','b'] + return 13 + case r == 99: // ['c','c'] + return 115 + case 100 <= r && r <= 122: // ['d','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S101 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 116 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S102 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 117 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S103 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 118 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S104 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 119 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S105 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 112 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S106 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 98: // ['a','b'] + return 13 + case r == 99: // ['c','c'] + return 120 + case 100 <= r && r <= 122: // ['d','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S107 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 121 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S108 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 122 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S109 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 123 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S110 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 124 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S111 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 125 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S112 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S113 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 83: // ['A','S'] + return 13 + case r == 84: // ['T','T'] + return 126 + case 85 <= r && r <= 90: // ['U','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S114 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 127 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S115 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 126 + case 117 <= r && r <= 122: // ['u','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S116 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 128 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S117 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 129 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S118 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 130 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S119 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 131 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S120 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 126 + case 117 <= r && r <= 122: // ['u','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S121 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 132 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S122 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 133 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S123 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 134 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S124 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S125 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S126 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S127 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 135 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S128 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 136 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S129 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 137 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S130 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S131 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S132 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 138 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S133 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 139 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S134 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S135 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 140 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S136 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S137 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S138 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S139 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, + // S140 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + } + return NoState + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/action.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/action.go new file mode 100644 index 00000000..10d7eccb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/action.go @@ -0,0 +1,61 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/actiontable.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/actiontable.go new file mode 100644 index 00000000..9596d120 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/actiontable.go @@ -0,0 +1,2199 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +type ( + actionTable [numStates]actionRow + actionRow struct { + canRecover bool + actions [numSymbols]action + } +) + +var actionTab = actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + shift(4), /* strict */ + reduce(4), /* graphx, reduce: OptStrict */ + reduce(4), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + accept(true), /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + shift(4), /* strict */ + reduce(4), /* graphx, reduce: OptStrict */ + reduce(4), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(1), /* $, reduce: File */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(1), /* strict, reduce: File */ + reduce(1), /* graphx, reduce: File */ + reduce(1), /* digraph, reduce: File */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + shift(7), /* graphx */ + shift(8), /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + reduce(5), /* graphx, reduce: OptStrict */ + reduce(5), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(2), /* $, reduce: File */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(2), /* strict, reduce: File */ + reduce(2), /* graphx, reduce: File */ + reduce(2), /* digraph, reduce: File */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(53), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(11), /* id */ + }, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(6), /* {, reduce: DirectedGraph */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(6), /* id, reduce: DirectedGraph */ + }, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(7), /* {, reduce: DirectedGraph */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(7), /* id, reduce: DirectedGraph */ + }, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(12), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(54), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + }, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(31), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(27), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(11), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + }, + }, + actionRow{ // S16 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(17), /* {, reduce: OptSemi */ + reduce(17), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(17), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + shift(34), /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(17), /* node, reduce: OptSemi */ + reduce(17), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(17), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(17), /* id, reduce: OptSemi */ + }, + }, + actionRow{ // S17 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(12), /* {, reduce: Stmt */ + reduce(12), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(12), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(12), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(12), /* node, reduce: Stmt */ + reduce(12), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(12), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(12), /* id, reduce: Stmt */ + }, + }, + actionRow{ // S18 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(13), /* {, reduce: Stmt */ + reduce(13), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(13), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(13), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(13), /* node, reduce: Stmt */ + reduce(13), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(13), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(13), /* id, reduce: Stmt */ + }, + }, + actionRow{ // S19 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(14), /* {, reduce: Stmt */ + reduce(14), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(14), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(14), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(14), /* node, reduce: Stmt */ + reduce(14), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(14), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(14), /* id, reduce: Stmt */ + }, + }, + actionRow{ // S20 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(15), /* {, reduce: Stmt */ + reduce(15), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(15), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(15), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(15), /* node, reduce: Stmt */ + reduce(15), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(15), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(15), /* id, reduce: Stmt */ + }, + }, + actionRow{ // S21 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(16), /* {, reduce: Stmt */ + reduce(16), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(16), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(16), /* ;, reduce: Stmt */ + reduce(46), /* --, reduce: Vertex */ + reduce(46), /* ->, reduce: Vertex */ + reduce(16), /* node, reduce: Stmt */ + reduce(16), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(16), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(16), /* id, reduce: Stmt */ + }, + }, + actionRow{ // S22 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(32), /* {, reduce: OptAttrList */ + reduce(32), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(32), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(32), /* ;, reduce: OptAttrList */ + reduce(45), /* --, reduce: Vertex */ + reduce(45), /* ->, reduce: Vertex */ + reduce(32), /* node, reduce: OptAttrList */ + reduce(32), /* edge, reduce: OptAttrList */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(32), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(32), /* id, reduce: OptAttrList */ + }, + }, + actionRow{ // S23 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + shift(40), /* -- */ + shift(41), /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S24 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S25 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(28), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S26 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(29), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S27 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(50), /* {, reduce: OptPort */ + reduce(50), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(50), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(50), /* ;, reduce: OptPort */ + reduce(50), /* --, reduce: OptPort */ + reduce(50), /* ->, reduce: OptPort */ + reduce(50), /* node, reduce: OptPort */ + reduce(50), /* edge, reduce: OptPort */ + reduce(50), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + shift(43), /* = */ + reduce(50), /* subgraph, reduce: OptPort */ + shift(46), /* : */ + reduce(50), /* id, reduce: OptPort */ + }, + }, + actionRow{ // S28 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(47), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S29 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(53), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(11), /* id */ + }, + }, + actionRow{ // S30 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + reduce(52), /* =, reduce: ID */ + reduce(52), /* subgraph, reduce: ID */ + reduce(52), /* :, reduce: ID */ + reduce(52), /* id, reduce: ID */ + }, + }, + actionRow{ // S31 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(3), /* $, reduce: Graph */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(3), /* strict, reduce: Graph */ + reduce(3), /* graphx, reduce: Graph */ + reduce(3), /* digraph, reduce: Graph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S32 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(17), /* {, reduce: OptSemi */ + reduce(17), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(17), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + shift(34), /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(17), /* node, reduce: OptSemi */ + reduce(17), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(17), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(17), /* id, reduce: OptSemi */ + }, + }, + actionRow{ // S33 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(8), /* {, reduce: StmtList */ + reduce(8), /* }, reduce: StmtList */ + nil, /* empty */ + nil, /* strict */ + reduce(8), /* graphx, reduce: StmtList */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(8), /* node, reduce: StmtList */ + reduce(8), /* edge, reduce: StmtList */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(8), /* subgraph, reduce: StmtList */ + nil, /* : */ + reduce(8), /* id, reduce: StmtList */ + }, + }, + actionRow{ // S34 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(18), /* {, reduce: OptSemi */ + reduce(18), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(18), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(18), /* node, reduce: OptSemi */ + reduce(18), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(18), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(18), /* id, reduce: OptSemi */ + }, + }, + actionRow{ // S35 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(19), /* {, reduce: NodeStmt */ + reduce(19), /* }, reduce: NodeStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(19), /* graphx, reduce: NodeStmt */ + nil, /* digraph */ + reduce(19), /* ;, reduce: NodeStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(19), /* node, reduce: NodeStmt */ + reduce(19), /* edge, reduce: NodeStmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(19), /* subgraph, reduce: NodeStmt */ + nil, /* : */ + reduce(19), /* id, reduce: NodeStmt */ + }, + }, + actionRow{ // S36 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(33), /* {, reduce: OptAttrList */ + reduce(33), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(33), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(33), /* ;, reduce: OptAttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(33), /* node, reduce: OptAttrList */ + reduce(33), /* edge, reduce: OptAttrList */ + shift(50), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(33), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(33), /* id, reduce: OptAttrList */ + }, + }, + actionRow{ // S37 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(36), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + }, + }, + actionRow{ // S38 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(32), /* {, reduce: OptAttrList */ + reduce(32), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(32), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(32), /* ;, reduce: OptAttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(32), /* node, reduce: OptAttrList */ + reduce(32), /* edge, reduce: OptAttrList */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(32), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(32), /* id, reduce: OptAttrList */ + }, + }, + actionRow{ // S39 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(62), /* id */ + }, + }, + actionRow{ // S40 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(22), /* {, reduce: DirectedEdge */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(22), /* subgraph, reduce: DirectedEdge */ + nil, /* : */ + reduce(22), /* id, reduce: DirectedEdge */ + }, + }, + actionRow{ // S41 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(23), /* {, reduce: DirectedEdge */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(23), /* subgraph, reduce: DirectedEdge */ + nil, /* : */ + reduce(23), /* id, reduce: DirectedEdge */ + }, + }, + actionRow{ // S42 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(26), /* {, reduce: AttrStmt */ + reduce(26), /* }, reduce: AttrStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(26), /* graphx, reduce: AttrStmt */ + nil, /* digraph */ + reduce(26), /* ;, reduce: AttrStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(26), /* node, reduce: AttrStmt */ + reduce(26), /* edge, reduce: AttrStmt */ + shift(50), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(26), /* subgraph, reduce: AttrStmt */ + nil, /* : */ + reduce(26), /* id, reduce: AttrStmt */ + }, + }, + actionRow{ // S43 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(64), /* id */ + }, + }, + actionRow{ // S44 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(47), /* {, reduce: Node */ + reduce(47), /* }, reduce: Node */ + nil, /* empty */ + nil, /* strict */ + reduce(47), /* graphx, reduce: Node */ + nil, /* digraph */ + reduce(47), /* ;, reduce: Node */ + reduce(47), /* --, reduce: Node */ + reduce(47), /* ->, reduce: Node */ + reduce(47), /* node, reduce: Node */ + reduce(47), /* edge, reduce: Node */ + reduce(47), /* [, reduce: Node */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(47), /* subgraph, reduce: Node */ + nil, /* : */ + reduce(47), /* id, reduce: Node */ + }, + }, + actionRow{ // S45 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(51), /* {, reduce: OptPort */ + reduce(51), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(51), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(51), /* ;, reduce: OptPort */ + reduce(51), /* --, reduce: OptPort */ + reduce(51), /* ->, reduce: OptPort */ + reduce(51), /* node, reduce: OptPort */ + reduce(51), /* edge, reduce: OptPort */ + reduce(51), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(51), /* subgraph, reduce: OptPort */ + nil, /* : */ + reduce(51), /* id, reduce: OptPort */ + }, + }, + actionRow{ // S46 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(62), /* id */ + }, + }, + actionRow{ // S47 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + }, + }, + actionRow{ // S48 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(44), /* {, reduce: OptSubgraphID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S49 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(9), /* {, reduce: StmtList */ + reduce(9), /* }, reduce: StmtList */ + nil, /* empty */ + nil, /* strict */ + reduce(9), /* graphx, reduce: StmtList */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(9), /* node, reduce: StmtList */ + reduce(9), /* edge, reduce: StmtList */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(9), /* subgraph, reduce: StmtList */ + nil, /* : */ + reduce(9), /* id, reduce: StmtList */ + }, + }, + actionRow{ // S50 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(36), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + }, + }, + actionRow{ // S51 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + shift(68), /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(38), /* ], reduce: OptSep */ + shift(70), /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(38), /* id, reduce: OptSep */ + }, + }, + actionRow{ // S52 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + shift(71), /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S53 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(37), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + }, + }, + actionRow{ // S54 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + shift(73), /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S55 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + reduce(52), /* =, reduce: ID */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S56 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(20), /* {, reduce: EdgeStmt */ + reduce(20), /* }, reduce: EdgeStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(20), /* graphx, reduce: EdgeStmt */ + nil, /* digraph */ + reduce(20), /* ;, reduce: EdgeStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(20), /* node, reduce: EdgeStmt */ + reduce(20), /* edge, reduce: EdgeStmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(20), /* subgraph, reduce: EdgeStmt */ + nil, /* : */ + reduce(20), /* id, reduce: EdgeStmt */ + }, + }, + actionRow{ // S57 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(46), /* {, reduce: Vertex */ + reduce(46), /* }, reduce: Vertex */ + nil, /* empty */ + nil, /* strict */ + reduce(46), /* graphx, reduce: Vertex */ + nil, /* digraph */ + reduce(46), /* ;, reduce: Vertex */ + reduce(46), /* --, reduce: Vertex */ + reduce(46), /* ->, reduce: Vertex */ + reduce(46), /* node, reduce: Vertex */ + reduce(46), /* edge, reduce: Vertex */ + reduce(46), /* [, reduce: Vertex */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(46), /* subgraph, reduce: Vertex */ + nil, /* : */ + reduce(46), /* id, reduce: Vertex */ + }, + }, + actionRow{ // S58 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(45), /* {, reduce: Vertex */ + reduce(45), /* }, reduce: Vertex */ + nil, /* empty */ + nil, /* strict */ + reduce(45), /* graphx, reduce: Vertex */ + nil, /* digraph */ + reduce(45), /* ;, reduce: Vertex */ + reduce(45), /* --, reduce: Vertex */ + reduce(45), /* ->, reduce: Vertex */ + reduce(45), /* node, reduce: Vertex */ + reduce(45), /* edge, reduce: Vertex */ + reduce(45), /* [, reduce: Vertex */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(45), /* subgraph, reduce: Vertex */ + nil, /* : */ + reduce(45), /* id, reduce: Vertex */ + }, + }, + actionRow{ // S59 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(24), /* {, reduce: OptEdge */ + reduce(24), /* }, reduce: OptEdge */ + nil, /* empty */ + nil, /* strict */ + reduce(24), /* graphx, reduce: OptEdge */ + nil, /* digraph */ + reduce(24), /* ;, reduce: OptEdge */ + shift(40), /* -- */ + shift(41), /* -> */ + reduce(24), /* node, reduce: OptEdge */ + reduce(24), /* edge, reduce: OptEdge */ + reduce(24), /* [, reduce: OptEdge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(24), /* subgraph, reduce: OptEdge */ + nil, /* : */ + reduce(24), /* id, reduce: OptEdge */ + }, + }, + actionRow{ // S60 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(50), /* {, reduce: OptPort */ + reduce(50), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(50), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(50), /* ;, reduce: OptPort */ + reduce(50), /* --, reduce: OptPort */ + reduce(50), /* ->, reduce: OptPort */ + reduce(50), /* node, reduce: OptPort */ + reduce(50), /* edge, reduce: OptPort */ + reduce(50), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(50), /* subgraph, reduce: OptPort */ + shift(46), /* : */ + reduce(50), /* id, reduce: OptPort */ + }, + }, + actionRow{ // S61 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(76), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S62 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + reduce(52), /* :, reduce: ID */ + reduce(52), /* id, reduce: ID */ + }, + }, + actionRow{ // S63 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(41), /* {, reduce: Attr */ + reduce(41), /* }, reduce: Attr */ + nil, /* empty */ + nil, /* strict */ + reduce(41), /* graphx, reduce: Attr */ + nil, /* digraph */ + reduce(41), /* ;, reduce: Attr */ + nil, /* -- */ + nil, /* -> */ + reduce(41), /* node, reduce: Attr */ + reduce(41), /* edge, reduce: Attr */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(41), /* subgraph, reduce: Attr */ + nil, /* : */ + reduce(41), /* id, reduce: Attr */ + }, + }, + actionRow{ // S64 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + nil, /* -- */ + nil, /* -> */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + }, + }, + actionRow{ // S65 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(48), /* {, reduce: Port */ + reduce(48), /* }, reduce: Port */ + nil, /* empty */ + nil, /* strict */ + reduce(48), /* graphx, reduce: Port */ + nil, /* digraph */ + reduce(48), /* ;, reduce: Port */ + reduce(48), /* --, reduce: Port */ + reduce(48), /* ->, reduce: Port */ + reduce(48), /* node, reduce: Port */ + reduce(48), /* edge, reduce: Port */ + reduce(48), /* [, reduce: Port */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(48), /* subgraph, reduce: Port */ + shift(77), /* : */ + reduce(48), /* id, reduce: Port */ + }, + }, + actionRow{ // S66 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(78), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S67 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + shift(79), /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S68 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(39), /* ], reduce: OptSep */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(39), /* id, reduce: OptSep */ + }, + }, + actionRow{ // S69 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(34), /* ], reduce: AList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(34), /* id, reduce: AList */ + }, + }, + actionRow{ // S70 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(40), /* ], reduce: OptSep */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(40), /* id, reduce: OptSep */ + }, + }, + actionRow{ // S71 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(30), /* {, reduce: AttrList */ + reduce(30), /* }, reduce: AttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(30), /* graphx, reduce: AttrList */ + nil, /* digraph */ + reduce(30), /* ;, reduce: AttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(30), /* node, reduce: AttrList */ + reduce(30), /* edge, reduce: AttrList */ + reduce(30), /* [, reduce: AttrList */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(30), /* subgraph, reduce: AttrList */ + nil, /* : */ + reduce(30), /* id, reduce: AttrList */ + }, + }, + actionRow{ // S72 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + shift(68), /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(38), /* ], reduce: OptSep */ + shift(70), /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(38), /* id, reduce: OptSep */ + }, + }, + actionRow{ // S73 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(82), /* id */ + }, + }, + actionRow{ // S74 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(25), /* {, reduce: OptEdge */ + reduce(25), /* }, reduce: OptEdge */ + nil, /* empty */ + nil, /* strict */ + reduce(25), /* graphx, reduce: OptEdge */ + nil, /* digraph */ + reduce(25), /* ;, reduce: OptEdge */ + nil, /* -- */ + nil, /* -> */ + reduce(25), /* node, reduce: OptEdge */ + reduce(25), /* edge, reduce: OptEdge */ + reduce(25), /* [, reduce: OptEdge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(25), /* subgraph, reduce: OptEdge */ + nil, /* : */ + reduce(25), /* id, reduce: OptEdge */ + }, + }, + actionRow{ // S75 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(21), /* {, reduce: Edge */ + reduce(21), /* }, reduce: Edge */ + nil, /* empty */ + nil, /* strict */ + reduce(21), /* graphx, reduce: Edge */ + nil, /* digraph */ + reduce(21), /* ;, reduce: Edge */ + nil, /* -- */ + nil, /* -> */ + reduce(21), /* node, reduce: Edge */ + reduce(21), /* edge, reduce: Edge */ + reduce(21), /* [, reduce: Edge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(21), /* subgraph, reduce: Edge */ + nil, /* : */ + reduce(21), /* id, reduce: Edge */ + }, + }, + actionRow{ // S76 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + }, + }, + actionRow{ // S77 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(85), /* id */ + }, + }, + actionRow{ // S78 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(42), /* {, reduce: Subgraph */ + reduce(42), /* }, reduce: Subgraph */ + nil, /* empty */ + nil, /* strict */ + reduce(42), /* graphx, reduce: Subgraph */ + nil, /* digraph */ + reduce(42), /* ;, reduce: Subgraph */ + reduce(42), /* --, reduce: Subgraph */ + reduce(42), /* ->, reduce: Subgraph */ + reduce(42), /* node, reduce: Subgraph */ + reduce(42), /* edge, reduce: Subgraph */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(42), /* subgraph, reduce: Subgraph */ + nil, /* : */ + reduce(42), /* id, reduce: Subgraph */ + }, + }, + actionRow{ // S79 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(31), /* {, reduce: AttrList */ + reduce(31), /* }, reduce: AttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(31), /* graphx, reduce: AttrList */ + nil, /* digraph */ + reduce(31), /* ;, reduce: AttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(31), /* node, reduce: AttrList */ + reduce(31), /* edge, reduce: AttrList */ + reduce(31), /* [, reduce: AttrList */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(31), /* subgraph, reduce: AttrList */ + nil, /* : */ + reduce(31), /* id, reduce: AttrList */ + }, + }, + actionRow{ // S80 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(35), /* ], reduce: AList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(35), /* id, reduce: AList */ + }, + }, + actionRow{ // S81 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + reduce(41), /* ;, reduce: Attr */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(41), /* ], reduce: Attr */ + reduce(41), /* ,, reduce: Attr */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(41), /* id, reduce: Attr */ + }, + }, + actionRow{ // S82 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(52), /* ], reduce: ID */ + reduce(52), /* ,, reduce: ID */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + }, + }, + actionRow{ // S83 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(86), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + }, + }, + actionRow{ // S84 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(49), /* {, reduce: Port */ + reduce(49), /* }, reduce: Port */ + nil, /* empty */ + nil, /* strict */ + reduce(49), /* graphx, reduce: Port */ + nil, /* digraph */ + reduce(49), /* ;, reduce: Port */ + reduce(49), /* --, reduce: Port */ + reduce(49), /* ->, reduce: Port */ + reduce(49), /* node, reduce: Port */ + reduce(49), /* edge, reduce: Port */ + reduce(49), /* [, reduce: Port */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(49), /* subgraph, reduce: Port */ + nil, /* : */ + reduce(49), /* id, reduce: Port */ + }, + }, + actionRow{ // S85 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + }, + }, + actionRow{ // S86 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(42), /* {, reduce: Subgraph */ + reduce(42), /* }, reduce: Subgraph */ + nil, /* empty */ + nil, /* strict */ + reduce(42), /* graphx, reduce: Subgraph */ + nil, /* digraph */ + reduce(42), /* ;, reduce: Subgraph */ + reduce(42), /* --, reduce: Subgraph */ + reduce(42), /* ->, reduce: Subgraph */ + reduce(42), /* node, reduce: Subgraph */ + reduce(42), /* edge, reduce: Subgraph */ + reduce(42), /* [, reduce: Subgraph */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(42), /* subgraph, reduce: Subgraph */ + nil, /* : */ + reduce(42), /* id, reduce: Subgraph */ + }, + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/gototable.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/gototable.go new file mode 100644 index 00000000..9c55e43d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/gototable.go @@ -0,0 +1,2807 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +const numNTSymbols = 30 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // S' + 1, // File + 2, // Graph + 3, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S1 + -1, // S' + -1, // File + 5, // Graph + 3, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S2 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S3 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + 6, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S4 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S5 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S6 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 10, // ID + 9, // OptID + }, + gotoRow{ // S7 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S8 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S9 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S10 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S11 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S12 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 13, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + }, + gotoRow{ // S13 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S14 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S15 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + 32, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + }, + gotoRow{ // S16 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + 33, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S17 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S18 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S19 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S20 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S21 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S22 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 36, // AttrList + 35, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S23 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + 38, // Edge + 39, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S24 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 42, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S25 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S26 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S27 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + 45, // Port + 44, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S28 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S29 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 10, // ID + 48, // OptID + }, + gotoRow{ // S30 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S31 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S32 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + 49, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S33 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S34 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S35 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S36 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S37 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + 53, // AList + 52, // OptAList + -1, // OptSep + 51, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + }, + gotoRow{ // S38 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 36, // AttrList + 56, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S39 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + 57, // Subgraph + 61, // OptSubgraphID + 59, // Vertex + 58, // Node + -1, // Port + -1, // OptPort + 60, // ID + -1, // OptID + }, + gotoRow{ // S40 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S41 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S42 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S43 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 63, // ID + -1, // OptID + }, + gotoRow{ // S44 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S45 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S46 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 65, // ID + -1, // OptID + }, + gotoRow{ // S47 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 66, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + }, + gotoRow{ // S48 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S49 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S50 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + 53, // AList + 67, // OptAList + -1, // OptSep + 51, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + }, + gotoRow{ // S51 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + 69, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S52 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S53 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 72, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + }, + gotoRow{ // S54 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S55 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S56 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S57 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S58 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S59 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + 74, // Edge + 39, // DirectedEdge + 75, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S60 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + 45, // Port + 44, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S61 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S62 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S63 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S64 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S65 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S66 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S67 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S68 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S69 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S70 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S71 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S72 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + 80, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S73 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 81, // ID + -1, // OptID + }, + gotoRow{ // S74 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S75 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S76 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 83, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + }, + gotoRow{ // S77 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 84, // ID + -1, // OptID + }, + gotoRow{ // S78 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S79 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S80 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S81 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S82 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S83 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S84 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S85 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, + gotoRow{ // S86 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go new file mode 100644 index 00000000..18e146e0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go @@ -0,0 +1,221 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "bytes" + "fmt" + + parseError "gonum.org/v1/gonum/graph/formats/dot/internal/errors" + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +const ( + numProductions = 55 + numStates = 87 + numSymbols = 50 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const iNITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, iNITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d:%d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + fmt.Fprintf(w, "%v", s.attrib[i]) + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + pos int +} + +type Scanner interface { + Scan() (tok *token.Token) +} + +func NewParser() *Parser { + p := &Parser{stack: newStack()} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range actionTab[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(int(p.stack.topIndex() - rs)) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = actionTab[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := actionTab[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { + p.Reset() + p.nextToken = scanner.Scan() + for acc := false; !acc; { + action := actionTab[p.stack.top()].actions[p.nextToken.Type] + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + p.nextToken = scanner.Scan() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser_test.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser_test.go new file mode 100644 index 00000000..c48cd6f6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser_test.go @@ -0,0 +1,114 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../testdata/empty.dot"}, + {in: "../testdata/graph.dot"}, + {in: "../testdata/digraph.dot"}, + {in: "../testdata/strict.dot"}, + {in: "../testdata/multi.dot"}, + {in: "../testdata/named_graph.dot"}, + {in: "../testdata/node_stmt.dot"}, + {in: "../testdata/edge_stmt.dot"}, + {in: "../testdata/attr_stmt.dot"}, + {in: "../testdata/attr.dot"}, + { + in: "../testdata/subgraph.dot", + out: "../testdata/subgraph.golden", + }, + { + in: "../testdata/semi.dot", + out: "../testdata/semi.golden", + }, + { + in: "../testdata/empty_attr.dot", + out: "../testdata/empty_attr.golden", + }, + { + in: "../testdata/attr_lists.dot", + out: "../testdata/attr_lists.golden", + }, + { + in: "../testdata/attr_sep.dot", + out: "../testdata/attr_sep.golden", + }, + {in: "../testdata/subgraph_vertex.dot"}, + { + in: "../testdata/port.dot", + out: "../testdata/port.golden", + }, + {in: "../testdata/quoted_id.dot"}, + { + in: "../testdata/backslash_newline_id.dot", + out: "../testdata/backslash_newline_id.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected `%s`, got `%s`", g.in, want, got) + } + } +} + +func TestParseError(t *testing.T) { + golden := []struct { + path string + want string + }{ + { + path: "../testdata/error.dot", + want: `Error in S30: INVALID(0,~), Pos(offset=13, line=2, column=7), expected one of: { } graphx ; -- -> node edge [ = subgraph : id `, + }, + } + for _, g := range golden { + _, err := dot.ParseFile(g.path) + if err == nil { + t.Errorf("%q: expected error, got nil", g.path) + continue + } + got := err.Error() + if got != g.want { + t.Errorf("%q: error mismatch; expected `%v`, got `%v`", g.path, g.want, got) + continue + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/productionstable.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/productionstable.go new file mode 100644 index 00000000..96c56350 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/productionstable.go @@ -0,0 +1,586 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/astx" +) + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func([]Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : File << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `File : Graph << astx.NewFile(X[0]) >>`, + Id: "File", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewFile(X[0]) + }, + }, + ProdTabEntry{ + String: `File : File Graph << astx.AppendGraph(X[0], X[1]) >>`, + Id: "File", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendGraph(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Graph : OptStrict DirectedGraph OptID "{" OptStmtList "}" << astx.NewGraph(X[0], X[1], X[2], X[4]) >>`, + Id: "Graph", + NTType: 2, + Index: 3, + NumSymbols: 6, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewGraph(X[0], X[1], X[2], X[4]) + }, + }, + ProdTabEntry{ + String: `OptStrict : empty << false, nil >>`, + Id: "OptStrict", + NTType: 3, + Index: 4, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `OptStrict : strict << true, nil >>`, + Id: "OptStrict", + NTType: 3, + Index: 5, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `DirectedGraph : graphx << false, nil >>`, + Id: "DirectedGraph", + NTType: 4, + Index: 6, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `DirectedGraph : digraph << true, nil >>`, + Id: "DirectedGraph", + NTType: 4, + Index: 7, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `StmtList : Stmt OptSemi << astx.NewStmtList(X[0]) >>`, + Id: "StmtList", + NTType: 5, + Index: 8, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewStmtList(X[0]) + }, + }, + ProdTabEntry{ + String: `StmtList : StmtList Stmt OptSemi << astx.AppendStmt(X[0], X[1]) >>`, + Id: "StmtList", + NTType: 5, + Index: 9, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `OptStmtList : empty << >>`, + Id: "OptStmtList", + NTType: 6, + Index: 10, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptStmtList : StmtList << >>`, + Id: "OptStmtList", + NTType: 6, + Index: 11, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : NodeStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 12, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : EdgeStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 13, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : AttrStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 14, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Attr << >>`, + Id: "Stmt", + NTType: 7, + Index: 15, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Subgraph << >>`, + Id: "Stmt", + NTType: 7, + Index: 16, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSemi : empty << >>`, + Id: "OptSemi", + NTType: 8, + Index: 17, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSemi : ";" << >>`, + Id: "OptSemi", + NTType: 8, + Index: 18, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `NodeStmt : Node OptAttrList << astx.NewNodeStmt(X[0], X[1]) >>`, + Id: "NodeStmt", + NTType: 9, + Index: 19, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewNodeStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `EdgeStmt : Vertex Edge OptAttrList << astx.NewEdgeStmt(X[0], X[1], X[2]) >>`, + Id: "EdgeStmt", + NTType: 10, + Index: 20, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewEdgeStmt(X[0], X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `Edge : DirectedEdge Vertex OptEdge << astx.NewEdge(X[0], X[1], X[2]) >>`, + Id: "Edge", + NTType: 11, + Index: 21, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewEdge(X[0], X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `DirectedEdge : "--" << false, nil >>`, + Id: "DirectedEdge", + NTType: 12, + Index: 22, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `DirectedEdge : "->" << true, nil >>`, + Id: "DirectedEdge", + NTType: 12, + Index: 23, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `OptEdge : empty << >>`, + Id: "OptEdge", + NTType: 13, + Index: 24, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptEdge : Edge << >>`, + Id: "OptEdge", + NTType: 13, + Index: 25, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `AttrStmt : Component AttrList << astx.NewAttrStmt(X[0], X[1]) >>`, + Id: "AttrStmt", + NTType: 14, + Index: 26, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttrStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Component : graphx << ast.GraphKind, nil >>`, + Id: "Component", + NTType: 15, + Index: 27, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.GraphKind, nil + }, + }, + ProdTabEntry{ + String: `Component : node << ast.NodeKind, nil >>`, + Id: "Component", + NTType: 15, + Index: 28, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.NodeKind, nil + }, + }, + ProdTabEntry{ + String: `Component : edge << ast.EdgeKind, nil >>`, + Id: "Component", + NTType: 15, + Index: 29, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.EdgeKind, nil + }, + }, + ProdTabEntry{ + String: `AttrList : "[" OptAList "]" << X[1], nil >>`, + Id: "AttrList", + NTType: 16, + Index: 30, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[1], nil + }, + }, + ProdTabEntry{ + String: `AttrList : AttrList "[" OptAList "]" << astx.AppendAttrList(X[0], X[2]) >>`, + Id: "AttrList", + NTType: 16, + Index: 31, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendAttrList(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `OptAttrList : empty << >>`, + Id: "OptAttrList", + NTType: 17, + Index: 32, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptAttrList : AttrList << >>`, + Id: "OptAttrList", + NTType: 17, + Index: 33, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `AList : Attr OptSep << astx.NewAttrList(X[0]) >>`, + Id: "AList", + NTType: 18, + Index: 34, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttrList(X[0]) + }, + }, + ProdTabEntry{ + String: `AList : AList Attr OptSep << astx.AppendAttr(X[0], X[1]) >>`, + Id: "AList", + NTType: 18, + Index: 35, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendAttr(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `OptAList : empty << >>`, + Id: "OptAList", + NTType: 19, + Index: 36, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptAList : AList << >>`, + Id: "OptAList", + NTType: 19, + Index: 37, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSep : empty << >>`, + Id: "OptSep", + NTType: 20, + Index: 38, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSep : ";" << >>`, + Id: "OptSep", + NTType: 20, + Index: 39, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSep : "," << >>`, + Id: "OptSep", + NTType: 20, + Index: 40, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Attr : ID "=" ID << astx.NewAttr(X[0], X[2]) >>`, + Id: "Attr", + NTType: 21, + Index: 41, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttr(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `Subgraph : OptSubgraphID "{" OptStmtList "}" << astx.NewSubgraph(X[0], X[2]) >>`, + Id: "Subgraph", + NTType: 22, + Index: 42, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewSubgraph(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `OptSubgraphID : empty << >>`, + Id: "OptSubgraphID", + NTType: 23, + Index: 43, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSubgraphID : subgraph OptID << X[1], nil >>`, + Id: "OptSubgraphID", + NTType: 23, + Index: 44, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[1], nil + }, + }, + ProdTabEntry{ + String: `Vertex : Node << >>`, + Id: "Vertex", + NTType: 24, + Index: 45, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Vertex : Subgraph << >>`, + Id: "Vertex", + NTType: 24, + Index: 46, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Node : ID OptPort << astx.NewNode(X[0], X[1]) >>`, + Id: "Node", + NTType: 25, + Index: 47, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewNode(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Port : ":" ID << astx.NewPort(X[1], nil) >>`, + Id: "Port", + NTType: 26, + Index: 48, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewPort(X[1], nil) + }, + }, + ProdTabEntry{ + String: `Port : ":" ID ":" ID << astx.NewPort(X[1], X[3]) >>`, + Id: "Port", + NTType: 26, + Index: 49, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewPort(X[1], X[3]) + }, + }, + ProdTabEntry{ + String: `OptPort : empty << >>`, + Id: "OptPort", + NTType: 27, + Index: 50, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptPort : Port << >>`, + Id: "OptPort", + NTType: 27, + Index: 51, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `ID : id << astx.NewID(X[0]) >>`, + Id: "ID", + NTType: 28, + Index: 52, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewID(X[0]) + }, + }, + ProdTabEntry{ + String: `OptID : empty << "", nil >>`, + Id: "OptID", + NTType: 29, + Index: 53, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return "", nil + }, + }, + ProdTabEntry{ + String: `OptID : ID << >>`, + Id: "OptID", + NTType: 29, + Index: 54, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/paste_copyright.bash b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/paste_copyright.bash new file mode 100755 index 00000000..569bd925 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/paste_copyright.bash @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +find . -type f -name '*.go' \ +| xargs sed -i -e "s|// Code generated by gocc; DO NOT EDIT.|\ +// Code generated by gocc; DO NOT EDIT.\n\ +\n\ +// This file is dual licensed under CC0 and The gonum license.\n\ +//\n\ +// Copyright ©2017 The gonum Authors. All rights reserved.\n\ +// Use of this source code is governed by a BSD-style\n\ +// license that can be found in the LICENSE file.\n\ +//\n\ +// Copyright ©2017 Robin Eklind.\n\ +// This file is made available under a Creative Commons CC0 1.0\n\ +// Universal Public Domain Dedication.\ +|" + diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr.dot new file mode 100644 index 00000000..dabe9734 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr.dot @@ -0,0 +1,4 @@ +digraph { + bgcolor=transparent + A +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.dot new file mode 100644 index 00000000..b71411cd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.dot @@ -0,0 +1,3 @@ +digraph { + A [style=filled] [fillcolor=red] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.golden new file mode 100644 index 00000000..14316d93 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_lists.golden @@ -0,0 +1,3 @@ +digraph { + A [style=filled fillcolor=red] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.dot new file mode 100644 index 00000000..ef47a120 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.dot @@ -0,0 +1,3 @@ +digraph { + A [style=filled, fillcolor=red; color=blue] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.golden new file mode 100644 index 00000000..95bfd972 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_sep.golden @@ -0,0 +1,3 @@ +digraph { + A [style=filled fillcolor=red color=blue] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_stmt.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_stmt.dot new file mode 100644 index 00000000..e87d70a4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/attr_stmt.dot @@ -0,0 +1,6 @@ +digraph { + graph [bgcolor=transparent] + node [style=filled fillcolor=white] + edge [minlen=2] + A -> B +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.dot new file mode 100644 index 00000000..81051384 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.dot @@ -0,0 +1,4 @@ +digraph { + A [name="hello \ +world"] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.golden new file mode 100644 index 00000000..449c3a3e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/backslash_newline_id.golden @@ -0,0 +1,3 @@ +digraph { + A [name="hello world"] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/digraph.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/digraph.dot new file mode 100644 index 00000000..1063ebfa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/digraph.dot @@ -0,0 +1,3 @@ +digraph { + A -> B +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/edge_stmt.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/edge_stmt.dot new file mode 100644 index 00000000..019d23d7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/edge_stmt.dot @@ -0,0 +1,4 @@ +digraph { + A -> B -> C + D -> E [color=red minlen=2] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty.dot new file mode 100644 index 00000000..418b7bca --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty.dot @@ -0,0 +1,2 @@ +graph { +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.dot new file mode 100644 index 00000000..b92d60e5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.dot @@ -0,0 +1,3 @@ +digraph { + A [] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.golden new file mode 100644 index 00000000..369e4495 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/empty_attr.golden @@ -0,0 +1,3 @@ +digraph { + A +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/error.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/error.dot new file mode 100644 index 00000000..ad77f61f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/error.dot @@ -0,0 +1,3 @@ +digraph { + A ~ B +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/graph.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/graph.dot new file mode 100644 index 00000000..0524c144 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/graph.dot @@ -0,0 +1,3 @@ +graph { + A -- B +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/multi.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/multi.dot new file mode 100644 index 00000000..21945188 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/multi.dot @@ -0,0 +1,6 @@ +digraph { + A -> B +} +digraph { + C -> D +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/named_graph.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/named_graph.dot new file mode 100644 index 00000000..3fc680da --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/named_graph.dot @@ -0,0 +1,3 @@ +graph G { + A +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/node_stmt.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/node_stmt.dot new file mode 100644 index 00000000..369e4495 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/node_stmt.dot @@ -0,0 +1,3 @@ +digraph { + A +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.dot new file mode 100644 index 00000000..1d4bf415 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.dot @@ -0,0 +1,11 @@ +digraph { + A:ne -> B:sw + C:foo -> D:bar:se + E:_ -> F + G:n + H:e + I:s + J:w + K:nw + L:c +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.golden new file mode 100644 index 00000000..18ca1f30 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/port.golden @@ -0,0 +1,11 @@ +digraph { + A:ne -> B:sw + C:foo -> D:bar:se + E -> F + G:n + H:e + I:s + J:w + K:nw + L:c +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/quoted_id.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/quoted_id.dot new file mode 100644 index 00000000..0c3b5652 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/quoted_id.dot @@ -0,0 +1,3 @@ +digraph { + "A" -> "B" ["color"="red"] +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.dot new file mode 100644 index 00000000..c8bcbf34 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.dot @@ -0,0 +1,3 @@ +digraph { + A -> B; C +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.golden new file mode 100644 index 00000000..61bca268 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/semi.golden @@ -0,0 +1,4 @@ +digraph { + A -> B + C +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/strict.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/strict.dot new file mode 100644 index 00000000..bf222ad9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/strict.dot @@ -0,0 +1,4 @@ +strict digraph { + A -> B + A -> B +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.dot new file mode 100644 index 00000000..a03667dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.dot @@ -0,0 +1,5 @@ +digraph { + {A} + subgraph {B} + subgraph S {C} +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.golden b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.golden new file mode 100644 index 00000000..0cd6fe72 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph.golden @@ -0,0 +1,5 @@ +digraph { + {A} + {B} + subgraph S {C} +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph_vertex.dot b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph_vertex.dot new file mode 100644 index 00000000..b414ad84 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/testdata/subgraph_vertex.dot @@ -0,0 +1,3 @@ +digraph { + {A B} -> C +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/token/token.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/token/token.go new file mode 100644 index 00000000..1492df0d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/token/token.go @@ -0,0 +1,116 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package token + +import ( + "fmt" +) + +type Token struct { + Type + Lit []byte + Pos +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + //TODO: refactor to print pos & token string properly + return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "$", + "{", + "}", + "empty", + "strict", + "graphx", + "digraph", + ";", + "--", + "->", + "node", + "edge", + "[", + "]", + ",", + "=", + "subgraph", + ":", + "id", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "$": 1, + "{": 2, + "}": 3, + "empty": 4, + "strict": 5, + "graphx": 6, + "digraph": 7, + ";": 8, + "--": 9, + "->": 10, + "node": 11, + "edge": 12, + "[": 13, + "]": 14, + ",": 15, + "=": 16, + "subgraph": 17, + ":": 18, + "id": 19, + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/litconv.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/litconv.go new file mode 100644 index 00000000..ed6e348b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/litconv.go @@ -0,0 +1,118 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/rune.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/rune.go new file mode 100644 index 00000000..583b1e06 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/util/rune.go @@ -0,0 +1,49 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package util + +import ( + "fmt" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/makeinternal.bash b/vendor/gonum.org/v1/gonum/graph/formats/dot/makeinternal.bash new file mode 100755 index 00000000..df377163 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/makeinternal.bash @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd internal +make clean && make diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/sem.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/sem.go new file mode 100644 index 00000000..eb55b031 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/sem.go @@ -0,0 +1,160 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package dot + +import ( + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/ast" +) + +// check validates the semantics of the given DOT file. +func check(file *ast.File) error { + for _, graph := range file.Graphs { + // TODO: Check graph.ID for duplicates? + if err := checkGraph(graph); err != nil { + return err + } + } + return nil +} + +// check validates the semantics of the given graph. +func checkGraph(graph *ast.Graph) error { + for _, stmt := range graph.Stmts { + if err := checkStmt(graph, stmt); err != nil { + return err + } + } + return nil +} + +// check validates the semantics of the given statement. +func checkStmt(graph *ast.Graph, stmt ast.Stmt) error { + switch stmt := stmt.(type) { + case *ast.NodeStmt: + return checkNodeStmt(graph, stmt) + case *ast.EdgeStmt: + return checkEdgeStmt(graph, stmt) + case *ast.AttrStmt: + return checkAttrStmt(graph, stmt) + case *ast.Attr: + // TODO: Verify that the attribute is indeed of graph component kind. + return checkAttr(graph, ast.GraphKind, stmt) + case *ast.Subgraph: + return checkSubgraph(graph, stmt) + default: + panic(fmt.Sprintf("support for statement of type %T not yet implemented", stmt)) + } +} + +// checkNodeStmt validates the semantics of the given node statement. +func checkNodeStmt(graph *ast.Graph, stmt *ast.NodeStmt) error { + if err := checkNode(graph, stmt.Node); err != nil { + return err + } + for _, attr := range stmt.Attrs { + // TODO: Verify that the attribute is indeed of node component kind. + if err := checkAttr(graph, ast.NodeKind, attr); err != nil { + return err + } + } + return nil +} + +// checkEdgeStmt validates the semantics of the given edge statement. +func checkEdgeStmt(graph *ast.Graph, stmt *ast.EdgeStmt) error { + // TODO: if graph.Strict, check for multi-edges. + if err := checkVertex(graph, stmt.From); err != nil { + return err + } + for _, attr := range stmt.Attrs { + // TODO: Verify that the attribute is indeed of edge component kind. + if err := checkAttr(graph, ast.EdgeKind, attr); err != nil { + return err + } + } + return checkEdge(graph, stmt.From, stmt.To) +} + +// checkEdge validates the semantics of the given edge. +func checkEdge(graph *ast.Graph, from ast.Vertex, to *ast.Edge) error { + if !graph.Directed && to.Directed { + return fmt.Errorf("undirected graph %q contains directed edge from %q to %q", graph.ID, from, to.Vertex) + } + if err := checkVertex(graph, to.Vertex); err != nil { + return err + } + if to.To != nil { + return checkEdge(graph, to.Vertex, to.To) + } + return nil +} + +// checkAttrStmt validates the semantics of the given attribute statement. +func checkAttrStmt(graph *ast.Graph, stmt *ast.AttrStmt) error { + for _, attr := range stmt.Attrs { + if err := checkAttr(graph, stmt.Kind, attr); err != nil { + return err + } + } + return nil +} + +// checkAttr validates the semantics of the given attribute for the given +// component kind. +func checkAttr(graph *ast.Graph, kind ast.Kind, attr *ast.Attr) error { + switch kind { + case ast.GraphKind: + // TODO: Validate key-value pairs for graphs. + return nil + case ast.NodeKind: + // TODO: Validate key-value pairs for nodes. + return nil + case ast.EdgeKind: + // TODO: Validate key-value pairs for edges. + return nil + default: + panic(fmt.Sprintf("support for component kind %v not yet supported", kind)) + } +} + +// checkSubgraph validates the semantics of the given subgraph. +func checkSubgraph(graph *ast.Graph, subgraph *ast.Subgraph) error { + // TODO: Check subgraph.ID for duplicates? + for _, stmt := range subgraph.Stmts { + // TODO: Refine handling of subgraph statements? + // checkSubgraphStmt(graph, subgraph, stmt) + if err := checkStmt(graph, stmt); err != nil { + return err + } + } + return nil +} + +// checkVertex validates the semantics of the given vertex. +func checkVertex(graph *ast.Graph, vertex ast.Vertex) error { + switch vertex := vertex.(type) { + case *ast.Node: + return checkNode(graph, vertex) + case *ast.Subgraph: + return checkSubgraph(graph, vertex) + default: + panic(fmt.Sprintf("support for vertex of type %T not yet supported", vertex)) + } +} + +// checNode validates the semantics of the given node. +func checkNode(graph *ast.Graph, node *ast.Node) error { + // TODO: Check node.ID for duplicates? + // TODO: Validate node.Port. + return nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/.gitignore b/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/.gitignore new file mode 100644 index 00000000..90453be2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/.gitignore @@ -0,0 +1,5 @@ +*.dot +*.png +graphviz +input +output diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/Makefile b/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/Makefile new file mode 100644 index 00000000..c3bfcb9b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/testdata/Makefile @@ -0,0 +1,106 @@ +# Dependencies: +# +# * imgcmp +# go get github.com/mewkiz/cmd/imgcmp +# * dotfmt +# go get github.com/graphism/dot/cmd/dotfmt +# * dot +# sudo pacman -S graphviz +# * recode +# sudo pacman -S recode + +DOT=$(wildcard *.dot) + +# Skip DOT files for which the generated PNG images mismatch. +# +# ref: https://github.com/graphism/dot/issues/2 +# +# pixel colors differ at x=550, y=1885 +DOT:=$(filter-out b51.dot, $(DOT)) +# pixel colors differ at x=5395, y=1920 +DOT:=$(filter-out b106.dot, $(DOT)) + +# Skip segfaulting files. +# +# Segmentation fault (core dumped) +DOT:=$(filter-out b15.dot, $(DOT)) +# Segmentation fault (core dumped) +DOT:=$(filter-out b81.dot, $(DOT)) +# *** stack smashing detected ***: dot terminated +DOT:=$(filter-out sides.dot, $(DOT)) +# *** stack smashing detected ***: dot terminated +DOT:=$(filter-out tee.dot, $(DOT)) + +# Skip DOT files above 100 kB. +DOT:=$(filter-out 4elt.dot, $(DOT)) +DOT:=$(filter-out b29.dot, $(DOT)) +DOT:=$(filter-out b81.dot, $(DOT)) +DOT:=$(filter-out b100.dot, $(DOT)) +DOT:=$(filter-out b102.dot, $(DOT)) +DOT:=$(filter-out b103.dot, $(DOT)) +DOT:=$(filter-out b104.dot, $(DOT)) +DOT:=$(filter-out root.dot, $(DOT)) +DOT:=$(filter-out root_circo.dot, $(DOT)) +DOT:=$(filter-out root_twopi.dot, $(DOT)) + +# Skip invalid DOT file. +# +# Error: No or improper image file="eqn.png" +# in label of node struct1 +DOT:=$(filter-out html4.dot, $(DOT)) + +# Skip multi-graph DOT file which outputs to standard output. +DOT:=$(filter-out multi.dot, $(DOT)) + +# *.dot -> *.png +PNG=$(DOT:.dot=.png) + +INPUT_PNG=$(addprefix input/,$(PNG)) +OUTPUT_PNG=$(addprefix output/,$(PNG)) + +all: + +test: input $(INPUT_PNG) output $(OUTPUT_PNG) + @echo "PASS" + +input: + mkdir -p $@ + dot -V + +input/%.png: %.dot + dot -Tpng -o $@ $< + +output: + mkdir -p $@ + +output/%.png: %.dot + dotfmt -o "output/$<" $< + dot -Tpng -o $@ "output/$<" + imgcmp "input/$(notdir $@)" $@ + +fetch: graphviz + # Copy *.gv and *.dot files. + find graphviz -type f -name '*.gv' -not -wholename "graphviz/rtest/share/b545.gv" -not -name "base.gv" | xargs -I '{}' cp "{}" . + find graphviz -type f -name '*.dot' | xargs -I '{}' cp "{}" . + + # Rename *.gv to *.dot. + #rename .gv .dot *.gv + ls *.gv | xargs -I '{}' basename "{}" .gv | xargs -I '{}' mv "{}.gv" "{}.dot" + + # Remove execute permissions. + chmod 0644 *.dot + + # Convert Latin1 encoded files to UTF-8. + grep -l "charset=latin1" *.dot | xargs -I '{}' recode ISO-8859-1..UTF8 "{}" + recode ISO-8859-1..UTF8 Latin1.dot + + # Clean up. + rm -rf graphviz + +graphviz: + git clone https://github.com/ellson/graphviz.git + +clean: + rm -rf *.dot input output + +.PHONY: all test fetch clean diff --git a/vendor/gonum.org/v1/gonum/graph/graph.go b/vendor/gonum.org/v1/gonum/graph/graph.go new file mode 100644 index 00000000..0ca587d8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graph.go @@ -0,0 +1,247 @@ +// Copyright ©2014 The gonum 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 graph + +// Node is a graph node. It returns a graph-unique integer ID. +type Node interface { + ID() int64 +} + +// Edge is a graph edge. In directed graphs, the direction of the +// edge is given from -> to, otherwise the edge is semantically +// unordered. +type Edge interface { + From() Node + To() Node +} + +// WeightedEdge is a weighted graph edge. In directed graphs, the direction +// of the edge is given from -> to, otherwise the edge is semantically +// unordered. +type WeightedEdge interface { + Edge + Weight() float64 +} + +// Graph is a generalized graph. +type Graph interface { + // Has returns whether the node exists within the graph. + Has(Node) bool + + // Nodes returns all the nodes in the graph. + Nodes() []Node + + // From returns all nodes that can be reached directly + // from the given node. + From(Node) []Node + + // HasEdgeBetween returns whether an edge exists between + // nodes x and y without considering direction. + HasEdgeBetween(x, y Node) bool + + // Edge returns the edge from u to v if such an edge + // exists and nil otherwise. The node v must be directly + // reachable from u as defined by the From method. + Edge(u, v Node) Edge +} + +// Weighted is a weighted graph. +type Weighted interface { + Graph + + // WeightedEdge returns the weighted edge from u to v if + // such an edge exists and nil otherwise. The node v must + // be directly reachable from u as defined by the + // From method. + WeightedEdge(u, v Node) WeightedEdge + + // Weight returns the weight for the edge between + // x and y if Edge(x, y) returns a non-nil Edge. + // If x and y are the same node or there is no + // joining edge between the two nodes the weight + // value returned is implementation dependent. + // Weight returns true if an edge exists between + // x and y or if x and y have the same ID, false + // otherwise. + Weight(x, y Node) (w float64, ok bool) +} + +// Undirected is an undirected graph. +type Undirected interface { + Graph + + // EdgeBetween returns the edge between nodes x and y. + EdgeBetween(x, y Node) Edge +} + +// WeightedUndirected is a weighted undirected graph. +type WeightedUndirected interface { + Weighted + + // WeightedEdgeBetween returns the edge between nodes + // x and y. + WeightedEdgeBetween(x, y Node) WeightedEdge +} + +// Directed is a directed graph. +type Directed interface { + Graph + + // HasEdgeFromTo returns whether an edge exists + // in the graph from u to v. + HasEdgeFromTo(u, v Node) bool + + // To returns all nodes that can reach directly + // to the given node. + To(Node) []Node +} + +// WeightedDirected is a weighted directed graph. +type WeightedDirected interface { + Weighted + + // HasEdgeFromTo returns whether an edge exists + // in the graph from u to v. + HasEdgeFromTo(u, v Node) bool + + // To returns all nodes that can reach directly + // to the given node. + To(Node) []Node +} + +// NodeAdder is an interface for adding arbitrary nodes to a graph. +type NodeAdder interface { + // NewNode returns a new Node with a unique + // arbitrary ID. + NewNode() Node + + // Adds a node to the graph. AddNode panics if + // the added node ID matches an existing node ID. + AddNode(Node) +} + +// NodeRemover is an interface for removing nodes from a graph. +type NodeRemover interface { + // RemoveNode removes a node from the graph, as + // well as any edges attached to it. If the node + // is not in the graph it is a no-op. + RemoveNode(Node) +} + +// EdgeAdder is an interface for adding edges to a graph. +type EdgeAdder interface { + // NewEdge returns a new Edge from the source to the destination node. + NewEdge(from, to Node) Edge + + // SetEdge adds an edge from one node to another. + // If the graph supports node addition the nodes + // will be added if they do not exist, otherwise + // SetEdge will panic. + // The behavior of an EdgeAdder when the IDs + // returned by e.From and e.To are equal is + // implementation-dependent. + SetEdge(e Edge) +} + +// WeightedEdgeAdder is an interface for adding edges to a graph. +type WeightedEdgeAdder interface { + // NewWeightedEdge returns a new WeightedEdge from + // the source to the destination node. + NewWeightedEdge(from, to Node, weight float64) WeightedEdge + + // SetWeightedEdge adds an edge from one node to + // another. If the graph supports node addition + // the nodes will be added if they do not exist, + // otherwise SetWeightedEdge will panic. + // The behavior of a WeightedEdgeAdder when the IDs + // returned by e.From and e.To are equal is + // implementation-dependent. + SetWeightedEdge(e WeightedEdge) +} + +// EdgeRemover is an interface for removing nodes from a graph. +type EdgeRemover interface { + // RemoveEdge removes the given edge, leaving the + // terminal nodes. If the edge does not exist it + // is a no-op. + RemoveEdge(Edge) +} + +// Builder is a graph that can have nodes and edges added. +type Builder interface { + NodeAdder + EdgeAdder +} + +// WeightedBuilder is a graph that can have nodes and weighted edges added. +type WeightedBuilder interface { + NodeAdder + WeightedEdgeAdder +} + +// UndirectedBuilder is an undirected graph builder. +type UndirectedBuilder interface { + Undirected + Builder +} + +// UndirectedWeightedBuilder is an undirected weighted graph builder. +type UndirectedWeightedBuilder interface { + Undirected + WeightedBuilder +} + +// DirectedBuilder is a directed graph builder. +type DirectedBuilder interface { + Directed + Builder +} + +// DirectedWeightedBuilder is a directed weighted graph builder. +type DirectedWeightedBuilder interface { + Directed + WeightedBuilder +} + +// Copy copies nodes and edges as undirected edges from the source to the destination +// without first clearing the destination. Copy will panic if a node ID in the source +// graph matches a node ID in the destination. +// +// If the source is undirected and the destination is directed both directions will +// be present in the destination after the copy is complete. +func Copy(dst Builder, src Graph) { + nodes := src.Nodes() + for _, n := range nodes { + dst.AddNode(n) + } + for _, u := range nodes { + for _, v := range src.From(u) { + dst.SetEdge(src.Edge(u, v)) + } + } +} + +// CopyWeighted copies nodes and edges as undirected edges from the source to the destination +// without first clearing the destination. Copy will panic if a node ID in the source +// graph matches a node ID in the destination. +// +// If the source is undirected and the destination is directed both directions will +// be present in the destination after the copy is complete. +// +// If the source is a directed graph, the destination is undirected, and a fundamental +// cycle exists with two nodes where the edge weights differ, the resulting destination +// graph's edge weight between those nodes is undefined. If there is a defined function +// to resolve such conflicts, an UndirectWeighted may be used to do this. +func CopyWeighted(dst WeightedBuilder, src Weighted) { + nodes := src.Nodes() + for _, n := range nodes { + dst.AddNode(n) + } + for _, u := range nodes { + for _, v := range src.From(u) { + dst.SetWeightedEdge(src.WeightedEdge(u, v)) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes.go new file mode 100644 index 00000000..4c578927 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes.go @@ -0,0 +1,357 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The functions in this file are random graph generators from the paper +// by Batagelj and Brandes http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + +package gen + +import ( + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// Gnp constructs a Gilbert’s model graph in the destination, dst, of order n. Edges +// between nodes are formed with the probability, p. If src is not nil it is used +// as the random source, otherwise rand.Float64 is used. The graph is constructed +// in O(n+m) time where m is the number of edges added. +func Gnp(dst GraphBuilder, n int, p float64, src *rand.Rand) error { + if p == 0 { + return nil + } + if p < 0 || p > 1 { + return fmt.Errorf("gen: bad probability: p=%v", p) + } + var r func() float64 + if src == nil { + r = rand.Float64 + } else { + r = src.Float64 + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + lp := math.Log(1 - p) + + // Add forward edges for all graphs. + for v, w := 1, -1; v < n; { + w += 1 + int(math.Log(1-r())/lp) + for w >= v && v < n { + w -= v + v++ + } + if v < n { + dst.SetEdge(simple.Edge{F: simple.Node(w), T: simple.Node(v)}) + } + } + + // Add backward edges for directed graphs. + if _, ok := dst.(graph.Directed); !ok { + return nil + } + for v, w := 1, -1; v < n; { + w += 1 + int(math.Log(1-r())/lp) + for w >= v && v < n { + w -= v + v++ + } + if v < n { + dst.SetEdge(simple.Edge{F: simple.Node(v), T: simple.Node(w)}) + } + } + + return nil +} + +// edgeNodesFor returns the pair of nodes for the ith edge in a simple +// undirected graph. The pair is returned such that w.ID < v.ID. +func edgeNodesFor(i int) (v, w simple.Node) { + // This is an algebraic simplification of the expressions described + // on p3 of http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + v = simple.Node(0.5 + math.Sqrt(float64(1+8*i))/2) + w = simple.Node(i) - v*(v-1)/2 + return v, w +} + +// Gnm constructs a Erdős-Rényi model graph in the destination, dst, of +// order n and size m. If src is not nil it is used as the random source, +// otherwise rand.Intn is used. The graph is constructed in O(m) expected +// time for m ≤ (n choose 2)/2. +func Gnm(dst GraphBuilder, n, m int, src *rand.Rand) error { + if m == 0 { + return nil + } + + hasEdge := dst.HasEdgeBetween + d, isDirected := dst.(graph.Directed) + if isDirected { + m /= 2 + hasEdge = d.HasEdgeFromTo + } + + nChoose2 := (n - 1) * n / 2 + if m < 0 || m > nChoose2 { + return fmt.Errorf("gen: bad size: m=%d", m) + } + + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + // Add forward edges for all graphs. + for i := 0; i < m; i++ { + for { + v, w := edgeNodesFor(rnd(nChoose2)) + e := simple.Edge{F: w, T: v} + if !hasEdge(e.F, e.T) { + dst.SetEdge(e) + break + } + } + } + + // Add backward edges for directed graphs. + if !isDirected { + return nil + } + for i := 0; i < m; i++ { + for { + v, w := edgeNodesFor(rnd(nChoose2)) + e := simple.Edge{F: v, T: w} + if !hasEdge(e.F, e.T) { + dst.SetEdge(e) + break + } + } + } + + return nil +} + +// SmallWorldsBB constructs a small worlds graph of order n in the destination, dst. +// Node degree is specified by d and edge replacement by the probability, p. +// If src is not nil it is used as the random source, otherwise rand.Float64 is used. +// The graph is constructed in O(nd) time. +// +// The algorithm used is described in http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf +func SmallWorldsBB(dst GraphBuilder, n, d int, p float64, src *rand.Rand) error { + if d < 1 || d > (n-1)/2 { + return fmt.Errorf("gen: bad degree: d=%d", d) + } + if p == 0 { + return nil + } + if p < 0 || p >= 1 { + return fmt.Errorf("gen: bad replacement: p=%v", p) + } + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + hasEdge := dst.HasEdgeBetween + dg, isDirected := dst.(graph.Directed) + if isDirected { + hasEdge = dg.HasEdgeFromTo + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + nChoose2 := (n - 1) * n / 2 + + lp := math.Log(1 - p) + + // Add forward edges for all graphs. + k := int(math.Log(1-rnd()) / lp) + m := 0 + replace := make(map[int]int) + for v := 0; v < n; v++ { + for i := 1; i <= d; i++ { + if k > 0 { + j := v*(v-1)/2 + (v+i)%n + var ej simple.Edge + ej.T, ej.F = edgeNodesFor(j) + if !hasEdge(ej.From(), ej.To()) { + dst.SetEdge(ej) + } + k-- + m++ + var em simple.Edge + em.T, em.F = edgeNodesFor(m) + if !hasEdge(em.From(), em.To()) { + replace[j] = m + } else { + replace[j] = replace[m] + } + } else { + k = int(math.Log(1-rnd()) / lp) + } + } + } + for i := m + 1; i <= n*d && i < nChoose2; i++ { + r := rndN(nChoose2-i) + i + var er simple.Edge + er.T, er.F = edgeNodesFor(r) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } else { + er.T, er.F = edgeNodesFor(replace[r]) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } + } + var ei simple.Edge + ei.T, ei.F = edgeNodesFor(i) + if !hasEdge(ei.From(), ei.To()) { + replace[r] = i + } else { + replace[r] = replace[i] + } + } + + // Add backward edges for directed graphs. + if !isDirected { + return nil + } + k = int(math.Log(1-rnd()) / lp) + m = 0 + replace = make(map[int]int) + for v := 0; v < n; v++ { + for i := 1; i <= d; i++ { + if k > 0 { + j := v*(v-1)/2 + (v+i)%n + var ej simple.Edge + ej.F, ej.T = edgeNodesFor(j) + if !hasEdge(ej.From(), ej.To()) { + dst.SetEdge(ej) + } + k-- + m++ + if !hasEdge(edgeNodesFor(m)) { + replace[j] = m + } else { + replace[j] = replace[m] + } + } else { + k = int(math.Log(1-rnd()) / lp) + } + } + } + for i := m + 1; i <= n*d && i < nChoose2; i++ { + r := rndN(nChoose2-i) + i + var er simple.Edge + er.F, er.T = edgeNodesFor(r) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } else { + er.F, er.T = edgeNodesFor(replace[r]) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } + } + if !hasEdge(edgeNodesFor(i)) { + replace[r] = i + } else { + replace[r] = replace[i] + } + } + + return nil +} + +/* +// Multigraph generators. + +type EdgeAdder interface { + AddEdge(graph.Edge) +} + +func PreferentialAttachment(dst EdgeAdder, n, d int, src *rand.Rand) { + if d < 1 { + panic("gen: bad d") + } + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + m := make([]simple.Node, 2*n*d) + for v := 0; v < n; v++ { + for i := 0; i < d; i++ { + m[2*(v*d+i)] = simple.Node(v) + m[2*(v*d+i)+1] = simple.Node(m[rnd(2*v*d+i+1)]) + } + } + for i := 0; i < n*d; i++ { + dst.AddEdge(simple.Edge{F: m[2*i], T: m[2*i+1], W: 1}) + } +} + +func BipartitePreferentialAttachment(dst EdgeAdder, n, d int, src *rand.Rand) { + if d < 1 { + panic("gen: bad d") + } + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + m1 := make([]simple.Node, 2*n*d) + m2 := make([]simple.Node, 2*n*d) + for v := 0; v < n; v++ { + for i := 0; i < d; i++ { + m1[2*(v*d+i)] = simple.Node(v) + m2[2*(v*d+i)] = simple.Node(n + v) + + if r := rnd(2*v*d + i + 1); r&0x1 == 0 { + m1[2*(v*d+i)+1] = m2[r] + } else { + m1[2*(v*d+i)+1] = m1[r] + } + + if r := rnd(2*v*d + i + 1); r&0x1 == 0 { + m2[2*(v*d+i)+1] = m1[r] + } else { + m2[2*(v*d+i)+1] = m2[r] + } + } + } + for i := 0; i < n*d; i++ { + dst.AddEdge(simple.Edge{F: m1[2*i], T: m1[2*i+1], W: 1}) + dst.AddEdge(simple.Edge{F: m2[2*i], T: m2[2*i+1], W: 1}) + } +} +*/ diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes_test.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes_test.go new file mode 100644 index 00000000..544e2e96 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/batagelj_brandes_test.go @@ -0,0 +1,174 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type gnUndirected struct { + graph.UndirectedBuilder + addBackwards bool + addSelfLoop bool + addMultipleEdge bool +} + +func (g *gnUndirected) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case e.From().ID() > e.To().ID(): + g.addBackwards = true + case g.UndirectedBuilder.HasEdgeBetween(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.UndirectedBuilder.SetEdge(e) +} + +type gnDirected struct { + graph.DirectedBuilder + addSelfLoop bool + addMultipleEdge bool +} + +func (g *gnDirected) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case g.DirectedBuilder.HasEdgeFromTo(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.DirectedBuilder.SetEdge(e) +} + +func TestGnpUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := Gnp(g, n, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, p=%v", n, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, p=%v", n, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) + } + } + } +} + +func TestGnpDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} + err := Gnp(g, n, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, p=%v", n, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) + } + } + } +} + +func TestGnmUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + nChoose2 := (n - 1) * n / 2 + for m := 0; m <= nChoose2; m++ { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := Gnm(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d", n, m) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} + +func TestGnmDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + nChoose2 := (n - 1) * n / 2 + for m := 0; m <= nChoose2*2; m++ { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} + err := Gnm(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} + +func TestSmallWorldsBBUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for d := 1; d <= (n-1)/2; d++ { + for p := 0.; p < 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := SmallWorldsBB(g, n, d, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, d=%d, p=%v", n, d, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) + } + } + } + } +} + +func TestSmallWorldsBBDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for d := 1; d <= (n-1)/2; d++ { + for p := 0.; p < 1; p += 0.1 { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} + err := SmallWorldsBB(g, n, d, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/doc.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/doc.go new file mode 100644 index 00000000..f5ebfcb5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 gen provides random graph generation functions. +package gen // import "gonum.org/v1/gonum/graph/graphs/gen" diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication.go new file mode 100644 index 00000000..8ffa578d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication.go @@ -0,0 +1,125 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// UndirectedMutator is an undirected graph builder that can remove edges. +type UndirectedMutator interface { + graph.UndirectedBuilder + graph.EdgeRemover +} + +// Duplication constructs a graph in the destination, dst, of order n. New nodes +// are created by duplicating an existing node and all its edges. Each new edge is +// deleted with probability delta. Additional edges are added between the new node +// and existing nodes with probability alpha/|V|. An exception to this addition +// rule is made for the parent node when sigma is not NaN; in this case an edge is +// created with probability sigma. With the exception of the sigma parameter, this +// corresponds to the completely correlated case in doi:10.1016/S0022-5193(03)00028-6. +// If src is not nil it is used as the random source, otherwise rand.Float64 is used. +func Duplication(dst UndirectedMutator, n int, delta, alpha, sigma float64, src *rand.Rand) error { + // As described in doi:10.1016/S0022-5193(03)00028-6 but + // also clarified in doi:10.1186/gb-2007-8-4-r51. + + if delta < 0 || delta > 1 { + return fmt.Errorf("gen: bad delta: delta=%v", delta) + } + if alpha <= 0 || alpha > 1 { + return fmt.Errorf("gen: bad alpha: alpha=%v", alpha) + } + if sigma < 0 || sigma > 1 { + return fmt.Errorf("gen: bad sigma: sigma=%v", sigma) + } + + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + nodes := dst.Nodes() + sort.Sort(ordered.ByID(nodes)) + if len(nodes) == 0 { + n-- + u := dst.NewNode() + dst.AddNode(u) + nodes = append(nodes, u) + } + for i := 0; i < n; i++ { + u := nodes[rndN(len(nodes))] + d := dst.NewNode() + + // Add the duplicate node. + dst.AddNode(d) + + // Loop until we have connectivity + // into the rest of the graph. + for { + // Add edges to parent's neighbours. + to := dst.From(u) + sort.Sort(ordered.ByID(to)) + for _, v := range to { + if rnd() < delta || dst.HasEdgeBetween(v, d) { + continue + } + if v.ID() < d.ID() { + dst.SetEdge(dst.NewEdge(v, d)) + } else { + dst.SetEdge(dst.NewEdge(d, v)) + } + } + + // Add edges to old nodes. + scaledAlpha := alpha / float64(len(nodes)) + for _, v := range nodes { + switch v.ID() { + case u.ID(): + if !math.IsNaN(sigma) { + if i == 0 || rnd() < sigma { + if v.ID() < d.ID() { + dst.SetEdge(dst.NewEdge(v, d)) + } else { + dst.SetEdge(dst.NewEdge(d, v)) + } + } + continue + } + fallthrough + default: + if rnd() < scaledAlpha && !dst.HasEdgeBetween(v, d) { + if v.ID() < d.ID() { + dst.SetEdge(dst.NewEdge(v, d)) + } else { + dst.SetEdge(dst.NewEdge(d, v)) + } + } + } + } + + if len(dst.From(d)) != 0 { + break + } + } + + nodes = append(nodes, d) + } + + return nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication_test.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication_test.go new file mode 100644 index 00000000..b58eb899 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/duplication_test.go @@ -0,0 +1,58 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type duplication struct { + UndirectedMutator + addBackwards bool + addSelfLoop bool + addMultipleEdge bool +} + +func (g *duplication) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case e.From().ID() > e.To().ID(): + g.addBackwards = true + case g.UndirectedMutator.HasEdgeBetween(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.UndirectedMutator.SetEdge(e) +} + +func TestDuplication(t *testing.T) { + for n := 2; n <= 50; n++ { + for alpha := 0.1; alpha <= 1; alpha += 0.1 { + for delta := 0.; delta <= 1; delta += 0.2 { + for sigma := 0.; sigma <= 1; sigma += 0.2 { + g := &duplication{UndirectedMutator: simple.NewUndirectedGraph()} + err := Duplication(g, n, delta, alpha, sigma, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, alpha=%v, delta=%v sigma=%v: %v", n, alpha, delta, sigma, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/gen.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/gen.go new file mode 100644 index 00000000..85c484e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/gen.go @@ -0,0 +1,21 @@ +// Copyright ©2015 The gonum 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 gen + +import "gonum.org/v1/gonum/graph" + +// GraphBuilder is a graph that can have nodes and edges added. +type GraphBuilder interface { + Has(graph.Node) bool + HasEdgeBetween(x, y graph.Node) bool + graph.Builder +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim.go new file mode 100644 index 00000000..457fb1be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim.go @@ -0,0 +1,160 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "errors" + "fmt" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/stat/sampleuv" +) + +// TunableClusteringScaleFree constructs a graph in the destination, dst, of order n. +// The graph is constructed successively starting from an m order graph with one node +// having degree m-1. At each iteration of graph addition, one node is added with m +// additional edges joining existing nodes with probability proportional to the nodes' +// degrees. The edges are formed as a triad with probability, p. +// If src is not nil it is used as the random source, otherwise rand.Float64 and +// rand.Intn are used. +// +// The algorithm is essentially as described in http://arxiv.org/abs/cond-mat/0110452. +func TunableClusteringScaleFree(dst graph.UndirectedBuilder, n, m int, p float64, src *rand.Rand) error { + if p < 0 || p > 1 { + return fmt.Errorf("gen: bad probability: p=%v", p) + } + if n <= m { + return fmt.Errorf("gen: n <= m: n=%v m=%d", n, m) + } + + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + // Initial condition. + wt := make([]float64, n) + for u := 0; u < m; u++ { + if !dst.Has(simple.Node(u)) { + dst.AddNode(simple.Node(u)) + } + // We need to give equal probability for + // adding the first generation of edges. + wt[u] = 1 + } + ws := sampleuv.NewWeighted(wt, src) + for i := range wt { + // These weights will organically grow + // after the first growth iteration. + wt[i] = 0 + } + + // Growth. + for v := m; v < n; v++ { + var u int + pa: + for i := 0; i < m; i++ { + // Triad formation. + if i != 0 && rnd() < p { + for _, w := range permute(dst.From(simple.Node(u)), rndN) { + wid := w.ID() + if wid == int64(v) || dst.HasEdgeBetween(w, simple.Node(v)) { + continue + } + dst.SetEdge(simple.Edge{F: w, T: simple.Node(v)}) + wt[wid]++ + wt[v]++ + continue pa + } + } + + // Preferential attachment. + for { + var ok bool + u, ok = ws.Take() + if !ok { + return errors.New("gen: depleted distribution") + } + if u == v || dst.HasEdgeBetween(simple.Node(u), simple.Node(v)) { + continue + } + dst.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + wt[u]++ + wt[v]++ + break + } + } + + ws.ReweightAll(wt) + } + + return nil +} + +func permute(n []graph.Node, rnd func(int) int) []graph.Node { + for i := range n[:len(n)-1] { + j := rnd(len(n)-i) + i + n[i], n[j] = n[j], n[i] + } + return n +} + +// PreferentialAttachment constructs a graph in the destination, dst, of order n. +// The graph is constructed successively starting from an m order graph with one +// node having degree m-1. At each iteration of graph addition, one node is added +// with m additional edges joining existing nodes with probability proportional +// to the nodes' degrees. If src is not nil it is used as the random source, +// otherwise rand.Float64 is used. +// +// The algorithm is essentially as described in http://arxiv.org/abs/cond-mat/0110452 +// after 10.1126/science.286.5439.509. +func PreferentialAttachment(dst graph.UndirectedBuilder, n, m int, src *rand.Rand) error { + if n <= m { + return fmt.Errorf("gen: n <= m: n=%v m=%d", n, m) + } + + // Initial condition. + wt := make([]float64, n) + for u := 0; u < m; u++ { + if !dst.Has(simple.Node(u)) { + dst.AddNode(simple.Node(u)) + } + // We need to give equal probability for + // adding the first generation of edges. + wt[u] = 1 + } + ws := sampleuv.NewWeighted(wt, src) + for i := range wt { + // These weights will organically grow + // after the first growth iteration. + wt[i] = 0 + } + + // Growth. + for v := m; v < n; v++ { + for i := 0; i < m; i++ { + // Preferential attachment. + u, ok := ws.Take() + if !ok { + return errors.New("gen: depleted distribution") + } + dst.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + wt[u]++ + wt[v]++ + } + ws.ReweightAll(wt) + } + + return nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim_test.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim_test.go new file mode 100644 index 00000000..82eb62a8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/holme_kim_test.go @@ -0,0 +1,55 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "testing" + + "gonum.org/v1/gonum/graph/simple" +) + +func TestTunableClusteringScaleFree(t *testing.T) { + for n := 2; n <= 20; n++ { + for m := 0; m < n; m++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := TunableClusteringScaleFree(g, n, m, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d, p=%v: %v", n, m, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d, p=%v", n, m, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d, p=%v", n, m, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d, p=%v", n, m, p) + } + } + } + } +} + +func TestPreferentialAttachment(t *testing.T) { + for n := 2; n <= 20; n++ { + for m := 0; m < n; m++ { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := PreferentialAttachment(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d", n, m) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world.go new file mode 100644 index 00000000..3ff40e87 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world.go @@ -0,0 +1,204 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "errors" + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/stat/sampleuv" +) + +// NavigableSmallWorld constructs an N-dimensional grid with guaranteed local connectivity +// and random long-range connectivity in the destination, dst. The dims parameters specifies +// the length of each of the N dimensions, p defines the Manhattan distance between local +// nodes, and q defines the number of out-going long-range connections from each node. Long- +// range connections are made with a probability proportional to |d(u,v)|^-r where d is the +// Manhattan distance between non-local nodes. +// +// The algorithm is essentially as described on p4 of http://www.cs.cornell.edu/home/kleinber/swn.pdf. +func NavigableSmallWorld(dst GraphBuilder, dims []int, p, q int, r float64, src *rand.Rand) (err error) { + if p < 1 { + return fmt.Errorf("gen: bad local distance: p=%v", p) + } + if q < 0 { + return fmt.Errorf("gen: bad distant link count: q=%v", q) + } + if r < 0 { + return fmt.Errorf("gen: bad decay constant: r=%v", r) + } + + n := 1 + for _, d := range dims { + n *= d + } + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + hasEdge := dst.HasEdgeBetween + d, isDirected := dst.(graph.Directed) + if isDirected { + hasEdge = d.HasEdgeFromTo + } + + locality := make([]int, len(dims)) + for i := range locality { + locality[i] = p*2 + 1 + } + iterateOver(dims, func(u []int) { + uid := idFrom(u, dims) + iterateOver(locality, func(delta []int) { + d := manhattanDelta(u, delta, dims, -p) + if d == 0 || d > p { + return + } + vid := idFromDelta(u, delta, dims, -p) + e := simple.Edge{F: simple.Node(uid), T: simple.Node(vid)} + if uid > vid { + e.F, e.T = e.T, e.F + } + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + if !isDirected { + return + } + e.F, e.T = e.T, e.F + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + }) + }) + + defer func() { + r := recover() + if r != nil { + if r != "depleted distribution" { + panic(r) + } + err = errors.New("depleted distribution") + } + }() + w := make([]float64, n) + ws := sampleuv.NewWeighted(w, src) + iterateOver(dims, func(u []int) { + uid := idFrom(u, dims) + iterateOver(dims, func(v []int) { + d := manhattanBetween(u, v) + if d <= p { + return + } + w[idFrom(v, dims)] = math.Pow(float64(d), -r) + }) + ws.ReweightAll(w) + for i := 0; i < q; i++ { + vid, ok := ws.Take() + if !ok { + panic("depleted distribution") + } + e := simple.Edge{F: simple.Node(uid), T: simple.Node(vid)} + if !isDirected && uid > vid { + e.F, e.T = e.T, e.F + } + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + } + for i := range w { + w[i] = 0 + } + }) + + return nil +} + +// iterateOver performs an iteration over all dimensions of dims, calling fn +// for each state. The elements of state must not be mutated by fn. +func iterateOver(dims []int, fn func(state []int)) { + iterator(0, dims, make([]int, len(dims)), fn) +} + +func iterator(d int, dims, state []int, fn func(state []int)) { + if d >= len(dims) { + fn(state) + return + } + for i := 0; i < dims[d]; i++ { + state[d] = i + iterator(d+1, dims, state, fn) + } +} + +// manhattanBetween returns the Manhattan distance between a and b. +func manhattanBetween(a, b []int) int { + if len(a) != len(b) { + panic("gen: unexpected dimension") + } + var d int + for i, v := range a { + d += abs(v - b[i]) + } + return d +} + +// manhattanDelta returns the Manhattan norm of delta+translate. If a +// translated by delta+translate is out of the range given by dims, +// zero is returned. +func manhattanDelta(a, delta, dims []int, translate int) int { + if len(a) != len(dims) { + panic("gen: unexpected dimension") + } + if len(delta) != len(dims) { + panic("gen: unexpected dimension") + } + var d int + for i, v := range delta { + v += translate + t := a[i] + v + if t < 0 || t >= dims[i] { + return 0 + } + d += abs(v) + } + return d +} + +// idFrom returns a node id for the slice n over the given dimensions. +func idFrom(n, dims []int) int { + s := 1 + var id int + for d, m := range dims { + p := n[d] + if p < 0 || p >= m { + panic("gen: element out of range") + } + id += p * s + s *= m + } + return id +} + +// idFromDelta returns a node id for the slice base plus the delta over the given +// dimensions and applying the translation. +func idFromDelta(base, delta, dims []int, translate int) int { + s := 1 + var id int + for d, m := range dims { + n := base[d] + delta[d] + translate + if n < 0 || n >= m { + panic("gen: element out of range") + } + id += n * s + s *= m + } + return id +} diff --git a/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world_test.go b/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world_test.go new file mode 100644 index 00000000..ef667146 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/graphs/gen/small_world_test.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum 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 gen + +import ( + "testing" + + "gonum.org/v1/gonum/graph/simple" +) + +var smallWorldDimensionParameters = [][]int{ + {50}, + {10, 10}, + {6, 5, 4}, +} + +func TestNavigableSmallWorldUndirected(t *testing.T) { + for p := 1; p < 5; p++ { + for q := 0; q < 10; q++ { + for r := 0.5; r < 10; r++ { + for _, dims := range smallWorldDimensionParameters { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} + err := NavigableSmallWorld(g, dims, p, q, r, nil) + n := 1 + for _, d := range dims { + n *= d + } + if err != nil { + t.Fatalf("unexpected error: dims=%v n=%d, p=%d, q=%d, r=%v: %v", dims, n, p, q, r, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + } + } + } + } +} + +func TestNavigableSmallWorldDirected(t *testing.T) { + for p := 1; p < 5; p++ { + for q := 0; q < 10; q++ { + for r := 0.5; r < 10; r++ { + for _, dims := range smallWorldDimensionParameters { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} + err := NavigableSmallWorld(g, dims, p, q, r, nil) + n := 1 + for _, d := range dims { + n *= d + } + if err != nil { + t.Fatalf("unexpected error: dims=%v n=%d, p=%d, q=%d, r=%v: %v", dims, n, p, q, r, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go b/vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go new file mode 100644 index 00000000..8828a561 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 linear provides common linear data structures. +package linear // import "gonum.org/v1/gonum/graph/internal/linear" diff --git a/vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go b/vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go new file mode 100644 index 00000000..610b45eb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go @@ -0,0 +1,73 @@ +// Copyright ©2015 The gonum 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 linear + +import ( + "gonum.org/v1/gonum/graph" +) + +// NodeStack implements a LIFO stack of graph.Node. +type NodeStack []graph.Node + +// Len returns the number of graph.Nodes on the stack. +func (s *NodeStack) Len() int { return len(*s) } + +// Pop returns the last graph.Node on the stack and removes it +// from the stack. +func (s *NodeStack) Pop() graph.Node { + v := *s + v, n := v[:len(v)-1], v[len(v)-1] + *s = v + return n +} + +// Push adds the node n to the stack at the last position. +func (s *NodeStack) Push(n graph.Node) { *s = append(*s, n) } + +// NodeQueue implements a FIFO queue. +type NodeQueue struct { + head int + data []graph.Node +} + +// Len returns the number of graph.Nodes in the queue. +func (q *NodeQueue) Len() int { return len(q.data) - q.head } + +// Enqueue adds the node n to the back of the queue. +func (q *NodeQueue) Enqueue(n graph.Node) { + if len(q.data) == cap(q.data) && q.head > 0 { + l := q.Len() + copy(q.data, q.data[q.head:]) + q.head = 0 + q.data = append(q.data[:l], n) + } else { + q.data = append(q.data, n) + } +} + +// Dequeue returns the graph.Node at the front of the queue and +// removes it from the queue. +func (q *NodeQueue) Dequeue() graph.Node { + if q.Len() == 0 { + panic("queue: empty queue") + } + + var n graph.Node + n, q.data[q.head] = q.data[q.head], nil + q.head++ + + if q.Len() == 0 { + q.head = 0 + q.data = q.data[:0] + } + + return n +} + +// Reset clears the queue for reuse. +func (q *NodeQueue) Reset() { + q.head = 0 + q.data = q.data[:0] +} diff --git a/vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go b/vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go new file mode 100644 index 00000000..8220c8fd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 ordered provides common sort ordering types. +package ordered // import "gonum.org/v1/gonum/graph/internal/ordered" diff --git a/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go b/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go new file mode 100644 index 00000000..4342daf1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go @@ -0,0 +1,69 @@ +// Copyright ©2015 The gonum 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 ordered + +import "gonum.org/v1/gonum/graph" + +// ByID implements the sort.Interface sorting a slice of graph.Node +// by ID. +type ByID []graph.Node + +func (n ByID) Len() int { return len(n) } +func (n ByID) Less(i, j int) bool { return n[i].ID() < n[j].ID() } +func (n ByID) Swap(i, j int) { n[i], n[j] = n[j], n[i] } + +// BySliceValues implements the sort.Interface sorting a slice of +// []int64 lexically by the values of the []int64. +type BySliceValues [][]int64 + +func (c BySliceValues) Len() int { return len(c) } +func (c BySliceValues) Less(i, j int) bool { + a, b := c[i], c[j] + l := len(a) + if len(b) < l { + l = len(b) + } + for k, v := range a[:l] { + if v < b[k] { + return true + } + if v > b[k] { + return false + } + } + return len(a) < len(b) +} +func (c BySliceValues) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + +// BySliceIDs implements the sort.Interface sorting a slice of +// []graph.Node lexically by the IDs of the []graph.Node. +type BySliceIDs [][]graph.Node + +func (c BySliceIDs) Len() int { return len(c) } +func (c BySliceIDs) Less(i, j int) bool { + a, b := c[i], c[j] + l := len(a) + if len(b) < l { + l = len(b) + } + for k, v := range a[:l] { + if v.ID() < b[k].ID() { + return true + } + if v.ID() > b[k].ID() { + return false + } + } + return len(a) < len(b) +} +func (c BySliceIDs) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + +// Int64s implements the sort.Interface sorting a slice of +// int64. +type Int64s []int64 + +func (s Int64s) Len() int { return len(s) } +func (s Int64s) Less(i, j int) bool { return s[i] < s[j] } +func (s Int64s) Swap(i, j int) { s[i], s[j] = s[j], s[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/doc.go b/vendor/gonum.org/v1/gonum/graph/internal/set/doc.go new file mode 100644 index 00000000..383615ef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 set provides integer and graph.Node sets. +package set // import "gonum.org/v1/gonum/graph/internal/set" diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/same.go b/vendor/gonum.org/v1/gonum/graph/internal/set/same.go new file mode 100644 index 00000000..c776dc32 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/same.go @@ -0,0 +1,36 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !appengine + +package set + +import "unsafe" + +// same determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use unsafe to get +// the maps' pointer values to compare. +func same(a, b Nodes) bool { + return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b)) +} + +// intsSame determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use unsafe to get +// the maps' pointer values to compare. +func intsSame(a, b Ints) bool { + return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b)) +} + +// int64sSame determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use unsafe to get +// the maps' pointer values to compare. +func int64sSame(a, b Int64s) bool { + return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b)) +} diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go b/vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go new file mode 100644 index 00000000..082ed265 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go @@ -0,0 +1,36 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build appengine + +package set + +import "reflect" + +// same determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use reflect to get +// the maps' pointer values to compare. +func same(a, b Nodes) bool { + return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() +} + +// intsSame determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use reflect to get +// the maps' pointer values to compare. +func intsSame(a, b Ints) bool { + return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() +} + +// int64sSame determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use reflect to get +// the maps' pointer values to compare. +func int64sSame(a, b Int64s) bool { + return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() +} diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/set.go b/vendor/gonum.org/v1/gonum/graph/internal/set/set.go new file mode 100644 index 00000000..339e9f63 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/set.go @@ -0,0 +1,256 @@ +// Copyright ©2014 The gonum 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 set + +import "gonum.org/v1/gonum/graph" + +// Ints is a set of int identifiers. +type Ints map[int]struct{} + +// The simple accessor methods for Ints are provided to allow ease of +// implementation change should the need arise. + +// Add inserts an element into the set. +func (s Ints) Add(e int) { + s[e] = struct{}{} +} + +// Has reports the existence of the element in the set. +func (s Ints) Has(e int) bool { + _, ok := s[e] + return ok +} + +// Remove deletes the specified element from the set. +func (s Ints) Remove(e int) { + delete(s, e) +} + +// Count reports the number of elements stored in the set. +func (s Ints) Count() int { + return len(s) +} + +// IntsEqual reports set equality between the parameters. Sets are equal if +// and only if they have the same elements. +func IntsEqual(a, b Ints) bool { + if intsSame(a, b) { + return true + } + + if len(a) != len(b) { + return false + } + + for e := range a { + if _, ok := b[e]; !ok { + return false + } + } + + return true +} + +// Int64s is a set of int64 identifiers. +type Int64s map[int64]struct{} + +// The simple accessor methods for Ints are provided to allow ease of +// implementation change should the need arise. + +// Add inserts an element into the set. +func (s Int64s) Add(e int64) { + s[e] = struct{}{} +} + +// Has reports the existence of the element in the set. +func (s Int64s) Has(e int64) bool { + _, ok := s[e] + return ok +} + +// Remove deletes the specified element from the set. +func (s Int64s) Remove(e int64) { + delete(s, e) +} + +// Count reports the number of elements stored in the set. +func (s Int64s) Count() int { + return len(s) +} + +// Int64sEqual reports set equality between the parameters. Sets are equal if +// and only if they have the same elements. +func Int64sEqual(a, b Int64s) bool { + if int64sSame(a, b) { + return true + } + + if len(a) != len(b) { + return false + } + + for e := range a { + if _, ok := b[e]; !ok { + return false + } + } + + return true +} + +// Nodes is a set of nodes keyed in their integer identifiers. +type Nodes map[int64]graph.Node + +// The simple accessor methods for Nodes are provided to allow ease of +// implementation change should the need arise. + +// Add inserts an element into the set. +func (s Nodes) Add(n graph.Node) { + s[n.ID()] = n +} + +// Remove deletes the specified element from the set. +func (s Nodes) Remove(e graph.Node) { + delete(s, e.ID()) +} + +// Has reports the existence of the element in the set. +func (s Nodes) Has(n graph.Node) bool { + _, ok := s[n.ID()] + return ok +} + +// clear clears the set, possibly using the same backing store. +func (s *Nodes) clear() { + if len(*s) != 0 { + *s = make(Nodes) + } +} + +// Copy performs a perfect copy from src to dst (meaning the sets will +// be equal). +func (dst Nodes) Copy(src Nodes) Nodes { + if same(src, dst) { + return dst + } + + if len(dst) > 0 { + dst = make(Nodes, len(src)) + } + + for e, n := range src { + dst[e] = n + } + + return dst +} + +// Equal reports set equality between the parameters. Sets are equal if +// and only if they have the same elements. +func Equal(a, b Nodes) bool { + if same(a, b) { + return true + } + + if len(a) != len(b) { + return false + } + + for e := range a { + if _, ok := b[e]; !ok { + return false + } + } + + return true +} + +// Union takes the union of a and b, and stores it in dst. +// +// The union of two sets, a and b, is the set containing all the +// elements of each, for instance: +// +// {a,b,c} UNION {d,e,f} = {a,b,c,d,e,f} +// +// Since sets may not have repetition, unions of two sets that overlap +// do not contain repeat elements, that is: +// +// {a,b,c} UNION {b,c,d} = {a,b,c,d} +// +func (dst Nodes) Union(a, b Nodes) Nodes { + if same(a, b) { + return dst.Copy(a) + } + + if !same(a, dst) && !same(b, dst) { + dst.clear() + } + + if !same(dst, a) { + for e, n := range a { + dst[e] = n + } + } + + if !same(dst, b) { + for e, n := range b { + dst[e] = n + } + } + + return dst +} + +// Intersect takes the intersection of a and b, and stores it in dst. +// +// The intersection of two sets, a and b, is the set containing all +// the elements shared between the two sets, for instance: +// +// {a,b,c} INTERSECT {b,c,d} = {b,c} +// +// The intersection between a set and itself is itself, and thus +// effectively a copy operation: +// +// {a,b,c} INTERSECT {a,b,c} = {a,b,c} +// +// The intersection between two sets that share no elements is the empty +// set: +// +// {a,b,c} INTERSECT {d,e,f} = {} +// +func (dst Nodes) Intersect(a, b Nodes) Nodes { + var swap Nodes + + if same(a, b) { + return dst.Copy(a) + } + if same(a, dst) { + swap = b + } else if same(b, dst) { + swap = a + } else { + dst.clear() + + if len(a) > len(b) { + a, b = b, a + } + + for e, n := range a { + if _, ok := b[e]; ok { + dst[e] = n + } + } + + return dst + } + + for e := range dst { + if _, ok := swap[e]; !ok { + delete(dst, e) + } + } + + return dst +} diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/set_test.go b/vendor/gonum.org/v1/gonum/graph/internal/set/set_test.go new file mode 100644 index 00000000..f665b398 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/set_test.go @@ -0,0 +1,413 @@ +// Copyright ©2014 The gonum 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 set + +import "testing" + +type node int64 + +func (n node) ID() int64 { return int64(n) } + +// count reports the number of elements stored in the node set. +func (s Nodes) count() int { + return len(s) +} + +// TestSame tests the assumption that pointer equality via unsafe conversion +// of a map[int]struct{} to uintptr is a valid test for perfect identity between +// set values. If any of the tests in TestSame fail, the package is broken and same +// must be reimplemented to conform to the runtime map implementation. The relevant +// code to look at (at least for gc) is in runtime/hashmap.{h,goc}. +func TestSame(t *testing.T) { + var ( + a = make(Nodes) + b = make(Nodes) + c = a + ) + + if same(a, b) { + t.Error("Independently created sets test as same") + } + if !same(a, c) { + t.Error("Set copy and original test as not same.") + } + a.Add(node(1)) + if !same(a, c) { + t.Error("Set copy and original test as not same after addition.") + } + if !same(nil, nil) { + t.Error("nil sets test as not same.") + } + if same(b, nil) { + t.Error("nil and empty sets test as same.") + } +} + +func TestAdd(t *testing.T) { + s := make(Nodes) + if s == nil { + t.Fatal("Set cannot be created successfully") + } + + if s.count() != 0 { + t.Error("Set somehow contains new elements upon creation") + } + + s.Add(node(1)) + s.Add(node(3)) + s.Add(node(5)) + + if s.count() != 3 { + t.Error("Incorrect number of set elements after adding") + } + + if !s.Has(node(1)) || !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set doesn't contain element that was added") + } + + s.Add(node(1)) + + if s.count() > 3 { + t.Error("Set double-adds element (element not unique)") + } else if s.count() < 3 { + t.Error("Set double-add lowered len") + } + + if !s.Has(node(1)) { + t.Error("Set doesn't contain double-added element") + } + + if !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set removes element on double-add") + } + + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key: %d != %d", e, n.ID()) + } + } +} + +func TestRemove(t *testing.T) { + s := make(Nodes) + + s.Add(node(1)) + s.Add(node(3)) + s.Add(node(5)) + + s.Remove(node(1)) + + if s.count() != 2 { + t.Error("Incorrect number of set elements after removing an element") + } + + if s.Has(node(1)) { + t.Error("Element present after removal") + } + + if !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set remove removed wrong element") + } + + s.Remove(node(1)) + + if s.count() != 2 || s.Has(node(1)) { + t.Error("Double set remove does something strange") + } + + s.Add(node(1)) + + if s.count() != 3 || !s.Has(node(1)) { + t.Error("Cannot add element after removal") + } +} + +func TestClear(t *testing.T) { + s := make(Nodes) + + s.Add(node(8)) + s.Add(node(9)) + s.Add(node(10)) + + s.clear() + + if s.count() != 0 { + t.Error("clear did not properly reset set to size 0") + } +} + +func TestSelfEqual(t *testing.T) { + s := make(Nodes) + + if !Equal(s, s) { + t.Error("Set is not equal to itself") + } + + s.Add(node(1)) + + if !Equal(s, s) { + t.Error("Set ceases self equality after adding element") + } +} + +func TestEqual(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + + if !Equal(a, b) { + t.Error("Two different empty sets not equal") + } + + a.Add(node(1)) + if Equal(a, b) { + t.Error("Two different sets with different elements not equal") + } + + b.Add(node(1)) + if !Equal(a, b) { + t.Error("Two sets with same element not equal") + } +} + +func TestCopy(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + a.Add(node(3)) + + b.Copy(a) + + if !Equal(a, b) { + t.Fatalf("Two sets not equal after copy") + } + + b.Remove(node(1)) + + if Equal(a, b) { + t.Errorf("Mutating one set mutated another after copy") + } +} + +func TestSelfCopy(t *testing.T) { + a := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + a.Copy(a) + + if a.count() != 2 { + t.Error("Something strange happened when copying into self") + } +} + +func TestUnionSame(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(1)) + b.Add(node(2)) + + c.Union(a, b) + + if c.count() != 2 { + t.Error("Union of same sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) { + t.Error("Union of same sets yields wrong elements") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestUnionDiff(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(3)) + + c.Union(a, b) + + if c.count() != 3 { + t.Error("Union of different sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Union of different sets yields set with wrong elements") + } + + if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 1)") + } + + if !b.Has(node(3)) || b.Has(node(1)) || b.Has(node(2)) || b.count() != 1 { + t.Error("Union of sets mutates non-destination set (argument 2)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestUnionOverlapping(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(2)) + b.Add(node(3)) + + c.Union(a, b) + + if c.count() != 3 { + t.Error("Union of overlapping sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Union of overlapping sets yields set with wrong elements") + } + + if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 1)") + } + + if !b.Has(node(3)) || b.Has(node(1)) || !b.Has(node(2)) || b.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 2)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectSame(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(2)) + b.Add(node(3)) + + c.Intersect(a, b) + + if card := c.count(); card != 2 { + t.Errorf("Intersection of identical sets yields set of wrong len %d", card) + } + + if !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Intersection of identical sets yields set of wrong elements") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectDiff(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(1)) + b.Add(node(4)) + + c.Intersect(a, b) + + if card := c.count(); card != 0 { + t.Errorf("Intersection of different yields non-empty set %d", card) + } + + if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(1)) || a.Has(node(4)) || a.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + if b.Has(node(2)) || b.Has(node(3)) || !b.Has(node(1)) || !b.Has(node(4)) || b.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectOverlapping(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(3)) + b.Add(node(4)) + + c.Intersect(a, b) + + if card := c.count(); card != 1 { + t.Errorf("Intersection of overlapping sets yields set of incorrect len %d", card) + } + + if !c.Has(node(3)) { + t.Errorf("Intersection of overlapping sets yields set with wrong element") + } + + if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(4)) || a.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + if b.Has(node(2)) || !b.Has(node(3)) || !b.Has(node(4)) || b.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/betweenness.go b/vendor/gonum.org/v1/gonum/graph/network/betweenness.go new file mode 100644 index 00000000..547f44f7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/betweenness.go @@ -0,0 +1,250 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/linear" + "gonum.org/v1/gonum/graph/path" +) + +// Betweenness returns the non-zero betweenness centrality for nodes in the unweighted graph g. +// +// C_B(v) = \sum_{s ≠ v ≠ t ∈ V} (\sigma_{st}(v) / \sigma_{st}) +// +// where \sigma_{st} and \sigma_{st}(v) are the number of shortest paths from s to t, +// and the subset of those paths containing v respectively. +func Betweenness(g graph.Graph) map[int64]float64 { + // Brandes' algorithm for finding betweenness centrality for nodes in + // and unweighted graph: + // + // http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf + + // TODO(kortschak): Consider using the parallel algorithm when + // GOMAXPROCS != 1. + // + // http://htor.inf.ethz.ch/publications/img/edmonds-hoefler-lumsdaine-bc.pdf + + // Also note special case for sparse networks: + // http://wwwold.iit.cnr.it/staff/marco.pellegrini/papiri/asonam-final.pdf + + cb := make(map[int64]float64) + brandes(g, func(s graph.Node, stack linear.NodeStack, p map[int64][]graph.Node, delta, sigma map[int64]float64) { + for stack.Len() != 0 { + w := stack.Pop() + for _, v := range p[w.ID()] { + delta[v.ID()] += sigma[v.ID()] / sigma[w.ID()] * (1 + delta[w.ID()]) + } + if w.ID() != s.ID() { + if d := delta[w.ID()]; d != 0 { + cb[w.ID()] += d + } + } + } + }) + return cb +} + +// EdgeBetweenness returns the non-zero betweenness centrality for edges in the +// unweighted graph g. For an edge e the centrality C_B is computed as +// +// C_B(e) = \sum_{s ≠ t ∈ V} (\sigma_{st}(e) / \sigma_{st}), +// +// where \sigma_{st} and \sigma_{st}(e) are the number of shortest paths from s +// to t, and the subset of those paths containing e, respectively. +// +// If g is undirected, edges are retained such that u.ID < v.ID where u and v are +// the nodes of e. +func EdgeBetweenness(g graph.Graph) map[[2]int64]float64 { + // Modified from Brandes' original algorithm as described in Algorithm 7 + // with the exception that node betweenness is not calculated: + // + // http://algo.uni-konstanz.de/publications/b-vspbc-08.pdf + + _, isUndirected := g.(graph.Undirected) + cb := make(map[[2]int64]float64) + brandes(g, func(s graph.Node, stack linear.NodeStack, p map[int64][]graph.Node, delta, sigma map[int64]float64) { + for stack.Len() != 0 { + w := stack.Pop() + for _, v := range p[w.ID()] { + c := sigma[v.ID()] / sigma[w.ID()] * (1 + delta[w.ID()]) + vid := v.ID() + wid := w.ID() + if isUndirected && wid < vid { + vid, wid = wid, vid + } + cb[[2]int64{vid, wid}] += c + delta[v.ID()] += c + } + } + }) + return cb +} + +// brandes is the common code for Betweenness and EdgeBetweenness. It corresponds +// to algorithm 1 in http://algo.uni-konstanz.de/publications/b-vspbc-08.pdf with +// the accumulation loop provided by the accumulate closure. +func brandes(g graph.Graph, accumulate func(s graph.Node, stack linear.NodeStack, p map[int64][]graph.Node, delta, sigma map[int64]float64)) { + var ( + nodes = g.Nodes() + stack linear.NodeStack + p = make(map[int64][]graph.Node, len(nodes)) + sigma = make(map[int64]float64, len(nodes)) + d = make(map[int64]int, len(nodes)) + delta = make(map[int64]float64, len(nodes)) + queue linear.NodeQueue + ) + for _, s := range nodes { + stack = stack[:0] + + for _, w := range nodes { + p[w.ID()] = p[w.ID()][:0] + } + + for _, t := range nodes { + sigma[t.ID()] = 0 + d[t.ID()] = -1 + } + sigma[s.ID()] = 1 + d[s.ID()] = 0 + + queue.Enqueue(s) + for queue.Len() != 0 { + v := queue.Dequeue() + stack.Push(v) + for _, w := range g.From(v) { + // w found for the first time? + if d[w.ID()] < 0 { + queue.Enqueue(w) + d[w.ID()] = d[v.ID()] + 1 + } + // shortest path to w via v? + if d[w.ID()] == d[v.ID()]+1 { + sigma[w.ID()] += sigma[v.ID()] + p[w.ID()] = append(p[w.ID()], v) + } + } + } + + for _, v := range nodes { + delta[v.ID()] = 0 + } + + // S returns vertices in order of non-increasing distance from s + accumulate(s, stack, p, delta, sigma) + } +} + +// BetweennessWeighted returns the non-zero betweenness centrality for nodes in the weighted +// graph g used to construct the given shortest paths. +// +// C_B(v) = \sum_{s ≠ v ≠ t ∈ V} (\sigma_{st}(v) / \sigma_{st}) +// +// where \sigma_{st} and \sigma_{st}(v) are the number of shortest paths from s to t, +// and the subset of those paths containing v respectively. +func BetweennessWeighted(g graph.Weighted, p path.AllShortest) map[int64]float64 { + cb := make(map[int64]float64) + + nodes := g.Nodes() + for i, s := range nodes { + for j, t := range nodes { + if i == j { + continue + } + d := p.Weight(s, t) + if math.IsInf(d, 0) { + continue + } + + // If we have a unique path, don't do the + // extra work needed to get all paths. + path, _, unique := p.Between(s, t) + if unique { + for _, v := range path[1 : len(path)-1] { + // For undirected graphs we double count + // passage though nodes. This is consistent + // with Brandes' algorithm's behaviour. + cb[v.ID()]++ + } + continue + } + + // Otherwise iterate over all paths. + paths, _ := p.AllBetween(s, t) + stFrac := 1 / float64(len(paths)) + for _, path := range paths { + for _, v := range path[1 : len(path)-1] { + cb[v.ID()] += stFrac + } + } + } + } + + return cb +} + +// EdgeBetweennessWeighted returns the non-zero betweenness centrality for edges in +// the weighted graph g. For an edge e the centrality C_B is computed as +// +// C_B(e) = \sum_{s ≠ t ∈ V} (\sigma_{st}(e) / \sigma_{st}), +// +// where \sigma_{st} and \sigma_{st}(e) are the number of shortest paths from s +// to t, and the subset of those paths containing e, respectively. +// +// If g is undirected, edges are retained such that u.ID < v.ID where u and v are +// the nodes of e. +func EdgeBetweennessWeighted(g graph.Weighted, p path.AllShortest) map[[2]int64]float64 { + cb := make(map[[2]int64]float64) + + _, isUndirected := g.(graph.Undirected) + nodes := g.Nodes() + for i, s := range nodes { + for j, t := range nodes { + if i == j { + continue + } + d := p.Weight(s, t) + if math.IsInf(d, 0) { + continue + } + + // If we have a unique path, don't do the + // extra work needed to get all paths. + path, _, unique := p.Between(s, t) + if unique { + for k, v := range path[1:] { + // For undirected graphs we double count + // passage though edges. This is consistent + // with Brandes' algorithm's behaviour. + uid := path[k].ID() + vid := v.ID() + if isUndirected && vid < uid { + uid, vid = vid, uid + } + cb[[2]int64{uid, vid}]++ + } + continue + } + + // Otherwise iterate over all paths. + paths, _ := p.AllBetween(s, t) + stFrac := 1 / float64(len(paths)) + for _, path := range paths { + for k, v := range path[1:] { + uid := path[k].ID() + vid := v.ID() + if isUndirected && vid < uid { + uid, vid = vid, uid + } + cb[[2]int64{uid, vid}] += stFrac + } + } + } + } + + return cb +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/betweenness_test.go b/vendor/gonum.org/v1/gonum/graph/network/betweenness_test.go new file mode 100644 index 00000000..04fcd056 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/betweenness_test.go @@ -0,0 +1,338 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +var betweennessTests = []struct { + g []set + + wantTol float64 + want map[int64]float64 + wantEdges map[[2]int64]float64 +}{ + { + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + g: []set{ + A: nil, + B: linksTo(C), + C: linksTo(B), + D: linksTo(A, B), + E: linksTo(D, B, F), + F: linksTo(B, E), + G: linksTo(B, E), + H: linksTo(B, E), + I: linksTo(B, E), + J: linksTo(E), + K: linksTo(E), + }, + + wantTol: 1e-1, + want: map[int64]float64{ + B: 32, + D: 18, + E: 48, + }, + wantEdges: map[[2]int64]float64{ + {A, D}: 20, + {B, C}: 20, + {B, D}: 16, + {B, E}: 12, + {B, F}: 9, + {B, G}: 9, + {B, H}: 9, + {B, I}: 9, + {D, E}: 20, + {E, F}: 11, + {E, G}: 11, + {E, H}: 11, + {E, I}: 11, + {E, J}: 20, + {E, K}: 20, + }, + }, + { + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + g: []set{ + A: linksTo(B, C), + B: linksTo(D), + C: linksTo(D, E), + D: linksTo(E), + E: linksTo(A), + }, + + wantTol: 1e-3, + want: map[int64]float64{ + A: 2, + B: 0.6667, + C: 0.6667, + D: 2, + E: 0.6667, + }, + wantEdges: map[[2]int64]float64{ + {A, B}: 2 + 2/3. + 4/2., + {A, C}: 2 + 2/3. + 2/2., + {A, E}: 2 + 2/3. + 2/2., + {B, D}: 2 + 2/3. + 4/2., + {C, D}: 2 + 2/3. + 2/2., + {C, E}: 2, + {D, E}: 2 + 2/3. + 2/2., + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + wantTol: 1e-3, + want: map[int64]float64{ + B: 2, + }, + wantEdges: map[[2]int64]float64{ + {A, B}: 4, + {B, C}: 4, + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + wantTol: 1e-3, + want: map[int64]float64{ + B: 6, + C: 8, + D: 6, + }, + wantEdges: map[[2]int64]float64{ + {A, B}: 8, + {B, C}: 12, + {C, D}: 12, + {D, E}: 8, + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + wantTol: 1e-3, + want: map[int64]float64{ + C: 12, + }, + wantEdges: map[[2]int64]float64{ + {A, C}: 8, + {B, C}: 8, + {C, D}: 8, + {C, E}: 8, + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + wantTol: 1e-3, + want: map[int64]float64{}, + wantEdges: map[[2]int64]float64{ + {A, B}: 2, + {A, C}: 2, + {A, D}: 2, + {A, E}: 2, + {B, C}: 2, + {B, D}: 2, + {B, E}: 2, + {C, D}: 2, + {C, E}: 2, + {D, E}: 2, + }, + }, +} + +func TestBetweenness(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := Betweenness(g) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + wantN, gotOK := got[int64(n)] + gotN, wantOK := test.want[int64(n)] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, node %c", i, n+'A') + } + if !floats.EqualWithinAbsOrRel(gotN, wantN, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestEdgeBetweenness(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := EdgeBetweenness(g) + prec := 1 - int(math.Log10(test.wantTol)) + outer: + for u := range test.g { + for v := range test.g { + wantQ, gotOK := got[[2]int64{int64(u), int64(v)}] + gotQ, wantOK := test.wantEdges[[2]int64{int64(u), int64(v)}] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, edge (%c,%c)", i, u+'A', v+'A') + } + if !floats.EqualWithinAbsOrRel(gotQ, wantQ, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedPairFloats(got, prec), orderedPairFloats(test.wantEdges, prec)) + break outer + } + } + } + } +} + +func TestBetweennessWeighted(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + got := BetweennessWeighted(g, p) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + gotN, gotOK := got[int64(n)] + wantN, wantOK := test.want[int64(n)] + if gotOK != wantOK { + t.Errorf("unexpected betweenness existence for test %d, node %c", i, n+'A') + } + if !floats.EqualWithinAbsOrRel(gotN, wantN, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestEdgeBetweennessWeighted(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + got := EdgeBetweennessWeighted(g, p) + prec := 1 - int(math.Log10(test.wantTol)) + outer: + for u := range test.g { + for v := range test.g { + wantQ, gotOK := got[[2]int64{int64(u), int64(v)}] + gotQ, wantOK := test.wantEdges[[2]int64{int64(u), int64(v)}] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, edge (%c,%c)", i, u+'A', v+'A') + } + if !floats.EqualWithinAbsOrRel(gotQ, wantQ, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedPairFloats(got, prec), orderedPairFloats(test.wantEdges, prec)) + break outer + } + } + } + } +} + +func orderedPairFloats(w map[[2]int64]float64, prec int) []pairKeyFloatVal { + o := make(orderedPairFloatsMap, 0, len(w)) + for k, v := range w { + o = append(o, pairKeyFloatVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type pairKeyFloatVal struct { + prec int + key [2]int64 + val float64 +} + +func (kv pairKeyFloatVal) String() string { + return fmt.Sprintf("(%c,%c):%.*f", kv.key[0]+'A', kv.key[1]+'A', kv.prec, kv.val) +} + +type orderedPairFloatsMap []pairKeyFloatVal + +func (o orderedPairFloatsMap) Len() int { return len(o) } +func (o orderedPairFloatsMap) Less(i, j int) bool { + return o[i].key[0] < o[j].key[0] || (o[i].key[0] == o[j].key[0] && o[i].key[1] < o[j].key[1]) +} +func (o orderedPairFloatsMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/network/distance.go b/vendor/gonum.org/v1/gonum/graph/network/distance.go new file mode 100644 index 00000000..7e5ef6a3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/distance.go @@ -0,0 +1,124 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" +) + +// Closeness returns the closeness centrality for nodes in the graph g used to +// construct the given shortest paths. +// +// C(v) = 1 / \sum_u d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Closeness(g graph.Graph, p path.AllShortest) map[int64]float64 { + nodes := g.Nodes() + c := make(map[int64]float64, len(nodes)) + for _, u := range nodes { + var sum float64 + for _, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + sum += d + } + c[u.ID()] = 1 / sum + } + return c +} + +// Farness returns the farness for nodes in the graph g used to construct +// the given shortest paths. +// +// F(v) = \sum_u d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Farness(g graph.Graph, p path.AllShortest) map[int64]float64 { + nodes := g.Nodes() + f := make(map[int64]float64, len(nodes)) + for _, u := range nodes { + var sum float64 + for _, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + sum += d + } + f[u.ID()] = sum + } + return f +} + +// Harmonic returns the harmonic centrality for nodes in the graph g used to +// construct the given shortest paths. +// +// H(v)= \sum_{u ≠ v} 1 / d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Harmonic(g graph.Graph, p path.AllShortest) map[int64]float64 { + nodes := g.Nodes() + h := make(map[int64]float64, len(nodes)) + for i, u := range nodes { + var sum float64 + for j, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + if i != j { + sum += 1 / d + } + } + h[u.ID()] = sum + } + return h +} + +// Residual returns the Dangalchev's residual closeness for nodes in the graph +// g used to construct the given shortest paths. +// +// C(v)= \sum_{u ≠ v} 1 / 2^d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Residual(g graph.Graph, p path.AllShortest) map[int64]float64 { + nodes := g.Nodes() + r := make(map[int64]float64, len(nodes)) + for i, u := range nodes { + var sum float64 + for j, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + if i != j { + sum += math.Exp2(-d) + } + } + r[u.ID()] = sum + } + return r +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/distance_test.go b/vendor/gonum.org/v1/gonum/graph/network/distance_test.go new file mode 100644 index 00000000..4015883b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/distance_test.go @@ -0,0 +1,394 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +var undirectedCentralityTests = []struct { + g []set + + farness map[int64]float64 + harmonic map[int64]float64 + residual map[int64]float64 +}{ + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + farness: map[int64]float64{ + A: 1 + 2, + B: 1 + 1, + C: 2 + 1, + }, + harmonic: map[int64]float64{ + A: 1 + 1.0/2.0, + B: 1 + 1, + C: 1.0/2.0 + 1, + }, + residual: map[int64]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(2), + B: 1/math.Exp2(1) + 1/math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + farness: map[int64]float64{ + A: 1 + 2 + 3 + 4, + B: 1 + 1 + 2 + 3, + C: 2 + 1 + 1 + 2, + D: 3 + 2 + 1 + 1, + E: 4 + 3 + 2 + 1, + }, + harmonic: map[int64]float64{ + A: 1 + 1.0/2.0 + 1.0/3.0 + 1.0/4.0, + B: 1 + 1 + 1.0/2.0 + 1.0/3.0, + C: 1.0/2.0 + 1 + 1 + 1.0/2.0, + D: 1.0/3.0 + 1.0/2.0 + 1 + 1, + E: 1.0/4.0 + 1.0/3.0 + 1.0/2.0 + 1, + }, + residual: map[int64]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(3) + 1/math.Exp2(4), + B: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(3), + C: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(2), + D: 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(4) + 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + farness: map[int64]float64{ + A: 2 + 2 + 1 + 2, + B: 2 + 1 + 2 + 2, + C: 1 + 1 + 1 + 1, + D: 2 + 1 + 2 + 2, + E: 2 + 2 + 1 + 2, + }, + harmonic: map[int64]float64{ + A: 1.0/2.0 + 1.0/2.0 + 1 + 1.0/2.0, + B: 1.0/2.0 + 1 + 1.0/2.0 + 1.0/2.0, + C: 1 + 1 + 1 + 1, + D: 1.0/2.0 + 1 + 1.0/2.0 + 1.0/2.0, + E: 1.0/2.0 + 1.0/2.0 + 1 + 1.0/2.0, + }, + residual: map[int64]float64{ + A: 1/math.Exp2(2) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2), + B: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(2), + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(2), + E: 1/math.Exp2(2) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2), + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + farness: map[int64]float64{ + A: 1 + 1 + 1 + 1, + B: 1 + 1 + 1 + 1, + C: 1 + 1 + 1 + 1, + D: 1 + 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + harmonic: map[int64]float64{ + A: 1 + 1 + 1 + 1, + B: 1 + 1 + 1 + 1, + C: 1 + 1 + 1 + 1, + D: 1 + 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + residual: map[int64]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + B: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + }, + }, +} + +func TestDistanceCentralityUndirected(t *testing.T) { + const tol = 1e-12 + prec := 1 - int(math.Log10(tol)) + + for i, test := range undirectedCentralityTests { + g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + var got map[int64]float64 + + got = Closeness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], 1/test.farness[int64(n)], tol, tol) { + want := make(map[int64]float64) + for n, v := range test.farness { + want[n] = 1 / v + } + t.Errorf("unexpected closeness centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(want, prec)) + break + } + } + + got = Farness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.farness[int64(n)], tol, tol) { + t.Errorf("unexpected farness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.farness, prec)) + break + } + } + + got = Harmonic(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.harmonic[int64(n)], tol, tol) { + t.Errorf("unexpected harmonic centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.harmonic, prec)) + break + } + } + + got = Residual(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.residual[int64(n)], tol, tol) { + t.Errorf("unexpected residual closeness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.residual, prec)) + break + } + } + } +} + +var directedCentralityTests = []struct { + g []set + + farness map[int64]float64 + harmonic map[int64]float64 + residual map[int64]float64 +}{ + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + farness: map[int64]float64{ + A: 0, + B: 1, + C: 2 + 1, + }, + harmonic: map[int64]float64{ + A: 0, + B: 1, + C: 1.0/2.0 + 1, + }, + residual: map[int64]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + farness: map[int64]float64{ + A: 0, + B: 1, + C: 2 + 1, + D: 3 + 2 + 1, + E: 4 + 3 + 2 + 1, + }, + harmonic: map[int64]float64{ + A: 0, + B: 1, + C: 1.0/2.0 + 1, + D: 1.0/3.0 + 1.0/2.0 + 1, + E: 1.0/4.0 + 1.0/3.0 + 1.0/2.0 + 1, + }, + residual: map[int64]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + D: 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + E: 1/math.Exp2(4) + 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + farness: map[int64]float64{ + A: 0, + B: 0, + C: 1 + 1 + 1 + 1, + D: 0, + E: 0, + }, + harmonic: map[int64]float64{ + A: 0, + B: 0, + C: 1 + 1 + 1 + 1, + D: 0, + E: 0, + }, + residual: map[int64]float64{ + A: 0, + B: 0, + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 0, + E: 0, + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + farness: map[int64]float64{ + A: 0, + B: 1, + C: 1 + 1, + D: 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + harmonic: map[int64]float64{ + A: 0, + B: 1, + C: 1 + 1, + D: 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + residual: map[int64]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + }, + }, +} + +func TestDistanceCentralityDirected(t *testing.T) { + const tol = 1e-12 + prec := 1 - int(math.Log10(tol)) + + for i, test := range directedCentralityTests { + g := simple.NewWeightedDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + var got map[int64]float64 + + got = Closeness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], 1/test.farness[int64(n)], tol, tol) { + want := make(map[int64]float64) + for n, v := range test.farness { + want[int64(n)] = 1 / v + } + t.Errorf("unexpected closeness centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(want, prec)) + break + } + } + + got = Farness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.farness[int64(n)], tol, tol) { + t.Errorf("unexpected farness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.farness, prec)) + break + } + } + + got = Harmonic(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.harmonic[int64(n)], tol, tol) { + t.Errorf("unexpected harmonic centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.harmonic, prec)) + break + } + } + + got = Residual(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.residual[int64(n)], tol, tol) { + t.Errorf("unexpected residual closeness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.residual, prec)) + break + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/doc.go b/vendor/gonum.org/v1/gonum/graph/network/doc.go new file mode 100644 index 00000000..c456f2da --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 network provides network analysis functions. +package network // import "gonum.org/v1/gonum/graph/network" diff --git a/vendor/gonum.org/v1/gonum/graph/network/hits.go b/vendor/gonum.org/v1/gonum/graph/network/hits.go new file mode 100644 index 00000000..53ef944c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/hits.go @@ -0,0 +1,101 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" +) + +// HubAuthority is a Hyperlink-Induced Topic Search hub-authority score pair. +type HubAuthority struct { + Hub float64 + Authority float64 +} + +// HITS returns the Hyperlink-Induced Topic Search hub-authority scores for +// nodes of the directed graph g. HITS terminates when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func HITS(g graph.Directed, tol float64) map[int64]HubAuthority { + nodes := g.Nodes() + + // Make a topological copy of g with dense node IDs. + indexOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + nodesLinkingTo := make([][]int, len(nodes)) + nodesLinkedFrom := make([][]int, len(nodes)) + for i, n := range nodes { + for _, u := range g.To(n) { + nodesLinkingTo[i] = append(nodesLinkingTo[i], indexOf[u.ID()]) + } + for _, v := range g.From(n) { + nodesLinkedFrom[i] = append(nodesLinkedFrom[i], indexOf[v.ID()]) + } + } + indexOf = nil + + w := make([]float64, 4*len(nodes)) + auth := w[:len(nodes)] + hub := w[len(nodes) : 2*len(nodes)] + for i := range nodes { + auth[i] = 1 + hub[i] = 1 + } + deltaAuth := w[2*len(nodes) : 3*len(nodes)] + deltaHub := w[3*len(nodes):] + + var norm float64 + for { + norm = 0 + for v := range nodes { + var a float64 + for _, u := range nodesLinkingTo[v] { + a += hub[u] + } + deltaAuth[v] = auth[v] + auth[v] = a + norm += a * a + } + norm = math.Sqrt(norm) + + for i := range auth { + auth[i] /= norm + deltaAuth[i] -= auth[i] + } + + norm = 0 + for u := range nodes { + var h float64 + for _, v := range nodesLinkedFrom[u] { + h += auth[v] + } + deltaHub[u] = hub[u] + hub[u] = h + norm += h * h + } + norm = math.Sqrt(norm) + + for i := range hub { + hub[i] /= norm + deltaHub[i] -= hub[i] + } + + if floats.Norm(deltaAuth, 2) < tol && floats.Norm(deltaHub, 2) < tol { + break + } + } + + hubAuth := make(map[int64]HubAuthority, len(nodes)) + for i, n := range nodes { + hubAuth[n.ID()] = HubAuthority{Hub: hub[i], Authority: auth[i]} + } + + return hubAuth +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/hits_test.go b/vendor/gonum.org/v1/gonum/graph/network/hits_test.go new file mode 100644 index 00000000..b711f36e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/hits_test.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/simple" +) + +var hitsTests = []struct { + g []set + tol float64 + + wantTol float64 + want map[int64]HubAuthority +}{ + { + // Example graph from http://www.cis.hut.fi/Opinnot/T-61.6020/2008/pagerank_hits.pdf page 8. + g: []set{ + A: linksTo(B, C, D), + B: linksTo(C, D), + C: linksTo(B), + D: nil, + }, + tol: 1e-4, + + wantTol: 1e-4, + want: map[int64]HubAuthority{ + A: {Hub: 0.7887, Authority: 0}, + B: {Hub: 0.5774, Authority: 0.4597}, + C: {Hub: 0.2113, Authority: 0.6280}, + D: {Hub: 0, Authority: 0.6280}, + }, + }, +} + +func TestHITS(t *testing.T) { + for i, test := range hitsTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := HITS(g, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)].Hub, test.want[int64(n)].Hub, test.wantTol, test.wantTol) { + t.Errorf("unexpected HITS result for test %d:\ngot: %v\nwant:%v", + i, orderedHubAuth(got, prec), orderedHubAuth(test.want, prec)) + break + } + if !floats.EqualWithinAbsOrRel(got[int64(n)].Authority, test.want[int64(n)].Authority, test.wantTol, test.wantTol) { + t.Errorf("unexpected HITS result for test %d:\ngot: %v\nwant:%v", + i, orderedHubAuth(got, prec), orderedHubAuth(test.want, prec)) + break + } + } + } +} + +func orderedHubAuth(w map[int64]HubAuthority, prec int) []keyHubAuthVal { + o := make(orderedHubAuthMap, 0, len(w)) + for k, v := range w { + o = append(o, keyHubAuthVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type keyHubAuthVal struct { + prec int + key int64 + val HubAuthority +} + +func (kv keyHubAuthVal) String() string { + return fmt.Sprintf("%d:{H:%.*f, A:%.*f}", + kv.key, kv.prec, kv.val.Hub, kv.prec, kv.val.Authority, + ) +} + +type orderedHubAuthMap []keyHubAuthVal + +func (o orderedHubAuthMap) Len() int { return len(o) } +func (o orderedHubAuthMap) Less(i, j int) bool { return o[i].key < o[j].key } +func (o orderedHubAuthMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/network/network.go b/vendor/gonum.org/v1/gonum/graph/network/network.go new file mode 100644 index 00000000..2faabdea --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/network.go @@ -0,0 +1,13 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(kortschak): Implement: +// * edge-weighted PageRank and HITS +// * PersonalizedPageRank: +// http://infolab.stanford.edu/~backrub/google.html 2.1.2 Intuitive Justification +// http://ilpubs.stanford.edu:8090/596/1/2003-35.pdf +// http://www.vldb.org/pvldb/vol7/p1023-maehara.pdf +// * other centrality measures + +package network diff --git a/vendor/gonum.org/v1/gonum/graph/network/network_test.go b/vendor/gonum.org/v1/gonum/graph/network/network_test.go new file mode 100644 index 00000000..b999c218 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/network_test.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 network + +const ( + A = iota + B + C + D + E + F + G + H + I + J + K +) + +// set is an integer set. +type set map[int64]struct{} + +func linksTo(i ...int64) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/page.go b/vendor/gonum.org/v1/gonum/graph/network/page.go new file mode 100644 index 00000000..fb2c58e3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/page.go @@ -0,0 +1,228 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/mat" +) + +// PageRank returns the PageRank weights for nodes of the directed graph g +// using the given damping factor and terminating when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func PageRank(g graph.Directed, damp, tol float64) map[int64]float64 { + // PageRank is implemented according to "How Google Finds Your Needle + // in the Web's Haystack". + // + // G.I^k = alpha.S.I^k + (1-alpha).1/n.1.I^k + // + // http://www.ams.org/samplings/feature-column/fcarc-pagerank + + nodes := g.Nodes() + indexOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + + m := mat.NewDense(len(nodes), len(nodes), nil) + dangling := damp / float64(len(nodes)) + for j, u := range nodes { + to := g.From(u) + f := damp / float64(len(to)) + for _, v := range to { + m.Set(indexOf[v.ID()], j, f) + } + if len(to) == 0 { + for i := range nodes { + m.Set(i, j, dangling) + } + } + } + matrix := m.RawMatrix().Data + dt := (1 - damp) / float64(len(nodes)) + for i := range matrix { + matrix[i] += dt + } + + last := make([]float64, len(nodes)) + for i := range last { + last[i] = 1 + } + lastV := mat.NewVecDense(len(nodes), last) + + vec := make([]float64, len(nodes)) + var sum float64 + for i := range vec { + r := rand.NormFloat64() + sum += r + vec[i] = r + } + f := 1 / sum + for i := range vec { + vec[i] *= f + } + v := mat.NewVecDense(len(nodes), vec) + + for { + lastV, v = v, lastV + v.MulVec(m, lastV) + if normDiff(vec, last) < tol { + break + } + } + + ranks := make(map[int64]float64, len(nodes)) + for i, r := range v.RawVector().Data { + ranks[nodes[i].ID()] = r + } + + return ranks +} + +// PageRankSparse returns the PageRank weights for nodes of the sparse directed +// graph g using the given damping factor and terminating when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func PageRankSparse(g graph.Directed, damp, tol float64) map[int64]float64 { + // PageRankSparse is implemented according to "How Google Finds Your Needle + // in the Web's Haystack". + // + // G.I^k = alpha.H.I^k + alpha.A.I^k + (1-alpha).1/n.1.I^k + // + // http://www.ams.org/samplings/feature-column/fcarc-pagerank + + nodes := g.Nodes() + indexOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + + m := make(rowCompressedMatrix, len(nodes)) + var dangling compressedRow + df := damp / float64(len(nodes)) + for j, u := range nodes { + to := g.From(u) + f := damp / float64(len(to)) + for _, v := range to { + m.addTo(indexOf[v.ID()], j, f) + } + if len(to) == 0 { + dangling.addTo(j, df) + } + } + + last := make([]float64, len(nodes)) + for i := range last { + last[i] = 1 + } + lastV := mat.NewVecDense(len(nodes), last) + + vec := make([]float64, len(nodes)) + var sum float64 + for i := range vec { + r := rand.NormFloat64() + sum += r + vec[i] = r + } + f := 1 / sum + for i := range vec { + vec[i] *= f + } + v := mat.NewVecDense(len(nodes), vec) + + dt := (1 - damp) / float64(len(nodes)) + for { + lastV, v = v, lastV + + m.mulVecUnitary(v, lastV) // First term of the G matrix equation; + with := dangling.dotUnitary(lastV) // Second term; + away := onesDotUnitary(dt, lastV) // Last term. + + floats.AddConst(with+away, v.RawVector().Data) + if normDiff(vec, last) < tol { + break + } + } + + ranks := make(map[int64]float64, len(nodes)) + for i, r := range v.RawVector().Data { + ranks[nodes[i].ID()] = r + } + + return ranks +} + +// rowCompressedMatrix implements row-compressed +// matrix/vector multiplication. +type rowCompressedMatrix []compressedRow + +// addTo adds the value v to the matrix element at (i,j). Repeated +// calls to addTo with the same column index will result in +// non-unique element representation. +func (m rowCompressedMatrix) addTo(i, j int, v float64) { m[i].addTo(j, v) } + +// mulVecUnitary multiplies the receiver by the src vector, storing +// the result in dst. It assumes src and dst are the same length as m +// and that both have unitary vector increments. +func (m rowCompressedMatrix) mulVecUnitary(dst, src *mat.VecDense) { + dMat := dst.RawVector().Data + for i, r := range m { + dMat[i] = r.dotUnitary(src) + } +} + +// compressedRow implements a simplified scatter-based Ddot. +type compressedRow []sparseElement + +// addTo adds the value v to the vector element at j. Repeated +// calls to addTo with the same vector index will result in +// non-unique element representation. +func (r *compressedRow) addTo(j int, v float64) { + *r = append(*r, sparseElement{index: j, value: v}) +} + +// dotUnitary performs a simplified scatter-based Ddot operations on +// v and the receiver. v must have have a unitary vector increment. +func (r compressedRow) dotUnitary(v *mat.VecDense) float64 { + var sum float64 + vec := v.RawVector().Data + for _, e := range r { + sum += vec[e.index] * e.value + } + return sum +} + +// sparseElement is a sparse vector or matrix element. +type sparseElement struct { + index int + value float64 +} + +// onesDotUnitary performs the equivalent of a Ddot of v with +// a ones vector of equal length. v must have have a unitary +// vector increment. +func onesDotUnitary(alpha float64, v *mat.VecDense) float64 { + var sum float64 + for _, f := range v.RawVector().Data { + sum += alpha * f + } + return sum +} + +// normDiff returns the 2-norm of the difference between x and y. +// This is a cut down version of gonum/floats.Distance. +func normDiff(x, y []float64) float64 { + var sum float64 + for i, v := range x { + d := v - y[i] + sum += d * d + } + return math.Sqrt(sum) +} diff --git a/vendor/gonum.org/v1/gonum/graph/network/page_test.go b/vendor/gonum.org/v1/gonum/graph/network/page_test.go new file mode 100644 index 00000000..0a85dcf2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/network/page_test.go @@ -0,0 +1,151 @@ +// Copyright ©2015 The gonum 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 network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/simple" +) + +var pageRankTests = []struct { + g []set + damp float64 + tol float64 + + wantTol float64 + want map[int64]float64 +}{ + { + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + g: []set{ + A: nil, + B: linksTo(C), + C: linksTo(B), + D: linksTo(A, B), + E: linksTo(D, B, F), + F: linksTo(B, E), + G: linksTo(B, E), + H: linksTo(B, E), + I: linksTo(B, E), + J: linksTo(E), + K: linksTo(E), + }, + damp: 0.85, + tol: 1e-8, + + wantTol: 1e-8, + want: map[int64]float64{ + A: 0.03278149, + B: 0.38440095, + C: 0.34291029, + D: 0.03908709, + E: 0.08088569, + F: 0.03908709, + G: 0.01616948, + H: 0.01616948, + I: 0.01616948, + J: 0.01616948, + K: 0.01616948, + }, + }, + { + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + // Expected result calculated with the given MATLAB code. + g: []set{ + A: linksTo(B, C), + B: linksTo(D), + C: linksTo(D, E), + D: linksTo(E), + E: linksTo(A), + }, + damp: 0.80, + tol: 1e-3, + + wantTol: 1e-3, + want: map[int64]float64{ + A: 0.250, + B: 0.140, + C: 0.140, + D: 0.208, + E: 0.262, + }, + }, +} + +func TestPageRank(t *testing.T) { + for i, test := range pageRankTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := PageRank(g, test.damp, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.want[int64(n)], test.wantTol, test.wantTol) { + t.Errorf("unexpected PageRank result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestPageRankSparse(t *testing.T) { + for i, test := range pageRankTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := PageRankSparse(g, test.damp, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[int64(n)], test.want[int64(n)], test.wantTol, test.wantTol) { + t.Errorf("unexpected PageRank result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func orderedFloats(w map[int64]float64, prec int) []keyFloatVal { + o := make(orderedFloatsMap, 0, len(w)) + for k, v := range w { + o = append(o, keyFloatVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type keyFloatVal struct { + prec int + key int64 + val float64 +} + +func (kv keyFloatVal) String() string { return fmt.Sprintf("%c:%.*f", kv.key+'A', kv.prec, kv.val) } + +type orderedFloatsMap []keyFloatVal + +func (o orderedFloatsMap) Len() int { return len(o) } +func (o orderedFloatsMap) Less(i, j int) bool { return o[i].key < o[j].key } +func (o orderedFloatsMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/path/a_star.go b/vendor/gonum.org/v1/gonum/graph/path/a_star.go new file mode 100644 index 00000000..0d24c084 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/a_star.go @@ -0,0 +1,151 @@ +// Copyright ©2014 The gonum 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 path + +import ( + "container/heap" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// AStar finds the A*-shortest path from s to t in g using the heuristic h. The path and +// its cost are returned in a Shortest along with paths and costs to all nodes explored +// during the search. The number of expanded nodes is also returned. This value may help +// with heuristic tuning. +// +// The path will be the shortest path if the heuristic is admissible. A heuristic is +// admissible if for any node, n, in the graph, the heuristic estimate of the cost of +// the path from n to t is less than or equal to the true cost of that path. +// +// If h is nil, AStar will use the g.HeuristicCost method if g implements HeuristicCoster, +// falling back to NullHeuristic otherwise. If the graph does not implement graph.Weighter, +// UniformCost is used. AStar will panic if g has an A*-reachable negative edge weight. +func AStar(s, t graph.Node, g graph.Graph, h Heuristic) (path Shortest, expanded int) { + if !g.Has(s) || !g.Has(t) { + return Shortest{from: s}, 0 + } + var weight Weighting + if wg, ok := g.(graph.Weighted); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + if h == nil { + if g, ok := g.(HeuristicCoster); ok { + h = g.HeuristicCost + } else { + h = NullHeuristic + } + } + + path = newShortestFrom(s, g.Nodes()) + tid := t.ID() + + visited := make(set.Int64s) + open := &aStarQueue{indexOf: make(map[int64]int)} + heap.Push(open, aStarNode{node: s, gscore: 0, fscore: h(s, t)}) + + for open.Len() != 0 { + u := heap.Pop(open).(aStarNode) + uid := u.node.ID() + i := path.indexOf[uid] + expanded++ + + if uid == tid { + break + } + + visited.Add(uid) + for _, v := range g.From(u.node) { + vid := v.ID() + if visited.Has(vid) { + continue + } + j := path.indexOf[vid] + + w, ok := weight(u.node, v) + if !ok { + panic("A*: unexpected invalid weight") + } + if w < 0 { + panic("A*: negative edge weight") + } + g := u.gscore + w + if n, ok := open.node(vid); !ok { + path.set(j, g, i) + heap.Push(open, aStarNode{node: v, gscore: g, fscore: g + h(v, t)}) + } else if g < n.gscore { + path.set(j, g, i) + open.update(vid, g, g+h(v, t)) + } + } + } + + return path, expanded +} + +// NullHeuristic is an admissible, consistent heuristic that will not speed up computation. +func NullHeuristic(_, _ graph.Node) float64 { + return 0 +} + +// aStarNode adds A* accounting to a graph.Node. +type aStarNode struct { + node graph.Node + gscore float64 + fscore float64 +} + +// aStarQueue is an A* priority queue. +type aStarQueue struct { + indexOf map[int64]int + nodes []aStarNode +} + +func (q *aStarQueue) Less(i, j int) bool { + return q.nodes[i].fscore < q.nodes[j].fscore +} + +func (q *aStarQueue) Swap(i, j int) { + q.indexOf[q.nodes[i].node.ID()] = j + q.indexOf[q.nodes[j].node.ID()] = i + q.nodes[i], q.nodes[j] = q.nodes[j], q.nodes[i] +} + +func (q *aStarQueue) Len() int { + return len(q.nodes) +} + +func (q *aStarQueue) Push(x interface{}) { + n := x.(aStarNode) + q.indexOf[n.node.ID()] = len(q.nodes) + q.nodes = append(q.nodes, n) +} + +func (q *aStarQueue) Pop() interface{} { + n := q.nodes[len(q.nodes)-1] + q.nodes = q.nodes[:len(q.nodes)-1] + delete(q.indexOf, n.node.ID()) + return n +} + +func (q *aStarQueue) update(id int64, g, f float64) { + i, ok := q.indexOf[id] + if !ok { + return + } + q.nodes[i].gscore = g + q.nodes[i].fscore = f + heap.Fix(q, i) +} + +func (q *aStarQueue) node(id int64) (aStarNode, bool) { + loc, ok := q.indexOf[id] + if ok { + return q.nodes[loc], true + } + return aStarNode{}, false +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/a_star_test.go b/vendor/gonum.org/v1/gonum/graph/path/a_star_test.go new file mode 100644 index 00000000..dd63d4b9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/a_star_test.go @@ -0,0 +1,310 @@ +// Copyright ©2014 The gonum 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 path + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/graph/topo" +) + +var aStarTests = []struct { + name string + g graph.Graph + + s, t int64 + heuristic Heuristic + wantPath []int64 +}{ + { + name: "simple path", + g: func() graph.Graph { + return internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ) + }(), + + s: 1, t: 14, + wantPath: []int64{1, 2, 6, 10, 14}, + }, + { + name: "small open graph", + g: internal.NewGrid(3, 3, true), + + s: 0, t: 8, + }, + { + name: "large open graph", + g: internal.NewGrid(1000, 1000, true), + + s: 0, t: 999*1000 + 999, + }, + { + name: "no path", + g: func() graph.Graph { + tg := internal.NewGrid(5, 5, true) + + // Create a complete "wall" across the middle row. + tg.Set(2, 0, false) + tg.Set(2, 1, false) + tg.Set(2, 2, false) + tg.Set(2, 3, false) + tg.Set(2, 4, false) + + return tg + }(), + + s: 2, t: 22, + }, + { + name: "partially obstructed", + g: func() graph.Graph { + tg := internal.NewGrid(10, 10, true) + + // Create a partial "wall" across the middle + // row with a gap at the left-hand end. + tg.Set(4, 1, false) + tg.Set(4, 2, false) + tg.Set(4, 3, false) + tg.Set(4, 4, false) + tg.Set(4, 5, false) + tg.Set(4, 6, false) + tg.Set(4, 7, false) + tg.Set(4, 8, false) + tg.Set(4, 9, false) + + return tg + }(), + + s: 5, t: 9*10 + 9, + }, + { + name: "partially obstructed with heuristic", + g: func() graph.Graph { + tg := internal.NewGrid(10, 10, true) + + // Create a partial "wall" across the middle + // row with a gap at the left-hand end. + tg.Set(4, 1, false) + tg.Set(4, 2, false) + tg.Set(4, 3, false) + tg.Set(4, 4, false) + tg.Set(4, 5, false) + tg.Set(4, 6, false) + tg.Set(4, 7, false) + tg.Set(4, 8, false) + tg.Set(4, 9, false) + + return tg + }(), + + s: 5, t: 9*10 + 9, + // Manhattan Heuristic + heuristic: func(u, v graph.Node) float64 { + uid := u.ID() + cu := (uid % 10) + ru := (uid - cu) / 10 + + vid := v.ID() + cv := (vid % 10) + rv := (vid - cv) / 10 + + return math.Abs(float64(ru-rv)) + math.Abs(float64(cu-cv)) + }, + }, +} + +func TestAStar(t *testing.T) { + for _, test := range aStarTests { + pt, _ := AStar(simple.Node(test.s), simple.Node(test.t), test.g, test.heuristic) + + p, cost := pt.To(simple.Node(test.t)) + + if !topo.IsPathIn(test.g, p) { + t.Errorf("got path that is not path in input graph for %q", test.name) + } + + bfp, ok := BellmanFordFrom(simple.Node(test.s), test.g) + if !ok { + t.Fatalf("unexpected negative cycle in %q", test.name) + } + if want := bfp.WeightTo(simple.Node(test.t)); cost != want { + t.Errorf("unexpected cost for %q: got:%v want:%v", test.name, cost, want) + } + + var got = make([]int64, 0, len(p)) + for _, n := range p { + got = append(got, n.ID()) + } + if test.wantPath != nil && !reflect.DeepEqual(got, test.wantPath) { + t.Errorf("unexpected result for %q:\ngot: %v\nwant:%v", test.name, got, test.wantPath) + } + } +} + +func TestExhaustiveAStar(t *testing.T) { + g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) + nodes := []locatedNode{ + {id: 1, x: 0, y: 6}, + {id: 2, x: 1, y: 0}, + {id: 3, x: 8, y: 7}, + {id: 4, x: 16, y: 0}, + {id: 5, x: 17, y: 6}, + {id: 6, x: 9, y: 8}, + } + for _, n := range nodes { + g.AddNode(n) + } + + edges := []weightedEdge{ + {from: g.Node(1), to: g.Node(2), cost: 7}, + {from: g.Node(1), to: g.Node(3), cost: 9}, + {from: g.Node(1), to: g.Node(6), cost: 14}, + {from: g.Node(2), to: g.Node(3), cost: 10}, + {from: g.Node(2), to: g.Node(4), cost: 15}, + {from: g.Node(3), to: g.Node(4), cost: 11}, + {from: g.Node(3), to: g.Node(6), cost: 2}, + {from: g.Node(4), to: g.Node(5), cost: 7}, + {from: g.Node(5), to: g.Node(6), cost: 9}, + } + for _, e := range edges { + g.SetWeightedEdge(e) + } + + heuristic := func(u, v graph.Node) float64 { + lu := u.(locatedNode) + lv := v.(locatedNode) + return math.Hypot(lu.x-lv.x, lu.y-lv.y) + } + + if ok, edge, goal := isMonotonic(g, heuristic); !ok { + t.Fatalf("non-monotonic heuristic at edge:%v for goal:%v", edge, goal) + } + + ps := DijkstraAllPaths(g) + for _, start := range g.Nodes() { + for _, goal := range g.Nodes() { + pt, _ := AStar(start, goal, g, heuristic) + gotPath, gotWeight := pt.To(goal) + wantPath, wantWeight, _ := ps.Between(start, goal) + if gotWeight != wantWeight { + t.Errorf("unexpected path weight from %v to %v result: got:%f want:%f", + start, goal, gotWeight, wantWeight) + } + if !reflect.DeepEqual(gotPath, wantPath) { + t.Errorf("unexpected path from %v to %v result:\ngot: %v\nwant:%v", + start, goal, gotPath, wantPath) + } + } + } +} + +type locatedNode struct { + id int64 + x, y float64 +} + +func (n locatedNode) ID() int64 { return n.id } + +type weightedEdge struct { + from, to graph.Node + cost float64 +} + +func (e weightedEdge) From() graph.Node { return e.from } +func (e weightedEdge) To() graph.Node { return e.to } +func (e weightedEdge) Weight() float64 { return e.cost } + +func isMonotonic(g UndirectedWeightLister, h Heuristic) (ok bool, at graph.Edge, goal graph.Node) { + for _, goal := range g.Nodes() { + for _, edge := range g.WeightedEdges() { + from := edge.From() + to := edge.To() + w, ok := g.Weight(from, to) + if !ok { + panic("A*: unexpected invalid weight") + } + if h(from, goal) > w+h(to, goal) { + return false, edge, goal + } + } + } + return true, nil, nil +} + +func TestAStarNullHeuristic(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + var ( + pt Shortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt, _ = AStar(test.Query.From(), test.Query.To(), g.(graph.Graph), nil) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", test.Name, pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore.go b/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore.go new file mode 100644 index 00000000..e7370b7c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore.go @@ -0,0 +1,67 @@ +// Copyright ©2015 The gonum 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 path + +import "gonum.org/v1/gonum/graph" + +// BellmanFordFrom returns a shortest-path tree for a shortest path from u to all nodes in +// the graph g, or false indicating that a negative cycle exists in the graph. If the graph +// does not implement graph.Weighter, UniformCost is used. +// +// The time complexity of BellmanFordFrom is O(|V|.|E|). +func BellmanFordFrom(u graph.Node, g graph.Graph) (path Shortest, ok bool) { + if !g.Has(u) { + return Shortest{from: u}, true + } + var weight Weighting + if wg, ok := g.(graph.Weighted); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + + path = newShortestFrom(u, nodes) + path.dist[path.indexOf[u.ID()]] = 0 + + // TODO(kortschak): Consider adding further optimisations + // from http://arxiv.org/abs/1111.5414. + for i := 1; i < len(nodes); i++ { + changed := false + for j, u := range nodes { + for _, v := range g.From(u) { + k := path.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("bellman-ford: unexpected invalid weight") + } + joint := path.dist[j] + w + if joint < path.dist[k] { + path.set(k, joint, j) + changed = true + } + } + } + if !changed { + break + } + } + + for j, u := range nodes { + for _, v := range g.From(u) { + k := path.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("bellman-ford: unexpected invalid weight") + } + if path.dist[j]+w < path.dist[k] { + return path, false + } + } + } + + return path, true +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore_test.go b/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore_test.go new file mode 100644 index 00000000..b753368f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/bellman_ford_moore_test.go @@ -0,0 +1,70 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestBellmanFordFrom(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + pt, ok := BellmanFordFrom(test.Query.From(), g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", test.Name, pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok = len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/bench_test.go b/vendor/gonum.org/v1/gonum/graph/path/bench_test.go new file mode 100644 index 00000000..e08525f0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/bench_test.go @@ -0,0 +1,141 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + gnpUndirected_10_tenth = gnpUndirected(10, 0.1) + gnpUndirected_100_tenth = gnpUndirected(100, 0.1) + gnpUndirected_1000_tenth = gnpUndirected(1000, 0.1) + gnpUndirected_10_half = gnpUndirected(10, 0.5) + gnpUndirected_100_half = gnpUndirected(100, 0.5) + gnpUndirected_1000_half = gnpUndirected(1000, 0.5) +) + +func gnpUndirected(n int, p float64) graph.Undirected { + g := simple.NewUndirectedGraph() + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkAStarNilHeuristic(b *testing.B, g graph.Undirected) { + var expanded int + for i := 0; i < b.N; i++ { + _, expanded = AStar(simple.Node(0), simple.Node(1), g, nil) + } + if expanded == 0 { + b.Fatal("unexpected number of expanded nodes") + } +} + +func BenchmarkAStarGnp_10_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_10_tenth) +} +func BenchmarkAStarGnp_100_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_100_tenth) +} +func BenchmarkAStarGnp_1000_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_1000_tenth) +} +func BenchmarkAStarGnp_10_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_10_half) +} +func BenchmarkAStarGnp_100_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_100_half) +} +func BenchmarkAStarGnp_1000_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_1000_half) +} + +var ( + nswUndirected_10_2_2_2 = navigableSmallWorldUndirected(10, 2, 2, 2) + nswUndirected_10_2_5_2 = navigableSmallWorldUndirected(10, 2, 5, 2) + nswUndirected_100_5_10_2 = navigableSmallWorldUndirected(100, 5, 10, 2) + nswUndirected_100_5_20_2 = navigableSmallWorldUndirected(100, 5, 20, 2) +) + +func navigableSmallWorldUndirected(n, p, q int, r float64) graph.Undirected { + g := simple.NewUndirectedGraph() + gen.NavigableSmallWorld(g, []int{n, n}, p, q, r, nil) + return g +} + +func coordinatesForID(n graph.Node, c, r int) [2]int { + id := n.ID() + if id >= int64(c*r) { + panic("out of range") + } + return [2]int{int(id) / r, int(id) % r} +} + +// manhattanBetween returns the Manhattan distance between a and b. +func manhattanBetween(a, b [2]int) float64 { + var d int + for i, v := range a { + d += abs(v - b[i]) + } + return float64(d) +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} + +func benchmarkAStarHeuristic(b *testing.B, g graph.Undirected, h Heuristic) { + var expanded int + for i := 0; i < b.N; i++ { + _, expanded = AStar(simple.Node(0), simple.Node(1), g, h) + } + if expanded == 0 { + b.Fatal("unexpected number of expanded nodes") + } +} + +func BenchmarkAStarUndirectedmallWorld_10_2_2_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_10_2_2_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_10_2_2_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 10, 10), coordinatesForID(y, 10, 10)) + } + benchmarkAStarHeuristic(b, nswUndirected_10_2_2_2, h) +} +func BenchmarkAStarUndirectedmallWorld_10_2_5_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_10_2_5_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_10_2_5_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 10, 10), coordinatesForID(y, 10, 10)) + } + benchmarkAStarHeuristic(b, nswUndirected_10_2_5_2, h) +} +func BenchmarkAStarUndirectedmallWorld_100_5_10_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_100_5_10_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_100_5_10_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 100, 100), coordinatesForID(y, 100, 100)) + } + benchmarkAStarHeuristic(b, nswUndirected_100_5_10_2, h) +} +func BenchmarkAStarUndirectedmallWorld_100_5_20_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_100_5_20_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_100_5_20_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 100, 100), coordinatesForID(y, 100, 100)) + } + benchmarkAStarHeuristic(b, nswUndirected_100_5_20_2, h) +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/control_flow.go b/vendor/gonum.org/v1/gonum/graph/path/control_flow.go new file mode 100644 index 00000000..5633e391 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/control_flow.go @@ -0,0 +1,118 @@ +// Copyright ©2014 The gonum 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 path + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// Dominators returns all dominators for all nodes in g. It does not +// prune for strict post-dominators, immediate dominators etc. +// +// A dominates B if and only if the only path through B travels through A. +func Dominators(start graph.Node, g graph.Graph) map[int64]set.Nodes { + allNodes := make(set.Nodes) + nlist := g.Nodes() + dominators := make(map[int64]set.Nodes, len(nlist)) + for _, node := range nlist { + allNodes.Add(node) + } + + var to func(graph.Node) []graph.Node + switch g := g.(type) { + case graph.Directed: + to = g.To + default: + to = g.From + } + + for _, node := range nlist { + dominators[node.ID()] = make(set.Nodes) + if node.ID() == start.ID() { + dominators[node.ID()].Add(start) + } else { + dominators[node.ID()].Copy(allNodes) + } + } + + for somethingChanged := true; somethingChanged; { + somethingChanged = false + for _, node := range nlist { + if node.ID() == start.ID() { + continue + } + preds := to(node) + if len(preds) == 0 { + continue + } + tmp := make(set.Nodes).Copy(dominators[preds[0].ID()]) + for _, pred := range preds[1:] { + tmp.Intersect(tmp, dominators[pred.ID()]) + } + + dom := make(set.Nodes) + dom.Add(node) + + dom.Union(dom, tmp) + if !set.Equal(dom, dominators[node.ID()]) { + dominators[node.ID()] = dom + somethingChanged = true + } + } + } + + return dominators +} + +// PostDominators returns all post-dominators for all nodes in g. It does not +// prune for strict post-dominators, immediate post-dominators etc. +// +// A post-dominates B if and only if all paths from B travel through A. +func PostDominators(end graph.Node, g graph.Graph) map[int64]set.Nodes { + allNodes := make(set.Nodes) + nlist := g.Nodes() + dominators := make(map[int64]set.Nodes, len(nlist)) + for _, node := range nlist { + allNodes.Add(node) + } + + for _, node := range nlist { + dominators[node.ID()] = make(set.Nodes) + if node.ID() == end.ID() { + dominators[node.ID()].Add(end) + } else { + dominators[node.ID()].Copy(allNodes) + } + } + + for somethingChanged := true; somethingChanged; { + somethingChanged = false + for _, node := range nlist { + if node.ID() == end.ID() { + continue + } + succs := g.From(node) + if len(succs) == 0 { + continue + } + tmp := make(set.Nodes).Copy(dominators[succs[0].ID()]) + for _, succ := range succs[1:] { + tmp.Intersect(tmp, dominators[succ.ID()]) + } + + dom := make(set.Nodes) + dom.Add(node) + + dom.Union(dom, tmp) + if !set.Equal(dom, dominators[node.ID()]) { + dominators[node.ID()] = dom + somethingChanged = true + } + } + } + + return dominators +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/dijkstra.go b/vendor/gonum.org/v1/gonum/graph/path/dijkstra.go new file mode 100644 index 00000000..4c14d2b4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dijkstra.go @@ -0,0 +1,147 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "container/heap" + + "gonum.org/v1/gonum/graph" +) + +// DijkstraFrom returns a shortest-path tree for a shortest path from u to all nodes in +// the graph g. If the graph does not implement graph.Weighter, UniformCost is used. +// DijkstraFrom will panic if g has a u-reachable negative edge weight. +// +// The time complexity of DijkstrFrom is O(|E|.log|V|). +func DijkstraFrom(u graph.Node, g graph.Graph) Shortest { + if !g.Has(u) { + return Shortest{from: u} + } + var weight Weighting + if wg, ok := g.(graph.Weighted); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + path := newShortestFrom(u, nodes) + + // Dijkstra's algorithm here is implemented essentially as + // described in Function B.2 in figure 6 of UTCS Technical + // Report TR-07-54. + // + // This implementation deviates from the report as follows: + // - the value of path.dist for the start vertex u is initialized to 0; + // - outdated elements from the priority queue (i.e. with respect to the dist value) + // are skipped. + // + // http://www.cs.utexas.edu/ftp/techreports/tr07-54.pdf + Q := priorityQueue{{node: u, dist: 0}} + for Q.Len() != 0 { + mid := heap.Pop(&Q).(distanceNode) + k := path.indexOf[mid.node.ID()] + if mid.dist > path.dist[k] { + continue + } + for _, v := range g.From(mid.node) { + j := path.indexOf[v.ID()] + w, ok := weight(mid.node, v) + if !ok { + panic("dijkstra: unexpected invalid weight") + } + if w < 0 { + panic("dijkstra: negative edge weight") + } + joint := path.dist[k] + w + if joint < path.dist[j] { + heap.Push(&Q, distanceNode{node: v, dist: joint}) + path.set(j, joint, k) + } + } + } + + return path +} + +// DijkstraAllPaths returns a shortest-path tree for shortest paths in the graph g. +// If the graph does not implement graph.Weighter, UniformCost is used. +// DijkstraAllPaths will panic if g has a negative edge weight. +// +// The time complexity of DijkstrAllPaths is O(|V|.|E|+|V|^2.log|V|). +func DijkstraAllPaths(g graph.Graph) (paths AllShortest) { + paths = newAllShortest(g.Nodes(), false) + dijkstraAllPaths(g, paths) + return paths +} + +// dijkstraAllPaths is the all-paths implementation of Dijkstra. It is shared +// between DijkstraAllPaths and JohnsonAllPaths to avoid repeated allocation +// of the nodes slice and the indexOf map. It returns nothing, but stores the +// result of the work in the paths parameter which is a reference type. +func dijkstraAllPaths(g graph.Graph, paths AllShortest) { + var weight Weighting + if wg, ok := g.(graph.Weighted); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + var Q priorityQueue + for i, u := range paths.nodes { + // Dijkstra's algorithm here is implemented essentially as + // described in Function B.2 in figure 6 of UTCS Technical + // Report TR-07-54 with the addition of handling multiple + // co-equal paths. + // + // http://www.cs.utexas.edu/ftp/techreports/tr07-54.pdf + + // Q must be empty at this point. + heap.Push(&Q, distanceNode{node: u, dist: 0}) + for Q.Len() != 0 { + mid := heap.Pop(&Q).(distanceNode) + k := paths.indexOf[mid.node.ID()] + if mid.dist < paths.dist.At(i, k) { + paths.dist.Set(i, k, mid.dist) + } + for _, v := range g.From(mid.node) { + j := paths.indexOf[v.ID()] + w, ok := weight(mid.node, v) + if !ok { + panic("dijkstra: unexpected invalid weight") + } + if w < 0 { + panic("dijkstra: negative edge weight") + } + joint := paths.dist.At(i, k) + w + if joint < paths.dist.At(i, j) { + heap.Push(&Q, distanceNode{node: v, dist: joint}) + paths.set(i, j, joint, k) + } else if joint == paths.dist.At(i, j) { + paths.add(i, j, k) + } + } + } + } +} + +type distanceNode struct { + node graph.Node + dist float64 +} + +// priorityQueue implements a no-dec priority queue. +type priorityQueue []distanceNode + +func (q priorityQueue) Len() int { return len(q) } +func (q priorityQueue) Less(i, j int) bool { return q[i].dist < q[j].dist } +func (q priorityQueue) Swap(i, j int) { q[i], q[j] = q[j], q[i] } +func (q *priorityQueue) Push(n interface{}) { *q = append(*q, n.(distanceNode)) } +func (q *priorityQueue) Pop() interface{} { + t := *q + var n interface{} + n, *q = t[len(t)-1], t[:len(t)-1] + return n +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/dijkstra_test.go b/vendor/gonum.org/v1/gonum/graph/path/dijkstra_test.go new file mode 100644 index 00000000..ccb74644 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dijkstra_test.go @@ -0,0 +1,178 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestDijkstraFrom(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + var ( + pt Shortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt = DijkstraFrom(test.Query.From(), g.(graph.Graph)) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", test.Name, pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} + +func TestDijkstraAllPaths(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + var ( + pt AllShortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt = DijkstraAllPaths(g.(graph.Graph)) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int64 + if len(paths) != 0 { + got = make([][]int64, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/disjoint.go b/vendor/gonum.org/v1/gonum/graph/path/disjoint.go new file mode 100644 index 00000000..4f530f69 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/disjoint.go @@ -0,0 +1,87 @@ +// Copyright ©2014 The gonum 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 path + +// A disjoint set is a collection of non-overlapping sets. That is, for any two sets in the +// disjoint set, their intersection is the empty set. +// +// A disjoint set has three principle operations: Make Set, Find, and Union. +// +// Make set creates a new set for an element (presuming it does not already exist in any set in +// the disjoint set), Find finds the set containing that element (if any), and Union merges two +// sets in the disjoint set. In general, algorithms operating on disjoint sets are "union-find" +// algorithms, where two sets are found with Find, and then joined with Union. +// +// A concrete example of a union-find algorithm can be found as discrete.Kruskal -- which unions +// two sets when an edge is created between two vertices, and refuses to make an edge between two +// vertices if they're part of the same set. +type disjointSet struct { + master map[int64]*disjointSetNode +} + +type disjointSetNode struct { + parent *disjointSetNode + rank int +} + +func newDisjointSet() *disjointSet { + return &disjointSet{master: make(map[int64]*disjointSetNode)} +} + +// If the element isn't already somewhere in there, adds it to the master set and its own tiny set. +func (ds *disjointSet) makeSet(e int64) { + if _, ok := ds.master[e]; ok { + return + } + dsNode := &disjointSetNode{rank: 0} + dsNode.parent = dsNode + ds.master[e] = dsNode +} + +// Returns the set the element belongs to, or nil if none. +func (ds *disjointSet) find(e int64) *disjointSetNode { + dsNode, ok := ds.master[e] + if !ok { + return nil + } + + return find(dsNode) +} + +func find(dsNode *disjointSetNode) *disjointSetNode { + if dsNode.parent != dsNode { + dsNode.parent = find(dsNode.parent) + } + + return dsNode.parent +} + +// Unions two subsets within the disjointSet. +// +// If x or y are not in this disjoint set, the behavior is undefined. If either pointer is nil, +// this function will panic. +func (ds *disjointSet) union(x, y *disjointSetNode) { + if x == nil || y == nil { + panic("Disjoint Set union on nil sets") + } + xRoot := find(x) + yRoot := find(y) + if xRoot == nil || yRoot == nil { + return + } + + if xRoot == yRoot { + return + } + + if xRoot.rank < yRoot.rank { + xRoot.parent = yRoot + } else if yRoot.rank < xRoot.rank { + yRoot.parent = xRoot + } else { + yRoot.parent = xRoot + xRoot.rank++ + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/disjoint_test.go b/vendor/gonum.org/v1/gonum/graph/path/disjoint_test.go new file mode 100644 index 00000000..2639592a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/disjoint_test.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum 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 path + +import ( + "testing" +) + +func TestDisjointSetMakeSet(t *testing.T) { + ds := newDisjointSet() + if ds.master == nil { + t.Fatal("Internal disjoint set map erroneously nil") + } else if len(ds.master) != 0 { + t.Error("Disjoint set master map of wrong size") + } + + ds.makeSet(3) + if len(ds.master) != 1 { + t.Error("Disjoint set master map of wrong size") + } + + if node, ok := ds.master[3]; !ok { + t.Error("Make set did not successfully add element") + } else { + if node == nil { + t.Fatal("Disjoint set node from makeSet is nil") + } + + if node.rank != 0 { + t.Error("Node rank set incorrectly") + } + + if node.parent != node { + t.Error("Node parent set incorrectly") + } + } +} + +func TestDisjointSetFind(t *testing.T) { + ds := newDisjointSet() + + ds.makeSet(3) + ds.makeSet(5) + + if ds.find(3) == ds.find(5) { + t.Error("Disjoint sets incorrectly found to be the same") + } +} + +func TestUnion(t *testing.T) { + ds := newDisjointSet() + + ds.makeSet(3) + ds.makeSet(5) + + ds.union(ds.find(3), ds.find(5)) + + if ds.find(3) != ds.find(5) { + t.Error("Sets found to be disjoint after union") + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/doc.go b/vendor/gonum.org/v1/gonum/graph/path/doc.go new file mode 100644 index 00000000..f9e7b1dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2016 The gonum 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 path provides graph path finding functions. +package path // import "gonum.org/v1/gonum/graph/path" diff --git a/vendor/gonum.org/v1/gonum/graph/path/dynamic/doc.go b/vendor/gonum.org/v1/gonum/graph/path/dynamic/doc.go new file mode 100644 index 00000000..a0e9458f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dynamic/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2016 The gonum 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 dynamic provides incremental heuristic graph path finding functions. +package dynamic // import "gonum.org/v1/gonum/graph/path/dynamic" diff --git a/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite.go b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite.go new file mode 100644 index 00000000..e8794dc8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite.go @@ -0,0 +1,491 @@ +// Copyright ©2014 The gonum 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 dynamic + +import ( + "container/heap" + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +// DStarLite implements the D* Lite dynamic re-planning path search algorithm. +// +// doi:10.1109/tro.2004.838026 and ISBN:0-262-51129-0 pp476-483 +// +type DStarLite struct { + s, t *dStarLiteNode + last *dStarLiteNode + + model WorldModel + queue dStarLiteQueue + keyModifier float64 + + weight path.Weighting + heuristic path.Heuristic +} + +// WorldModel is a mutable weighted directed graph that returns nodes identified +// by id number. +type WorldModel interface { + graph.WeightedBuilder + graph.WeightedDirected + Node(id int64) graph.Node +} + +// NewDStarLite returns a new DStarLite planner for the path from s to t in g using the +// heuristic h. The world model, m, is used to store shortest path information during path +// planning. The world model must be an empty graph when NewDStarLite is called. +// +// If h is nil, the DStarLite will use the g.HeuristicCost method if g implements +// path.HeuristicCoster, falling back to path.NullHeuristic otherwise. If the graph does not +// implement graph.Weighter, path.UniformCost is used. NewDStarLite will panic if g has +// a negative edge weight. +func NewDStarLite(s, t graph.Node, g graph.Graph, h path.Heuristic, m WorldModel) *DStarLite { + /* + procedure Initialize() + {02”} U = ∅; + {03”} k_m = 0; + {04”} for all s ∈ S rhs(s) = g(s) = ∞; + {05”} rhs(s_goal) = 0; + {06”} U.Insert(s_goal, [h(s_start, s_goal); 0]); + */ + + d := &DStarLite{ + s: newDStarLiteNode(s), + t: newDStarLiteNode(t), // badKey is overwritten below. + + model: m, + + heuristic: h, + } + d.t.rhs = 0 + + /* + procedure Main() + {29”} s_last = s_start; + {30”} Initialize(); + */ + d.last = d.s + + if wg, ok := g.(graph.Weighted); ok { + d.weight = wg.Weight + } else { + d.weight = path.UniformCost(g) + } + if d.heuristic == nil { + if g, ok := g.(path.HeuristicCoster); ok { + d.heuristic = g.HeuristicCost + } else { + d.heuristic = path.NullHeuristic + } + } + + d.queue.insert(d.t, key{d.heuristic(s, t), 0}) + + for _, n := range g.Nodes() { + switch n.ID() { + case d.s.ID(): + d.model.AddNode(d.s) + case d.t.ID(): + d.model.AddNode(d.t) + default: + d.model.AddNode(newDStarLiteNode(n)) + } + } + for _, u := range d.model.Nodes() { + for _, v := range g.From(u) { + w := edgeWeight(d.weight, u, v) + if w < 0 { + panic("D* Lite: negative edge weight") + } + d.model.SetWeightedEdge(simple.WeightedEdge{F: u, T: d.model.Node(v.ID()), W: w}) + } + } + + /* + procedure Main() + {31”} ComputeShortestPath(); + */ + d.findShortestPath() + + return d +} + +// edgeWeight is a helper function that returns the weight of the edge between +// two connected nodes, u and v, using the provided weight function. It panics +// if there is no edge between u and v. +func edgeWeight(weight path.Weighting, u, v graph.Node) float64 { + w, ok := weight(u, v) + if !ok { + panic("D* Lite: unexpected invalid weight") + } + return w +} + +// keyFor is the CalculateKey procedure in the D* Lite papers. +func (d *DStarLite) keyFor(s *dStarLiteNode) key { + /* + procedure CalculateKey(s) + {01”} return [min(g(s), rhs(s)) + h(s_start, s) + k_m; min(g(s), rhs(s))]; + */ + k := key{1: math.Min(s.g, s.rhs)} + k[0] = k[1] + d.heuristic(d.s.Node, s.Node) + d.keyModifier + return k +} + +// update is the UpdateVertex procedure in the D* Lite papers. +func (d *DStarLite) update(u *dStarLiteNode) { + /* + procedure UpdateVertex(u) + {07”} if (g(u) != rhs(u) AND u ∈ U) U.Update(u,CalculateKey(u)); + {08”} else if (g(u) != rhs(u) AND u /∈ U) U.Insert(u,CalculateKey(u)); + {09”} else if (g(u) = rhs(u) AND u ∈ U) U.Remove(u); + */ + inQueue := u.inQueue() + switch { + case inQueue && u.g != u.rhs: + d.queue.update(u, d.keyFor(u)) + case !inQueue && u.g != u.rhs: + d.queue.insert(u, d.keyFor(u)) + case inQueue && u.g == u.rhs: + d.queue.remove(u) + } +} + +// findShortestPath is the ComputeShortestPath procedure in the D* Lite papers. +func (d *DStarLite) findShortestPath() { + /* + procedure ComputeShortestPath() + {10”} while (U.TopKey() < CalculateKey(s_start) OR rhs(s_start) > g(s_start)) + {11”} u = U.Top(); + {12”} k_old = U.TopKey(); + {13”} k_new = CalculateKey(u); + {14”} if(k_old < k_new) + {15”} U.Update(u, k_new); + {16”} else if (g(u) > rhs(u)) + {17”} g(u) = rhs(u); + {18”} U.Remove(u); + {19”} for all s ∈ Pred(u) + {20”} if (s != s_goal) rhs(s) = min(rhs(s), c(s, u) + g(u)); + {21”} UpdateVertex(s); + {22”} else + {23”} g_old = g(u); + {24”} g(u) = ∞; + {25”} for all s ∈ Pred(u) ∪ {u} + {26”} if (rhs(s) = c(s, u) + g_old) + {27”} if (s != s_goal) rhs(s) = min s'∈Succ(s)(c(s, s') + g(s')); + {28”} UpdateVertex(s); + */ + for d.queue.Len() != 0 { // We use d.queue.Len since d.queue does not return an infinite key when empty. + u := d.queue.top() + if !u.key.less(d.keyFor(d.s)) && d.s.rhs <= d.s.g { + break + } + switch kNew := d.keyFor(u); { + case u.key.less(kNew): + d.queue.update(u, kNew) + case u.g > u.rhs: + u.g = u.rhs + d.queue.remove(u) + for _, _s := range d.model.To(u) { + s := _s.(*dStarLiteNode) + if s.ID() != d.t.ID() { + s.rhs = math.Min(s.rhs, edgeWeight(d.model.Weight, s, u)+u.g) + } + d.update(s) + } + default: + gOld := u.g + u.g = math.Inf(1) + for _, _s := range append(d.model.To(u), u) { + s := _s.(*dStarLiteNode) + if s.rhs == edgeWeight(d.model.Weight, s, u)+gOld { + if s.ID() != d.t.ID() { + s.rhs = math.Inf(1) + for _, t := range d.model.From(s) { + s.rhs = math.Min(s.rhs, edgeWeight(d.model.Weight, s, t)+t.(*dStarLiteNode).g) + } + } + } + d.update(s) + } + } + } +} + +// Step performs one movement step along the best path towards the goal. +// It returns false if no further progression toward the goal can be +// achieved, either because the goal has been reached or because there +// is no path. +func (d *DStarLite) Step() bool { + /* + procedure Main() + {32”} while (s_start != s_goal) + {33”} // if (rhs(s_start) = ∞) then there is no known path + {34”} s_start = argmin s'∈Succ(s_start)(c(s_start, s') + g(s')); + */ + if d.s.ID() == d.t.ID() { + return false + } + if math.IsInf(d.s.rhs, 1) { + return false + } + + // We use rhs comparison to break ties + // between coequally weighted nodes. + rhs := math.Inf(1) + min := math.Inf(1) + + var next *dStarLiteNode + for _, _s := range d.model.From(d.s) { + s := _s.(*dStarLiteNode) + w := edgeWeight(d.model.Weight, d.s, s) + s.g + if w < min || (w == min && s.rhs < rhs) { + next = s + min = w + rhs = s.rhs + } + } + d.s = next + + /* + procedure Main() + {35”} Move to s_start; + */ + return true +} + +// MoveTo moves to n in the world graph. +func (d *DStarLite) MoveTo(n graph.Node) { + d.last = d.s + d.s = d.model.Node(n.ID()).(*dStarLiteNode) + d.keyModifier += d.heuristic(d.last, d.s) +} + +// UpdateWorld updates or adds edges in the world graph. UpdateWorld will +// panic if changes include a negative edge weight. +func (d *DStarLite) UpdateWorld(changes []graph.Edge) { + /* + procedure Main() + {36”} Scan graph for changed edge costs; + {37”} if any edge costs changed + {38”} k_m = k_m + h(s_last, s_start); + {39”} s_last = s_start; + {40”} for all directed edges (u, v) with changed edge costs + {41”} c_old = c(u, v); + {42”} Update the edge cost c(u, v); + {43”} if (c_old > c(u, v)) + {44”} if (u != s_goal) rhs(u) = min(rhs(u), c(u, v) + g(v)); + {45”} else if (rhs(u) = c_old + g(v)) + {46”} if (u != s_goal) rhs(u) = min s'∈Succ(u)(c(u, s') + g(s')); + {47”} UpdateVertex(u); + {48”} ComputeShortestPath() + */ + if len(changes) == 0 { + return + } + d.keyModifier += d.heuristic(d.last, d.s) + d.last = d.s + for _, e := range changes { + from := e.From() + to := e.To() + c, _ := d.weight(from, to) + if c < 0 { + panic("D* Lite: negative edge weight") + } + cOld, _ := d.model.Weight(from, to) + u := d.worldNodeFor(from) + v := d.worldNodeFor(to) + d.model.SetWeightedEdge(simple.WeightedEdge{F: u, T: v, W: c}) + if cOld > c { + if u.ID() != d.t.ID() { + u.rhs = math.Min(u.rhs, c+v.g) + } + } else if u.rhs == cOld+v.g { + if u.ID() != d.t.ID() { + u.rhs = math.Inf(1) + for _, t := range d.model.From(u) { + u.rhs = math.Min(u.rhs, edgeWeight(d.model.Weight, u, t)+t.(*dStarLiteNode).g) + } + } + } + d.update(u) + } + d.findShortestPath() +} + +func (d *DStarLite) worldNodeFor(n graph.Node) *dStarLiteNode { + switch w := d.model.Node(n.ID()).(type) { + case *dStarLiteNode: + return w + case graph.Node: + panic(fmt.Sprintf("D* Lite: illegal world model node type: %T", w)) + default: + return newDStarLiteNode(n) + } +} + +// Here returns the current location. +func (d *DStarLite) Here() graph.Node { + return d.s.Node +} + +// Path returns the path from the current location to the goal and the +// weight of the path. +func (d *DStarLite) Path() (p []graph.Node, weight float64) { + u := d.s + p = []graph.Node{u.Node} + for u.ID() != d.t.ID() { + if math.IsInf(u.rhs, 1) { + return nil, math.Inf(1) + } + + // We use stored rhs comparison to break + // ties between calculated rhs-coequal nodes. + rhsMin := math.Inf(1) + min := math.Inf(1) + var ( + next *dStarLiteNode + cost float64 + ) + for _, _v := range d.model.From(u) { + v := _v.(*dStarLiteNode) + w := edgeWeight(d.model.Weight, u, v) + if rhs := w + v.g; rhs < min || (rhs == min && v.rhs < rhsMin) { + next = v + min = rhs + rhsMin = v.rhs + cost = w + } + } + if next == nil { + return nil, math.NaN() + } + u = next + weight += cost + p = append(p, u.Node) + } + return p, weight +} + +/* +The pseudocode uses the following functions to manage the priority +queue: + + * U.Top() returns a vertex with the smallest priority of all + vertices in priority queue U. + * U.TopKey() returns the smallest priority of all vertices in + priority queue U. (If is empty, then U.TopKey() returns [∞;∞].) + * U.Pop() deletes the vertex with the smallest priority in + priority queue U and returns the vertex. + * U.Insert(s, k) inserts vertex s into priority queue with + priority k. + * U.Update(s, k) changes the priority of vertex s in priority + queue U to k. (It does nothing if the current priority of vertex + s already equals k.) + * Finally, U.Remove(s) removes vertex s from priority queue U. +*/ + +// key is a D* Lite priority queue key. +type key [2]float64 + +var badKey = key{math.NaN(), math.NaN()} + +// less returns whether k is less than other. From ISBN:0-262-51129-0 pp476-483: +// +// k ≤ k' iff k₁ < k'₁ OR (k₁ == k'₁ AND k₂ ≤ k'₂) +// +func (k key) less(other key) bool { + if k != k || other != other { + panic("D* Lite: poisoned key") + } + return k[0] < other[0] || (k[0] == other[0] && k[1] < other[1]) +} + +// dStarLiteNode adds D* Lite accounting to a graph.Node. +type dStarLiteNode struct { + graph.Node + key key + idx int + rhs float64 + g float64 +} + +// newDStarLiteNode returns a dStarLite node that is in a legal state +// for existence outside the DStarLite priority queue. +func newDStarLiteNode(n graph.Node) *dStarLiteNode { + return &dStarLiteNode{ + Node: n, + rhs: math.Inf(1), + g: math.Inf(1), + key: badKey, + idx: -1, + } +} + +// inQueue returns whether the node is in the queue. +func (q *dStarLiteNode) inQueue() bool { + return q.idx >= 0 +} + +// dStarLiteQueue is a D* Lite priority queue. +type dStarLiteQueue []*dStarLiteNode + +func (q dStarLiteQueue) Less(i, j int) bool { + return q[i].key.less(q[j].key) +} + +func (q dStarLiteQueue) Swap(i, j int) { + q[i], q[j] = q[j], q[i] + q[i].idx = i + q[j].idx = j +} + +func (q dStarLiteQueue) Len() int { + return len(q) +} + +func (q *dStarLiteQueue) Push(x interface{}) { + n := x.(*dStarLiteNode) + n.idx = len(*q) + *q = append(*q, n) +} + +func (q *dStarLiteQueue) Pop() interface{} { + n := (*q)[len(*q)-1] + n.idx = -1 + *q = (*q)[:len(*q)-1] + return n +} + +// top returns the top node in the queue. Note that instead of +// returning a key [∞;∞] when q is empty, the caller checks for +// an empty queue by calling q.Len. +func (q dStarLiteQueue) top() *dStarLiteNode { + return q[0] +} + +// insert puts the node u into the queue with the key k. +func (q *dStarLiteQueue) insert(u *dStarLiteNode, k key) { + u.key = k + heap.Push(q, u) +} + +// update updates the node in the queue identified by id with the key k. +func (q *dStarLiteQueue) update(n *dStarLiteNode, k key) { + n.key = k + heap.Fix(q, n.idx) +} + +// remove removes the node identified by id from the queue. +func (q *dStarLiteQueue) remove(n *dStarLiteNode) { + heap.Remove(q, n.idx) + n.key = badKey + n.idx = -1 +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite_test.go b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite_test.go new file mode 100644 index 00000000..9c53a5da --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dstarlite_test.go @@ -0,0 +1,680 @@ +// Copyright ©2015 The gonum 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 dynamic + +import ( + "bytes" + "flag" + "fmt" + "math" + "reflect" + "strings" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + debug = flag.Bool("debug", false, "write path progress for failing dynamic case tests") + vdebug = flag.Bool("vdebug", false, "write path progress for all dynamic case tests (requires test.v)") + maxWide = flag.Int("maxwidth", 5, "maximum width grid to dump for debugging") +) + +func TestDStarLiteNullHeuristic(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + // Skip zero-weight cycles. + if strings.HasPrefix(test.Name, "zero-weight") { + continue + } + + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + var ( + d *DStarLite + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + d = NewDStarLite(test.Query.From(), test.Query.To(), g.(graph.Graph), path.NullHeuristic, simple.NewWeightedDirectedGraph(0, math.Inf(1))) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + p, weight := d.Path() + + if !math.IsInf(weight, 1) && p[0].ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", test.Name, p[0].ID(), test.Query.From().ID()) + } + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } +} + +var dynamicDStarLiteTests = []struct { + g *internal.Grid + radius float64 + all bool + diag, unit bool + remember []bool + modify func(*internal.LimitedVisionGrid) + + heuristic func(dx, dy float64) float64 + + s, t graph.Node + + want []graph.Node + weight float64 + wantedPaths map[int64][]graph.Node +}{ + { + // This is the example shown in figures 6 and 7 of doi:10.1109/tro.2004.838026. + g: internal.NewGridFrom( + "...", + ".*.", + ".*.", + ".*.", + "...", + ), + radius: 1.5, + all: true, + diag: true, + unit: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(3), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(3), + simple.Node(6), + simple.Node(9), + simple.Node(13), + simple.Node(14), + }, + weight: 4, + }, + { + // This is a small example that has the property that the first corner + // may be taken incorrectly at 90° or correctly at 45° because the + // calculated rhs values of 12 and 17 are tied when moving from node + // 16, and the grid is small enough to examine by a dump. + g: internal.NewGridFrom( + ".....", + "...*.", + "**.*.", + "...*.", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(15), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(15), + simple.Node(16), + simple.Node(12), + simple.Node(7), + simple.Node(3), + simple.Node(9), + simple.Node(14), + }, + weight: 7.242640687119285, + wantedPaths: map[int64][]graph.Node{ + 12: {simple.Node(12), simple.Node(7), simple.Node(3), simple.Node(9), simple.Node(14)}, + }, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count and only allowing information to be known + // from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "......*...........", + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(149), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 21.242640687119287, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count, not closing the exit and only allowing + // information to be known from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "..................", // Keep open. + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(150), + simple.Node(151), + simple.Node(152), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 18.656854249492383, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count, the exit is closed at a distance and + // information is allowed to be known from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "........*.........", + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(150), + simple.Node(151), + simple.Node(150), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 24.07106781186548, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "......*...........", // Forget this wall. + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{true}, + + modify: func(l *internal.LimitedVisionGrid) { + all := l.Grid.AllVisible + l.Grid.AllVisible = false + for _, n := range l.Nodes() { + l.Known[n.ID()] = !l.Grid.Has(n) + } + l.Grid.AllVisible = all + + const ( + wallRow = 8 + wallCol = 6 + ) + l.Known[l.NodeAt(wallRow, wallCol).ID()] = false + + // Check we have a correctly modified representation. + for _, u := range l.Nodes() { + for _, v := range l.Nodes() { + if l.HasEdgeBetween(u, v) != l.Grid.HasEdgeBetween(u, v) { + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if (ur == wallRow && uc == wallCol) || (vr == wallRow && vc == wallCol) { + if !l.HasEdgeBetween(u, v) { + panic(fmt.Sprintf("expected to believe edge between %v (%d,%d) and %v (%d,%d) is passable", + u, v, ur, uc, vr, vc)) + } + continue + } + panic(fmt.Sprintf("disagreement about edge between %v (%d,%d) and %v (%d,%d): got:%t want:%t", + u, v, ur, uc, vr, vc, l.HasEdgeBetween(u, v), l.Grid.HasEdgeBetween(u, v))) + } + } + } + }, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(149), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 21.242640687119287, + }, + { + g: internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + all: true, + diag: false, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(1), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(1), + simple.Node(2), + simple.Node(6), + simple.Node(10), + simple.Node(14), + }, + weight: 4, + }, + { + g: internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(1), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(1), + simple.Node(6), + simple.Node(10), + simple.Node(14), + }, + weight: math.Sqrt2 + 2, + }, + { + g: internal.NewGridFrom( + "...", + ".*.", + ".*.", + ".*.", + ".*.", + ), + radius: 1, + all: true, + diag: false, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(6), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(6), + simple.Node(9), + simple.Node(12), + simple.Node(9), + simple.Node(6), + simple.Node(3), + simple.Node(0), + simple.Node(1), + simple.Node(2), + simple.Node(5), + simple.Node(8), + simple.Node(11), + simple.Node(14), + }, + weight: 12, + }, +} + +func TestDStarLiteDynamic(t *testing.T) { + for i, test := range dynamicDStarLiteTests { + for _, remember := range test.remember { + l := &internal.LimitedVisionGrid{ + Grid: test.g, + VisionRadius: test.radius, + Location: test.s, + } + if remember { + l.Known = make(map[int64]bool) + } + + l.Grid.AllVisible = test.all + + l.Grid.AllowDiagonal = test.diag + l.Grid.UnitEdgeWeight = test.unit + + if test.modify != nil { + test.modify(l) + } + + got := []graph.Node{test.s} + l.MoveTo(test.s) + + heuristic := func(a, b graph.Node) float64 { + ax, ay := l.XY(a) + bx, by := l.XY(b) + return test.heuristic(ax-bx, ay-by) + } + + world := simple.NewWeightedDirectedGraph(0, math.Inf(1)) + d := NewDStarLite(test.s, test.t, l, heuristic, world) + var ( + dp *dumper + buf bytes.Buffer + ) + _, c := l.Grid.Dims() + if c <= *maxWide && (*debug || *vdebug) { + dp = &dumper{ + w: &buf, + + dStarLite: d, + grid: l, + } + } + + dp.dump(true) + dp.printEdges("Initial world knowledge: %s\n\n", simpleWeightedEdgesOf(l, world.Edges())) + for d.Step() { + changes, _ := l.MoveTo(d.Here()) + got = append(got, l.Location) + d.UpdateWorld(changes) + dp.dump(true) + if wantedPath, ok := test.wantedPaths[l.Location.ID()]; ok { + gotPath, _ := d.Path() + if !samePath(gotPath, wantedPath) { + t.Errorf("unexpected intermediate path estimation for test %d %s memory:\ngot: %v\nwant:%v", + i, memory(remember), gotPath, wantedPath) + } + } + dp.printEdges("Edges changing after last step:\n%s\n\n", simpleWeightedEdgesOf(l, changes)) + } + + if weight := weightOf(got, l.Grid); !samePath(got, test.want) || weight != test.weight { + t.Errorf("unexpected path for test %d %s memory got weight:%v want weight:%v:\ngot: %v\nwant:%v", + i, memory(remember), weight, test.weight, got, test.want) + b, err := l.Render(got) + t.Errorf("path taken (err:%v):\n%s", err, b) + if c <= *maxWide && (*debug || *vdebug) { + t.Error(buf.String()) + } + } else if c <= *maxWide && *vdebug { + t.Logf("Test %d:\n%s", i, buf.String()) + } + } + } +} + +type memory bool + +func (m memory) String() string { + if m { + return "with" + } + return "without" +} + +// samePath compares two paths for equality ignoring nodes that are nil. +func samePath(a, b []graph.Node) bool { + if len(a) != len(b) { + return false + } + for i, e := range a { + if e == nil || b[i] == nil { + continue + } + if e.ID() != b[i].ID() { + return false + } + } + return true +} + +// weightOf return the weight of the path in g. +func weightOf(path []graph.Node, g graph.Weighted) float64 { + var w float64 + if len(path) > 1 { + for p, n := range path[1:] { + ew, ok := g.Weight(path[p], n) + if !ok { + return math.Inf(1) + } + w += ew + } + } + return w +} + +// simpleWeightedEdgesOf returns the weighted edges in g corresponding to the given edges. +func simpleWeightedEdgesOf(g graph.Weighted, edges []graph.Edge) []simple.WeightedEdge { + w := make([]simple.WeightedEdge, len(edges)) + for i, e := range edges { + w[i].F = e.From() + w[i].T = e.To() + ew, _ := g.Weight(e.From(), e.To()) + w[i].W = ew + } + return w +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/dynamic/dumper_test.go b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dumper_test.go new file mode 100644 index 00000000..f76a3649 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/dynamic/dumper_test.go @@ -0,0 +1,153 @@ +// Copyright ©2015 The gonum 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 dynamic + +import ( + "bytes" + "fmt" + "io" + "sort" + "text/tabwriter" + + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/simple" +) + +// dumper implements a grid D* Lite statistics dump. +type dumper struct { + step int + + dStarLite *DStarLite + grid *internal.LimitedVisionGrid + + w io.Writer +} + +// dump writes a single step of a D* Lite path search to the dumper's io.Writer. +func (d *dumper) dump(withpath bool) { + if d == nil { + return + } + var pathStep map[int64]int + if withpath { + pathStep = make(map[int64]int) + path, _ := d.dStarLite.Path() + for i, n := range path { + pathStep[n.ID()] = i + } + } + fmt.Fprintf(d.w, "Step:%d kₘ=%v\n", d.step, d.dStarLite.keyModifier) + d.step++ + w := tabwriter.NewWriter(d.w, 0, 0, 0, ' ', tabwriter.Debug) + rows, cols := d.grid.Grid.Dims() + for r := 0; r < rows; r++ { + if r == 0 { + for c := 0; c < cols; c++ { + if c != 0 { + fmt.Fprint(w, "\t") + } + fmt.Fprint(w, "-------------------") + } + fmt.Fprintln(w) + } + for ln := 0; ln < 6; ln++ { + for c := 0; c < cols; c++ { + if c != 0 { + fmt.Fprint(w, "\t") + } + n := d.dStarLite.model.Node(d.grid.NodeAt(r, c).ID()).(*dStarLiteNode) + switch ln { + case 0: + if n.ID() == d.grid.Location.ID() { + if d.grid.Grid.HasOpen(n) { + fmt.Fprintf(w, "id:%2d >@<", n.ID()) + } else { + // Mark location as illegal. + fmt.Fprintf(w, "id:%2d >!<", n.ID()) + } + } else if n.ID() == d.dStarLite.t.ID() { + fmt.Fprintf(w, "id:%2d G", n.ID()) + // Mark goal cell as illegal. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, "!") + } + } else if pathStep[n.ID()] > 0 { + fmt.Fprintf(w, "id:%2d %2d", n.ID(), pathStep[n.ID()]) + // Mark path cells with an obstruction. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, "!") + } + } else { + fmt.Fprintf(w, "id:%2d", n.ID()) + // Mark cells with an obstruction. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, " *") + } + } + case 1: + fmt.Fprintf(w, "h: %.4v", d.dStarLite.heuristic(n, d.dStarLite.Here())) + case 2: + fmt.Fprintf(w, "g: %.4v", n.g) + case 3: + fmt.Fprintf(w, "rhs:%.4v", n.rhs) + case 4: + if n.g != n.rhs { + fmt.Fprintf(w, "key:%.3f", n.key) + } + if n.key == n.key { + // Mark keys for nodes in the priority queue. + // We use NaN inequality for this check since all + // keys not in the queue must have their key set + // to badKey. + // + // This should always mark cells where key is + // printed. + fmt.Fprint(w, "*") + } + if n.g > n.rhs { + fmt.Fprint(w, "^") + } + if n.g < n.rhs { + fmt.Fprint(w, "v") + } + default: + fmt.Fprint(w, "-------------------") + } + } + fmt.Fprintln(w) + } + } + w.Flush() + fmt.Fprintln(d.w) +} + +// printEdges pretty prints the given edges to the dumper's io.Writer using the provided +// format string. The edges are first formated to a string, so the format string must use +// the %s verb to indicate where the edges are to be printed. +func (d *dumper) printEdges(format string, edges []simple.WeightedEdge) { + if d == nil { + return + } + var buf bytes.Buffer + sort.Sort(lexically(edges)) + for i, e := range edges { + if i != 0 { + fmt.Fprint(&buf, ", ") + } + fmt.Fprintf(&buf, "%d->%d:%.4v", e.From().ID(), e.To().ID(), e.Weight()) + } + if len(edges) == 0 { + fmt.Fprint(&buf, "none") + } + fmt.Fprintf(d.w, format, buf.Bytes()) +} + +type lexically []simple.WeightedEdge + +func (l lexically) Len() int { return len(l) } +func (l lexically) Less(i, j int) bool { + return l[i].From().ID() < l[j].From().ID() || (l[i].From().ID() == l[j].From().ID() && l[i].To().ID() < l[j].To().ID()) +} +func (l lexically) Swap(i, j int) { l[i], l[j] = l[j], l[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/path/floydwarshall.go b/vendor/gonum.org/v1/gonum/graph/path/floydwarshall.go new file mode 100644 index 00000000..310fec6d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/floydwarshall.go @@ -0,0 +1,59 @@ +// Copyright ©2015 The gonum 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 path + +import "gonum.org/v1/gonum/graph" + +// FloydWarshall returns a shortest-path tree for the graph g or false indicating +// that a negative cycle exists in the graph. If the graph does not implement +// graph.Weighter, UniformCost is used. +// +// The time complexity of FloydWarshall is O(|V|^3). +func FloydWarshall(g graph.Graph) (paths AllShortest, ok bool) { + var weight Weighting + if wg, ok := g.(graph.Weighted); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + paths = newAllShortest(nodes, true) + for i, u := range nodes { + paths.dist.Set(i, i, 0) + for _, v := range g.From(u) { + j := paths.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("floyd-warshall: unexpected invalid weight") + } + paths.set(i, j, w, j) + } + } + + for k := range nodes { + for i := range nodes { + for j := range nodes { + ij := paths.dist.At(i, j) + joint := paths.dist.At(i, k) + paths.dist.At(k, j) + if ij > joint { + paths.set(i, j, joint, paths.at(i, k)...) + } else if ij-joint == 0 { + paths.add(i, j, paths.at(i, k)...) + } + } + } + } + + ok = true + for i := range nodes { + if paths.dist.At(i, i) < 0 { + ok = false + break + } + } + + return paths, ok +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/floydwarshall_test.go b/vendor/gonum.org/v1/gonum/graph/path/floydwarshall_test.go new file mode 100644 index 00000000..d23c0341 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/floydwarshall_test.go @@ -0,0 +1,102 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestFloydWarshall(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + pt, ok := FloydWarshall(g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int64 + if len(paths) != 0 { + got = make([][]int64, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/internal/grid.go b/vendor/gonum.org/v1/gonum/graph/path/internal/grid.go new file mode 100644 index 00000000..4afe8fb6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/internal/grid.go @@ -0,0 +1,296 @@ +// Copyright ©2014 The gonum 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 internal + +import ( + "errors" + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +const ( + Closed = '*' // Closed is the closed grid node representation. + Open = '.' // Open is the open grid node repesentation. + Unknown = '?' // Unknown is the unknown grid node repesentation. +) + +// Grid is a 2D grid planar undirected graph. +type Grid struct { + // AllowDiagonal specifies whether + // diagonally adjacent nodes can + // be connected by an edge. + AllowDiagonal bool + // UnitEdgeWeight specifies whether + // finite edge weights are returned as + // the unit length. Otherwise edge + // weights are the Euclidean distance + // between connected nodes. + UnitEdgeWeight bool + + // AllVisible specifies whether + // non-open nodes are visible + // in calls to Nodes and HasNode. + AllVisible bool + + open []bool + r, c int +} + +// NewGrid returns an r by c grid with all positions +// set to the specified open state. +func NewGrid(r, c int, open bool) *Grid { + states := make([]bool, r*c) + if open { + for i := range states { + states[i] = true + } + } + return &Grid{ + open: states, + r: r, + c: c, + } +} + +// NewGridFrom returns a grid specified by the rows strings. All rows must +// be the same length and must only contain the Open or Closed characters, +// NewGridFrom will panic otherwise. +func NewGridFrom(rows ...string) *Grid { + if len(rows) == 0 { + return nil + } + for i, r := range rows[:len(rows)-1] { + if len(r) != len(rows[i+1]) { + panic("grid: unequal row lengths") + } + } + states := make([]bool, 0, len(rows)*len(rows[0])) + for _, r := range rows { + for _, b := range r { + switch b { + case Closed: + states = append(states, false) + case Open: + states = append(states, true) + default: + panic(fmt.Sprintf("grid: invalid state: %q", r)) + } + } + } + return &Grid{ + open: states, + r: len(rows), + c: len(rows[0]), + } +} + +// Nodes returns all the open nodes in the grid if AllVisible is +// false, otherwise all nodes are returned. +func (g *Grid) Nodes() []graph.Node { + var nodes []graph.Node + for id, ok := range g.open { + if ok || g.AllVisible { + nodes = append(nodes, simple.Node(id)) + } + } + return nodes +} + +// Has returns whether n is a node in the grid. The state of +// the AllVisible field determines whether a non-open node is +// present. +func (g *Grid) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *Grid) has(id int64) bool { + return 0 <= id && id < int64(len(g.open)) && (g.AllVisible || g.open[id]) +} + +// HasOpen returns whether n is an open node in the grid. +func (g *Grid) HasOpen(n graph.Node) bool { + id := n.ID() + return 0 <= id && id < int64(len(g.open)) && g.open[id] +} + +// Set sets the node at position (r, c) to the specified open state. +func (g *Grid) Set(r, c int, open bool) { + if r < 0 || r >= g.r { + panic("grid: illegal row index") + } + if c < 0 || c >= g.c { + panic("grid: illegal column index") + } + g.open[r*g.c+c] = open +} + +// Dims returns the dimensions of the grid. +func (g *Grid) Dims() (r, c int) { + return g.r, g.c +} + +// RowCol returns the row and column of the id. RowCol will panic if the +// node id is outside the range of the grid. +func (g *Grid) RowCol(id int64) (r, c int) { + if id < 0 || int64(len(g.open)) <= id { + panic("grid: illegal node id") + } + return int(id) / g.c, int(id) % g.c +} + +// XY returns the cartesian coordinates of n. If n is not a node +// in the grid, (NaN, NaN) is returned. +func (g *Grid) XY(n graph.Node) (x, y float64) { + if !g.Has(n) { + return math.NaN(), math.NaN() + } + r, c := g.RowCol(n.ID()) + return float64(c), float64(r) +} + +// NodeAt returns the node at (r, c). The returned node may be open or closed. +func (g *Grid) NodeAt(r, c int) graph.Node { + if r < 0 || r >= g.r || c < 0 || c >= g.c { + return nil + } + return simple.Node(r*g.c + c) +} + +// From returns all the nodes reachable from u. Reachabilty requires that both +// ends of an edge must be open. +func (g *Grid) From(u graph.Node) []graph.Node { + if !g.HasOpen(u) { + return nil + } + nr, nc := g.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + if v := g.NodeAt(r, c); v != nil && g.HasEdgeBetween(u, v) { + to = append(to, v) + } + } + } + return to +} + +// HasEdgeBetween returns whether there is an edge between u and v. +func (g *Grid) HasEdgeBetween(u, v graph.Node) bool { + if !g.HasOpen(u) || !g.HasOpen(v) || u.ID() == v.ID() { + return false + } + ur, uc := g.RowCol(u.ID()) + vr, vc := g.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + return g.AllowDiagonal || ur == vr || uc == vc +} + +func abs(i int) int { + if i < 0 { + return -i + } + return i +} + +// Edge returns the edge between u and v. +func (g *Grid) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdge returns the weighted edge between u and v. +func (g *Grid) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return g.WeightedEdgeBetween(u, v) +} + +// EdgeBetween returns the edge between u and v. +func (g *Grid) EdgeBetween(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdgeBetween returns the weighted edge between u and v. +func (g *Grid) WeightedEdgeBetween(u, v graph.Node) graph.WeightedEdge { + if g.HasEdgeBetween(u, v) { + if !g.AllowDiagonal || g.UnitEdgeWeight { + return simple.WeightedEdge{F: u, T: v, W: 1} + } + ux, uy := g.XY(u) + vx, vy := g.XY(v) + return simple.WeightedEdge{F: u, T: v, W: math.Hypot(ux-vx, uy-vy)} + } + return nil +} + +// Weight returns the weight of the given edge. +func (g *Grid) Weight(x, y graph.Node) (w float64, ok bool) { + if x.ID() == y.ID() { + return 0, true + } + if !g.HasEdgeBetween(x, y) { + return math.Inf(1), false + } + if e := g.EdgeBetween(x, y); e != nil { + if !g.AllowDiagonal || g.UnitEdgeWeight { + return 1, true + } + ux, uy := g.XY(e.From()) + vx, vy := g.XY(e.To()) + return math.Hypot(ux-vx, uy-vy), true + } + return math.Inf(1), true +} + +// String returns a string representation of the grid. +func (g *Grid) String() string { + b, _ := g.Render(nil) + return string(b) +} + +// Render returns a text representation of the graph +// with the given path included. If the path is not a path +// in the grid Render returns a non-nil error and the +// path up to that point. +func (g *Grid) Render(path []graph.Node) ([]byte, error) { + b := make([]byte, g.r*(g.c+1)-1) + for r := 0; r < g.r; r++ { + for c := 0; c < g.c; c++ { + if g.open[r*g.c+c] { + b[r*(g.c+1)+c] = Open + } else { + b[r*(g.c+1)+c] = Closed + } + } + if r < g.r-1 { + b[r*(g.c+1)+g.c] = '\n' + } + } + + // We don't use topo.IsPathIn at the outset because we + // want to draw as much as possible before failing. + for i, n := range path { + if !g.Has(n) || (i != 0 && !g.HasEdgeBetween(path[i-1], n)) { + id := n.ID() + if 0 <= id && id < int64(len(g.open)) { + r, c := g.RowCol(n.ID()) + b[r*(g.c+1)+c] = '!' + } + return b, errors.New("grid: not a path in graph") + } + r, c := g.RowCol(n.ID()) + switch i { + case len(path) - 1: + b[r*(g.c+1)+c] = 'G' + case 0: + b[r*(g.c+1)+c] = 'S' + default: + b[r*(g.c+1)+c] = 'o' + } + } + return b, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/internal/grid_test.go b/vendor/gonum.org/v1/gonum/graph/path/internal/grid_test.go new file mode 100644 index 00000000..66ff4d8f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/internal/grid_test.go @@ -0,0 +1,258 @@ +// Copyright ©2014 The gonum 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 internal + +import ( + "bytes" + "errors" + "reflect" + "strings" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +var _ graph.Graph = (*Grid)(nil) + +func join(g ...string) string { return strings.Join(g, "\n") } + +type node int64 + +func (n node) ID() int64 { return int64(n) } + +func TestGrid(t *testing.T) { + g := NewGrid(4, 4, false) + + got := g.String() + want := join( + "****", + "****", + "****", + "****", + ) + if got != want { + t.Fatalf("unexpected grid rendering:\ngot: %q\nwant:%q", got, want) + } + + var ops = []struct { + r, c int + state bool + want string + }{ + { + r: 0, c: 1, + state: true, + want: join( + "*.**", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 1, + state: false, + want: join( + "****", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 1, + state: true, + want: join( + "*.**", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 2, + state: true, + want: join( + "*..*", + "****", + "****", + "****", + ), + }, + { + r: 1, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "****", + "****", + ), + }, + { + r: 2, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "**.*", + "****", + ), + }, + { + r: 3, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "**.*", + "**.*", + ), + }, + } + for _, test := range ops { + g.Set(test.r, test.c, test.state) + got := g.String() + if got != test.want { + t.Fatalf("unexpected grid rendering after set (%d, %d) open state to %t:\ngot: %q\nwant:%q", + test.r, test.c, test.state, got, test.want) + } + } + + // Match the last state from the loop against the + // explicit description of the grid. + got = NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ).String() + want = g.String() + if got != want { + t.Fatalf("unexpected grid rendering from NewGridFrom:\ngot: %q\nwant:%q", got, want) + } + + var paths = []struct { + path []graph.Node + diagonal bool + want string + }{ + { + path: nil, + diagonal: false, + want: join( + "*..*", + "**.*", + "**.*", + "**.*", + ), + }, + { + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + diagonal: false, + want: join( + "*So*", + "**o*", + "**o*", + "**G*", + ), + }, + { + path: []graph.Node{node(1), node(6), node(10), node(14)}, + diagonal: false, + want: join( + "*S.*", + "**!*", + "**.*", + "**.*", + ), + }, + { + path: []graph.Node{node(1), node(6), node(10), node(14)}, + diagonal: true, + want: join( + "*S.*", + "**o*", + "**o*", + "**G*", + ), + }, + { + path: []graph.Node{node(1), node(5), node(9)}, + diagonal: false, + want: join( + "*S.*", + "*!.*", + "**.*", + "**.*", + ), + }, + } + for _, test := range paths { + g.AllowDiagonal = test.diagonal + got, err := g.Render(test.path) + errored := err != nil + if bytes.Contains(got, []byte{'!'}) != errored { + t.Fatalf("unexpected error return: got:%v want:%v", err, errors.New("grid: not a path in graph")) + } + if string(got) != test.want { + t.Fatalf("unexpected grid path rendering for %v:\ngot: %q\nwant:%q", test.path, got, want) + } + } + + var coords = []struct { + r, c int + id int64 + }{ + {r: 0, c: 0, id: 0}, + {r: 0, c: 3, id: 3}, + {r: 3, c: 0, id: 12}, + {r: 3, c: 3, id: 15}, + } + for _, test := range coords { + if id := g.NodeAt(test.r, test.c).ID(); id != test.id { + t.Fatalf("unexpected ID for node at (%d, %d):\ngot: %d\nwant:%d", test.r, test.c, id, test.id) + } + if r, c := g.RowCol(test.id); r != test.r || c != test.c { + t.Fatalf("unexpected row/col for node %d:\ngot: (%d, %d)\nwant:(%d, %d)", test.id, r, c, test.r, test.c) + } + } + + var reach = []struct { + from graph.Node + diagonal bool + to []graph.Node + }{ + { + from: node(0), + diagonal: false, + to: nil, + }, + { + from: node(2), + diagonal: false, + to: []graph.Node{simple.Node(1), simple.Node(6)}, + }, + { + from: node(1), + diagonal: false, + to: []graph.Node{simple.Node(2)}, + }, + { + from: node(1), + diagonal: true, + to: []graph.Node{simple.Node(2), simple.Node(6)}, + }, + } + for _, test := range reach { + g.AllowDiagonal = test.diagonal + got := g.From(test.from) + if !reflect.DeepEqual(got, test.to) { + t.Fatalf("unexpected nodes from %d with allow diagonal=%t:\ngot: %v\nwant:%v", + test.from, test.diagonal, got, test.to) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/internal/limited.go b/vendor/gonum.org/v1/gonum/graph/path/internal/limited.go new file mode 100644 index 00000000..3a2d768d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/internal/limited.go @@ -0,0 +1,316 @@ +// Copyright ©2015 The gonum 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 internal + +import ( + "errors" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// LimitedVisionGrid is a 2D grid planar undirected graph where the capacity +// to determine the presence of edges is dependent on the current and past +// positions on the grid. In the absence of information, the grid is +// optimistic. +type LimitedVisionGrid struct { + Grid *Grid + + // Location is the current + // location on the grid. + Location graph.Node + + // VisionRadius specifies how far + // away edges can be detected. + VisionRadius float64 + + // Known holds a store of known + // nodes, if not nil. + Known map[int64]bool +} + +// MoveTo moves to the node n on the grid and returns a slice of newly seen and +// already known edges. MoveTo panics if n is nil. +func (l *LimitedVisionGrid) MoveTo(n graph.Node) (new, old []graph.Edge) { + l.Location = n + row, column := l.RowCol(n.ID()) + x := float64(column) + y := float64(row) + seen := make(map[[2]int64]bool) + bound := int(l.VisionRadius + 0.5) + for r := row - bound; r <= row+bound; r++ { + for c := column - bound; c <= column+bound; c++ { + u := l.NodeAt(r, c) + if u == nil { + continue + } + ux, uy := l.XY(u) + if math.Hypot(x-ux, y-uy) > l.VisionRadius { + continue + } + for _, v := range l.allPossibleFrom(u) { + if seen[[2]int64{u.ID(), v.ID()}] { + continue + } + seen[[2]int64{u.ID(), v.ID()}] = true + + vx, vy := l.XY(v) + if !l.Known[v.ID()] && math.Hypot(x-vx, y-vy) > l.VisionRadius { + continue + } + + e := simple.Edge{F: u, T: v} + if !l.Known[u.ID()] || !l.Known[v.ID()] { + new = append(new, e) + } else { + old = append(old, e) + } + } + } + } + + if l.Known != nil { + for r := row - bound; r <= row+bound; r++ { + for c := column - bound; c <= column+bound; c++ { + u := l.NodeAt(r, c) + if u == nil { + continue + } + ux, uy := l.XY(u) + if math.Hypot(x-ux, y-uy) > l.VisionRadius { + continue + } + for _, v := range l.allPossibleFrom(u) { + vx, vy := l.XY(v) + if math.Hypot(x-vx, y-vy) > l.VisionRadius { + continue + } + l.Known[v.ID()] = true + } + l.Known[u.ID()] = true + } + } + + } + + return new, old +} + +// allPossibleFrom returns all the nodes possibly reachable from u. +func (l *LimitedVisionGrid) allPossibleFrom(u graph.Node) []graph.Node { + if !l.Has(u) { + return nil + } + nr, nc := l.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + v := l.NodeAt(r, c) + if v == nil || u.ID() == v.ID() { + continue + } + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + continue + } + if !l.Grid.AllowDiagonal && ur != vr && uc != vc { + continue + } + to = append(to, v) + } + } + return to +} + +// RowCol returns the row and column of the id. RowCol will panic if the +// node id is outside the range of the grid. +func (l *LimitedVisionGrid) RowCol(id int64) (r, c int) { + return l.Grid.RowCol(id) +} + +// XY returns the cartesian coordinates of n. If n is not a node +// in the grid, (NaN, NaN) is returned. +func (l *LimitedVisionGrid) XY(n graph.Node) (x, y float64) { + if !l.Has(n) { + return math.NaN(), math.NaN() + } + r, c := l.RowCol(n.ID()) + return float64(c), float64(r) +} + +// Nodes returns all the nodes in the grid. +func (l *LimitedVisionGrid) Nodes() []graph.Node { + nodes := make([]graph.Node, 0, len(l.Grid.open)) + for id := range l.Grid.open { + nodes = append(nodes, simple.Node(id)) + } + return nodes +} + +// NodeAt returns the node at (r, c). The returned node may be open or closed. +func (l *LimitedVisionGrid) NodeAt(r, c int) graph.Node { + return l.Grid.NodeAt(r, c) +} + +// Has returns whether n is a node in the grid. +func (l *LimitedVisionGrid) Has(n graph.Node) bool { + return l.has(n.ID()) +} + +func (l *LimitedVisionGrid) has(id int64) bool { + return 0 <= id && id < int64(len(l.Grid.open)) +} + +// From returns nodes that are optimistically reachable from u. +func (l *LimitedVisionGrid) From(u graph.Node) []graph.Node { + if !l.Has(u) { + return nil + } + + nr, nc := l.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + if v := l.NodeAt(r, c); v != nil && l.HasEdgeBetween(u, v) { + to = append(to, v) + } + } + } + return to +} + +// HasEdgeBetween optimistically returns whether an edge is exists between u and v. +func (l *LimitedVisionGrid) HasEdgeBetween(u, v graph.Node) bool { + if u.ID() == v.ID() { + return false + } + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + if !l.Grid.AllowDiagonal && ur != vr && uc != vc { + return false + } + + x, y := l.XY(l.Location) + ux, uy := l.XY(u) + vx, vy := l.XY(v) + uKnown := l.Known[u.ID()] || math.Hypot(x-ux, y-uy) <= l.VisionRadius + vKnown := l.Known[v.ID()] || math.Hypot(x-vx, y-vy) <= l.VisionRadius + + switch { + case uKnown && vKnown: + return l.Grid.HasEdgeBetween(u, v) + case uKnown: + return l.Grid.HasOpen(u) + case vKnown: + return l.Grid.HasOpen(v) + default: + return true + } +} + +// Edge optimistically returns the edge from u to v. +func (l *LimitedVisionGrid) Edge(u, v graph.Node) graph.Edge { + return l.WeightedEdgeBetween(u, v) +} + +// Edge optimistically returns the weighted edge from u to v. +func (l *LimitedVisionGrid) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return l.WeightedEdgeBetween(u, v) +} + +// WeightedEdgeBetween optimistically returns the edge between u and v. +func (l *LimitedVisionGrid) EdgeBetween(u, v graph.Node) graph.Edge { + return l.WeightedEdgeBetween(u, v) +} + +// WeightedEdgeBetween optimistically returns the weighted edge between u and v. +func (l *LimitedVisionGrid) WeightedEdgeBetween(u, v graph.Node) graph.WeightedEdge { + if l.HasEdgeBetween(u, v) { + if !l.Grid.AllowDiagonal || l.Grid.UnitEdgeWeight { + return simple.WeightedEdge{F: u, T: v, W: 1} + } + ux, uy := l.XY(u) + vx, vy := l.XY(v) + return simple.WeightedEdge{F: u, T: v, W: math.Hypot(ux-vx, uy-vy)} + } + return nil +} + +// Weight returns the weight of the given edge. +func (l *LimitedVisionGrid) Weight(x, y graph.Node) (w float64, ok bool) { + if x.ID() == y.ID() { + return 0, true + } + if !l.HasEdgeBetween(x, y) { + return math.Inf(1), false + } + if e := l.EdgeBetween(x, y); e != nil { + if !l.Grid.AllowDiagonal || l.Grid.UnitEdgeWeight { + return 1, true + } + ux, uy := l.XY(e.From()) + vx, vy := l.XY(e.To()) + return math.Hypot(ux-vx, uy-vy), true + + } + return math.Inf(1), true +} + +// String returns a string representation of the grid. +func (l *LimitedVisionGrid) String() string { + b, _ := l.Render(nil) + return string(b) +} + +// Render returns a text representation of the graph +// with the given path included. If the path is not a path +// in the grid Render returns a non-nil error and the +// path up to that point. +func (l *LimitedVisionGrid) Render(path []graph.Node) ([]byte, error) { + rows, cols := l.Grid.Dims() + b := make([]byte, rows*(cols+1)-1) + for r := 0; r < rows; r++ { + for c := 0; c < cols; c++ { + if !l.Known[int64(r*cols+c)] { + b[r*(cols+1)+c] = Unknown + } else if l.Grid.open[r*cols+c] { + b[r*(cols+1)+c] = Open + } else { + b[r*(cols+1)+c] = Closed + } + } + if r < rows-1 { + b[r*(cols+1)+cols] = '\n' + } + } + + // We don't use topo.IsPathIn at the outset because we + // want to draw as much as possible before failing. + for i, n := range path { + if !l.Has(n) || (i != 0 && !l.HasEdgeBetween(path[i-1], n)) { + id := n.ID() + if 0 <= id && id < int64(len(l.Grid.open)) { + r, c := l.RowCol(n.ID()) + b[r*(cols+1)+c] = '!' + } + return b, errors.New("grid: not a path in graph") + } + r, c := l.RowCol(n.ID()) + switch i { + case len(path) - 1: + b[r*(cols+1)+c] = 'G' + case 0: + b[r*(cols+1)+c] = 'S' + default: + b[r*(cols+1)+c] = 'o' + } + } + return b, nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/internal/limited_test.go b/vendor/gonum.org/v1/gonum/graph/path/internal/limited_test.go new file mode 100644 index 00000000..018dd778 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/internal/limited_test.go @@ -0,0 +1,1242 @@ +// Copyright ©2015 The gonum 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 internal + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type changes struct { + n graph.Node + + new, old []simple.WeightedEdge +} + +var limitedVisionTests = []struct { + g *Grid + radius float64 + diag bool + remember bool + + path []graph.Node + + want []changes +}{ + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: false, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: false, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: false, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + }, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: false, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: nil, + old: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: true, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: true, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: true, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: []simple.WeightedEdge{ + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: true, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.WeightedEdge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.WeightedEdge{ + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: nil, + old: []simple.WeightedEdge{ + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + }, + }, + }, +} + +func TestLimitedVisionGrid(t *testing.T) { + for i, test := range limitedVisionTests { + l := &LimitedVisionGrid{ + Grid: test.g, + VisionRadius: test.radius, + Location: test.path[0], + } + if test.remember { + l.Known = make(map[int64]bool) + } + l.Grid.AllowDiagonal = test.diag + + x, y := l.XY(test.path[0]) + for _, u := range l.Nodes() { + ux, uy := l.XY(u) + uNear := math.Hypot(x-ux, y-uy) <= test.radius + for _, v := range l.Nodes() { + vx, vy := l.XY(v) + vNear := math.Hypot(x-vx, y-vy) <= test.radius + if u.ID() == v.ID() && l.HasEdgeBetween(u, v) { + t.Errorf("unexpected self edge: %v -- %v", u, v) + } + if !uNear && !vNear && !l.HasEdgeBetween(u, v) && couldConnectIn(l, u, v) { + t.Errorf("unexpected pessimism: no hope in distant edge between %v and %v for test %d", + u, v, i) + } + if (uNear && vNear) && l.HasEdgeBetween(u, v) != l.Grid.HasEdgeBetween(u, v) { + t.Errorf("unrealistic optimism: disagreement about edge between %v and %v for test %d: got:%t want:%t", + u, v, i, l.HasEdgeBetween(u, v), l.Grid.HasEdgeBetween(u, v)) + } + } + } + + var got []changes + for _, n := range test.path { + new, old := l.MoveTo(n) + got = append(got, changes{n: n, new: asConcreteEdges(new, l), old: asConcreteEdges(old, l)}) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected walk for test %d:\ngot: %+v\nwant:%+v", i, got, test.want) + } + } +} + +func asConcreteEdges(changes []graph.Edge, in graph.Weighted) []simple.WeightedEdge { + if changes == nil { + return nil + } + we := make([]simple.WeightedEdge, len(changes)) + for i, e := range changes { + we[i].F = e.From() + we[i].T = e.To() + w, ok := in.Weight(e.From(), e.To()) + if !ok && !math.IsInf(w, 1) { + panic("unexpected invalid finite weight") + } + we[i].W = w + } + return we +} + +func couldConnectIn(l *LimitedVisionGrid, u, v graph.Node) bool { + if u.ID() == v.ID() { + return false + } + + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + if (ur != vr || uc != vc) && !l.Grid.AllowDiagonal { + return false + } + + if !l.Known[u.ID()] && !l.Known[v.ID()] { + return true + } + if l.Known[u.ID()] && !l.Grid.HasOpen(u) { + return false + } + if l.Known[v.ID()] && !l.Grid.HasOpen(v) { + return false + } + + return true +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/internal/testgraphs/shortest.go b/vendor/gonum.org/v1/gonum/graph/path/internal/testgraphs/shortest.go new file mode 100644 index 00000000..3a9c6bc8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/internal/testgraphs/shortest.go @@ -0,0 +1,654 @@ +// Copyright ©2014 The gonum 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 testgraphs + +import ( + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +func init() { + for _, test := range ShortestPathTests { + if len(test.WantPaths) != 1 && test.HasUniquePath { + panic(fmt.Sprintf("%q: bad shortest path test: non-unique paths marked unique", test.Name)) + } + } +} + +// ShortestPathTests are graphs used to test the static shortest path routines in path: BellmanFord, +// DijkstraAllPaths, DijkstraFrom, FloydWarshall and Johnson, and the static degenerate case for the +// dynamic shortest path routine in path/dynamic: DStarLite. +var ShortestPathTests = []struct { + Name string + Graph func() graph.WeightedEdgeAdder + Edges []simple.WeightedEdge + HasNegativeWeight bool + HasNegativeCycle bool + + Query simple.Edge + Weight float64 + WantPaths [][]int64 + HasUniquePath bool + + NoPathFor simple.Edge +}{ + // Positive weighted graphs. + { + Name: "empty directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: math.Inf(1), + + NoPathFor: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "empty undirected", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: math.Inf(1), + + NoPathFor: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "one edge directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: 1, + WantPaths: [][]int64{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge self directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(0)}, + Weight: 0, + WantPaths: [][]int64{ + {0}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge undirected", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: 1, + WantPaths: [][]int64{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "two paths directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(2), W: 2}, + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(2)}, + Weight: 2, + WantPaths: [][]int64{ + {0, 1, 2}, + {0, 2}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(1)}, + }, + { + Name: "two paths undirected", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(2), W: 2}, + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(2)}, + Weight: 2, + WantPaths: [][]int64{ + {0, 1, 2}, + {0, 2}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(4)}, + }, + { + Name: "confounding paths directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add direct edge to goal of weight 4 + {F: simple.Node(0), T: simple.Node(5), W: 4}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "confounding paths undirected", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add direct edge to goal of weight 4 + {F: simple.Node(0), T: simple.Node(5), W: 4}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(5), T: simple.Node(6)}, + }, + { + Name: "confounding paths directed 2-step", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add two step path to goal of weight 4 + {F: simple.Node(0), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(5), W: 2}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 6, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "confounding paths undirected 2-step", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add two step path to goal of weight 4 + {F: simple.Node(0), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(5), W: 2}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 6, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(5), T: simple.Node(7)}, + }, + { + Name: "zero-weight cycle directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^2 directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^2 confounding directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + // But leading to the target. + {F: simple.Node(5), T: simple.Node(4), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + {0, 1, 5, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^3 directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(6), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(6), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight 3·cycle^2 confounding directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With 3 of its own zero-weight cycles. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(5), W: 0}, + // Each leading to the target. + {F: simple.Node(5), T: simple.Node(4), W: 3}, + {F: simple.Node(6), T: simple.Node(4), W: 3}, + {F: simple.Node(7), T: simple.Node(4), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + {0, 1, 5, 4}, + {0, 1, 5, 6, 4}, + {0, 1, 5, 7, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight reversed 3·cycle^2 confounding directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(3), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(3), W: 0}, + // With 3 of its own zero-weight cycles. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(5), W: 0}, + // Each leading from the source. + {F: simple.Node(0), T: simple.Node(5), W: 3}, + {F: simple.Node(0), T: simple.Node(6), W: 3}, + {F: simple.Node(0), T: simple.Node(7), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + {0, 5, 3, 4}, + {0, 6, 5, 3, 4}, + {0, 7, 5, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight |V|·cycle^(n/|V|) directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.WeightedEdge { + e := []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + next := len(e) + 1 + + // Add n zero-weight cycles. + const n = 100 + for i := 0; i < n; i++ { + e = append(e, + simple.WeightedEdge{F: simple.Node(next + i), T: simple.Node(i), W: 0}, + simple.WeightedEdge{F: simple.Node(i), T: simple.Node(next + i), W: 0}, + ) + } + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight n·cycle directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.WeightedEdge { + e := []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + next := len(e) + 1 + + // Add n zero-weight cycles. + const n = 100 + for i := 0; i < n; i++ { + e = append(e, + simple.WeightedEdge{F: simple.Node(next + i), T: simple.Node(1), W: 0}, + simple.WeightedEdge{F: simple.Node(1), T: simple.Node(next + i), W: 0}, + ) + } + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight bi-directional tree with single exit directed", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.WeightedEdge { + e := []simple.WeightedEdge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + + // Make a bi-directional tree rooted at node 2 with + // a single exit to node 4 and co-equal cost from + // 2 to 4. + const ( + depth = 4 + branching = 4 + ) + + next := len(e) + 1 + src := 2 + var i, last int + for l := 0; l < depth; l++ { + for i = 0; i < branching; i++ { + last = next + i + e = append(e, simple.WeightedEdge{F: simple.Node(src), T: simple.Node(last), W: 0}) + e = append(e, simple.WeightedEdge{F: simple.Node(last), T: simple.Node(src), W: 0}) + } + src = next + 1 + next += branching + } + e = append(e, simple.WeightedEdge{F: simple.Node(last), T: simple.Node(4), W: 2}) + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int64{ + {0, 1, 2, 3, 4}, + {0, 1, 2, 6, 10, 14, 20, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + + // Negative weighted graphs. + { + Name: "one edge directed negative", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: -1}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: -1, + WantPaths: [][]int64{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge undirected negative", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: -1}, + }, + HasNegativeWeight: true, + HasNegativeCycle: true, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "wp graph negative", // http://en.wikipedia.org/w/index.php?title=Johnson%27s_algorithm&oldid=564595231 + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node('w'), T: simple.Node('z'), W: 2}, + {F: simple.Node('x'), T: simple.Node('w'), W: 6}, + {F: simple.Node('x'), T: simple.Node('y'), W: 3}, + {F: simple.Node('y'), T: simple.Node('w'), W: 4}, + {F: simple.Node('y'), T: simple.Node('z'), W: 5}, + {F: simple.Node('z'), T: simple.Node('x'), W: -7}, + {F: simple.Node('z'), T: simple.Node('y'), W: -3}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node('z'), T: simple.Node('y')}, + Weight: -4, + WantPaths: [][]int64{ + {'z', 'x', 'y'}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "roughgarden negative", + Graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.WeightedEdge{ + {F: simple.Node('a'), T: simple.Node('b'), W: -2}, + {F: simple.Node('b'), T: simple.Node('c'), W: -1}, + {F: simple.Node('c'), T: simple.Node('a'), W: 4}, + {F: simple.Node('c'), T: simple.Node('x'), W: 2}, + {F: simple.Node('c'), T: simple.Node('y'), W: -3}, + {F: simple.Node('z'), T: simple.Node('x'), W: 1}, + {F: simple.Node('z'), T: simple.Node('y'), W: -4}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node('a'), T: simple.Node('y')}, + Weight: -6, + WantPaths: [][]int64{ + {'a', 'b', 'c', 'y'}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp.go b/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp.go new file mode 100644 index 00000000..444564f1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp.go @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// JohnsonAllPaths returns a shortest-path tree for shortest paths in the graph g. +// If the graph does not implement graph.Weighter, UniformCost is used. +// +// The time complexity of JohnsonAllPaths is O(|V|.|E|+|V|^2.log|V|). +func JohnsonAllPaths(g graph.Graph) (paths AllShortest, ok bool) { + jg := johnsonWeightAdjuster{ + g: g, + from: g.From, + edgeTo: g.Edge, + } + if wg, ok := g.(graph.Weighted); ok { + jg.weight = wg.Weight + } else { + jg.weight = UniformCost(g) + } + + paths = newAllShortest(g.Nodes(), false) + + sign := int64(-1) + for { + // Choose a random node ID until we find + // one that is not in g. + jg.q = sign * rand.Int63() + if _, exists := paths.indexOf[jg.q]; !exists { + break + } + sign *= -1 + } + + jg.bellmanFord = true + jg.adjustBy, ok = BellmanFordFrom(johnsonGraphNode(jg.q), jg) + if !ok { + return paths, false + } + + jg.bellmanFord = false + dijkstraAllPaths(jg, paths) + + for i, u := range paths.nodes { + hu := jg.adjustBy.WeightTo(u) + for j, v := range paths.nodes { + if i == j { + continue + } + hv := jg.adjustBy.WeightTo(v) + paths.dist.Set(i, j, paths.dist.At(i, j)-hu+hv) + } + } + + return paths, ok +} + +type johnsonWeightAdjuster struct { + q int64 + g graph.Graph + + from func(graph.Node) []graph.Node + edgeTo func(graph.Node, graph.Node) graph.Edge + weight Weighting + + bellmanFord bool + adjustBy Shortest +} + +var ( + // johnsonWeightAdjuster has the behaviour + // of a directed graph, but we don't need + // to be explicit with the type since it + // is not exported. + _ graph.Graph = johnsonWeightAdjuster{} + _ graph.Weighted = johnsonWeightAdjuster{} +) + +func (g johnsonWeightAdjuster) Has(n graph.Node) bool { + if g.bellmanFord && n.ID() == g.q { + return true + } + return g.g.Has(n) + +} + +func (g johnsonWeightAdjuster) Nodes() []graph.Node { + if g.bellmanFord { + return append(g.g.Nodes(), johnsonGraphNode(g.q)) + } + return g.g.Nodes() +} + +func (g johnsonWeightAdjuster) From(n graph.Node) []graph.Node { + if g.bellmanFord && n.ID() == g.q { + return g.g.Nodes() + } + return g.from(n) +} + +func (g johnsonWeightAdjuster) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + panic("path: unintended use of johnsonWeightAdjuster") +} + +func (g johnsonWeightAdjuster) Edge(u, v graph.Node) graph.Edge { + if g.bellmanFord && u.ID() == g.q && g.g.Has(v) { + return simple.Edge{F: johnsonGraphNode(g.q), T: v} + } + return g.edgeTo(u, v) +} + +func (g johnsonWeightAdjuster) Weight(x, y graph.Node) (w float64, ok bool) { + if g.bellmanFord { + switch g.q { + case x.ID(): + return 0, true + case y.ID(): + return math.Inf(1), false + default: + return g.weight(x, y) + } + } + w, ok = g.weight(x, y) + return w + g.adjustBy.WeightTo(x) - g.adjustBy.WeightTo(y), ok +} + +func (johnsonWeightAdjuster) HasEdgeBetween(_, _ graph.Node) bool { + panic("path: unintended use of johnsonWeightAdjuster") +} + +type johnsonGraphNode int64 + +func (n johnsonGraphNode) ID() int64 { return int64(n) } diff --git a/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp_test.go b/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp_test.go new file mode 100644 index 00000000..1635ce92 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/johnson_apsp_test.go @@ -0,0 +1,102 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestJohnsonAllPaths(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetWeightedEdge(e) + } + + pt, ok := JohnsonAllPaths(g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int64 + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int64 + if len(paths) != 0 { + got = make([][]int64, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/shortest.go b/vendor/gonum.org/v1/gonum/graph/path/shortest.go new file mode 100644 index 00000000..a21a7d4f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/shortest.go @@ -0,0 +1,319 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/mat" +) + +// Shortest is a shortest-path tree created by the BellmanFordFrom or DijkstraFrom +// single-source shortest path functions. +type Shortest struct { + // from holds the source node given to + // DijkstraFrom. + from graph.Node + + // nodes hold the nodes of the analysed + // graph. + nodes []graph.Node + // indexOf contains a mapping between + // the id-dense representation of the + // graph and the potentially id-sparse + // nodes held in nodes. + indexOf map[int64]int + + // dist and next represent the shortest + // paths between nodes. + // + // Indices into dist and next are + // mapped through indexOf. + // + // dist contains the distances + // from the from node for each + // node in the graph. + dist []float64 + // next contains the shortest-path + // tree of the graph. The index is a + // linear mapping of to-dense-id. + next []int +} + +func newShortestFrom(u graph.Node, nodes []graph.Node) Shortest { + indexOf := make(map[int64]int, len(nodes)) + uid := u.ID() + for i, n := range nodes { + indexOf[n.ID()] = i + if n.ID() == uid { + u = n + } + } + + p := Shortest{ + from: u, + + nodes: nodes, + indexOf: indexOf, + + dist: make([]float64, len(nodes)), + next: make([]int, len(nodes)), + } + for i := range nodes { + p.dist[i] = math.Inf(1) + p.next[i] = -1 + } + p.dist[indexOf[uid]] = 0 + + return p +} + +func (p Shortest) set(to int, weight float64, mid int) { + p.dist[to] = weight + p.next[to] = mid +} + +// From returns the starting node of the paths held by the Shortest. +func (p Shortest) From() graph.Node { return p.from } + +// WeightTo returns the weight of the minimum path to v. +func (p Shortest) WeightTo(v graph.Node) float64 { + to, toOK := p.indexOf[v.ID()] + if !toOK { + return math.Inf(1) + } + return p.dist[to] +} + +// To returns a shortest path to v and the weight of the path. +func (p Shortest) To(v graph.Node) (path []graph.Node, weight float64) { + to, toOK := p.indexOf[v.ID()] + if !toOK || math.IsInf(p.dist[to], 1) { + return nil, math.Inf(1) + } + from := p.indexOf[p.from.ID()] + path = []graph.Node{p.nodes[to]} + for to != from { + path = append(path, p.nodes[p.next[to]]) + to = p.next[to] + } + reverse(path) + return path, p.dist[p.indexOf[v.ID()]] +} + +// AllShortest is a shortest-path tree created by the DijkstraAllPaths, FloydWarshall +// or JohnsonAllPaths all-pairs shortest paths functions. +type AllShortest struct { + // nodes hold the nodes of the analysed + // graph. + nodes []graph.Node + // indexOf contains a mapping between + // the id-dense representation of the + // graph and the potentially id-sparse + // nodes held in nodes. + indexOf map[int64]int + + // dist, next and forward represent + // the shortest paths between nodes. + // + // Indices into dist and next are + // mapped through indexOf. + // + // dist contains the pairwise + // distances between nodes. + dist *mat.Dense + // next contains the shortest-path + // tree of the graph. The first index + // is a linear mapping of from-dense-id + // and to-dense-id, to-major with a + // stride equal to len(nodes); the + // slice indexed to is the list of + // intermediates leading from the 'from' + // node to the 'to' node represented + // by dense id. + // The interpretation of next is + // dependent on the state of forward. + next [][]int + // forward indicates the direction of + // path reconstruction. Forward + // reconstruction is used for Floyd- + // Warshall and reverse is used for + // Dijkstra. + forward bool +} + +func newAllShortest(nodes []graph.Node, forward bool) AllShortest { + indexOf := make(map[int64]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + dist := make([]float64, len(nodes)*len(nodes)) + for i := range dist { + dist[i] = math.Inf(1) + } + return AllShortest{ + nodes: nodes, + indexOf: indexOf, + + dist: mat.NewDense(len(nodes), len(nodes), dist), + next: make([][]int, len(nodes)*len(nodes)), + forward: forward, + } +} + +func (p AllShortest) at(from, to int) (mid []int) { + return p.next[from+to*len(p.nodes)] +} + +func (p AllShortest) set(from, to int, weight float64, mid ...int) { + p.dist.Set(from, to, weight) + p.next[from+to*len(p.nodes)] = append(p.next[from+to*len(p.nodes)][:0], mid...) +} + +func (p AllShortest) add(from, to int, mid ...int) { +loop: // These are likely to be rare, so just loop over collisions. + for _, k := range mid { + for _, v := range p.next[from+to*len(p.nodes)] { + if k == v { + continue loop + } + } + p.next[from+to*len(p.nodes)] = append(p.next[from+to*len(p.nodes)], k) + } +} + +// Weight returns the weight of the minimum path between u and v. +func (p AllShortest) Weight(u, v graph.Node) float64 { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK { + return math.Inf(1) + } + return p.dist.At(from, to) +} + +// Between returns a shortest path from u to v and the weight of the path. If more than +// one shortest path exists between u and v, a randomly chosen path will be returned and +// unique is returned false. If a cycle with zero weight exists in the path, it will not +// be included, but unique will be returned false. +func (p AllShortest) Between(u, v graph.Node) (path []graph.Node, weight float64, unique bool) { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK || len(p.at(from, to)) == 0 { + if u.ID() == v.ID() { + return []graph.Node{p.nodes[from]}, 0, true + } + return nil, math.Inf(1), false + } + + seen := make([]int, len(p.nodes)) + for i := range seen { + seen[i] = -1 + } + var n graph.Node + if p.forward { + n = p.nodes[from] + seen[from] = 0 + } else { + n = p.nodes[to] + seen[to] = 0 + } + + path = []graph.Node{n} + weight = p.dist.At(from, to) + unique = true + + var next int + for from != to { + c := p.at(from, to) + if len(c) != 1 { + unique = false + next = c[rand.Intn(len(c))] + } else { + next = c[0] + } + if seen[next] >= 0 { + path = path[:seen[next]] + } + seen[next] = len(path) + path = append(path, p.nodes[next]) + if p.forward { + from = next + } else { + to = next + } + } + if !p.forward { + reverse(path) + } + + return path, weight, unique +} + +// AllBetween returns all shortest paths from u to v and the weight of the paths. Paths +// containing zero-weight cycles are not returned. +func (p AllShortest) AllBetween(u, v graph.Node) (paths [][]graph.Node, weight float64) { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK || len(p.at(from, to)) == 0 { + if u.ID() == v.ID() { + return [][]graph.Node{{p.nodes[from]}}, 0 + } + return nil, math.Inf(1) + } + + var n graph.Node + if p.forward { + n = u + } else { + n = v + } + seen := make([]bool, len(p.nodes)) + paths = p.allBetween(from, to, seen, []graph.Node{n}, nil) + + return paths, p.dist.At(from, to) +} + +func (p AllShortest) allBetween(from, to int, seen []bool, path []graph.Node, paths [][]graph.Node) [][]graph.Node { + if p.forward { + seen[from] = true + } else { + seen[to] = true + } + if from == to { + if path == nil { + return paths + } + if !p.forward { + reverse(path) + } + return append(paths, path) + } + first := true + for _, n := range p.at(from, to) { + if seen[n] { + continue + } + if first { + path = append([]graph.Node(nil), path...) + first = false + } + if p.forward { + from = n + } else { + to = n + } + paths = p.allBetween(from, to, append([]bool(nil), seen...), append(path, p.nodes[n]), paths) + } + return paths +} + +func reverse(p []graph.Node) { + for i, j := 0, len(p)-1; i < j; i, j = i+1, j-1 { + p[i], p[j] = p[j], p[i] + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/spanning_tree.go b/vendor/gonum.org/v1/gonum/graph/path/spanning_tree.go new file mode 100644 index 00000000..a21a3e83 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/spanning_tree.go @@ -0,0 +1,187 @@ +// Copyright ©2014 The gonum 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 path + +import ( + "container/heap" + "math" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// WeightedBuilder is a type that can add nodes and weighted edges. +type WeightedBuilder interface { + AddNode(graph.Node) + SetWeightedEdge(graph.WeightedEdge) +} + +// Prim generates a minimum spanning tree of g by greedy tree extension, placing +// the result in the destination, dst. If the edge weights of g are distinct +// it will be the unique minimum spanning tree of g. The destination is not cleared +// first. The weight of the minimum spanning tree is returned. If g is not connected, +// a minimum spanning forest will be constructed in dst and the sum of minimum +// spanning tree weights will be returned. +// +// Nodes and Edges from g are used to construct dst, so if the Node and Edge +// types used in g are pointer or reference-like, then the values will be shared +// between the graphs. +// +// If dst has nodes that exist in g, Prim will panic. +func Prim(dst WeightedBuilder, g graph.WeightedUndirected) float64 { + nodes := g.Nodes() + if len(nodes) == 0 { + return 0 + } + + q := &primQueue{ + indexOf: make(map[int64]int, len(nodes)-1), + nodes: make([]simple.WeightedEdge, 0, len(nodes)-1), + } + dst.AddNode(nodes[0]) + for _, u := range nodes[1:] { + dst.AddNode(u) + heap.Push(q, simple.WeightedEdge{F: u, W: math.Inf(1)}) + } + + u := nodes[0] + for _, v := range g.From(u) { + w, ok := g.Weight(u, v) + if !ok { + panic("prim: unexpected invalid weight") + } + q.update(v, u, w) + } + + var w float64 + for q.Len() > 0 { + e := heap.Pop(q).(simple.WeightedEdge) + if e.To() != nil && g.HasEdgeBetween(e.From(), e.To()) { + dst.SetWeightedEdge(g.WeightedEdge(e.From(), e.To())) + w += e.Weight() + } + + u = e.From() + for _, n := range g.From(u) { + if key, ok := q.key(n); ok { + w, ok := g.Weight(u, n) + if !ok { + panic("prim: unexpected invalid weight") + } + if w < key { + q.update(n, u, w) + } + } + } + } + return w +} + +// primQueue is a Prim's priority queue. The priority queue is a +// queue of edge From nodes keyed on the minimum edge weight to +// a node in the set of nodes already connected to the minimum +// spanning forest. +type primQueue struct { + indexOf map[int64]int + nodes []simple.WeightedEdge +} + +func (q *primQueue) Less(i, j int) bool { + return q.nodes[i].Weight() < q.nodes[j].Weight() +} + +func (q *primQueue) Swap(i, j int) { + q.indexOf[q.nodes[i].From().ID()] = j + q.indexOf[q.nodes[j].From().ID()] = i + q.nodes[i], q.nodes[j] = q.nodes[j], q.nodes[i] +} + +func (q *primQueue) Len() int { + return len(q.nodes) +} + +func (q *primQueue) Push(x interface{}) { + n := x.(simple.WeightedEdge) + q.indexOf[n.From().ID()] = len(q.nodes) + q.nodes = append(q.nodes, n) +} + +func (q *primQueue) Pop() interface{} { + n := q.nodes[len(q.nodes)-1] + q.nodes = q.nodes[:len(q.nodes)-1] + delete(q.indexOf, n.From().ID()) + return n +} + +// key returns the key for the node u and whether the node is +// in the queue. If the node is not in the queue, key is returned +// as +Inf. +func (q *primQueue) key(u graph.Node) (key float64, ok bool) { + i, ok := q.indexOf[u.ID()] + if !ok { + return math.Inf(1), false + } + return q.nodes[i].Weight(), ok +} + +// update updates u's position in the queue with the new closest +// MST-connected neighbour, v, and the key weight between u and v. +func (q *primQueue) update(u, v graph.Node, key float64) { + id := u.ID() + i, ok := q.indexOf[id] + if !ok { + return + } + q.nodes[i].T = v + q.nodes[i].W = key + heap.Fix(q, i) +} + +// UndirectedWeightLister is an undirected graph that returns edge weights and +// the set of edges in the graph. +type UndirectedWeightLister interface { + graph.WeightedUndirected + WeightedEdges() []graph.WeightedEdge +} + +// Kruskal generates a minimum spanning tree of g by greedy tree coalescence, placing +// the result in the destination, dst. If the edge weights of g are distinct +// it will be the unique minimum spanning tree of g. The destination is not cleared +// first. The weight of the minimum spanning tree is returned. If g is not connected, +// a minimum spanning forest will be constructed in dst and the sum of minimum +// spanning tree weights will be returned. +// +// Nodes and Edges from g are used to construct dst, so if the Node and Edge +// types used in g are pointer or reference-like, then the values will be shared +// between the graphs. +// +// If dst has nodes that exist in g, Kruskal will panic. +func Kruskal(dst WeightedBuilder, g UndirectedWeightLister) float64 { + edges := g.WeightedEdges() + sort.Sort(byWeight(edges)) + + ds := newDisjointSet() + for _, node := range g.Nodes() { + dst.AddNode(node) + ds.makeSet(node.ID()) + } + + var w float64 + for _, e := range edges { + if s1, s2 := ds.find(e.From().ID()), ds.find(e.To().ID()); s1 != s2 { + ds.union(s1, s2) + dst.SetWeightedEdge(g.WeightedEdge(e.From(), e.To())) + w += e.Weight() + } + } + return w +} + +type byWeight []graph.WeightedEdge + +func (e byWeight) Len() int { return len(e) } +func (e byWeight) Less(i, j int) bool { return e[i].Weight() < e[j].Weight() } +func (e byWeight) Swap(i, j int) { e[i], e[j] = e[j], e[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/path/spanning_tree_test.go b/vendor/gonum.org/v1/gonum/graph/path/spanning_tree_test.go new file mode 100644 index 00000000..e6515335 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/spanning_tree_test.go @@ -0,0 +1,294 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +func init() { + for _, test := range spanningTreeTests { + var w float64 + for _, e := range test.treeEdges { + w += e.W + } + if w != test.want { + panic(fmt.Sprintf("bad test: %s weight mismatch: %v != %v", test.name, w, test.want)) + } + } +} + +type spanningGraph interface { + graph.WeightedBuilder + graph.WeightedUndirected + WeightedEdges() []graph.WeightedEdge +} + +var spanningTreeTests = []struct { + name string + graph func() spanningGraph + edges []simple.WeightedEdge + want float64 + treeEdges []simple.WeightedEdge +}{ + { + name: "Empty", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + want: 0, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/f/f7/Prim%27s_algorithm.svg + // Modified to make edge weights unique; A--B is increased to 2.5 otherwise + // to prevent the alternative solution being found. + name: "Prim WP figure 1", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 2.5}, + {F: simple.Node('A'), T: simple.Node('D'), W: 1}, + {F: simple.Node('B'), T: simple.Node('D'), W: 2}, + {F: simple.Node('C'), T: simple.Node('D'), W: 3}, + }, + + want: 6, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('D'), W: 1}, + {F: simple.Node('B'), T: simple.Node('D'), W: 2}, + {F: simple.Node('C'), T: simple.Node('D'), W: 3}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/5/5c/MST_kruskal_en.gif + name: "Kruskal WP figure 1", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node('a'), T: simple.Node('b'), W: 3}, + {F: simple.Node('a'), T: simple.Node('e'), W: 1}, + {F: simple.Node('b'), T: simple.Node('c'), W: 5}, + {F: simple.Node('b'), T: simple.Node('e'), W: 4}, + {F: simple.Node('c'), T: simple.Node('d'), W: 2}, + {F: simple.Node('c'), T: simple.Node('e'), W: 6}, + {F: simple.Node('d'), T: simple.Node('e'), W: 7}, + }, + + want: 11, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node('a'), T: simple.Node('b'), W: 3}, + {F: simple.Node('a'), T: simple.Node('e'), W: 1}, + {F: simple.Node('b'), T: simple.Node('c'), W: 5}, + {F: simple.Node('c'), T: simple.Node('d'), W: 2}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/8/87/Kruskal_Algorithm_6.svg + name: "Kruskal WP example", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 7}, + {F: simple.Node('A'), T: simple.Node('D'), W: 5}, + {F: simple.Node('B'), T: simple.Node('C'), W: 8}, + {F: simple.Node('B'), T: simple.Node('D'), W: 9}, + {F: simple.Node('B'), T: simple.Node('E'), W: 7}, + {F: simple.Node('C'), T: simple.Node('E'), W: 5}, + {F: simple.Node('D'), T: simple.Node('E'), W: 15}, + {F: simple.Node('D'), T: simple.Node('F'), W: 6}, + {F: simple.Node('E'), T: simple.Node('F'), W: 8}, + {F: simple.Node('E'), T: simple.Node('G'), W: 9}, + {F: simple.Node('F'), T: simple.Node('G'), W: 11}, + }, + + want: 39, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 7}, + {F: simple.Node('A'), T: simple.Node('D'), W: 5}, + {F: simple.Node('B'), T: simple.Node('E'), W: 7}, + {F: simple.Node('C'), T: simple.Node('E'), W: 5}, + {F: simple.Node('D'), T: simple.Node('F'), W: 6}, + {F: simple.Node('E'), T: simple.Node('G'), W: 9}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/2/2e/Boruvka%27s_algorithm_%28Sollin%27s_algorithm%29_Anim.gif + name: "Borůvka WP example", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 13}, + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('C'), T: simple.Node('D'), W: 14}, + {F: simple.Node('C'), T: simple.Node('E'), W: 8}, + {F: simple.Node('C'), T: simple.Node('H'), W: 20}, + {F: simple.Node('D'), T: simple.Node('E'), W: 9}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('E'), T: simple.Node('J'), W: 18}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('J'), W: 19}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('H'), T: simple.Node('J'), W: 17}, + {F: simple.Node('I'), T: simple.Node('K'), W: 11}, + {F: simple.Node('J'), T: simple.Node('K'), W: 16}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + + want: 83, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('E'), T: simple.Node('J'), W: 18}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/d/d2/Minimum_spanning_tree.svg + // Nodes labelled row major. + name: "Minimum Spanning Tree WP figure 1", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 4}, + {F: simple.Node(1), T: simple.Node(3), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: 4}, + {F: simple.Node(2), T: simple.Node(3), W: 5}, + {F: simple.Node(2), T: simple.Node(5), W: 9}, + {F: simple.Node(2), T: simple.Node(6), W: 9}, + {F: simple.Node(2), T: simple.Node(8), W: 7}, + {F: simple.Node(3), T: simple.Node(4), W: 3}, + {F: simple.Node(3), T: simple.Node(8), W: 9}, + {F: simple.Node(4), T: simple.Node(8), W: 10}, + {F: simple.Node(4), T: simple.Node(10), W: 18}, + {F: simple.Node(5), T: simple.Node(6), W: 2}, + {F: simple.Node(5), T: simple.Node(7), W: 4}, + {F: simple.Node(5), T: simple.Node(9), W: 6}, + {F: simple.Node(6), T: simple.Node(7), W: 2}, + {F: simple.Node(6), T: simple.Node(8), W: 8}, + {F: simple.Node(7), T: simple.Node(8), W: 9}, + {F: simple.Node(7), T: simple.Node(9), W: 3}, + {F: simple.Node(7), T: simple.Node(10), W: 9}, + {F: simple.Node(8), T: simple.Node(10), W: 8}, + {F: simple.Node(9), T: simple.Node(10), W: 9}, + }, + + want: 38, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node(1), T: simple.Node(2), W: 4}, + {F: simple.Node(1), T: simple.Node(3), W: 1}, + {F: simple.Node(2), T: simple.Node(8), W: 7}, + {F: simple.Node(3), T: simple.Node(4), W: 3}, + {F: simple.Node(5), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(7), W: 2}, + {F: simple.Node(6), T: simple.Node(8), W: 8}, + {F: simple.Node(7), T: simple.Node(9), W: 3}, + {F: simple.Node(8), T: simple.Node(10), W: 8}, + }, + }, + + { + // https://upload.wikimedia.org/wikipedia/commons/2/2e/Boruvka%27s_algorithm_%28Sollin%27s_algorithm%29_Anim.gif + // but with C--H and E--J cut. + name: "Borůvka WP example cut", + graph: func() spanningGraph { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 13}, + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('C'), T: simple.Node('D'), W: 14}, + {F: simple.Node('C'), T: simple.Node('E'), W: 8}, + {F: simple.Node('D'), T: simple.Node('E'), W: 9}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('J'), W: 19}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('H'), T: simple.Node('J'), W: 17}, + {F: simple.Node('I'), T: simple.Node('K'), W: 11}, + {F: simple.Node('J'), T: simple.Node('K'), W: 16}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + + want: 65, + treeEdges: []simple.WeightedEdge{ + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + }, +} + +func testMinumumSpanning(mst func(dst WeightedBuilder, g spanningGraph) float64, t *testing.T) { + for _, test := range spanningTreeTests { + g := test.graph() + for _, e := range test.edges { + g.SetWeightedEdge(e) + } + + dst := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) + w := mst(dst, g) + if w != test.want { + t.Errorf("unexpected minimum spanning tree weight for %q: got: %f want: %f", + test.name, w, test.want) + } + var got float64 + for _, e := range dst.WeightedEdges() { + got += e.Weight() + } + if got != test.want { + t.Errorf("unexpected minimum spanning tree edge weight sum for %q: got: %f want: %f", + test.name, got, test.want) + } + + gotEdges := dst.Edges() + if len(gotEdges) != len(test.treeEdges) { + t.Errorf("unexpected number of spanning tree edges for %q: got: %d want: %d", + test.name, len(gotEdges), len(test.treeEdges)) + } + for _, e := range test.treeEdges { + w, ok := dst.Weight(e.From(), e.To()) + if !ok { + t.Errorf("spanning tree edge not found in graph for %q: %+v", + test.name, e) + } + if w != e.Weight() { + t.Errorf("unexpected spanning tree edge weight for %q: got: %f want: %f", + test.name, w, e.Weight()) + } + } + } +} + +func TestKruskal(t *testing.T) { + testMinumumSpanning(func(dst WeightedBuilder, g spanningGraph) float64 { + return Kruskal(dst, g) + }, t) +} + +func TestPrim(t *testing.T) { + testMinumumSpanning(func(dst WeightedBuilder, g spanningGraph) float64 { + return Prim(dst, g) + }, t) +} diff --git a/vendor/gonum.org/v1/gonum/graph/path/weight.go b/vendor/gonum.org/v1/gonum/graph/path/weight.go new file mode 100644 index 00000000..91b9d321 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/path/weight.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum 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 path + +import ( + "math" + + "gonum.org/v1/gonum/graph" +) + +// Weighting is a mapping between a pair of nodes and a weight. It follows the +// semantics of the Weighter interface. +type Weighting func(x, y graph.Node) (w float64, ok bool) + +// UniformCost returns a Weighting that returns an edge cost of 1 for existing +// edges, zero for node identity and Inf for otherwise absent edges. +func UniformCost(g graph.Graph) Weighting { + return func(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return 0, true + } + if e := g.Edge(x, y); e != nil { + return 1, true + } + return math.Inf(1), false + } +} + +// Heuristic returns an estimate of the cost of travelling between two nodes. +type Heuristic func(x, y graph.Node) float64 + +// HeuristicCoster wraps the HeuristicCost method. A graph implementing the +// interface provides a heuristic between any two given nodes. +type HeuristicCoster interface { + HeuristicCost(x, y graph.Node) float64 +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go b/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go new file mode 100644 index 00000000..b6db362d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go @@ -0,0 +1,300 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/mat" +) + +// DirectedMatrix represents a directed graph using an adjacency +// matrix such that all IDs are in a contiguous block from 0 to n-1. +// Edges are stored implicitly as an edge weight, so edges stored in +// the graph are not recoverable. +type DirectedMatrix struct { + mat *mat.Dense + nodes []graph.Node + + self float64 + absent float64 +} + +// NewDirectedMatrix creates a directed dense graph with n nodes. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewDirectedMatrix(n int, init, self, absent float64) *DirectedMatrix { + matrix := make([]float64, n*n) + if init != 0 { + for i := range matrix { + matrix[i] = init + } + } + for i := 0; i < len(matrix); i += n + 1 { + matrix[i] = self + } + return &DirectedMatrix{ + mat: mat.NewDense(n, n, matrix), + self: self, + absent: absent, + } +} + +// NewDirectedMatrixFrom creates a directed dense graph with the given nodes. +// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may +// be in any order. If IDs are not contiguous NewDirectedMatrixFrom will panic. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewDirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *DirectedMatrix { + sort.Sort(ordered.ByID(nodes)) + for i, n := range nodes { + if int64(i) != n.ID() { + panic("simple: non-contiguous node IDs") + } + } + g := NewDirectedMatrix(len(nodes), init, self, absent) + g.nodes = nodes + return g +} + +// Node returns the node in the graph with the given ID. +func (g *DirectedMatrix) Node(id int64) graph.Node { + if !g.has(id) { + return nil + } + if g.nodes == nil { + return Node(id) + } + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *DirectedMatrix) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *DirectedMatrix) has(id int64) bool { + r, _ := g.mat.Dims() + return 0 <= id && id < int64(r) +} + +// Nodes returns all the nodes in the graph. +func (g *DirectedMatrix) Nodes() []graph.Node { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return nodes + } + r, _ := g.mat.Dims() + nodes := make([]graph.Node, r) + for i := 0; i < r; i++ { + nodes[i] = Node(i) + } + return nodes +} + +// Edges returns all the edges in the graph. +func (g *DirectedMatrix) Edges() []graph.Edge { + var edges []graph.Edge + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + for j := 0; j < r; j++ { + if i == j { + continue + } + if w := g.mat.At(i, j); !isSame(w, g.absent) { + edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w}) + } + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *DirectedMatrix) From(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + _, c := g.mat.Dims() + for j := 0; j < c; j++ { + if int64(j) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(int(id), j), g.absent) { + neighbors = append(neighbors, g.Node(int64(j))) + } + } + return neighbors +} + +// To returns all nodes in g that can reach directly to n. +func (g *DirectedMatrix) To(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + if int64(i) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(i, int(id)), g.absent) { + neighbors = append(neighbors, g.Node(int64(i))) + } + } + return neighbors +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *DirectedMatrix) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + if !g.has(xid) { + return false + } + yid := y.ID() + if !g.has(yid) { + return false + } + // xid and yid are not greater than maximum int by this point. + return xid != yid && (!isSame(g.mat.At(int(xid), int(yid)), g.absent) || !isSame(g.mat.At(int(yid), int(xid)), g.absent)) +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *DirectedMatrix) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdge(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *DirectedMatrix) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + if g.HasEdgeFromTo(u, v) { + // x.ID() and y.ID() are not greater than maximum int by this point. + return WeightedEdge{F: g.Node(u.ID()), T: g.Node(v.ID()), W: g.mat.At(int(u.ID()), int(v.ID()))} + } + return nil +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *DirectedMatrix) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + if !g.has(uid) { + return false + } + vid := v.ID() + if !g.has(vid) { + return false + } + // uid and vid are not greater than maximum int by this point. + return uid != vid && !isSame(g.mat.At(int(uid), int(vid)), g.absent) +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *DirectedMatrix) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if g.has(xid) && g.has(yid) { + // xid and yid are not greater than maximum int by this point. + return g.mat.At(int(xid), int(yid)), true + } + return g.absent, false +} + +// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge +// are not in g or the edge is a self loop, SetEdge panics. +func (g *DirectedMatrix) SetEdge(e graph.Edge) { + g.setWeightedEdge(e, 1) +} + +// SetWeightedEdge sets e, an edge from one node to another. If the ends of the edge are not in g +// or the edge is a self loop, SetWeightedEdge panics. +func (g *DirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { + g.setWeightedEdge(e, e.Weight()) +} + +func (g *DirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { + fid := e.From().ID() + tid := e.To().ID() + if fid == tid { + panic("simple: set illegal edge") + } + if int64(int(fid)) != fid { + panic("simple: unavailable from node ID for dense graph") + } + if int64(int(tid)) != tid { + panic("simple: unavailable to node ID for dense graph") + } + // fid and tid are not greater than maximum int by this point. + g.mat.Set(int(fid), int(tid), weight) +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *DirectedMatrix) RemoveEdge(e graph.Edge) { + fid := e.From().ID() + if !g.has(fid) { + return + } + tid := e.To().ID() + if !g.has(tid) { + return + } + // fid and tid are not greater than maximum int by this point. + g.mat.Set(int(fid), int(tid), g.absent) +} + +// Degree returns the in+out degree of n in g. +func (g *DirectedMatrix) Degree(n graph.Node) int { + id := n.ID() + if !g.has(id) { + return 0 + } + var deg int + r, c := g.mat.Dims() + for i := 0; i < r; i++ { + if int64(i) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(int(id), i), g.absent) { + deg++ + } + } + for i := 0; i < c; i++ { + if int64(i) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(i, int(id)), g.absent) { + deg++ + } + } + return deg +} + +// Matrix returns the mat.Matrix representation of the graph. The orientation +// of the matrix is such that the matrix entry at G_{ij} is the weight of the edge +// from node i to node j. +func (g *DirectedMatrix) Matrix() mat.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go b/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go new file mode 100644 index 00000000..da4cb4f3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go @@ -0,0 +1,261 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/mat" +) + +// UndirectedMatrix represents an undirected graph using an adjacency +// matrix such that all IDs are in a contiguous block from 0 to n-1. +// Edges are stored implicitly as an edge weight, so edges stored in +// the graph are not recoverable. +type UndirectedMatrix struct { + mat *mat.SymDense + nodes []graph.Node + + self float64 + absent float64 +} + +// NewUndirectedMatrix creates an undirected dense graph with n nodes. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewUndirectedMatrix(n int, init, self, absent float64) *UndirectedMatrix { + matrix := make([]float64, n*n) + if init != 0 { + for i := range matrix { + matrix[i] = init + } + } + for i := 0; i < len(matrix); i += n + 1 { + matrix[i] = self + } + return &UndirectedMatrix{ + mat: mat.NewSymDense(n, matrix), + self: self, + absent: absent, + } +} + +// NewUndirectedMatrixFrom creates an undirected dense graph with the given nodes. +// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may +// be in any order. If IDs are not contiguous NewUndirectedMatrixFrom will panic. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewUndirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *UndirectedMatrix { + sort.Sort(ordered.ByID(nodes)) + for i, n := range nodes { + if int64(i) != n.ID() { + panic("simple: non-contiguous node IDs") + } + } + g := NewUndirectedMatrix(len(nodes), init, self, absent) + g.nodes = nodes + return g +} + +// Node returns the node in the graph with the given ID. +func (g *UndirectedMatrix) Node(id int64) graph.Node { + if !g.has(id) { + return nil + } + if g.nodes == nil { + return Node(id) + } + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *UndirectedMatrix) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *UndirectedMatrix) has(id int64) bool { + r := g.mat.Symmetric() + return 0 <= id && id < int64(r) +} + +// Nodes returns all the nodes in the graph. +func (g *UndirectedMatrix) Nodes() []graph.Node { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return nodes + } + r := g.mat.Symmetric() + nodes := make([]graph.Node, r) + for i := 0; i < r; i++ { + nodes[i] = Node(i) + } + return nodes +} + +// Edges returns all the edges in the graph. +func (g *UndirectedMatrix) Edges() []graph.Edge { + var edges []graph.Edge + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + for j := i + 1; j < r; j++ { + if w := g.mat.At(i, j); !isSame(w, g.absent) { + edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w}) + } + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *UndirectedMatrix) From(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + r := g.mat.Symmetric() + for i := 0; i < r; i++ { + if int64(i) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(int(id), i), g.absent) { + neighbors = append(neighbors, g.Node(int64(i))) + } + } + return neighbors +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *UndirectedMatrix) HasEdgeBetween(u, v graph.Node) bool { + uid := u.ID() + if !g.has(uid) { + return false + } + vid := v.ID() + if !g.has(vid) { + return false + } + // uid and vid are not greater than maximum int by this point. + return uid != vid && !isSame(g.mat.At(int(uid), int(vid)), g.absent) +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *UndirectedMatrix) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *UndirectedMatrix) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return g.WeightedEdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedMatrix) EdgeBetween(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g *UndirectedMatrix) WeightedEdgeBetween(u, v graph.Node) graph.WeightedEdge { + if g.HasEdgeBetween(u, v) { + // u.ID() and v.ID() are not greater than maximum int by this point. + return WeightedEdge{F: g.Node(u.ID()), T: g.Node(v.ID()), W: g.mat.At(int(u.ID()), int(v.ID()))} + } + return nil +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *UndirectedMatrix) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if g.has(xid) && g.has(yid) { + // xid and yid are not greater than maximum int by this point. + return g.mat.At(int(xid), int(yid)), true + } + return g.absent, false +} + +// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge are +// not in g or the edge is a self loop, SetEdge panics. +func (g *UndirectedMatrix) SetEdge(e graph.Edge) { + g.setWeightedEdge(e, 1) +} + +// SetWeightedEdge sets e, an edge from one node to another. If the ends of the edge are not in g +// or the edge is a self loop, SetWeightedEdge panics. +func (g *UndirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { + g.setWeightedEdge(e, e.Weight()) +} + +func (g *UndirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { + fid := e.From().ID() + tid := e.To().ID() + if fid == tid { + panic("simple: set illegal edge") + } + if int64(int(fid)) != fid { + panic("simple: unavailable from node ID for dense graph") + } + if int64(int(tid)) != tid { + panic("simple: unavailable to node ID for dense graph") + } + // fid and tid are not greater than maximum int by this point. + g.mat.SetSym(int(fid), int(tid), weight) +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *UndirectedMatrix) RemoveEdge(e graph.Edge) { + fid := e.From().ID() + if !g.has(fid) { + return + } + tid := e.To().ID() + if !g.has(tid) { + return + } + // fid and tid are not greater than maximum int by this point. + g.mat.SetSym(int(fid), int(tid), g.absent) +} + +// Degree returns the degree of n in g. +func (g *UndirectedMatrix) Degree(n graph.Node) int { + id := n.ID() + if !g.has(id) { + return 0 + } + var deg int + r := g.mat.Symmetric() + for i := 0; i < r; i++ { + if int64(i) == id { + continue + } + // id is not greater than maximum int by this point. + if !isSame(g.mat.At(int(id), i), g.absent) { + deg++ + } + } + return deg +} + +// Matrix returns the mat.Matrix representation of the graph. +func (g *UndirectedMatrix) Matrix() mat.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/densegraph_test.go b/vendor/gonum.org/v1/gonum/graph/simple/densegraph_test.go new file mode 100644 index 00000000..5a68c219 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/densegraph_test.go @@ -0,0 +1,149 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +var ( + directedMatrix = (*DirectedMatrix)(nil) + + _ graph.Graph = directedMatrix + _ graph.Directed = directedMatrix + _ graph.WeightedDirected = directedMatrix + + undirectedMatrix = (*UndirectedMatrix)(nil) + + _ graph.Graph = undirectedMatrix + _ graph.Undirected = undirectedMatrix + _ graph.WeightedUndirected = undirectedMatrix +) + +func TestBasicDenseImpassable(t *testing.T) { + dg := NewUndirectedMatrix(5, math.Inf(1), 0, math.Inf(1)) + if dg == nil { + t.Fatal("Directed graph could not be made") + } + + for i := 0; i < 5; i++ { + if !dg.Has(Node(i)) { + t.Errorf("Node that should exist doesn't: %d", i) + } + + if degree := dg.Degree(Node(i)); degree != 0 { + t.Errorf("Node in impassable graph has a neighbor. Node: %d Degree: %d", i, degree) + } + } + + for i := 5; i < 10; i++ { + if dg.Has(Node(i)) { + t.Errorf("Node exists that shouldn't: %d", i) + } + } +} + +func TestBasicDensePassable(t *testing.T) { + dg := NewUndirectedMatrix(5, 1, 0, math.Inf(1)) + if dg == nil { + t.Fatal("Directed graph could not be made") + } + + for i := 0; i < 5; i++ { + if !dg.Has(Node(i)) { + t.Errorf("Node that should exist doesn't: %d", i) + } + + if degree := dg.Degree(Node(i)); degree != 4 { + t.Errorf("Node in passable graph missing neighbors. Node: %d Degree: %d", i, degree) + } + } + + for i := 5; i < 10; i++ { + if dg.Has(Node(i)) { + t.Errorf("Node exists that shouldn't: %d", i) + } + } +} + +func TestDirectedDenseAddRemove(t *testing.T) { + dg := NewDirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) + dg.SetWeightedEdge(WeightedEdge{F: Node(0), T: Node(2), W: 1}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 || + dg.Edge(Node(0), Node(2)) == nil { + t.Errorf("Adding edge didn't create successor") + } + + dg.RemoveEdge(Edge{F: Node(0), T: Node(2)}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 0 || dg.Edge(Node(0), Node(2)) != nil { + t.Errorf("Removing edge didn't properly remove successor") + } + + if neighbors := dg.To(Node(2)); len(neighbors) != 0 || dg.Edge(Node(0), Node(2)) != nil { + t.Errorf("Removing directed edge wrongly kept predecessor") + } + + dg.SetWeightedEdge(WeightedEdge{F: Node(0), T: Node(2), W: 2}) + // I figure we've torture tested From/To at this point + // so we'll just use the bool functions now + if dg.Edge(Node(0), Node(2)) == nil { + t.Fatal("Adding directed edge didn't change successor back") + } + c1, _ := dg.Weight(Node(2), Node(0)) + c2, _ := dg.Weight(Node(0), Node(2)) + if c1 == c2 { + t.Error("Adding directed edge affected cost in undirected manner") + } +} + +func TestUndirectedDenseAddRemove(t *testing.T) { + dg := NewUndirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) + dg.SetEdge(Edge{F: Node(0), T: Node(2)}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 || + dg.EdgeBetween(Node(0), Node(2)) == nil { + t.Errorf("Couldn't add neighbor") + } + + if neighbors := dg.From(Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 || + dg.EdgeBetween(Node(2), Node(0)) == nil { + t.Errorf("Adding an undirected neighbor didn't add it reciprocally") + } +} + +func TestDenseLists(t *testing.T) { + dg := NewDirectedMatrix(15, 1, 0, math.Inf(1)) + nodes := dg.Nodes() + + if len(nodes) != 15 { + t.Fatalf("Wrong number of nodes") + } + + sort.Sort(ordered.ByID(nodes)) + + for i, node := range dg.Nodes() { + if int64(i) != node.ID() { + t.Errorf("Node list doesn't return properly id'd nodes") + } + } + + edges := dg.Edges() + if len(edges) != 15*14 { + t.Errorf("Improper number of edges for passable dense graph") + } + + dg.RemoveEdge(Edge{F: Node(12), T: Node(11)}) + edges = dg.Edges() + if len(edges) != (15*14)-1 { + t.Errorf("Removing edge didn't affect edge listing properly") + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/directed.go b/vendor/gonum.org/v1/gonum/graph/simple/directed.go new file mode 100644 index 00000000..0796cb13 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/directed.go @@ -0,0 +1,245 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" +) + +// DirectedGraph implements a generalized directed graph. +type DirectedGraph struct { + nodes map[int64]graph.Node + from map[int64]map[int64]graph.Edge + to map[int64]map[int64]graph.Edge + + nodeIDs idSet +} + +// NewDirectedGraph returns a DirectedGraph with the specified self and absent +// edge weight values. +func NewDirectedGraph() *DirectedGraph { + return &DirectedGraph{ + nodes: make(map[int64]graph.Node), + from: make(map[int64]map[int64]graph.Edge), + to: make(map[int64]map[int64]graph.Edge), + + nodeIDs: newIDSet(), + } +} + +// NewNode returns a new unique Node to be added to g. The Node's ID does +// not become valid in g until the Node is added to g. +func (g *DirectedGraph) NewNode() graph.Node { + if len(g.nodes) == 0 { + return Node(0) + } + if int64(len(g.nodes)) == maxInt { + panic("simple: cannot allocate node: no slot") + } + return Node(g.nodeIDs.newID()) +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *DirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.from[n.ID()] = make(map[int64]graph.Edge) + g.to[n.ID()] = make(map[int64]graph.Edge) + g.nodeIDs.use(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *DirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.from[n.ID()] { + delete(g.to[from], n.ID()) + } + delete(g.from, n.ID()) + + for to := range g.to[n.ID()] { + delete(g.from[to], n.ID()) + } + delete(g.to, n.ID()) + + g.nodeIDs.release(n.ID()) +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *DirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &Edge{F: from, T: to} +} + +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *DirectedGraph) SetEdge(e graph.Edge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.from[fid][tid] = e + g.to[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *DirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.from[from.ID()], to.ID()) + delete(g.to[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *DirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *DirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *DirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.from)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *DirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *DirectedGraph) From(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + from := make([]graph.Node, len(g.from[n.ID()])) + i := 0 + for id := range g.from[n.ID()] { + from[i] = g.nodes[id] + i++ + } + + return from +} + +// To returns all nodes in g that can reach directly to n. +func (g *DirectedGraph) To(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + to := make([]graph.Node, len(g.to[n.ID()])) + i := 0 + for id := range g.to[n.ID()] { + to[i] = g.nodes[id] + i++ + } + + return to +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *DirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if _, ok := g.nodes[xid]; !ok { + return false + } + if _, ok := g.nodes[yid]; !ok { + return false + } + if _, ok := g.from[xid][yid]; ok { + return true + } + _, ok := g.from[yid][xid] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *DirectedGraph) Edge(u, v graph.Node) graph.Edge { + if _, ok := g.nodes[u.ID()]; !ok { + return nil + } + if _, ok := g.nodes[v.ID()]; !ok { + return nil + } + edge, ok := g.from[u.ID()][v.ID()] + if !ok { + return nil + } + return edge +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *DirectedGraph) HasEdgeFromTo(u, v graph.Node) bool { + if _, ok := g.nodes[u.ID()]; !ok { + return false + } + if _, ok := g.nodes[v.ID()]; !ok { + return false + } + if _, ok := g.from[u.ID()][v.ID()]; !ok { + return false + } + return true +} + +// Degree returns the in+out degree of n in g. +func (g *DirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.from[n.ID()]) + len(g.to[n.ID()]) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/directed_test.go b/vendor/gonum.org/v1/gonum/graph/simple/directed_test.go new file mode 100644 index 00000000..b66845bd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/directed_test.go @@ -0,0 +1,65 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "testing" + + "gonum.org/v1/gonum/graph" +) + +var ( + directedGraph = (*DirectedGraph)(nil) + + _ graph.Graph = directedGraph + _ graph.Directed = directedGraph +) + +// Tests Issue #27 +func TestEdgeOvercounting(t *testing.T) { + g := generateDummyGraph() + + if neigh := g.From(Node(Node(2))); len(neigh) != 2 { + t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh)) + } +} + +func generateDummyGraph() *DirectedGraph { + nodes := [4]struct{ srcID, targetID int }{ + {2, 1}, + {1, 0}, + {2, 0}, + {0, 2}, + } + + g := NewDirectedGraph() + + for _, n := range nodes { + g.SetEdge(Edge{F: Node(n.srcID), T: Node(n.targetID)}) + } + + return g +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123DirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewDirectedGraph() + + n0 := g.NewNode() + g.AddNode(n0) + + n1 := g.NewNode() + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := g.NewNode() + g.AddNode(n2) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/doc.go b/vendor/gonum.org/v1/gonum/graph/simple/doc.go new file mode 100644 index 00000000..1b688a95 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 simple provides a suite of simple graph implementations satisfying +// the gonum/graph interfaces. +package simple // import "gonum.org/v1/gonum/graph/simple" diff --git a/vendor/gonum.org/v1/gonum/graph/simple/simple.go b/vendor/gonum.org/v1/gonum/graph/simple/simple.go new file mode 100644 index 00000000..13c1618a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/simple.go @@ -0,0 +1,99 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// Node is a simple graph node. +type Node int64 + +// ID returns the ID number of the node. +func (n Node) ID() int64 { + return int64(n) +} + +// Edge is a simple graph edge. +type Edge struct { + F, T graph.Node +} + +// From returns the from-node of the edge. +func (e Edge) From() graph.Node { return e.F } + +// To returns the to-node of the edge. +func (e Edge) To() graph.Node { return e.T } + +// WeightedEdge is a simple weighted graph edge. +type WeightedEdge struct { + F, T graph.Node + W float64 +} + +// From returns the from-node of the edge. +func (e WeightedEdge) From() graph.Node { return e.F } + +// To returns the to-node of the edge. +func (e WeightedEdge) To() graph.Node { return e.T } + +// Weight returns the weight of the edge. +func (e WeightedEdge) Weight() float64 { return e.W } + +// isSame returns whether two float64 values are the same where NaN values +// are equalable. +func isSame(a, b float64) bool { + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} + +// maxInt is the maximum value of int64. +const maxInt = int64(^uint64(0) >> 1) + +// idSet implements available ID storage. +type idSet struct { + maxID int64 + used, free set.Int64s +} + +// newIDSet returns a new idSet. The returned value should not be passed +// except by pointer. +func newIDSet() idSet { + return idSet{maxID: -1, used: make(set.Int64s), free: make(set.Int64s)} +} + +// newID returns a new unique ID. The ID returned is not considered used +// until passed in a call to use. +func (s *idSet) newID() int64 { + for id := range s.free { + return id + } + if s.maxID != maxInt { + return s.maxID + 1 + } + for id := int64(0); id <= s.maxID+1; id++ { + if !s.used.Has(id) { + return id + } + } + panic("unreachable") +} + +// use adds the id to the used IDs in the idSet. +func (s *idSet) use(id int64) { + s.used.Add(id) + s.free.Remove(id) + if id > s.maxID { + s.maxID = id + } +} + +// free frees the id for reuse. +func (s *idSet) release(id int64) { + s.free.Add(id) + s.used.Remove(id) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/undirected.go b/vendor/gonum.org/v1/gonum/graph/simple/undirected.go new file mode 100644 index 00000000..7254e4a0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/undirected.go @@ -0,0 +1,205 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" +) + +// UndirectedGraph implements a generalized undirected graph. +type UndirectedGraph struct { + nodes map[int64]graph.Node + edges map[int64]map[int64]graph.Edge + + nodeIDs idSet +} + +// NewUndirectedGraph returns an UndirectedGraph with the specified self and absent +// edge weight values. +func NewUndirectedGraph() *UndirectedGraph { + return &UndirectedGraph{ + nodes: make(map[int64]graph.Node), + edges: make(map[int64]map[int64]graph.Edge), + + nodeIDs: newIDSet(), + } +} + +// NewNode returns a new unique Node to be added to g. The Node's ID does +// not become valid in g until the Node is added to g. +func (g *UndirectedGraph) NewNode() graph.Node { + if len(g.nodes) == 0 { + return Node(0) + } + if int64(len(g.nodes)) == maxInt { + panic("simple: cannot allocate node: no slot") + } + return Node(g.nodeIDs.newID()) +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *UndirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.edges[n.ID()] = make(map[int64]graph.Edge) + g.nodeIDs.use(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *UndirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.edges[n.ID()] { + delete(g.edges[from], n.ID()) + } + delete(g.edges, n.ID()) + + g.nodeIDs.release(n.ID()) +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &Edge{F: from, T: to} +} + +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *UndirectedGraph) SetEdge(e graph.Edge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.edges[fid][tid] = e + g.edges[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *UndirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.edges[from.ID()], to.ID()) + delete(g.edges[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *UndirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *UndirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *UndirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *UndirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *UndirectedGraph) From(n graph.Node) []graph.Node { + if !g.Has(n) { + return nil + } + + nodes := make([]graph.Node, len(g.edges[n.ID()])) + i := 0 + for from := range g.edges[n.ID()] { + nodes[i] = g.nodes[from] + i++ + } + + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *UndirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + _, ok := g.edges[x.ID()][y.ID()] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *UndirectedGraph) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge { + // We don't need to check if neigh exists because + // it's implicit in the edges access. + if !g.Has(x) { + return nil + } + + return g.edges[x.ID()][y.ID()] +} + +// Degree returns the degree of n in g. +func (g *UndirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.edges[n.ID()]) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/undirected_test.go b/vendor/gonum.org/v1/gonum/graph/simple/undirected_test.go new file mode 100644 index 00000000..f5c0dafc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/undirected_test.go @@ -0,0 +1,67 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "testing" + + "gonum.org/v1/gonum/graph" +) + +var ( + undirectedGraph = (*UndirectedGraph)(nil) + + _ graph.Graph = undirectedGraph + _ graph.Undirected = undirectedGraph +) + +func TestAssertMutableNotDirected(t *testing.T) { + var g graph.UndirectedBuilder = NewUndirectedGraph() + if _, ok := g.(graph.Directed); ok { + t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!") + } +} + +func TestMaxID(t *testing.T) { + g := NewUndirectedGraph() + nodes := make(map[graph.Node]struct{}) + for i := Node(0); i < 3; i++ { + g.AddNode(i) + nodes[i] = struct{}{} + } + g.RemoveNode(Node(0)) + delete(nodes, Node(0)) + g.RemoveNode(Node(2)) + delete(nodes, Node(2)) + n := g.NewNode() + g.AddNode(n) + if !g.Has(n) { + t.Error("added node does not exist in graph") + } + if _, exists := nodes[n]; exists { + t.Errorf("Created already existing node id: %v", n.ID()) + } +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123UndirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewUndirectedGraph() + + n0 := g.NewNode() + g.AddNode(n0) + + n1 := g.NewNode() + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := g.NewNode() + g.AddNode(n2) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go new file mode 100644 index 00000000..fbe3ae80 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go @@ -0,0 +1,285 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" +) + +// WeightedDirectedGraph implements a generalized weighted directed graph. +type WeightedDirectedGraph struct { + nodes map[int64]graph.Node + from map[int64]map[int64]graph.WeightedEdge + to map[int64]map[int64]graph.WeightedEdge + + self, absent float64 + + nodeIDs idSet +} + +// NewWeightedDirectedGraph returns a WeightedDirectedGraph with the specified self and absent +// edge weight values. +func NewWeightedDirectedGraph(self, absent float64) *WeightedDirectedGraph { + return &WeightedDirectedGraph{ + nodes: make(map[int64]graph.Node), + from: make(map[int64]map[int64]graph.WeightedEdge), + to: make(map[int64]map[int64]graph.WeightedEdge), + + self: self, + absent: absent, + + nodeIDs: newIDSet(), + } +} + +// NewNode returns a new unique Node to be added to g. The Node's ID does +// not become valid in g until the Node is added to g. +func (g *WeightedDirectedGraph) NewNode() graph.Node { + if len(g.nodes) == 0 { + return Node(0) + } + if int64(len(g.nodes)) == maxInt { + panic("simple: cannot allocate node: no slot") + } + return Node(g.nodeIDs.newID()) +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *WeightedDirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.from[n.ID()] = make(map[int64]graph.WeightedEdge) + g.to[n.ID()] = make(map[int64]graph.WeightedEdge) + g.nodeIDs.use(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *WeightedDirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.from[n.ID()] { + delete(g.to[from], n.ID()) + } + delete(g.from, n.ID()) + + for to := range g.to[n.ID()] { + delete(g.from[to], n.ID()) + } + delete(g.to, n.ID()) + + g.nodeIDs.release(n.ID()) +} + +// NewWeightedEdge returns a new weighted edge from the source to the destination node. +func (g *WeightedDirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { + return &WeightedEdge{F: from, T: to, W: weight} +} + +// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *WeightedDirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.from[fid][tid] = e + g.to[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *WeightedDirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.from[from.ID()], to.ID()) + delete(g.to[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *WeightedDirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *WeightedDirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *WeightedDirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.from)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *WeightedDirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + return edges +} + +// WeightedEdges returns all the weighted edges in the graph. +func (g *WeightedDirectedGraph) WeightedEdges() []graph.WeightedEdge { + var edges []graph.WeightedEdge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *WeightedDirectedGraph) From(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + from := make([]graph.Node, len(g.from[n.ID()])) + i := 0 + for id := range g.from[n.ID()] { + from[i] = g.nodes[id] + i++ + } + + return from +} + +// To returns all nodes in g that can reach directly to n. +func (g *WeightedDirectedGraph) To(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + to := make([]graph.Node, len(g.to[n.ID()])) + i := 0 + for id := range g.to[n.ID()] { + to[i] = g.nodes[id] + i++ + } + + return to +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *WeightedDirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if _, ok := g.nodes[xid]; !ok { + return false + } + if _, ok := g.nodes[yid]; !ok { + return false + } + if _, ok := g.from[xid][yid]; ok { + return true + } + _, ok := g.from[yid][xid] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *WeightedDirectedGraph) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdge(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *WeightedDirectedGraph) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + if _, ok := g.nodes[u.ID()]; !ok { + return nil + } + if _, ok := g.nodes[v.ID()]; !ok { + return nil + } + edge, ok := g.from[u.ID()][v.ID()] + if !ok { + return nil + } + return edge +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *WeightedDirectedGraph) HasEdgeFromTo(u, v graph.Node) bool { + if _, ok := g.nodes[u.ID()]; !ok { + return false + } + if _, ok := g.nodes[v.ID()]; !ok { + return false + } + if _, ok := g.from[u.ID()][v.ID()]; !ok { + return false + } + return true +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *WeightedDirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if to, ok := g.from[xid]; ok { + if e, ok := to[yid]; ok { + return e.Weight(), true + } + } + return g.absent, false +} + +// Degree returns the in+out degree of n in g. +func (g *WeightedDirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.from[n.ID()]) + len(g.to[n.ID()]) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed_test.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed_test.go new file mode 100644 index 00000000..714b067d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed_test.go @@ -0,0 +1,67 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" +) + +var ( + weightedDirectedGraph = (*WeightedDirectedGraph)(nil) + + _ graph.Graph = weightedDirectedGraph + _ graph.Directed = weightedDirectedGraph + _ graph.WeightedDirected = weightedDirectedGraph +) + +// Tests Issue #27 +func TestWeightedEdgeOvercounting(t *testing.T) { + g := generateDummyGraph() + + if neigh := g.From(Node(Node(2))); len(neigh) != 2 { + t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh)) + } +} + +func generateDummyWeightedGraph() *WeightedDirectedGraph { + nodes := [4]struct{ srcID, targetID int }{ + {2, 1}, + {1, 0}, + {2, 0}, + {0, 2}, + } + + g := NewWeightedDirectedGraph(0, math.Inf(1)) + + for _, n := range nodes { + g.SetWeightedEdge(WeightedEdge{F: Node(n.srcID), T: Node(n.targetID), W: 1}) + } + + return g +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123WeightedDirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewWeightedDirectedGraph(0, math.Inf(1)) + + n0 := g.NewNode() + g.AddNode(n0) + + n1 := g.NewNode() + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := g.NewNode() + g.AddNode(n2) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go new file mode 100644 index 00000000..9ec4cd61 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go @@ -0,0 +1,260 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" +) + +// WeightedUndirectedGraph implements a generalized weighted undirected graph. +type WeightedUndirectedGraph struct { + nodes map[int64]graph.Node + edges map[int64]map[int64]graph.WeightedEdge + + self, absent float64 + + nodeIDs idSet +} + +// NewWeightedUndirectedGraph returns an WeightedUndirectedGraph with the specified self and absent +// edge weight values. +func NewWeightedUndirectedGraph(self, absent float64) *WeightedUndirectedGraph { + return &WeightedUndirectedGraph{ + nodes: make(map[int64]graph.Node), + edges: make(map[int64]map[int64]graph.WeightedEdge), + + self: self, + absent: absent, + + nodeIDs: newIDSet(), + } +} + +// NewNode returns a new unique Node to be added to g. The Node's ID does +// not become valid in g until the Node is added to g. +func (g *WeightedUndirectedGraph) NewNode() graph.Node { + if len(g.nodes) == 0 { + return Node(0) + } + if int64(len(g.nodes)) == maxInt { + panic("simple: cannot allocate node: no slot") + } + return Node(g.nodeIDs.newID()) +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *WeightedUndirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.edges[n.ID()] = make(map[int64]graph.WeightedEdge) + g.nodeIDs.use(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *WeightedUndirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.edges[n.ID()] { + delete(g.edges[from], n.ID()) + } + delete(g.edges, n.ID()) + + g.nodeIDs.release(n.ID()) +} + +// NewWeightedEdge returns a new weighted edge from the source to the destination node. +func (g *WeightedUndirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { + return &WeightedEdge{F: from, T: to, W: weight} +} + +// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *WeightedUndirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.edges[fid][tid] = e + g.edges[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *WeightedUndirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.edges[from.ID()], to.ID()) + delete(g.edges[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *WeightedUndirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *WeightedUndirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *WeightedUndirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *WeightedUndirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + + return edges +} + +// WeightedEdges returns all the weighted edges in the graph. +func (g *WeightedUndirectedGraph) WeightedEdges() []graph.WeightedEdge { + var edges []graph.WeightedEdge + + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *WeightedUndirectedGraph) From(n graph.Node) []graph.Node { + if !g.Has(n) { + return nil + } + + nodes := make([]graph.Node, len(g.edges[n.ID()])) + i := 0 + for from := range g.edges[n.ID()] { + nodes[i] = g.nodes[from] + i++ + } + + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *WeightedUndirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + _, ok := g.edges[x.ID()][y.ID()] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *WeightedUndirectedGraph) Edge(u, v graph.Node) graph.Edge { + return g.WeightedEdgeBetween(u, v) +} + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *WeightedUndirectedGraph) WeightedEdge(u, v graph.Node) graph.WeightedEdge { + return g.WeightedEdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *WeightedUndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge { + return g.WeightedEdgeBetween(x, y) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g *WeightedUndirectedGraph) WeightedEdgeBetween(x, y graph.Node) graph.WeightedEdge { + // We don't need to check if neigh exists because + // it's implicit in the edges access. + if !g.Has(x) { + return nil + } + + return g.edges[x.ID()][y.ID()] +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *WeightedUndirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if n, ok := g.edges[xid]; ok { + if e, ok := n[yid]; ok { + return e.Weight(), true + } + } + return g.absent, false +} + +// Degree returns the degree of n in g. +func (g *WeightedUndirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.edges[n.ID()]) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected_test.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected_test.go new file mode 100644 index 00000000..a3796ee3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected_test.go @@ -0,0 +1,69 @@ +// Copyright ©2014 The gonum 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 simple + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" +) + +var ( + weightedUndirectedGraph = (*WeightedUndirectedGraph)(nil) + + _ graph.Graph = weightedUndirectedGraph + _ graph.Undirected = weightedUndirectedGraph + _ graph.WeightedUndirected = weightedUndirectedGraph +) + +func TestAssertWeightedMutableNotDirected(t *testing.T) { + var g graph.UndirectedWeightedBuilder = NewWeightedUndirectedGraph(0, math.Inf(1)) + if _, ok := g.(graph.Directed); ok { + t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!") + } +} + +func TestWeightedMaxID(t *testing.T) { + g := NewWeightedUndirectedGraph(0, math.Inf(1)) + nodes := make(map[graph.Node]struct{}) + for i := Node(0); i < 3; i++ { + g.AddNode(i) + nodes[i] = struct{}{} + } + g.RemoveNode(Node(0)) + delete(nodes, Node(0)) + g.RemoveNode(Node(2)) + delete(nodes, Node(2)) + n := g.NewNode() + g.AddNode(n) + if !g.Has(n) { + t.Error("added node does not exist in graph") + } + if _, exists := nodes[n]; exists { + t.Errorf("Created already existing node id: %v", n.ID()) + } +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123WeightedUndirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewWeightedUndirectedGraph(0, math.Inf(1)) + + n0 := g.NewNode() + g.AddNode(n0) + + n1 := g.NewNode() + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := g.NewNode() + g.AddNode(n2) +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/bench_test.go b/vendor/gonum.org/v1/gonum/graph/topo/bench_test.go new file mode 100644 index 00000000..7b2bdc3e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/bench_test.go @@ -0,0 +1,57 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + gnpDirected_10_tenth = gnpDirected(10, 0.1) + gnpDirected_100_tenth = gnpDirected(100, 0.1) + gnpDirected_1000_tenth = gnpDirected(1000, 0.1) + gnpDirected_10_half = gnpDirected(10, 0.5) + gnpDirected_100_half = gnpDirected(100, 0.5) + gnpDirected_1000_half = gnpDirected(1000, 0.5) +) + +func gnpDirected(n int, p float64) graph.Directed { + g := simple.NewDirectedGraph() + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkTarjanSCC(b *testing.B, g graph.Directed) { + var sccs [][]graph.Node + for i := 0; i < b.N; i++ { + sccs = TarjanSCC(g) + } + if len(sccs) == 0 { + b.Fatal("unexpected number zero-sized SCC set") + } +} + +func BenchmarkTarjanSCCGnp_10_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_10_tenth) +} +func BenchmarkTarjanSCCGnp_100_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_100_tenth) +} +func BenchmarkTarjanSCCGnp_1000_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_1000_tenth) +} +func BenchmarkTarjanSCCGnp_10_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_10_half) +} +func BenchmarkTarjanSCCGnp_100_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_100_half) +} +func BenchmarkTarjanSCCGnp_1000_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_1000_half) +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go new file mode 100644 index 00000000..9c478056 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go @@ -0,0 +1,225 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// VertexOrdering returns the vertex ordering and the k-cores of +// the undirected graph g. +func VertexOrdering(g graph.Undirected) (order []graph.Node, cores [][]graph.Node) { + nodes := g.Nodes() + + // The algorithm used here is essentially as described at + // http://en.wikipedia.org/w/index.php?title=Degeneracy_%28graph_theory%29&oldid=640308710 + + // Initialize an output list L. + var l []graph.Node + + // Compute a number d_v for each vertex v in G, + // the number of neighbors of v that are not already in L. + // Initially, these numbers are just the degrees of the vertices. + dv := make(map[int64]int, len(nodes)) + var ( + maxDegree int + neighbours = make(map[int64][]graph.Node) + ) + for _, n := range nodes { + adj := g.From(n) + neighbours[n.ID()] = adj + dv[n.ID()] = len(adj) + if len(adj) > maxDegree { + maxDegree = len(adj) + } + } + + // Initialize an array D such that D[i] contains a list of the + // vertices v that are not already in L for which d_v = i. + d := make([][]graph.Node, maxDegree+1) + for _, n := range nodes { + deg := dv[n.ID()] + d[deg] = append(d[deg], n) + } + + // Initialize k to 0. + k := 0 + // Repeat n times: + s := []int{0} + for range nodes { + // Scan the array cells D[0], D[1], ... until + // finding an i for which D[i] is nonempty. + var ( + i int + di []graph.Node + ) + for i, di = range d { + if len(di) != 0 { + break + } + } + + // Set k to max(k,i). + if i > k { + k = i + s = append(s, make([]int, k-len(s)+1)...) + } + + // Select a vertex v from D[i]. Add v to the + // beginning of L and remove it from D[i]. + var v graph.Node + v, d[i] = di[len(di)-1], di[:len(di)-1] + l = append(l, v) + s[k]++ + delete(dv, v.ID()) + + // For each neighbor w of v not already in L, + // subtract one from d_w and move w to the + // cell of D corresponding to the new value of d_w. + for _, w := range neighbours[v.ID()] { + dw, ok := dv[w.ID()] + if !ok { + continue + } + for i, n := range d[dw] { + if n.ID() == w.ID() { + d[dw][i], d[dw] = d[dw][len(d[dw])-1], d[dw][:len(d[dw])-1] + dw-- + d[dw] = append(d[dw], w) + break + } + } + dv[w.ID()] = dw + } + } + + for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 { + l[i], l[j] = l[j], l[i] + } + cores = make([][]graph.Node, len(s)) + offset := len(l) + for i, n := range s { + cores[i] = l[offset-n : offset] + offset -= n + } + return l, cores +} + +// BronKerbosch returns the set of maximal cliques of the undirected graph g. +func BronKerbosch(g graph.Undirected) [][]graph.Node { + nodes := g.Nodes() + + // The algorithm used here is essentially BronKerbosch3 as described at + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + + p := make(set.Nodes, len(nodes)) + for _, n := range nodes { + p.Add(n) + } + x := make(set.Nodes) + var bk bronKerbosch + order, _ := VertexOrdering(g) + for _, v := range order { + neighbours := g.From(v) + nv := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nv.Add(n) + } + bk.maximalCliquePivot(g, []graph.Node{v}, make(set.Nodes).Intersect(p, nv), make(set.Nodes).Intersect(x, nv)) + p.Remove(v) + x.Add(v) + } + return bk +} + +type bronKerbosch [][]graph.Node + +func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p, x set.Nodes) { + if len(p) == 0 && len(x) == 0 { + *bk = append(*bk, r) + return + } + + neighbours := bk.choosePivotFrom(g, p, x) + nu := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nu.Add(n) + } + for _, v := range p { + if nu.Has(v) { + continue + } + neighbours := g.From(v) + nv := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nv.Add(n) + } + + var found bool + for _, n := range r { + if n.ID() == v.ID() { + found = true + break + } + } + var sr []graph.Node + if !found { + sr = append(r[:len(r):len(r)], v) + } + + bk.maximalCliquePivot(g, sr, make(set.Nodes).Intersect(p, nv), make(set.Nodes).Intersect(x, nv)) + p.Remove(v) + x.Add(v) + } +} + +func (*bronKerbosch) choosePivotFrom(g graph.Undirected, p, x set.Nodes) (neighbors []graph.Node) { + // TODO(kortschak): Investigate the impact of pivot choice that maximises + // |p ⋂ neighbours(u)| as a function of input size. Until then, leave as + // compile time option. + if !tomitaTanakaTakahashi { + for _, n := range p { + return g.From(n) + } + for _, n := range x { + return g.From(n) + } + panic("bronKerbosch: empty set") + } + + var ( + max = -1 + pivot graph.Node + ) + maxNeighbors := func(s set.Nodes) { + outer: + for _, u := range s { + nb := g.From(u) + c := len(nb) + if c <= max { + continue + } + for n := range nb { + if _, ok := p[int64(n)]; ok { + continue + } + c-- + if c <= max { + continue outer + } + } + max = c + pivot = u + neighbors = nb + } + } + maxNeighbors(p) + maxNeighbors(x) + if pivot == nil { + panic("bronKerbosch: empty set") + } + return neighbors +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch_test.go b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch_test.go new file mode 100644 index 00000000..8fdb67c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch_test.go @@ -0,0 +1,163 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var vOrderTests = []struct { + g []intset + wantCore [][]int64 + wantK int +}{ + { + g: []intset{ + 0: linksTo(1, 2, 4, 6), + 1: linksTo(2, 4, 6), + 2: linksTo(3, 6), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + wantCore: [][]int64{ + {}, + {5}, + {3}, + {0, 1, 2, 4, 6}, + }, + wantK: 3, + }, + { + g: batageljZaversnikGraph, + wantCore: [][]int64{ + {0}, + {5, 9, 10, 16}, + {1, 2, 3, 4, 11, 12, 13, 15}, + {6, 7, 8, 14, 17, 18, 19, 20}, + }, + wantK: 3, + }, +} + +func TestVertexOrdering(t *testing.T) { + for i, test := range vOrderTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + order, core := VertexOrdering(g) + if len(core)-1 != test.wantK { + t.Errorf("unexpected value of k for test %d: got: %d want: %d", i, len(core)-1, test.wantK) + } + var offset int + for k, want := range test.wantCore { + sort.Sort(ordered.Int64s(want)) + got := make([]int64, len(want)) + for j, n := range order[len(order)-len(want)-offset : len(order)-offset] { + got[j] = n.ID() + } + sort.Sort(ordered.Int64s(got)) + if !reflect.DeepEqual(got, want) { + t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, test.wantCore) + } + + for j, n := range core[k] { + got[j] = n.ID() + } + sort.Sort(ordered.Int64s(got)) + if !reflect.DeepEqual(got, want) { + t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, test.wantCore) + } + offset += len(want) + } + } +} + +var bronKerboschTests = []struct { + g []intset + want [][]int64 +}{ + { + // This is the example given in the Bron-Kerbosch article on wikipedia (renumbered). + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + g: []intset{ + 0: linksTo(1, 4), + 1: linksTo(2, 4), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: nil, + 5: nil, + }, + want: [][]int64{ + {0, 1, 4}, + {1, 2}, + {2, 3}, + {3, 4}, + {3, 5}, + }, + }, + { + g: batageljZaversnikGraph, + want: [][]int64{ + {0}, + {1, 2}, + {1, 3}, + {2, 4}, + {3, 4}, + {4, 5}, + {6, 7, 8, 14}, + {7, 11, 12}, + {9, 11}, + {10, 11}, + {12, 18}, + {13, 14, 15}, + {14, 15, 17}, + {15, 16}, + {17, 18, 19, 20}, + }, + }, +} + +func TestBronKerbosch(t *testing.T) { + for i, test := range bronKerboschTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cliques := BronKerbosch(g) + got := make([][]int64, len(cliques)) + for j, c := range cliques { + ids := make([]int64, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Sort(ordered.Int64s(ids)) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected cliques for test %d:\ngot: %v\nwant:%v", i, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/common_test.go b/vendor/gonum.org/v1/gonum/graph/topo/common_test.go new file mode 100644 index 00000000..6b09e78b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/common_test.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum 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 topo + +// batageljZaversnikGraph is the example graph from +// figure 1 of http://arxiv.org/abs/cs/0310049v1 +var batageljZaversnikGraph = []intset{ + 0: nil, + + 1: linksTo(2, 3), + 2: linksTo(4), + 3: linksTo(4), + 4: linksTo(5), + 5: nil, + + 6: linksTo(7, 8, 14), + 7: linksTo(8, 11, 12, 14), + 8: linksTo(14), + 9: linksTo(11), + 10: linksTo(11), + 11: linksTo(12), + 12: linksTo(18), + 13: linksTo(14, 15), + 14: linksTo(15, 17), + 15: linksTo(16, 17), + 16: nil, + 17: linksTo(18, 19, 20), + 18: linksTo(19, 20), + 19: linksTo(20), + 20: nil, +} + +// intset is an integer set. +type intset map[int64]struct{} + +func linksTo(i ...int64) intset { + if len(i) == 0 { + return nil + } + s := make(intset) + for _, v := range i { + s[v] = struct{}{} + } + return s +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/doc.go b/vendor/gonum.org/v1/gonum/graph/topo/doc.go new file mode 100644 index 00000000..ba1bf552 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 topo provides graph topology analysis functions. +package topo // import "gonum.org/v1/gonum/graph/topo" diff --git a/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go new file mode 100644 index 00000000..de84cf9c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go @@ -0,0 +1,280 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// johnson implements Johnson's "Finding all the elementary +// circuits of a directed graph" algorithm. SIAM J. Comput. 4(1):1975. +// +// Comments in the johnson methods are kept in sync with the comments +// and labels from the paper. +type johnson struct { + adjacent johnsonGraph // SCC adjacency list. + b []set.Ints // Johnson's "B-list". + blocked []bool + s int + + stack []graph.Node + + result [][]graph.Node +} + +// DirectedCyclesIn returns the set of elementary cycles in the graph g. +func DirectedCyclesIn(g graph.Directed) [][]graph.Node { + jg := johnsonGraphFrom(g) + j := johnson{ + adjacent: jg, + b: make([]set.Ints, len(jg.orig)), + blocked: make([]bool, len(jg.orig)), + } + + // len(j.nodes) is the order of g. + for j.s < len(j.adjacent.orig)-1 { + // We use the previous SCC adjacency to reduce the work needed. + sccs := TarjanSCC(j.adjacent.subgraph(j.s)) + // A_k = adjacency structure of strong component K with least + // vertex in subgraph of G induced by {s, s+1, ... ,n}. + j.adjacent = j.adjacent.sccSubGraph(sccs, 2) // Only allow SCCs with >= 2 vertices. + if j.adjacent.order() == 0 { + break + } + + // s = least vertex in V_k + if s := j.adjacent.leastVertexIndex(); s < j.s { + j.s = s + } + for i, v := range j.adjacent.orig { + if !j.adjacent.nodes.Has(v.ID()) { + continue + } + if len(j.adjacent.succ[v.ID()]) > 0 { + j.blocked[i] = false + j.b[i] = make(set.Ints) + } + } + //L3: + _ = j.circuit(j.s) + j.s++ + } + + return j.result +} + +// circuit is the CIRCUIT sub-procedure in the paper. +func (j *johnson) circuit(v int) bool { + f := false + n := j.adjacent.orig[v] + j.stack = append(j.stack, n) + j.blocked[v] = true + + //L1: + for w := range j.adjacent.succ[n.ID()] { + w := j.adjacent.indexOf(w) + if w == j.s { + // Output circuit composed of stack followed by s. + r := make([]graph.Node, len(j.stack)+1) + copy(r, j.stack) + r[len(r)-1] = j.adjacent.orig[j.s] + j.result = append(j.result, r) + f = true + } else if !j.blocked[w] { + if j.circuit(w) { + f = true + } + } + } + + //L2: + if f { + j.unblock(v) + } else { + for w := range j.adjacent.succ[n.ID()] { + j.b[j.adjacent.indexOf(w)].Add(v) + } + } + j.stack = j.stack[:len(j.stack)-1] + + return f +} + +// unblock is the UNBLOCK sub-procedure in the paper. +func (j *johnson) unblock(u int) { + j.blocked[u] = false + for w := range j.b[u] { + j.b[u].Remove(w) + if j.blocked[w] { + j.unblock(w) + } + } +} + +// johnsonGraph is an edge list representation of a graph with helpers +// necessary for Johnson's algorithm +type johnsonGraph struct { + // Keep the original graph nodes and a + // look-up to into the non-sparse + // collection of potentially sparse IDs. + orig []graph.Node + index map[int64]int + + nodes set.Int64s + succ map[int64]set.Int64s +} + +// johnsonGraphFrom returns a deep copy of the graph g. +func johnsonGraphFrom(g graph.Directed) johnsonGraph { + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + c := johnsonGraph{ + orig: nodes, + index: make(map[int64]int, len(nodes)), + + nodes: make(set.Int64s, len(nodes)), + succ: make(map[int64]set.Int64s), + } + for i, u := range nodes { + c.index[u.ID()] = i + for _, v := range g.From(u) { + if c.succ[u.ID()] == nil { + c.succ[u.ID()] = make(set.Int64s) + c.nodes.Add(u.ID()) + } + c.nodes.Add(v.ID()) + c.succ[u.ID()].Add(v.ID()) + } + } + return c +} + +// order returns the order of the graph. +func (g johnsonGraph) order() int { return g.nodes.Count() } + +// indexOf returns the index of the retained node for the given node ID. +func (g johnsonGraph) indexOf(id int64) int { + return g.index[id] +} + +// leastVertexIndex returns the index into orig of the least vertex. +func (g johnsonGraph) leastVertexIndex() int { + for _, v := range g.orig { + if g.nodes.Has(v.ID()) { + return g.indexOf(v.ID()) + } + } + panic("johnsonCycles: empty set") +} + +// subgraph returns a subgraph of g induced by {s, s+1, ... , n}. The +// subgraph is destructively generated in g. +func (g johnsonGraph) subgraph(s int) johnsonGraph { + sn := g.orig[s].ID() + for u, e := range g.succ { + if u < sn { + g.nodes.Remove(u) + delete(g.succ, u) + continue + } + for v := range e { + if v < sn { + g.succ[u].Remove(v) + } + } + } + return g +} + +// sccSubGraph returns the graph of the tarjan's strongly connected +// components with each SCC containing at least min vertices. +// sccSubGraph returns nil if there is no SCC with at least min +// members. +func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph { + if len(g.nodes) == 0 { + g.nodes = nil + g.succ = nil + return g + } + sub := johnsonGraph{ + orig: g.orig, + index: g.index, + nodes: make(set.Int64s), + succ: make(map[int64]set.Int64s), + } + + var n int + for _, scc := range sccs { + if len(scc) < min { + continue + } + n++ + for _, u := range scc { + for _, v := range scc { + if _, ok := g.succ[u.ID()][v.ID()]; ok { + if sub.succ[u.ID()] == nil { + sub.succ[u.ID()] = make(set.Int64s) + sub.nodes.Add(u.ID()) + } + sub.nodes.Add(v.ID()) + sub.succ[u.ID()].Add(v.ID()) + } + } + } + } + if n == 0 { + g.nodes = nil + g.succ = nil + return g + } + + return sub +} + +// Nodes is required to satisfy Tarjan. +func (g johnsonGraph) Nodes() []graph.Node { + n := make([]graph.Node, 0, len(g.nodes)) + for id := range g.nodes { + n = append(n, johnsonGraphNode(id)) + } + return n +} + +// Successors is required to satisfy Tarjan. +func (g johnsonGraph) From(n graph.Node) []graph.Node { + adj := g.succ[n.ID()] + if len(adj) == 0 { + return nil + } + succ := make([]graph.Node, 0, len(adj)) + for n := range adj { + succ = append(succ, johnsonGraphNode(n)) + } + return succ +} + +func (johnsonGraph) Has(graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) HasEdgeBetween(_, _ graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) Edge(_, _ graph.Node) graph.Edge { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) HasEdgeFromTo(_, _ graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) To(graph.Node) []graph.Node { + panic("topo: unintended use of johnsonGraph") +} + +type johnsonGraphNode int64 + +func (n johnsonGraphNode) ID() int64 { return int64(n) } diff --git a/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles_test.go b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles_test.go new file mode 100644 index 00000000..bf53120d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles_test.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var cyclesInTests = []struct { + g []intset + want [][]int64 +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + want: [][]int64{ + {0, 1, 7, 0}, + {2, 3, 4, 2}, + {2, 6, 3, 4, 2}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + want: [][]int64{ + {1, 2, 3, 1}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + want: [][]int64{ + {0, 1, 0}, + {1, 2, 1}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + want: nil, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + want: [][]int64{ + {0, 1, 2, 0}, + {3, 4, 3}, + }, + }, +} + +func TestDirectedCyclesIn(t *testing.T) { + for i, test := range cyclesInTests { + g := simple.NewDirectedGraph() + g.AddNode(simple.Node(-10)) // Make sure we test graphs with sparse IDs. + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cycles := DirectedCyclesIn(g) + var got [][]int64 + if cycles != nil { + got = make([][]int64, len(cycles)) + } + // johnson.circuit does range iteration over maps, + // so sort to ensure consistent ordering. + for j, c := range cycles { + ids := make([]int64, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected johnson result for %d:\n\tgot:%#v\n\twant:%#v", i, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go b/vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go new file mode 100644 index 00000000..de09ebd8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go @@ -0,0 +1,9 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !tomita + +package topo + +const tomitaTanakaTakahashi = false diff --git a/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go new file mode 100644 index 00000000..d012ecaa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go @@ -0,0 +1,81 @@ +// Copyright ©2017 The gonum 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 topo + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/linear" + "gonum.org/v1/gonum/graph/internal/set" +) + +// UndirectedCyclesIn returns a set of cycles that forms a cycle basis in the graph g. +// Any cycle in g can be constructed as a symmetric difference of its elements. +func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node { + // From "An algorithm for finding a fundamental set of cycles of a graph" + // https://doi.org/10.1145/363219.363232 + + var cycles [][]graph.Node + done := make(set.Int64s) + var tree linear.NodeStack + for _, n := range g.Nodes() { + id := n.ID() + if done.Has(id) { + continue + } + done.Add(id) + + tree = tree[:0] + tree.Push(n) + from := sets{id: set.Int64s{}} + to := map[int64]graph.Node{id: n} + + for tree.Len() != 0 { + u := tree.Pop() + uid := u.ID() + adj := from[uid] + for _, v := range g.From(u) { + vid := v.ID() + switch { + case uid == vid: + cycles = append(cycles, []graph.Node{u}) + case !from.has(vid): + done.Add(vid) + to[vid] = u + tree.Push(v) + from.add(uid, vid) + case !adj.Has(vid): + c := []graph.Node{v, u} + adj := from[vid] + p := to[uid] + for !adj.Has(p.ID()) { + c = append(c, p) + p = to[p.ID()] + } + c = append(c, p, c[0]) + cycles = append(cycles, c) + adj.Add(uid) + } + } + } + } + + return cycles +} + +type sets map[int64]set.Int64s + +func (s sets) add(uid, vid int64) { + e, ok := s[vid] + if !ok { + e = make(set.Int64s) + s[vid] = e + } + e.Add(uid) +} + +func (s sets) has(uid int64) bool { + _, ok := s[uid] + return ok +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles_test.go b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles_test.go new file mode 100644 index 00000000..c36590be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles_test.go @@ -0,0 +1,143 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var undirectedCyclesInTests = []struct { + g []intset + want [][][]int64 +}{ + { + g: []intset{ + 0: linksTo(1, 2), + 1: linksTo(2, 4, 5, 9), + 2: linksTo(4, 7, 9), + 3: linksTo(5), + 4: linksTo(8), + 5: linksTo(7, 8), + 6: nil, + 7: nil, + 8: nil, + 9: nil, + 10: linksTo(11, 12), + 11: linksTo(12), + 12: nil, + }, + want: [][][]int64{ + { + {0, 1, 2, 0}, + {1, 2, 7, 5, 1}, + {1, 2, 9, 1}, + {1, 4, 8, 5, 1}, + {2, 4, 8, 5, 7, 2}, + {10, 11, 12, 10}, + }, + { + {0, 1, 2, 0}, + {1, 2, 4, 1}, + {1, 2, 7, 5, 1}, + {1, 2, 9, 1}, + {1, 4, 8, 5, 1}, + {10, 11, 12, 10}, + }, + { + {0, 1, 2, 0}, + {1, 2, 4, 1}, + {1, 2, 9, 1}, + {1, 4, 8, 5, 1}, + {2, 4, 8, 5, 7, 2}, + {10, 11, 12, 10}, + }, + { + {0, 1, 2, 0}, + {1, 2, 4, 1}, + {1, 2, 7, 5, 1}, + {1, 2, 9, 1}, + {2, 4, 8, 5, 7, 2}, + {10, 11, 12, 10}, + }, + }, + }, +} + +func TestUndirectedCyclesIn(t *testing.T) { + for i, test := range undirectedCyclesInTests { + g := simple.NewUndirectedGraph() + g.AddNode(simple.Node(-10)) // Make sure we test graphs with sparse IDs. + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cycles := UndirectedCyclesIn(g) + var got [][]int64 + if cycles != nil { + got = make([][]int64, len(cycles)) + } + // Canonicalise the cycles. + for j, c := range cycles { + ids := make([]int64, len(c)) + for k, n := range canonicalise(c[:len(c)-1]) { + ids[k] = n.ID() + } + ids[len(ids)-1] = ids[0] + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + var matched bool + for _, want := range test.want { + if reflect.DeepEqual(got, want) { + matched = true + break + } + } + if !matched { + t.Errorf("unexpected paton result for %d:\n\tgot:%#v\n\twant from:%#v", i, got, test.want) + } + } +} + +// canonicalise returns the cycle path c cyclicly permuted such that +// the first element has the lowest ID and then conditionally +// reversed so that the second element has the lowest possible +// neighbouring ID. +// c lists each node only onces - the final node must not be a +// reiteration of the first node. +func canonicalise(c []graph.Node) []graph.Node { + if len(c) < 2 { + return c + } + idx := 0 + min := c[0].ID() + for i, n := range c[1:] { + if id := n.ID(); id < min { + idx = i + 1 + min = id + } + } + if idx != 0 { + c = append(c[idx:], c[:idx]...) + } + if c[len(c)-1].ID() < c[1].ID() { + s := c[1:] + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } + } + return c +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go b/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go new file mode 100644 index 00000000..cd5d6a86 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go @@ -0,0 +1,203 @@ +// Copyright ©2015 The gonum 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 topo + +import ( + "fmt" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// Unorderable is an error containing sets of unorderable graph.Nodes. +type Unorderable [][]graph.Node + +// Error satisfies the error interface. +func (e Unorderable) Error() string { + const maxNodes = 10 + var n int + for _, c := range e { + n += len(c) + } + if n > maxNodes { + // Don't return errors that are too long. + return fmt.Sprintf("topo: no topological ordering: %d nodes in %d cyclic components", n, len(e)) + } + return fmt.Sprintf("topo: no topological ordering: cyclic components: %v", [][]graph.Node(e)) +} + +func lexical(nodes []graph.Node) { sort.Sort(ordered.ByID(nodes)) } + +// Sort performs a topological sort of the directed graph g returning the 'from' to 'to' +// sort order. If a topological ordering is not possible, an Unorderable error is returned +// listing cyclic components in g with each cyclic component's members sorted by ID. When +// an Unorderable error is returned, each cyclic component's topological position within +// the sorted nodes is marked with a nil graph.Node. +func Sort(g graph.Directed) (sorted []graph.Node, err error) { + sccs := TarjanSCC(g) + return sortedFrom(sccs, lexical) +} + +// SortStabilized performs a topological sort of the directed graph g returning the 'from' +// to 'to' sort order, or the order defined by the in place order sort function where there +// is no unambiguous topological ordering. If a topological ordering is not possible, an +// Unorderable error is returned listing cyclic components in g with each cyclic component's +// members sorted by the provided order function. If order is nil, nodes are ordered lexically +// by node ID. When an Unorderable error is returned, each cyclic component's topological +// position within the sorted nodes is marked with a nil graph.Node. +func SortStabilized(g graph.Directed, order func([]graph.Node)) (sorted []graph.Node, err error) { + if order == nil { + order = lexical + } + sccs := tarjanSCCstabilized(g, order) + return sortedFrom(sccs, order) +} + +func sortedFrom(sccs [][]graph.Node, order func([]graph.Node)) ([]graph.Node, error) { + sorted := make([]graph.Node, 0, len(sccs)) + var sc Unorderable + for _, s := range sccs { + if len(s) != 1 { + order(s) + sc = append(sc, s) + sorted = append(sorted, nil) + continue + } + sorted = append(sorted, s[0]) + } + var err error + if sc != nil { + for i, j := 0, len(sc)-1; i < j; i, j = i+1, j-1 { + sc[i], sc[j] = sc[j], sc[i] + } + err = sc + } + reverse(sorted) + return sorted, err +} + +func reverse(p []graph.Node) { + for i, j := 0, len(p)-1; i < j; i, j = i+1, j-1 { + p[i], p[j] = p[j], p[i] + } +} + +// TarjanSCC returns the strongly connected components of the graph g using Tarjan's algorithm. +// +// A strongly connected component of a graph is a set of vertices where it's possible to reach any +// vertex in the set from any other (meaning there's a cycle between them.) +// +// Generally speaking, a directed graph where the number of strongly connected components is equal +// to the number of nodes is acyclic, unless you count reflexive edges as a cycle (which requires +// only a little extra testing.) +// +func TarjanSCC(g graph.Directed) [][]graph.Node { + return tarjanSCCstabilized(g, nil) +} + +func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.Node { + nodes := g.Nodes() + var succ func(graph.Node) []graph.Node + if order == nil { + succ = g.From + } else { + order(nodes) + reverse(nodes) + + succ = func(n graph.Node) []graph.Node { + to := g.From(n) + order(to) + reverse(to) + return to + } + } + + t := tarjan{ + succ: succ, + + indexTable: make(map[int64]int, len(nodes)), + lowLink: make(map[int64]int, len(nodes)), + onStack: make(set.Int64s), + } + for _, v := range nodes { + if t.indexTable[v.ID()] == 0 { + t.strongconnect(v) + } + } + return t.sccs +} + +// tarjan implements Tarjan's strongly connected component finding +// algorithm. The implementation is from the pseudocode at +// +// http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm?oldid=642744644 +// +type tarjan struct { + succ func(graph.Node) []graph.Node + + index int + indexTable map[int64]int + lowLink map[int64]int + onStack set.Int64s + + stack []graph.Node + + sccs [][]graph.Node +} + +// strongconnect is the strongconnect function described in the +// wikipedia article. +func (t *tarjan) strongconnect(v graph.Node) { + vID := v.ID() + + // Set the depth index for v to the smallest unused index. + t.index++ + t.indexTable[vID] = t.index + t.lowLink[vID] = t.index + t.stack = append(t.stack, v) + t.onStack.Add(vID) + + // Consider successors of v. + for _, w := range t.succ(v) { + wID := w.ID() + if t.indexTable[wID] == 0 { + // Successor w has not yet been visited; recur on it. + t.strongconnect(w) + t.lowLink[vID] = min(t.lowLink[vID], t.lowLink[wID]) + } else if t.onStack.Has(wID) { + // Successor w is in stack s and hence in the current SCC. + t.lowLink[vID] = min(t.lowLink[vID], t.indexTable[wID]) + } + } + + // If v is a root node, pop the stack and generate an SCC. + if t.lowLink[vID] == t.indexTable[vID] { + // Start a new strongly connected component. + var ( + scc []graph.Node + w graph.Node + ) + for { + w, t.stack = t.stack[len(t.stack)-1], t.stack[:len(t.stack)-1] + t.onStack.Remove(w.ID()) + // Add w to current strongly connected component. + scc = append(scc, w) + if w.ID() == vID { + break + } + } + // Output the current strongly connected component. + t.sccs = append(t.sccs, scc) + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/tarjan_test.go b/vendor/gonum.org/v1/gonum/graph/topo/tarjan_test.go new file mode 100644 index 00000000..8751c507 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/tarjan_test.go @@ -0,0 +1,308 @@ +// Copyright ©2014 The gonum 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 topo + +import ( + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +type interval struct{ start, end int } + +var tarjanTests = []struct { + g []intset + + ambiguousOrder []interval + want [][]int64 + + sortedLength int + unorderableLength int + sortable bool +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + + want: [][]int64{ + {5}, + {2, 3, 4, 6}, + {0, 1, 7}, + }, + + sortedLength: 1, + unorderableLength: 2, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + + want: [][]int64{ + {1, 2, 3}, + {0}, + }, + + sortedLength: 1, + unorderableLength: 1, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + + want: [][]int64{ + {0, 1, 2}, + }, + + sortedLength: 0, + unorderableLength: 1, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + + // Node pairs (2, 3) and (4, 5) are not + // relatively orderable within each pair. + ambiguousOrder: []interval{ + {0, 3}, // This includes node 6 since it only needs to be before 4 in topo sort. + {3, 5}, + }, + want: [][]int64{ + {6}, {5}, {4}, {3}, {2}, {1}, {0}, + }, + + sortedLength: 7, + sortable: true, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + + // SCCs are not relatively ordable. + ambiguousOrder: []interval{ + {0, 2}, + }, + want: [][]int64{ + {0, 1, 2}, + {3, 4}, + }, + + sortedLength: 0, + unorderableLength: 2, + sortable: false, + }, +} + +func TestSort(t *testing.T) { + for i, test := range tarjanTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + sorted, err := Sort(g) + var gotSortedLen int + for _, n := range sorted { + if n != nil { + gotSortedLen++ + } + } + if gotSortedLen != test.sortedLength { + t.Errorf("unexpected number of sortable nodes for test %d: got:%d want:%d", i, gotSortedLen, test.sortedLength) + } + if err == nil != test.sortable { + t.Errorf("unexpected sortability for test %d: got error: %v want: nil-error=%t", i, err, test.sortable) + } + if err != nil && len(err.(Unorderable)) != test.unorderableLength { + t.Errorf("unexpected number of unorderable nodes for test %d: got:%d want:%d", i, len(err.(Unorderable)), test.unorderableLength) + } + } +} + +func TestTarjanSCC(t *testing.T) { + for i, test := range tarjanTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + gotSCCs := TarjanSCC(g) + // tarjan.strongconnect does range iteration over maps, + // so sort SCC members to ensure consistent ordering. + gotIDs := make([][]int64, len(gotSCCs)) + for i, scc := range gotSCCs { + gotIDs[i] = make([]int64, len(scc)) + for j, id := range scc { + gotIDs[i][j] = id.ID() + } + sort.Sort(ordered.Int64s(gotIDs[i])) + } + for _, iv := range test.ambiguousOrder { + sort.Sort(ordered.BySliceValues(test.want[iv.start:iv.end])) + sort.Sort(ordered.BySliceValues(gotIDs[iv.start:iv.end])) + } + if !reflect.DeepEqual(gotIDs, test.want) { + t.Errorf("unexpected Tarjan scc result for %d:\n\tgot:%v\n\twant:%v", i, gotIDs, test.want) + } + } +} + +var stabilizedSortTests = []struct { + g []intset + + want []graph.Node + err error +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + + want: []graph.Node{nil, nil, simple.Node(5)}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(7)}, + {simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(6)}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + + want: []graph.Node{simple.Node(0), nil}, + err: Unorderable{ + {simple.Node(1), simple.Node(2), simple.Node(3)}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + + want: []graph.Node{nil}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + + want: []graph.Node{simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6)}, + err: nil, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + + want: []graph.Node{nil, nil}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4)}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3, 4, 5, 6), + 1: linksTo(7), + 2: linksTo(7), + 3: linksTo(7), + 4: linksTo(7), + 5: linksTo(7), + 6: linksTo(7), + 7: nil, + }, + + want: []graph.Node{simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + err: nil, + }, +} + +func TestSortStabilized(t *testing.T) { + for i, test := range stabilizedSortTests { + g := simple.NewDirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got, err := SortStabilized(g, nil) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected sort result for test %d: got:%d want:%d", i, got, test.want) + } + if !reflect.DeepEqual(err, test.err) { + t.Errorf("unexpected sort error for test %d: got:%v want:%v", i, err, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go b/vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go new file mode 100644 index 00000000..d4eca625 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go @@ -0,0 +1,9 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build tomita + +package topo + +const tomitaTanakaTakahashi = true diff --git a/vendor/gonum.org/v1/gonum/graph/topo/topo.go b/vendor/gonum.org/v1/gonum/graph/topo/topo.go new file mode 100644 index 00000000..fe55f428 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/topo.go @@ -0,0 +1,68 @@ +// Copyright ©2014 The gonum 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 topo + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/traverse" +) + +// IsPathIn returns whether path is a path in g. +// +// As special cases, IsPathIn returns true for a zero length path or for +// a path of length 1 when the node in path exists in the graph. +func IsPathIn(g graph.Graph, path []graph.Node) bool { + switch len(path) { + case 0: + return true + case 1: + return g.Has(path[0]) + default: + var canReach func(u, v graph.Node) bool + switch g := g.(type) { + case graph.Directed: + canReach = g.HasEdgeFromTo + default: + canReach = g.HasEdgeBetween + } + + for i, u := range path[:len(path)-1] { + if !canReach(u, path[i+1]) { + return false + } + } + return true + } +} + +// PathExistsIn returns whether there is a path in g starting at from extending +// to to. +// +// PathExistsIn exists as a helper function. If many tests for path existence +// are being performed, other approaches will be more efficient. +func PathExistsIn(g graph.Graph, from, to graph.Node) bool { + var t traverse.BreadthFirst + return t.Walk(g, from, func(n graph.Node, _ int) bool { return n.ID() == to.ID() }) != nil +} + +// ConnectedComponents returns the connected components of the undirected graph g. +func ConnectedComponents(g graph.Undirected) [][]graph.Node { + var ( + w traverse.DepthFirst + c []graph.Node + cc [][]graph.Node + ) + during := func(n graph.Node) { + c = append(c, n) + } + after := func() { + cc = append(cc, []graph.Node(nil)) + cc[len(cc)-1] = append(cc[len(cc)-1], c...) + c = c[:0] + } + w.WalkAll(g, nil, after, during) + + return cc +} diff --git a/vendor/gonum.org/v1/gonum/graph/topo/topo_test.go b/vendor/gonum.org/v1/gonum/graph/topo/topo_test.go new file mode 100644 index 00000000..bb75796d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/topo/topo_test.go @@ -0,0 +1,175 @@ +// Copyright ©2014 The gonum 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 topo + +import ( + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +func TestIsPath(t *testing.T) { + dg := simple.NewDirectedGraph() + if !IsPathIn(dg, nil) { + t.Error("IsPath returns false on nil path") + } + p := []graph.Node{simple.Node(0)} + if IsPathIn(dg, p) { + t.Error("IsPath returns true on nonexistant node") + } + dg.AddNode(p[0]) + if !IsPathIn(dg, p) { + t.Error("IsPath returns false on single-length path with existing node") + } + p = append(p, simple.Node(1)) + dg.AddNode(p[1]) + if IsPathIn(dg, p) { + t.Error("IsPath returns true on bad path of length 2") + } + dg.SetEdge(simple.Edge{F: p[0], T: p[1]}) + if !IsPathIn(dg, p) { + t.Error("IsPath returns false on correct path of length 2") + } + p[0], p[1] = p[1], p[0] + if IsPathIn(dg, p) { + t.Error("IsPath erroneously returns true for a reverse path") + } + p = []graph.Node{p[1], p[0], simple.Node(2)} + dg.SetEdge(simple.Edge{F: p[1], T: p[2]}) + if !IsPathIn(dg, p) { + t.Error("IsPath does not find a correct path for path > 2 nodes") + } + ug := simple.NewUndirectedGraph() + ug.SetEdge(simple.Edge{F: p[1], T: p[0]}) + ug.SetEdge(simple.Edge{F: p[1], T: p[2]}) + if !IsPathIn(dg, p) { + t.Error("IsPath does not correctly account for undirected behavior") + } +} + +var pathExistsInUndirectedTests = []struct { + g []intset + from, to int + want bool +}{ + {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, + {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 1, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, + {g: batageljZaversnikGraph, from: 20, to: 6, want: true}, +} + +func TestPathExistsInUndirected(t *testing.T) { + for i, test := range pathExistsInUndirectedTests { + g := simple.NewUndirectedGraph() + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) + if got != test.want { + t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want) + } + } +} + +var pathExistsInDirectedTests = []struct { + g []intset + from, to int + want bool +}{ + // The graph definition is such that from node IDs are + // less than to node IDs. + {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, + {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, + {g: batageljZaversnikGraph, from: 20, to: 6, want: false}, + {g: batageljZaversnikGraph, from: 6, to: 20, want: true}, +} + +func TestPathExistsInDirected(t *testing.T) { + for i, test := range pathExistsInDirectedTests { + g := simple.NewDirectedGraph() + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) + if got != test.want { + t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want) + } + } +} + +var connectedComponentTests = []struct { + g []intset + want [][]int64 +}{ + { + g: batageljZaversnikGraph, + want: [][]int64{ + {0}, + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, +} + +func TestConnectedComponents(t *testing.T) { + for i, test := range connectedComponentTests { + g := simple.NewUndirectedGraph() + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cc := ConnectedComponents(g) + got := make([][]int64, len(cc)) + for j, c := range cc { + ids := make([]int64, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Sort(ordered.Int64s(ids)) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected connected components for test %d %T:\ngot: %v\nwant:%v", i, g, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/graph/traverse/doc.go b/vendor/gonum.org/v1/gonum/graph/traverse/doc.go new file mode 100644 index 00000000..7bb3ca11 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/traverse/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 traverse provides basic graph traversal primitives. +package traverse // import "gonum.org/v1/gonum/graph/traverse" diff --git a/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go b/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go new file mode 100644 index 00000000..329649e2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go @@ -0,0 +1,180 @@ +// Copyright ©2015 The gonum 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 traverse + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/linear" + "gonum.org/v1/gonum/graph/internal/set" +) + +// BreadthFirst implements stateful breadth-first graph traversal. +type BreadthFirst struct { + EdgeFilter func(graph.Edge) bool + Visit func(u, v graph.Node) + queue linear.NodeQueue + visited set.Int64s +} + +// Walk performs a breadth-first traversal of the graph g starting from the given node, +// depending on the the EdgeFilter field and the until parameter if they are non-nil. The +// traversal follows edges for which EdgeFilter(edge) is true and returns the first node +// for which until(node, depth) is true. During the traversal, if the Visit field is +// non-nil, it is called with the nodes joined by each followed edge. +func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node { + if b.visited == nil { + b.visited = make(set.Int64s) + } + b.queue.Enqueue(from) + b.visited.Add(from.ID()) + + var ( + depth int + children int + untilNext = 1 + ) + for b.queue.Len() > 0 { + t := b.queue.Dequeue() + if until != nil && until(t, depth) { + return t + } + for _, n := range g.From(t) { + if b.EdgeFilter != nil && !b.EdgeFilter(g.Edge(t, n)) { + continue + } + if b.visited.Has(n.ID()) { + continue + } + if b.Visit != nil { + b.Visit(t, n) + } + b.visited.Add(n.ID()) + children++ + b.queue.Enqueue(n) + } + if untilNext--; untilNext == 0 { + depth++ + untilNext = children + children = 0 + } + } + + return nil +} + +// WalkAll calls Walk for each unvisited node of the graph g using edges independent +// of their direction. The functions before and after are called prior to commencing +// and after completing each walk if they are non-nil respectively. The function +// during is called on each node as it is traversed. +func (b *BreadthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) { + b.Reset() + for _, from := range g.Nodes() { + if b.Visited(from) { + continue + } + if before != nil { + before() + } + b.Walk(g, from, func(n graph.Node, _ int) bool { + if during != nil { + during(n) + } + return false + }) + if after != nil { + after() + } + } +} + +// Visited returned whether the node n was visited during a traverse. +func (b *BreadthFirst) Visited(n graph.Node) bool { + return b.visited.Has(n.ID()) +} + +// Reset resets the state of the traverser for reuse. +func (b *BreadthFirst) Reset() { + b.queue.Reset() + b.visited = nil +} + +// DepthFirst implements stateful depth-first graph traversal. +type DepthFirst struct { + EdgeFilter func(graph.Edge) bool + Visit func(u, v graph.Node) + stack linear.NodeStack + visited set.Int64s +} + +// Walk performs a depth-first traversal of the graph g starting from the given node, +// depending on the the EdgeFilter field and the until parameter if they are non-nil. The +// traversal follows edges for which EdgeFilter(edge) is true and returns the first node +// for which until(node) is true. During the traversal, if the Visit field is non-nil, it +// is called with the nodes joined by each followed edge. +func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node { + if d.visited == nil { + d.visited = make(set.Int64s) + } + d.stack.Push(from) + d.visited.Add(from.ID()) + + for d.stack.Len() > 0 { + t := d.stack.Pop() + if until != nil && until(t) { + return t + } + for _, n := range g.From(t) { + if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) { + continue + } + if d.visited.Has(n.ID()) { + continue + } + if d.Visit != nil { + d.Visit(t, n) + } + d.visited.Add(n.ID()) + d.stack.Push(n) + } + } + + return nil +} + +// WalkAll calls Walk for each unvisited node of the graph g using edges independent +// of their direction. The functions before and after are called prior to commencing +// and after completing each walk if they are non-nil respectively. The function +// during is called on each node as it is traversed. +func (d *DepthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) { + d.Reset() + for _, from := range g.Nodes() { + if d.Visited(from) { + continue + } + if before != nil { + before() + } + d.Walk(g, from, func(n graph.Node) bool { + if during != nil { + during(n) + } + return false + }) + if after != nil { + after() + } + } +} + +// Visited returned whether the node n was visited during a traverse. +func (d *DepthFirst) Visited(n graph.Node) bool { + return d.visited.Has(n.ID()) +} + +// Reset resets the state of the traverser for reuse. +func (d *DepthFirst) Reset() { + d.stack = d.stack[:0] + d.visited = nil +} diff --git a/vendor/gonum.org/v1/gonum/graph/traverse/traverse_test.go b/vendor/gonum.org/v1/gonum/graph/traverse/traverse_test.go new file mode 100644 index 00000000..ad817352 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/traverse/traverse_test.go @@ -0,0 +1,433 @@ +// Copyright ©2015 The gonum 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 traverse + +import ( + "fmt" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + // batageljZaversnikGraph is the example graph from + // figure 1 of http://arxiv.org/abs/cs/0310049v1 + batageljZaversnikGraph = []intset{ + 0: nil, + + 1: linksTo(2, 3), + 2: linksTo(4), + 3: linksTo(4), + 4: linksTo(5), + 5: nil, + + 6: linksTo(7, 8, 14), + 7: linksTo(8, 11, 12, 14), + 8: linksTo(14), + 9: linksTo(11), + 10: linksTo(11), + 11: linksTo(12), + 12: linksTo(18), + 13: linksTo(14, 15), + 14: linksTo(15, 17), + 15: linksTo(16, 17), + 16: nil, + 17: linksTo(18, 19, 20), + 18: linksTo(19, 20), + 19: linksTo(20), + 20: nil, + } + + // wpBronKerboschGraph is the example given in the Bron-Kerbosch article on wikipedia (renumbered). + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + wpBronKerboschGraph = []intset{ + 0: linksTo(1, 4), + 1: linksTo(2, 4), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: nil, + 5: nil, + } +) + +var breadthFirstTests = []struct { + g []intset + from graph.Node + edge func(graph.Edge) bool + until func(graph.Node, int) bool + final map[graph.Node]bool + want [][]int64 +}{ + { + g: wpBronKerboschGraph, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: [][]int64{ + {1}, + {0, 2, 4}, + {3}, + {5}, + }, + }, + { + g: wpBronKerboschGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 3 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 3) + }, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: [][]int64{ + {1}, + {0, 2, 4}, + {3}, + }, + }, + { + g: wpBronKerboschGraph, + from: simple.Node(1), + until: func(n graph.Node, _ int) bool { return n == simple.Node(3) }, + final: map[graph.Node]bool{simple.Node(3): true}, + want: [][]int64{ + {1}, + {0, 2, 4}, + }, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + final: map[graph.Node]bool{nil: true}, + want: [][]int64{ + {13}, + {14, 15}, + {6, 7, 8, 16, 17}, + {11, 12, 18, 19, 20}, + {9, 10}, + }, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + until: func(_ graph.Node, d int) bool { return d > 2 }, + final: map[graph.Node]bool{ + simple.Node(11): true, + simple.Node(12): true, + simple.Node(18): true, + simple.Node(19): true, + simple.Node(20): true, + }, + want: [][]int64{ + {13}, + {14, 15}, + {6, 7, 8, 16, 17}, + }, + }, +} + +func TestBreadthFirst(t *testing.T) { + for i, test := range breadthFirstTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + w := BreadthFirst{ + EdgeFilter: test.edge, + } + var got [][]int64 + final := w.Walk(g, test.from, func(n graph.Node, d int) bool { + if test.until != nil && test.until(n, d) { + return true + } + if d >= len(got) { + got = append(got, []int64(nil)) + } + got[d] = append(got[d], n.ID()) + return false + }) + if !test.final[final] { + t.Errorf("unexepected final node for test %d:\ngot: %v\nwant: %v", i, final, test.final) + } + for _, l := range got { + sort.Sort(ordered.Int64s(l)) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexepected BFS level structure for test %d:\ngot: %v\nwant: %v", i, got, test.want) + } + } +} + +var depthFirstTests = []struct { + g []intset + from graph.Node + edge func(graph.Edge) bool + until func(graph.Node) bool + final map[graph.Node]bool + want []int64 +}{ + { + g: wpBronKerboschGraph, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: []int64{0, 1, 2, 3, 4, 5}, + }, + { + g: wpBronKerboschGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 3 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 3) + }, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: []int64{0, 1, 2, 3, 4}, + }, + { + g: wpBronKerboschGraph, + from: simple.Node(1), + until: func(n graph.Node) bool { return n == simple.Node(3) }, + final: map[graph.Node]bool{simple.Node(3): true}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(0), + final: map[graph.Node]bool{nil: true}, + want: []int64{0}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(3), + final: map[graph.Node]bool{nil: true}, + want: []int64{1, 2, 3, 4, 5}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + final: map[graph.Node]bool{nil: true}, + want: []int64{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, +} + +func TestDepthFirst(t *testing.T) { + for i, test := range depthFirstTests { + g := simple.NewUndirectedGraph() + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + w := DepthFirst{ + EdgeFilter: test.edge, + } + var got []int64 + final := w.Walk(g, test.from, func(n graph.Node) bool { + if test.until != nil && test.until(n) { + return true + } + got = append(got, n.ID()) + return false + }) + if !test.final[final] { + t.Errorf("unexepected final node for test %d:\ngot: %v\nwant: %v", i, final, test.final) + } + sort.Sort(ordered.Int64s(got)) + if test.want != nil && !reflect.DeepEqual(got, test.want) { + t.Errorf("unexepected DFS traversed nodes for test %d:\ngot: %v\nwant: %v", i, got, test.want) + } + } +} + +var walkAllTests = []struct { + g []intset + edge func(graph.Edge) bool + want [][]int64 +}{ + { + g: batageljZaversnikGraph, + want: [][]int64{ + {0}, + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, + { + g: batageljZaversnikGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 4 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 4) + }, + want: [][]int64{ + {0}, + {1, 2, 3, 4}, + {5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, +} + +func TestWalkAll(t *testing.T) { + for i, test := range walkAllTests { + g := simple.NewUndirectedGraph() + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + type walker interface { + WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) + } + for _, w := range []walker{ + &BreadthFirst{}, + &DepthFirst{}, + } { + var ( + c []graph.Node + cc [][]graph.Node + ) + switch w := w.(type) { + case *BreadthFirst: + w.EdgeFilter = test.edge + case *DepthFirst: + w.EdgeFilter = test.edge + default: + panic(fmt.Sprintf("bad walker type: %T", w)) + } + during := func(n graph.Node) { + c = append(c, n) + } + after := func() { + cc = append(cc, []graph.Node(nil)) + cc[len(cc)-1] = append(cc[len(cc)-1], c...) + c = c[:0] + } + w.WalkAll(g, nil, after, during) + + got := make([][]int64, len(cc)) + for j, c := range cc { + ids := make([]int64, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Sort(ordered.Int64s(ids)) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected connected components for test %d using %T:\ngot: %v\nwant:%v", i, w, got, test.want) + } + } + } +} + +// intset is an integer set. +type intset map[int]struct{} + +func linksTo(i ...int) intset { + if len(i) == 0 { + return nil + } + s := make(intset) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + gnpUndirected_10_tenth = gnpUndirected(10, 0.1) + gnpUndirected_100_tenth = gnpUndirected(100, 0.1) + gnpUndirected_1000_tenth = gnpUndirected(1000, 0.1) + gnpUndirected_10_half = gnpUndirected(10, 0.5) + gnpUndirected_100_half = gnpUndirected(100, 0.5) + gnpUndirected_1000_half = gnpUndirected(1000, 0.5) +) + +func gnpUndirected(n int, p float64) graph.Undirected { + g := simple.NewUndirectedGraph() + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkWalkAllBreadthFirst(b *testing.B, g graph.Undirected) { + n := len(g.Nodes()) + b.ResetTimer() + var bft BreadthFirst + for i := 0; i < b.N; i++ { + bft.WalkAll(g, nil, nil, nil) + } + if len(bft.visited) != n { + b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, len(bft.visited)) + } +} + +func BenchmarkWalkAllBreadthFirstGnp_10_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_10_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_100_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_100_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_1000_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_1000_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_10_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_10_half) +} +func BenchmarkWalkAllBreadthFirstGnp_100_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_100_half) +} +func BenchmarkWalkAllBreadthFirstGnp_1000_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_1000_half) +} + +func benchmarkWalkAllDepthFirst(b *testing.B, g graph.Undirected) { + n := len(g.Nodes()) + b.ResetTimer() + var dft DepthFirst + for i := 0; i < b.N; i++ { + dft.WalkAll(g, nil, nil, nil) + } + if len(dft.visited) != n { + b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, len(dft.visited)) + } +} + +func BenchmarkWalkAllDepthFirstGnp_10_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_10_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_100_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_100_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_1000_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_1000_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_10_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_10_half) +} +func BenchmarkWalkAllDepthFirstGnp_100_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_100_half) +} +func BenchmarkWalkAllDepthFirstGnp_1000_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_1000_half) +} diff --git a/vendor/gonum.org/v1/gonum/graph/undirect.go b/vendor/gonum.org/v1/gonum/graph/undirect.go new file mode 100644 index 00000000..e045dad4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/undirect.go @@ -0,0 +1,224 @@ +// Copyright ©2015 The gonum 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 graph + +// Undirect converts a directed graph to an undirected graph. +type Undirect struct { + G Directed +} + +var _ Undirected = Undirect{} + +// Has returns whether the node exists within the graph. +func (g Undirect) Has(n Node) bool { return g.G.Has(n) } + +// Nodes returns all the nodes in the graph. +func (g Undirect) Nodes() []Node { return g.G.Nodes() } + +// From returns all nodes in g that can be reached directly from u. +func (g Undirect) From(u Node) []Node { + var nodes []Node + seen := make(map[int64]struct{}) + for _, n := range g.G.From(u) { + seen[n.ID()] = struct{}{} + nodes = append(nodes, n) + } + for _, n := range g.G.To(u) { + id := n.ID() + if _, ok := seen[id]; ok { + continue + } + seen[n.ID()] = struct{}{} + nodes = append(nodes, n) + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g Undirect) HasEdgeBetween(x, y Node) bool { return g.G.HasEdgeBetween(x, y) } + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +// If an edge exists, the Edge returned is an EdgePair. The weight of +// the edge is determined by applying the Merge func to the weights of the +// edges between u and v. +func (g Undirect) Edge(u, v Node) Edge { return g.EdgeBetween(u, v) } + +// EdgeBetween returns the edge between nodes x and y. If an edge exists, the +// Edge returned is an EdgePair. The weight of the edge is determined by +// applying the Merge func to the weights of edges between x and y. +func (g Undirect) EdgeBetween(x, y Node) Edge { + fe := g.G.Edge(x, y) + re := g.G.Edge(y, x) + if fe == nil && re == nil { + return nil + } + + return EdgePair{fe, re} +} + +// UndirectWeighted converts a directed weighted graph to an undirected weighted graph, +// resolving edge weight conflicts. +type UndirectWeighted struct { + G WeightedDirected + + // Absent is the value used to + // represent absent edge weights + // passed to Merge if the reverse + // edge is present. + Absent float64 + + // Merge defines how discordant edge + // weights in G are resolved. A merge + // is performed if at least one edge + // exists between the nodes being + // considered. The edges corresponding + // to the two weights are also passed, + // in the same order. + // The order of weight parameters + // passed to Merge is not defined, so + // the function should be commutative. + // If Merge is nil, the arithmetic + // mean is used to merge weights. + Merge func(x, y float64, xe, ye Edge) float64 +} + +var ( + _ Undirected = UndirectWeighted{} + _ WeightedUndirected = UndirectWeighted{} +) + +// Has returns whether the node exists within the graph. +func (g UndirectWeighted) Has(n Node) bool { return g.G.Has(n) } + +// Nodes returns all the nodes in the graph. +func (g UndirectWeighted) Nodes() []Node { return g.G.Nodes() } + +// From returns all nodes in g that can be reached directly from u. +func (g UndirectWeighted) From(u Node) []Node { + var nodes []Node + seen := make(map[int64]struct{}) + for _, n := range g.G.From(u) { + seen[n.ID()] = struct{}{} + nodes = append(nodes, n) + } + for _, n := range g.G.To(u) { + id := n.ID() + if _, ok := seen[id]; ok { + continue + } + seen[n.ID()] = struct{}{} + nodes = append(nodes, n) + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g UndirectWeighted) HasEdgeBetween(x, y Node) bool { return g.G.HasEdgeBetween(x, y) } + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +// If an edge exists, the Edge returned is an EdgePair. The weight of +// the edge is determined by applying the Merge func to the weights of the +// edges between u and v. +func (g UndirectWeighted) Edge(u, v Node) Edge { return g.WeightedEdgeBetween(u, v) } + +// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +// If an edge exists, the Edge returned is an EdgePair. The weight of +// the edge is determined by applying the Merge func to the weights of the +// edges between u and v. +func (g UndirectWeighted) WeightedEdge(u, v Node) WeightedEdge { return g.WeightedEdgeBetween(u, v) } + +// EdgeBetween returns the edge between nodes x and y. If an edge exists, the +// Edge returned is an EdgePair. The weight of the edge is determined by +// applying the Merge func to the weights of edges between x and y. +func (g UndirectWeighted) EdgeBetween(x, y Node) Edge { + return g.WeightedEdgeBetween(x, y) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. If an edge exists, the +// Edge returned is an EdgePair. The weight of the edge is determined by +// applying the Merge func to the weights of edges between x and y. +func (g UndirectWeighted) WeightedEdgeBetween(x, y Node) WeightedEdge { + fe := g.G.Edge(x, y) + re := g.G.Edge(y, x) + if fe == nil && re == nil { + return nil + } + + f, ok := g.G.Weight(x, y) + if !ok { + f = g.Absent + } + r, ok := g.G.Weight(y, x) + if !ok { + r = g.Absent + } + + var w float64 + if g.Merge == nil { + w = (f + r) / 2 + } else { + w = g.Merge(f, r, fe, re) + } + return WeightedEdgePair{EdgePair: [2]Edge{fe, re}, W: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g UndirectWeighted) Weight(x, y Node) (w float64, ok bool) { + fe := g.G.Edge(x, y) + re := g.G.Edge(y, x) + + f, fOk := g.G.Weight(x, y) + if !fOk { + f = g.Absent + } + r, rOK := g.G.Weight(y, x) + if !rOK { + r = g.Absent + } + ok = fOk || rOK + + if g.Merge == nil { + return (f + r) / 2, ok + } + return g.Merge(f, r, fe, re), ok +} + +// EdgePair is an opposed pair of directed edges. +type EdgePair [2]Edge + +// From returns the from node of the first non-nil edge, or nil. +func (e EdgePair) From() Node { + if e[0] != nil { + return e[0].From() + } else if e[1] != nil { + return e[1].From() + } + return nil +} + +// To returns the to node of the first non-nil edge, or nil. +func (e EdgePair) To() Node { + if e[0] != nil { + return e[0].To() + } else if e[1] != nil { + return e[1].To() + } + return nil +} + +// WeightedEdgePair is an opposed pair of directed edges. +type WeightedEdgePair struct { + EdgePair + W float64 +} + +// Weight returns the merged edge weights of the two edges. +func (e WeightedEdgePair) Weight() float64 { return e.W } diff --git a/vendor/gonum.org/v1/gonum/graph/undirect_test.go b/vendor/gonum.org/v1/gonum/graph/undirect_test.go new file mode 100644 index 00000000..8b9b9883 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/undirect_test.go @@ -0,0 +1,175 @@ +// Copyright ©2015 The gonum 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 graph_test + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/mat" +) + +type weightedDirectedBuilder interface { + graph.WeightedBuilder + graph.WeightedDirected +} + +var weightedDirectedGraphs = []struct { + skipUnweighted bool + + g func() weightedDirectedBuilder + edges []simple.WeightedEdge + absent float64 + merge func(x, y float64, xe, ye graph.Edge) float64 + + want mat.Matrix +}{ + { + g: func() weightedDirectedBuilder { return simple.NewWeightedDirectedGraph(0, 0) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + want: mat.NewSymDense(3, []float64{ + 0, (1. + 2.) / 2., 0, + (1. + 2.) / 2., 0, 1. / 2., + 0, 1. / 2., 0, + }), + }, + { + g: func() weightedDirectedBuilder { return simple.NewWeightedDirectedGraph(0, 0) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + absent: 1, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Sqrt(x * y) }, + want: mat.NewSymDense(3, []float64{ + 0, math.Sqrt(1 * 2), 0, + math.Sqrt(1 * 2), 0, math.Sqrt(1 * 1), + 0, math.Sqrt(1 * 1), 0, + }), + }, + { + skipUnweighted: true, // The min merge function cannot be used in the unweighted case. + + g: func() weightedDirectedBuilder { return simple.NewWeightedDirectedGraph(0, 0) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Min(x, y) }, + want: mat.NewSymDense(3, []float64{ + 0, math.Min(1, 2), 0, + math.Min(1, 2), 0, math.Min(1, 0), + 0, math.Min(1, 0), 0, + }), + }, + { + g: func() weightedDirectedBuilder { return simple.NewWeightedDirectedGraph(0, 0) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, xe, ye graph.Edge) float64 { + if xe == nil { + return y + } + if ye == nil { + return x + } + return math.Min(x, y) + }, + want: mat.NewSymDense(3, []float64{ + 0, math.Min(1, 2), 0, + math.Min(1, 2), 0, 1, + 0, 1, 0, + }), + }, + { + g: func() weightedDirectedBuilder { return simple.NewWeightedDirectedGraph(0, 0) }, + edges: []simple.WeightedEdge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Max(x, y) }, + want: mat.NewSymDense(3, []float64{ + 0, math.Max(1, 2), 0, + math.Max(1, 2), 0, math.Max(1, 0), + 0, math.Max(1, 0), 0, + }), + }, +} + +func TestUndirect(t *testing.T) { + for i, test := range weightedDirectedGraphs { + if test.skipUnweighted { + continue + } + g := test.g() + for _, e := range test.edges { + g.SetWeightedEdge(e) + } + + src := graph.Undirect{G: g} + dst := simple.NewUndirectedMatrixFrom(src.Nodes(), 0, 0, 0) + for _, u := range src.Nodes() { + for _, v := range src.From(u) { + dst.SetEdge(src.Edge(u, v)) + } + } + + want := unit{test.want} + if !mat.Equal(dst.Matrix(), want) { + t.Errorf("unexpected result for case %d:\ngot:\n%.4v\nwant:\n%.4v", i, + mat.Formatted(dst.Matrix()), + mat.Formatted(want), + ) + } + } +} + +func TestUndirectWeighted(t *testing.T) { + for i, test := range weightedDirectedGraphs { + g := test.g() + for _, e := range test.edges { + g.SetWeightedEdge(e) + } + + src := graph.UndirectWeighted{G: g, Absent: test.absent, Merge: test.merge} + dst := simple.NewUndirectedMatrixFrom(src.Nodes(), 0, 0, 0) + for _, u := range src.Nodes() { + for _, v := range src.From(u) { + dst.SetWeightedEdge(src.WeightedEdge(u, v)) + } + } + + if !mat.Equal(dst.Matrix(), test.want) { + t.Errorf("unexpected result for case %d:\ngot:\n%.4v\nwant:\n%.4v", i, + mat.Formatted(dst.Matrix()), + mat.Formatted(test.want), + ) + } + } +} + +type unit struct { + mat.Matrix +} + +func (m unit) At(i, j int) float64 { + v := m.Matrix.At(i, j) + if v == 0 { + return 0 + } + return 1 +} diff --git a/vendor/gonum.org/v1/gonum/integrate/README.md b/vendor/gonum.org/v1/gonum/integrate/README.md new file mode 100644 index 00000000..1c929a8d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/README.md @@ -0,0 +1,3 @@ +# Gonum integrate [![GoDoc](https://godoc.org/gonum.org/v1/gonum/integrate?status.svg)](https://godoc.org/gonum.org/v1/gonum/integrate) + +Package integrate provides numerical evaluation of definite integrals of single-variable functions for the Go programming language. diff --git a/vendor/gonum.org/v1/gonum/integrate/doc.go b/vendor/gonum.org/v1/gonum/integrate/doc.go new file mode 100644 index 00000000..81bddb3b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2016 The gonum 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 integrate provides functions to compute an integral given a +// specific list of evaluations. +package integrate // import "gonum.org/v1/gonum/integrate" diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/doc.go b/vendor/gonum.org/v1/gonum/integrate/quad/doc.go new file mode 100644 index 00000000..480edcc0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 quad provides numerical evaluation of definite integrals of single-variable functions. +// +package quad // import "gonum.org/v1/gonum/integrate/quad" diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/example_test.go b/vendor/gonum.org/v1/gonum/integrate/quad/example_test.go new file mode 100644 index 00000000..32a4886a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/example_test.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum 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 quad_test + +import ( + "fmt" + "math" + "runtime" + + "gonum.org/v1/gonum/integrate/quad" + "gonum.org/v1/gonum/stat/distuv" +) + +func Example() { + fmt.Println("Evaluate the expected value of x^2 + 3 under a Weibull distribution") + f := func(x float64) float64 { + d := distuv.Weibull{Lambda: 1, K: 1.5} + return (x*x + 3) * d.Prob(x) + } + ev := quad.Fixed(f, 0, math.Inf(1), 10, nil, 0) + fmt.Printf("EV with 10 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 30, nil, 0) + fmt.Printf("EV with 30 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 100, nil, 0) + fmt.Printf("EV with 100 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 10000, nil, 0) + fmt.Printf("EV with 10000 points = %0.6v\n\n", ev) + + fmt.Println("Estimate using parallel evaluations of f.") + concurrent := runtime.GOMAXPROCS(0) + ev = quad.Fixed(f, 0, math.Inf(1), 100, nil, concurrent) + fmt.Printf("EV = %0.6v\n", ev) + // Output: + // Evaluate the expected value of x^2 + 3 under a Weibull distribution + // EV with 10 points = 4.20175 + // EV with 30 points = 4.19066 + // EV with 100 points = 4.19064 + // EV with 10000 points = 4.19064 + // + // Estimate using parallel evaluations of f. + // EV = 4.19064 +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/hermite.go b/vendor/gonum.org/v1/gonum/integrate/quad/hermite.go new file mode 100644 index 00000000..d2755f0e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/hermite.go @@ -0,0 +1,314 @@ +// Copyright ©2016 The gonum 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 quad + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" +) + +// Hermite generates sample locations and weights for performing quadrature with +// with a squared-exponential weight +// int_-inf^inf e^(-x^2) f(x) dx . +type Hermite struct{} + +func (h Hermite) FixedLocations(x, weight []float64, min, max float64) { + // TODO(btracey): Implement the case where x > 20, x < 200 so that we don't + // need to store all of that data. + + // Algorithm adapted from Chebfun http://www.chebfun.org/. + // + // References: + // Algorithm: + // G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature rules", + // Math. Comp. 23:221-230, 1969. + // A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the + // calculation of the roots of special functions", SIAM Journal + // on Scientific Computing", 29(4):1420-1438:, 2007. + // A. Townsend, T. Trogdon, and S.Olver, Fast computation of Gauss quadrature + // nodes and weights on the whole real line, IMA J. Numer. Anal., 36: 337–358, + // 2016. http://arxiv.org/abs/1410.5286 + + if len(x) != len(weight) { + panic("hermite: slice length mismatch") + } + if min >= max { + panic("hermite: min >= max") + } + if !math.IsInf(min, -1) || !math.IsInf(max, 1) { + panic("hermite: non-infinite bound") + } + h.locations(x, weight) +} + +func (h Hermite) locations(x, weights []float64) { + n := len(x) + switch { + case 0 < n && n <= 200: + copy(x, xCacheHermite[n-1]) + copy(weights, wCacheHermite[n-1]) + case n > 200: + h.locationsAsy(x, weights) + } +} + +// Algorithm adapted from Chebfun http://www.chebfun.org/. Specific code +// https://github.com/chebfun/chebfun/blob/development/hermpts.m. + +// Original Copyright Notice: + +/* +Copyright (c) 2015, The Chancellor, Masters and Scholars of the University +of Oxford, and the Chebfun Developers. 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 the University of Oxford 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. +*/ + +// locationAsy returns the node locations and weights of a Hermite quadrature rule +// with len(x) points. +func (h Hermite) locationsAsy(x, w []float64) { + // A. Townsend, T. Trogdon, and S.Olver, Fast computation of Gauss quadrature + // nodes and weights the whole real line, IMA J. Numer. Anal., + // 36: 337–358, 2016. http://arxiv.org/abs/1410.5286 + + // Find the positive locations and weights. + n := len(x) + l := n / 2 + xa := x[l:] + wa := w[l:] + for i := range xa { + xa[i], wa[i] = h.locationsAsy0(i, n) + } + // Flip around zero -- copy the negative x locations with the corresponding + // weights. + if n%2 == 0 { + l-- + } + for i, v := range xa { + x[l-i] = -v + } + for i, v := range wa { + w[l-i] = v + } + sumW := floats.Sum(w) + c := math.SqrtPi / sumW + floats.Scale(c, w) +} + +// locationsAsy0 returns the location and weight for location i in an n-point +// quadrature rule. The rule is symmetric, so i should be <= n/2 + n%2. +func (h Hermite) locationsAsy0(i, n int) (x, w float64) { + const convTol = 1e-16 + const convIter = 20 + theta0 := h.hermiteInitialGuess(i, n) + t0 := theta0 / math.Sqrt(2*float64(n)+1) + theta0 = math.Acos(t0) + sqrt2np1 := math.Sqrt(2*float64(n) + 1) + var vali, dvali float64 + for k := 0; k < convIter; k++ { + vali, dvali = h.hermpolyAsyAiry(i, n, theta0) + dt := -vali / (math.Sqrt2 * sqrt2np1 * dvali * math.Sin(theta0)) + theta0 -= dt + if math.Abs(theta0) < convTol { + break + } + } + x = sqrt2np1 * math.Cos(theta0) + ders := x*vali + math.Sqrt2*dvali + w = math.Exp(-x*x) / (ders * ders) + return x, w +} + +// hermpolyAsyAiry evaluates the Hermite polynomials using the Airy asymptotic +// formula in theta-space. +func (h Hermite) hermpolyAsyAiry(i, n int, t float64) (valVec, dvalVec float64) { + musq := 2*float64(n) + 1 + cosT := math.Cos(t) + sinT := math.Sin(t) + sin2T := 2 * cosT * sinT + eta := 0.5*t - 0.25*sin2T + chi := -math.Pow(3*eta/2, 2.0/3) + phi := math.Pow(-chi/(sinT*sinT), 1.0/4) + cnst := 2 * math.SqrtPi * math.Pow(musq, 1.0/6) * phi + airy0 := real(mathext.AiryAi(complex(math.Pow(musq, 2.0/3)*chi, 0))) + airy1 := real(mathext.AiryAiDeriv(complex(math.Pow(musq, 2.0/3)*chi, 0))) + + // Terms in 12.10.43: + const ( + a1 = 15.0 / 144 + b1 = -7.0 / 5 * a1 + a2 = 5.0 * 7 * 9 * 11.0 / 2.0 / 144.0 / 144.0 + b2 = -13.0 / 11 * a2 + a3 = 7.0 * 9 * 11 * 13 * 15 * 17 / 6.0 / 144.0 / 144.0 / 144.0 + b3 = -19.0 / 17 * a3 + ) + + // Pre-compute terms. + cos2T := cosT * cosT + cos3T := cos2T * cosT + cos4T := cos3T * cosT + cos5T := cos4T * cosT + cos7T := cos5T * cos2T + cos9T := cos7T * cos2T + + chi2 := chi * chi + chi3 := chi2 * chi + chi4 := chi3 * chi + chi5 := chi4 * chi + + phi6 := math.Pow(phi, 6) + phi12 := phi6 * phi6 + phi18 := phi12 * phi6 + + // u polynomials in 12.10.9. + u1 := (cos3T - 6*cosT) / 24.0 + u2 := (-9*cos4T + 249*cos2T + 145) / 1152.0 + u3 := (-4042*cos9T + 18189*cos7T - 28287*cos5T - 151995*cos3T - 259290*cosT) / 414720.0 + + val := airy0 + B0 := -(phi6*u1 + a1) / chi2 + val += B0 * airy1 / math.Pow(musq, 4.0/3) + A1 := (phi12*u2 + b1*phi6*u1 + b2) / chi3 + val += A1 * airy0 / (musq * musq) + B1 := -(phi18*u3 + a1*phi12*u2 + a2*phi6*u1 + a3) / chi5 + val += B1 * airy1 / math.Pow(musq, 4.0/3+2) + val *= cnst + + // Derivative. + eta = 0.5*t - 0.25*sin2T + chi = -math.Pow(3*eta/2, 2.0/3) + phi = math.Pow(-chi/(sinT*sinT), 1.0/4) + cnst = math.Sqrt2 * math.SqrtPi * math.Pow(musq, 1.0/3) / phi + + // v polynomials in 12.10.10. + v1 := (cos3T + 6*cosT) / 24 + v2 := (15*cos4T - 327*cos2T - 143) / 1152 + v3 := (259290*cosT + 238425*cos3T - 36387*cos5T + 18189*cos7T - 4042*cos9T) / 414720 + + C0 := -(phi6*v1 + b1) / chi + dval := C0 * airy0 / math.Pow(musq, 2.0/3) + dval += airy1 + C1 := -(phi18*v3 + b1*phi12*v2 + b2*phi6*v1 + b3) / chi4 + dval += C1 * airy0 / math.Pow(musq, 2.0/3+2) + D1 := (phi12*v2 + a1*phi6*v1 + a2) / chi3 + dval += D1 * airy1 / (musq * musq) + dval *= cnst + return val, dval +} + +// hermiteInitialGuess returns the initial guess for node i in an n-point Hermite +// quadrature rule. The rule is symmetric, so i should be <= n/2 + n%2. +func (h Hermite) hermiteInitialGuess(i, n int) float64 { + // There are two different formulas for the initial guesses of the hermite + // quadrature locations. The first uses the Gatteschi formula and is good + // near x = sqrt(n+0.5) + // [1] L. Gatteschi, Asymptotics and bounds for the zeros of Laguerre + // polynomials: a survey, J. Comput. Appl. Math., 144 (2002), pp. 7-27. + // The second is the Tricomi initial guesses, good near x = 0. This is + // equation 2.1 in [1] and is originally from + // [2] F. G. Tricomi, Sugli zeri delle funzioni di cui si conosce una + // rappresentazione asintotica, Ann. Mat. Pura Appl. 26 (1947), pp. 283-300. + + // If the number of points is odd, there is a quadrature point at 1, which + // has an initial guess of 0. + if n%2 == 1 { + if i == 0 { + return 0 + } + i-- + } + + m := n / 2 + a := -0.5 + if n%2 == 1 { + a = 0.5 + } + nu := 4*float64(m) + 2*a + 2 + + // Find the split between Gatteschi guesses and Tricomi guesses. + p := 0.4985 + math.SmallestNonzeroFloat64 + pidx := int(math.Floor(p * float64(n))) + + // Use the Tricomi initial guesses in the first half where x is nearer to zero. + // Note: zeros of besselj(+/-.5,x) are integer and half-integer multiples of pi. + if i < pidx { + rhs := math.Pi * (4*float64(m) - 4*(float64(i)+1) + 3) / nu + tnk := math.Pi / 2 + for k := 0; k < 7; k++ { + val := tnk - math.Sin(tnk) - rhs + dval := 1 - math.Cos(tnk) + dTnk := val / dval + tnk -= dTnk + if math.Abs(dTnk) < 1e-14 { + break + } + } + vc := math.Cos(tnk / 2) + t := vc * vc + return math.Sqrt(nu*t - (5.0/(4.0*(1-t)*(1-t))-1.0/(1-t)-1+3*a*a)/3/nu) + } + + // Use Gatteschi guesses in the second half where x is nearer to sqrt(n+0.5) + i = i + 1 - m + var ar float64 + if i < len(airyRtsExact) { + ar = airyRtsExact[i] + } else { + t := 3.0 / 8 * math.Pi * (4*(float64(i)+1) - 1) + ar = math.Pow(t, 2.0/3) * (1 + + 5.0/48*math.Pow(t, -2) - + 5.0/36*math.Pow(t, -4) + + 77125.0/82944*math.Pow(t, -6) - + 108056875.0/6967296*math.Pow(t, -8) + + 162375596875.0/334430208*math.Pow(t, -10)) + } + r := nu + math.Pow(2, 2.0/3)*ar*math.Pow(nu, 1.0/3) + + 0.2*math.Pow(2, 4.0/3)*ar*ar*math.Pow(nu, -1.0/3) + + (11.0/35-a*a-12.0/175*ar*ar*ar)/nu + + (16.0/1575*ar+92.0/7875*math.Pow(ar, 4))*math.Pow(2, 2.0/3)*math.Pow(nu, -5.0/3) - + (15152.0/3031875*math.Pow(ar, 5)+1088.0/121275*ar*ar)*math.Pow(2, 1.0/3)*math.Pow(nu, -7.0/3) + if r < 0 { + ar = 0 + } else { + ar = math.Sqrt(r) + } + return ar +} + +// airyRtsExact are the first airy roots. +var airyRtsExact = []float64{ + -2.338107410459762, + -4.087949444130970, + -5.520559828095555, + -6.786708090071765, + -7.944133587120863, + -9.022650853340979, + -10.040174341558084, + -11.008524303733260, + -11.936015563236262, + -12.828776752865757, +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/hermite_data.go b/vendor/gonum.org/v1/gonum/integrate/quad/hermite_data.go new file mode 100644 index 00000000..c50c8dbb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/hermite_data.go @@ -0,0 +1,413 @@ +// Copyright ©2016 The gonum 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 quad + +// xCache computed from Chebfun. +var xCacheHermite = [][]float64{ + {0.0000000000000000e+00}, + {-7.0710678118654757e-01, 7.0710678118654757e-01}, + {-1.2247448713915887e+00, 0.0000000000000000e+00, 1.2247448713915887e+00}, + {-1.6506801238857842e+00, -5.2464762327529035e-01, 5.2464762327529035e-01, 1.6506801238857842e+00}, + {-2.0201828704560856e+00, -9.5857246461381873e-01, 0.0000000000000000e+00, 9.5857246461381873e-01, 2.0201828704560856e+00}, + {-2.3506049736744914e+00, -1.3358490740136970e+00, -4.3607741192761657e-01, 4.3607741192761657e-01, 1.3358490740136970e+00, 2.3506049736744914e+00}, + {-2.6519613568352316e+00, -1.6735516287674714e+00, -8.1628788285896481e-01, 0.0000000000000000e+00, 8.1628788285896481e-01, 1.6735516287674714e+00, 2.6519613568352316e+00}, + {-2.9306374202572436e+00, -1.9816567566958443e+00, -1.1571937124467804e+00, -3.8118699020732216e-01, 3.8118699020732216e-01, 1.1571937124467804e+00, 1.9816567566958443e+00, 2.9306374202572436e+00}, + {-3.1909932017815295e+00, -2.2665805845318427e+00, -1.4685532892166682e+00, -7.2355101875283767e-01, 0.0000000000000000e+00, 7.2355101875283767e-01, 1.4685532892166682e+00, 2.2665805845318427e+00, 3.1909932017815295e+00}, + {-3.4361591188377378e+00, -2.5327316742327901e+00, -1.7566836492998816e+00, -1.0366108297895138e+00, -3.4290132722370481e-01, 3.4290132722370481e-01, 1.0366108297895138e+00, 1.7566836492998816e+00, 2.5327316742327901e+00, 3.4361591188377378e+00}, + {-3.6684708465595812e+00, -2.7832900997816514e+00, -2.0259480158257550e+00, -1.3265570844949326e+00, -6.5680956688209979e-01, 0.0000000000000000e+00, 6.5680956688209979e-01, 1.3265570844949326e+00, 2.0259480158257550e+00, 2.7832900997816514e+00, 3.6684708465595812e+00}, + {-3.8897248978697814e+00, -3.0206370251208896e+00, -2.2795070805010593e+00, -1.5976826351526043e+00, -9.4778839124016367e-01, -3.1424037625435908e-01, 3.1424037625435908e-01, 9.4778839124016367e-01, 1.5976826351526043e+00, 2.2795070805010593e+00, 3.0206370251208896e+00, 3.8897248978697814e+00}, + {-4.1013375961786389e+00, -3.2466089783724090e+00, -2.5197356856782389e+00, -1.8531076516015121e+00, -1.2200550365907483e+00, -6.0576387917106034e-01, 0.0000000000000000e+00, 6.0576387917106034e-01, 1.2200550365907483e+00, 1.8531076516015121e+00, 2.5197356856782389e+00, 3.2466089783724090e+00, 4.1013375961786389e+00}, + {-4.3044485704736335e+00, -3.4626569336022701e+00, -2.7484707249854017e+00, -2.0951832585077166e+00, -1.4766827311411406e+00, -8.7871378732939931e-01, -2.9174551067256199e-01, 2.9174551067256199e-01, 8.7871378732939931e-01, 1.4766827311411406e+00, 2.0951832585077166e+00, 2.7484707249854017e+00, 3.4626569336022701e+00, 4.3044485704736335e+00}, + {-4.4999907073093910e+00, -3.6699503734044541e+00, -2.9671669279056028e+00, -2.3257324861738580e+00, -1.7199925751864888e+00, -1.1361155852109204e+00, -5.6506958325557588e-01, 0.0000000000000000e+00, 5.6506958325557588e-01, 1.1361155852109204e+00, 1.7199925751864888e+00, 2.3257324861738580e+00, 2.9671669279056028e+00, 3.6699503734044541e+00, 4.4999907073093910e+00}, + {-4.6887389393058223e+00, -3.8694479048601238e+00, -3.1769991619799529e+00, -2.5462021578474796e+00, -1.9517879909162528e+00, -1.3802585391988815e+00, -8.2295144914465546e-01, -2.7348104613815244e-01, 2.7348104613815244e-01, 8.2295144914465546e-01, 1.3802585391988815e+00, 1.9517879909162528e+00, 2.5462021578474796e+00, 3.1769991619799529e+00, 3.8694479048601238e+00, 4.6887389393058223e+00}, + {-4.8713451936744061e+00, -4.0619466758754772e+00, -3.3789320911414946e+00, -2.7577629157038897e+00, -2.1735028266666214e+00, -1.6129243142212311e+00, -1.0676487257434508e+00, -5.3163300134265479e-01, 0.0000000000000000e+00, 5.3163300134265479e-01, 1.0676487257434508e+00, 1.6129243142212311e+00, 2.1735028266666214e+00, 2.7577629157038897e+00, 3.3789320911414946e+00, 4.0619466758754772e+00, 4.8713451936744061e+00}, + {-5.0483640088744668e+00, -4.2481178735681260e+00, -3.5737690684862655e+00, -2.9613775055316052e+00, -2.3862990891666858e+00, -1.8355316042616294e+00, -1.3009208583896172e+00, -7.7668291926741173e-01, -2.5826775051909689e-01, 2.5826775051909689e-01, 7.7668291926741173e-01, 1.3009208583896172e+00, 1.8355316042616294e+00, 2.3862990891666858e+00, 2.9613775055316052e+00, 3.5737690684862655e+00, 4.2481178735681260e+00, 5.0483640088744668e+00}, + {-5.2202716905374844e+00, -4.4285328066037799e+00, -3.7621873519640201e+00, -3.1578488183476034e+00, -2.5911337897945423e+00, -2.0492317098506181e+00, -1.5241706193935327e+00, -1.0103683871343114e+00, -5.0352016342388828e-01, 0.0000000000000000e+00, 5.0352016342388828e-01, 1.0103683871343114e+00, 1.5241706193935327e+00, 2.0492317098506181e+00, 2.5911337897945423e+00, 3.1578488183476034e+00, 3.7621873519640201e+00, 4.4285328066037799e+00, 5.2202716905374844e+00}, + {-5.3874808900112319e+00, -4.6036824495507451e+00, -3.9447640401156265e+00, -3.3478545673832172e+00, -2.7888060584281313e+00, -2.2549740020892761e+00, -1.7385377121165857e+00, -1.2340762153953231e+00, -7.3747372854539406e-01, -2.4534070830090132e-01, 2.4534070830090132e-01, 7.3747372854539406e-01, 1.2340762153953231e+00, 1.7385377121165857e+00, 2.2549740020892761e+00, 2.7888060584281313e+00, 3.3478545673832172e+00, 3.9447640401156265e+00, 4.6036824495507451e+00, 5.3874808900112319e+00}, + {-5.5503518732646775e+00, -4.7739923434112193e+00, -4.1219955474918395e+00, -3.5319728771376777e+00, -2.9799912077045980e+00, -2.4535521245128376e+00, -1.9449629491862539e+00, -1.4489342506507319e+00, -9.6149963441836894e-01, -4.7945070707910747e-01, -0.0000000000000000e+00, 4.7945070707910747e-01, 9.6149963441836894e-01, 1.4489342506507319e+00, 1.9449629491862539e+00, 2.4535521245128376e+00, 2.9799912077045980e+00, 3.5319728771376777e+00, 4.1219955474918395e+00, 4.7739923434112193e+00, 5.5503518732646775e+00}, + {-5.7092013532052626e+00, -4.9398341310601763e+00, -4.2943124805931614e+00, -3.7107015328778048e+00, -3.1652659092021374e+00, -2.6456374410581724e+00, -2.1442335927985341e+00, -1.6558743732864223e+00, -1.1767139584812445e+00, -7.0368609717000696e-01, -2.3417913993099065e-01, 2.3417913993099065e-01, 7.0368609717000696e-01, 1.1767139584812445e+00, 1.6558743732864223e+00, 2.1442335927985341e+00, 2.6456374410581724e+00, 3.1652659092021374e+00, 3.7107015328778048e+00, 4.2943124805931614e+00, 4.9398341310601763e+00, 5.7092013532052626e+00}, + {-5.8643094989845714e+00, -5.1015346104766763e+00, -4.4620911737400064e+00, -3.8844727081061015e+00, -3.3451271599412244e+00, -2.8318037871261570e+00, -2.3370162114744559e+00, -1.8556770376713707e+00, -1.3840395856824952e+00, -9.1915146544256365e-01, -4.5853835006810478e-01, -0.0000000000000000e+00, 4.5853835006810478e-01, 9.1915146544256365e-01, 1.3840395856824952e+00, 1.8556770376713707e+00, 2.3370162114744559e+00, 2.8318037871261570e+00, 3.3451271599412244e+00, 3.8844727081061015e+00, 4.4620911737400064e+00, 5.1015346104766763e+00, 5.8643094989845714e+00}, + {-6.0159255614257390e+00, -5.2593829276680442e+00, -4.6256627564237878e+00, -4.0536644024481490e+00, -3.5200068130345241e+00, -3.0125461375655647e+00, -2.5238810170114268e+00, -2.0490035736616985e+00, -1.5842500109616942e+00, -1.1267608176112451e+00, -6.7417110703721217e-01, -2.2441454747251557e-01, 2.2441454747251557e-01, 6.7417110703721217e-01, 1.1267608176112451e+00, 1.5842500109616942e+00, 2.0490035736616985e+00, 2.5238810170114268e+00, 3.0125461375655647e+00, 3.5200068130345241e+00, 4.0536644024481490e+00, 4.6256627564237878e+00, 5.2593829276680442e+00, 6.0159255614257390e+00}, + {-6.1642724340524513e+00, -5.4136363552800333e+00, -4.7853203673522238e+00, -4.2186094443865612e+00, -3.6902828769983551e+00, -3.1882949244251044e+00, -2.7053202371730256e+00, -2.2364201302672808e+00, -1.7780011243371474e+00, -1.3272807020730839e+00, -8.8198275621382138e-01, -4.4014729864530827e-01, -0.0000000000000000e+00, 4.4014729864530827e-01, 8.8198275621382138e-01, 1.3272807020730839e+00, 1.7780011243371474e+00, 2.2364201302672808e+00, 2.7053202371730256e+00, 3.1882949244251044e+00, 3.6902828769983551e+00, 4.2186094443865612e+00, 4.7853203673522238e+00, 5.4136363552800333e+00, 6.1642724340524513e+00}, + {-6.3095503856256920e+00, -5.5645249819501030e+00, -4.9413249572413793e+00, -4.3796026629833040e+00, -3.8562884199091489e+00, -3.3594271823508297e+00, -2.8817622195430865e+00, -2.4184157647737790e+00, -1.9658547856411364e+00, -1.5213615166519212e+00, -1.0827330110778832e+00, -6.4809521399344827e-01, -2.1577785624346338e-01, 2.1577785624346338e-01, 6.4809521399344827e-01, 1.0827330110778832e+00, 1.5213615166519212e+00, 1.9658547856411364e+00, 2.4184157647737790e+00, 2.8817622195430865e+00, 3.3594271823508297e+00, 3.8562884199091489e+00, 4.3796026629833040e+00, 4.9413249572413793e+00, 5.5645249819501030e+00, 6.3095503856256920e+00}, + {-6.4519401407534707e+00, -5.7122555528165355e+00, -5.0939100031131836e+00, -4.5369066633724415e+00, -4.0183186704087381e+00, -3.5262753401343527e+00, -3.0535824198222552e+00, -2.5954163389108178e+00, -2.1482966453616275e+00, -1.7095607392603374e+00, -1.2770668173398578e+00, -8.4901134206010298e-01, -4.2380790054385303e-01, -0.0000000000000000e+00, 4.2380790054385303e-01, 8.4901134206010298e-01, 1.2770668173398578e+00, 1.7095607392603374e+00, 2.1482966453616275e+00, 2.5954163389108178e+00, 3.0535824198222552e+00, 3.5262753401343527e+00, 4.0183186704087381e+00, 4.5369066633724415e+00, 5.0939100031131836e+00, 5.7122555528165355e+00, 6.4519401407534707e+00}, + {-6.5916054423677419e+00, -5.8570146413828503e+00, -5.2432853732029354e+00, -4.6907565239431177e+00, -4.1766367421292676e+00, -3.6891342384616794e+00, -3.2211120765614556e+00, -2.7677953529135935e+00, -2.3257498426564407e+00, -1.8923604968376853e+00, -1.4655372634574091e+00, -1.0435352737542081e+00, -6.2483671950520925e-01, -2.0806738269073688e-01, 2.0806738269073688e-01, 6.2483671950520925e-01, 1.0435352737542081e+00, 1.4655372634574091e+00, 1.8923604968376853e+00, 2.3257498426564407e+00, 2.7677953529135935e+00, 3.2211120765614556e+00, 3.6891342384616794e+00, 4.1766367421292676e+00, 4.6907565239431177e+00, 5.2432853732029354e+00, 5.8570146413828503e+00, 6.5916054423677419e+00}, + {-6.7286951986088495e+00, -5.9989712894638192e+00, -5.3896405219667507e+00, -4.8413636510591642e+00, -4.3314782938191501e+00, -3.8482667922136202e+00, -3.3846451410922138e+00, -2.9358825042901264e+00, -2.4985856910194042e+00, -2.0701810760534278e+00, -1.6486229138923163e+00, -1.2322157550847530e+00, -8.1949868127091163e-01, -4.0916463639492873e-01, -0.0000000000000000e+00, 4.0916463639492873e-01, 8.1949868127091163e-01, 1.2322157550847530e+00, 1.6486229138923163e+00, 2.0701810760534278e+00, 2.4985856910194042e+00, 2.9358825042901264e+00, 3.3846451410922138e+00, 3.8482667922136202e+00, 4.3314782938191501e+00, 4.8413636510591642e+00, 5.3896405219667507e+00, 5.9989712894638192e+00, 6.7286951986088495e+00}, + {-6.8633452935298900e+00, -6.1382792201239331e+00, -5.5331471515674950e+00, -4.9889189685899442e+00, -4.4830553570925176e+00, -4.0039086038612286e+00, -3.5444438731553496e+00, -3.0999705295864417e+00, -2.6671321245356170e+00, -2.2433914677615041e+00, -1.8267411436036880e+00, -1.4155278001981884e+00, -1.0083382710467235e+00, -6.0392105862555223e-01, -2.0112857654887151e-01, 2.0112857654887151e-01, 6.0392105862555223e-01, 1.0083382710467235e+00, 1.4155278001981884e+00, 1.8267411436036880e+00, 2.2433914677615041e+00, 2.6671321245356170e+00, 3.0999705295864417e+00, 3.5444438731553496e+00, 4.0039086038612286e+00, 4.4830553570925176e+00, 4.9889189685899442e+00, 5.5331471515674950e+00, 6.1382792201239331e+00, 6.8633452935298900e+00}, + {-6.9956801237185395e+00, -6.2750787049428602e+00, -5.6739614446185875e+00, -5.1335955771123798e+00, -4.6315595063128594e+00, -4.1562717558181452e+00, -3.7007434032314697e+00, -3.2603207323135406e+00, -2.8316804533902054e+00, -2.4123177054804201e+00, -2.0002585489356388e+00, -1.5938858604721398e+00, -1.1918269983500462e+00, -7.9287697691530890e-01, -3.9594273647142297e-01, -0.0000000000000000e+00, 3.9594273647142297e-01, 7.9287697691530890e-01, 1.1918269983500462e+00, 1.5938858604721398e+00, 2.0002585489356388e+00, 2.4123177054804201e+00, 2.8316804533902054e+00, 3.2603207323135406e+00, 3.7007434032314697e+00, 4.1562717558181452e+00, 4.6315595063128594e+00, 5.1335955771123798e+00, 5.6739614446185875e+00, 6.2750787049428602e+00, 6.9956801237185395e+00}, + {-7.1258139098307272e+00, -6.4094981492696599e+00, -5.8122259495159128e+00, -5.2755509865158796e+00, -4.7771645035025960e+00, -4.3055479533511987e+00, -3.8537554854714444e+00, -3.4171674928185705e+00, -2.9924908250023741e+00, -2.5772495377323170e+00, -2.1694991836061122e+00, -1.7676541094632017e+00, -1.3703764109528718e+00, -9.7650046358968279e-01, -5.8497876543593241e-01, -1.9484074156939934e-01, 1.9484074156939934e-01, 5.8497876543593241e-01, 9.7650046358968279e-01, 1.3703764109528718e+00, 1.7676541094632017e+00, 2.1694991836061122e+00, 2.5772495377323170e+00, 2.9924908250023741e+00, 3.4171674928185705e+00, 3.8537554854714444e+00, 4.3055479533511987e+00, 4.7771645035025960e+00, 5.2755509865158796e+00, 5.8122259495159128e+00, 6.4094981492696599e+00, 7.1258139098307272e+00}, + {-7.2538518220151991e+00, -6.5416554457380762e+00, -5.9480711820871450e+00, -5.4149290026141923e+00, -4.9200285205950083e+00, -4.4519111488328269e+00, -4.0036716099569309e+00, -3.5707219802327179e+00, -3.1497966817038248e+00, -2.7384458243513548e+00, -2.3347511515295150e+00, -1.9371545818222065e+00, -1.5443482612431219e+00, -1.1552002041267895e+00, -7.6870137975886854e-01, -3.8392601450840907e-01, -0.0000000000000000e+00, 3.8392601450840907e-01, 7.6870137975886854e-01, 1.1552002041267895e+00, 1.5443482612431219e+00, 1.9371545818222065e+00, 2.3347511515295150e+00, 2.7384458243513548e+00, 3.1497966817038248e+00, 3.5707219802327179e+00, 4.0036716099569309e+00, 4.4519111488328269e+00, 4.9200285205950083e+00, 5.4149290026141923e+00, 5.9480711820871450e+00, 6.5416554457380762e+00, 7.2538518220151991e+00}, + {-7.3798909504812453e+00, -6.6716591360701694e+00, -6.0816169939363158e+00, -5.5518613309887774e+00, -5.0602960186057615e+00, -4.5955197481081704e+00, -4.1506656029707809e+00, -3.7211752324761531e+00, -3.3038084315644154e+00, -2.8961389431744311e+00, -2.4962719408165470e+00, -2.1026736904673324e+00, -1.7140625533873379e+00, -1.3293355518847858e+00, -9.4751645803344731e-01, -5.6771726855487448e-01, -1.8910806052714246e-01, 1.8910806052714246e-01, 5.6771726855487448e-01, 9.4751645803344731e-01, 1.3293355518847858e+00, 1.7140625533873379e+00, 2.1026736904673324e+00, 2.4962719408165470e+00, 2.8961389431744311e+00, 3.3038084315644154e+00, 3.7211752324761531e+00, 4.1506656029707809e+00, 4.5955197481081704e+00, 5.0602960186057615e+00, 5.5518613309887774e+00, 6.0816169939363158e+00, 6.6716591360701694e+00, 7.3798909504812453e+00}, + {-7.5040211464489355e+00, -6.7996094132841307e+00, -6.2129737476337166e+00, -5.6864689480904413e+00, -5.1980993461977523e+00, -4.7365184774132105e+00, -4.2948958144927625e+00, -3.8687007309691541e+00, -3.4547164957519905e+00, -3.0505384204304464e+00, -2.6542927811971722e+00, -2.2644675010425686e+00, -1.8798039887309170e+00, -1.4992244886117301e+00, -1.1217809907203027e+00, -7.4661763987986696e-01, -3.7294171704961682e-01, -0.0000000000000000e+00, 3.7294171704961682e-01, 7.4661763987986696e-01, 1.1217809907203027e+00, 1.4992244886117301e+00, 1.8798039887309170e+00, 2.2644675010425686e+00, 2.6542927811971722e+00, 3.0505384204304464e+00, 3.4547164957519905e+00, 3.8687007309691541e+00, 4.2948958144927625e+00, 4.7365184774132105e+00, 5.1980993461977523e+00, 5.6864689480904413e+00, 6.2129737476337166e+00, 6.7996094132841307e+00, 7.5040211464489355e+00}, + {-7.6263257540038927e+00, -6.9255989902599406e+00, -6.3422433309944113e+00, -5.8188632795055772e+00, -5.3335601071130636e+00, -4.8750399724670830e+00, -4.4365069701928563e+00, -4.0134565677494702e+00, -3.6026938571484757e+00, -3.2018339457881582e+00, -2.8090222351311036e+00, -2.4227660420535617e+00, -2.0418271835544202e+00, -1.6651500018434142e+00, -1.2918109588209239e+00, -9.2098180157075304e-01, -5.5190143329042274e-01, -1.8385336710581282e-01, 1.8385336710581282e-01, 5.5190143329042274e-01, 9.2098180157075304e-01, 1.2918109588209239e+00, 1.6651500018434142e+00, 2.0418271835544202e+00, 2.4227660420535617e+00, 2.8090222351311036e+00, 3.2018339457881582e+00, 3.6026938571484757e+00, 4.0134565677494702e+00, 4.4365069701928563e+00, 4.8750399724670830e+00, 5.3335601071130636e+00, 5.8188632795055772e+00, 6.3422433309944113e+00, 6.9255989902599406e+00, 7.6263257540038927e+00}, + {-7.7468822496494552e+00, -7.0497138557782293e+00, -6.4695200365240302e+00, -5.9491472174619711e+00, -5.4667903359685601e+00, -5.0112061385730726e+00, -4.5756317486673579e+00, -4.1555872811264782e+00, -3.7478982064754800e+00, -3.3501978949725357e+00, -2.9606491813032889e+00, -2.5777768581132716e+00, -2.2003609340092520e+00, -1.8273652487636047e+00, -1.4578876468742090e+00, -1.0911237649759331e+00, -7.2633961660512014e-01, -3.6284990505065795e-01, -0.0000000000000000e+00, 3.6284990505065795e-01, 7.2633961660512014e-01, 1.0911237649759331e+00, 1.4578876468742090e+00, 1.8273652487636047e+00, 2.2003609340092520e+00, 2.5777768581132716e+00, 2.9606491813032889e+00, 3.3501978949725357e+00, 3.7478982064754800e+00, 4.1555872811264782e+00, 4.5756317486673579e+00, 5.0112061385730726e+00, 5.4667903359685601e+00, 5.9491472174619711e+00, 6.4695200365240302e+00, 7.0497138557782293e+00, 7.7468822496494552e+00}, + {-7.8657628033800400e+00, -7.1720339353200302e+00, -6.5948913272654934e+00, -6.0774160035375608e+00, -5.5978935141846780e+00, -5.1451293207408231e+00, -4.7123921320848874e+00, -4.2952254197496051e+00, -3.8904737609633409e+00, -3.4957874548356260e+00, -3.1093453117179419e+00, -2.7296879628883253e+00, -2.3556117330355080e+00, -1.9860977780390656e+00, -1.6202627556330140e+00, -1.2573231317007134e+00, -8.9656834619313597e-01, -5.3733981087098337e-01, -1.7901372329587750e-01, 1.7901372329587750e-01, 5.3733981087098337e-01, 8.9656834619313597e-01, 1.2573231317007134e+00, 1.6202627556330140e+00, 1.9860977780390656e+00, 2.3556117330355080e+00, 2.7296879628883253e+00, 3.1093453117179419e+00, 3.4957874548356260e+00, 3.8904737609633409e+00, 4.2952254197496051e+00, 4.7123921320848874e+00, 5.1451293207408231e+00, 5.5978935141846780e+00, 6.0774160035375608e+00, 6.5948913272654934e+00, 7.1720339353200302e+00, 7.8657628033800400e+00}, + {-7.9830347727197806e+00, -7.2926336708657198e+00, -6.7184385064440910e+00, -6.2037579977281085e+00, -5.7269654517821049e+00, -5.2769133152304262e+00, -4.8469005687435258e+00, -4.4324928825930368e+00, -4.0305528146024674e+00, -3.6387464248745358e+00, -3.2552672359922297e+00, -2.8786703113749548e+00, -2.5077666938913192e+00, -2.1415530119868800e+00, -1.7791625828543136e+00, -1.4198301576857355e+00, -1.0628655672811786e+00, -7.0763327334857218e-01, -3.5353584699632934e-01, -0.0000000000000000e+00, 3.5353584699632934e-01, 7.0763327334857218e-01, 1.0628655672811786e+00, 1.4198301576857355e+00, 1.7791625828543136e+00, 2.1415530119868800e+00, 2.5077666938913192e+00, 2.8786703113749548e+00, 3.2552672359922297e+00, 3.6387464248745358e+00, 4.0305528146024674e+00, 4.4324928825930368e+00, 4.8469005687435258e+00, 5.2769133152304262e+00, 5.7269654517821049e+00, 6.2037579977281085e+00, 6.7184385064440910e+00, 7.2926336708657198e+00, 7.9830347727197806e+00}, + {-8.0987611392508505e+00, -7.4115825314854691e+00, -6.8402373052493548e+00, -6.3282553512200810e+00, -5.8540950560303990e+00, -5.4066542479701267e+00, -4.9792609785452555e+00, -4.5675020728443938e+00, -4.1682570668324992e+00, -3.7792067534352229e+00, -3.3985582658596281e+00, -3.0248798839012840e+00, -2.6569959984428957e+00, -2.2939171418750832e+00, -1.9347914722822956e+00, -1.5788698949316138e+00, -1.2254801090462888e+00, -8.7400661235708799e-01, -5.2387471383227713e-01, -1.7453721459758240e-01, 1.7453721459758240e-01, 5.2387471383227713e-01, 8.7400661235708799e-01, 1.2254801090462888e+00, 1.5788698949316138e+00, 1.9347914722822956e+00, 2.2939171418750832e+00, 2.6569959984428957e+00, 3.0248798839012840e+00, 3.3985582658596281e+00, 3.7792067534352229e+00, 4.1682570668324992e+00, 4.5675020728443938e+00, 4.9792609785452555e+00, 5.4066542479701267e+00, 5.8540950560303990e+00, 6.3282553512200810e+00, 6.8402373052493548e+00, 7.4115825314854691e+00, 8.0987611392508505e+00}, + {-8.2130008955982792e+00, -7.5289454645396203e+00, -6.9603584006367480e+00, -6.4509845971747524e+00, -5.9793650041651327e+00, -5.5344413406134461e+00, -5.1095696265331334e+00, -4.7003568963041156e+00, -4.3036987671546498e+00, -3.9172898548377817e+00, -3.5393499373637116e+00, -3.1684594539419857e+00, -2.8034549614843187e+00, -2.4433595531234111e+00, -2.0873346819187244e+00, -1.7346456088220295e+00, -1.3846357891600325e+00, -1.0367072529242058e+00, -6.9030505233020811e-01, -3.4490446301543276e-01, -0.0000000000000000e+00, 3.4490446301543276e-01, 6.9030505233020811e-01, 1.0367072529242058e+00, 1.3846357891600325e+00, 1.7346456088220295e+00, 2.0873346819187244e+00, 2.4433595531234111e+00, 2.8034549614843187e+00, 3.1684594539419857e+00, 3.5393499373637116e+00, 3.9172898548377817e+00, 4.3036987671546498e+00, 4.7003568963041156e+00, 5.1095696265331334e+00, 5.5344413406134461e+00, 5.9793650041651327e+00, 6.4509845971747524e+00, 6.9603584006367480e+00, 7.5289454645396203e+00, 8.2130008955982792e+00}, + {-8.3258093895669294e+00, -7.6447832957047419e+00, -7.0788678730491084e+00, -6.5720171713874747e+00, -6.1028523343815264e+00, -5.6603575812830567e+00, -5.2379158850176495e+00, -4.8311536291282762e+00, -4.4369817058810304e+00, -4.0531077444247670e+00, -3.6777633163885568e+00, -3.3095400965109221e+00, -2.9472857823054786e+00, -2.5900348706171261e+00, -2.2369607870543176e+00, -1.8873416205434848e+00, -1.5405348009155460e+00, -1.1959577943778097e+00, -8.5307290916055367e-01, -5.1137491831546933e-01, -1.7038058556181696e-01, 1.7038058556181696e-01, 5.1137491831546933e-01, 8.5307290916055367e-01, 1.1959577943778097e+00, 1.5405348009155460e+00, 1.8873416205434848e+00, 2.2369607870543176e+00, 2.5900348706171261e+00, 2.9472857823054786e+00, 3.3095400965109221e+00, 3.6777633163885568e+00, 4.0531077444247670e+00, 4.4369817058810304e+00, 4.8311536291282762e+00, 5.2379158850176495e+00, 5.6603575812830567e+00, 6.1028523343815264e+00, 6.5720171713874747e+00, 7.0788678730491084e+00, 7.6447832957047419e+00, 8.3258093895669294e+00}, + {-8.4372386310833765e+00, -7.7591530847325343e+00, -7.1958276123464335e+00, -6.6914198727121068e+00, -6.2246289668942199e+00, -5.7844803140775571e+00, -5.3643829011515560e+00, -4.9599816751949550e+00, -4.5682020755441552e+00, -4.1867640213660025e+00, -3.8139101240654272e+00, -3.4482424822200026e+00, -3.0886190396004185e+00, -2.7340846945379047e+00, -2.3838237072843595e+00, -2.0371256888641933e+00, -1.6933605309399098e+00, -1.3519593686708704e+00, -1.0123996845633196e+00, -6.7419327674231389e-01, -3.3687619662553298e-01, -0.0000000000000000e+00, 3.3687619662553298e-01, 6.7419327674231389e-01, 1.0123996845633196e+00, 1.3519593686708704e+00, 1.6933605309399098e+00, 2.0371256888641933e+00, 2.3838237072843595e+00, 2.7340846945379047e+00, 3.0886190396004185e+00, 3.4482424822200026e+00, 3.8139101240654272e+00, 4.1867640213660025e+00, 4.5682020755441552e+00, 4.9599816751949550e+00, 5.3643829011515560e+00, 5.7844803140775571e+00, 6.2246289668942199e+00, 6.6914198727121068e+00, 7.1958276123464335e+00, 7.7591530847325343e+00, 8.4372386310833765e+00}, + {-8.5473375667355391e+00, -7.8721084427748513e+00, -7.3112956789163306e+00, -6.8092552715358323e+00, -6.3447621648968919e+00, -5.9068817590275451e+00, -5.4890481838807421e+00, -5.0869242297582531e+00, -4.6974492230014393e+00, -4.3183547234421118e+00, -3.9478937115246548e+00, -3.5846779931052279e+00, -3.2275749742774260e+00, -2.8756390821704421e+00, -2.5280644271476649e+00, -2.1841510195665261e+00, -1.8432799206176103e+00, -1.5048944344828714e+00, -1.1684854631902055e+00, -8.3357976100207332e-01, -4.9973020830067427e-01, -1.6650746707363237e-01, 1.6650746707363237e-01, 4.9973020830067427e-01, 8.3357976100207332e-01, 1.1684854631902055e+00, 1.5048944344828714e+00, 1.8432799206176103e+00, 2.1841510195665261e+00, 2.5280644271476649e+00, 2.8756390821704421e+00, 3.2275749742774260e+00, 3.5846779931052279e+00, 3.9478937115246548e+00, 4.3183547234421118e+00, 4.6974492230014393e+00, 5.0869242297582531e+00, 5.4890481838807421e+00, 5.9068817590275451e+00, 6.3447621648968919e+00, 6.8092552715358323e+00, 7.3112956789163306e+00, 7.8721084427748513e+00, 8.5473375667355391e+00}, + {-8.6561523259903268e+00, -7.9836998162220016e+00, -7.4253266258561936e+00, -6.9255820732775950e+00, -6.4633149436642530e+00, -6.0276294722536941e+00, -5.6119841218396642e+00, -5.2120588631620075e+00, -4.8248063087032573e+00, -4.4479690736019313e+00, -4.0798099079253927e+00, -3.7189496893415628e+00, -3.3642645958565400e+00, -3.0148178197492252e+00, -2.6698124652513462e+00, -2.3285579714531894e+00, -1.9904454586466382e+00, -1.6549291191547923e+00, -1.3215117856392311e+00, -9.8973342486571125e-01, -6.5916168887413507e-01, -3.2938389969666915e-01, -0.0000000000000000e+00, 3.2938389969666915e-01, 6.5916168887413507e-01, 9.8973342486571125e-01, 1.3215117856392311e+00, 1.6549291191547923e+00, 1.9904454586466382e+00, 2.3285579714531894e+00, 2.6698124652513462e+00, 3.0148178197492252e+00, 3.3642645958565400e+00, 3.7189496893415628e+00, 4.0798099079253927e+00, 4.4479690736019313e+00, 4.8248063087032573e+00, 5.2120588631620075e+00, 5.6119841218396642e+00, 6.0276294722536941e+00, 6.4633149436642530e+00, 6.9255820732775950e+00, 7.4253266258561936e+00, 7.9836998162220016e+00, 8.6561523259903268e+00}, + {-8.7637264425763934e+00, -8.0939747412671181e+00, -7.5379717872258256e+00, -7.0404554428052171e+00, -6.5803464347374083e+00, -6.1467867545054018e+00, -5.7332584418499435e+00, -5.3354580360572301e+00, -4.9503508867398853e+00, -4.5756901345704328e+00, -4.2097477613269749e+00, -3.8511531505025514e+00, -3.4987906412463645e+00, -3.1517315196384712e+00, -2.8091871354772668e+00, -2.4704755132281426e+00, -2.1349968729707256e+00, -1.8022151950574945e+00, -1.4716439717320722e+00, -1.1428349031264304e+00, -8.1536867934468149e-01, -4.8884723585117468e-01, -1.6288702795526222e-01, 1.6288702795526222e-01, 4.8884723585117468e-01, 8.1536867934468149e-01, 1.1428349031264304e+00, 1.4716439717320722e+00, 1.8022151950574945e+00, 2.1349968729707256e+00, 2.4704755132281426e+00, 2.8091871354772668e+00, 3.1517315196384712e+00, 3.4987906412463645e+00, 3.8511531505025514e+00, 4.2097477613269749e+00, 4.5756901345704328e+00, 4.9503508867398853e+00, 5.3354580360572301e+00, 5.7332584418499435e+00, 6.1467867545054018e+00, 6.5803464347374083e+00, 7.0404554428052171e+00, 7.5379717872258256e+00, 8.0939747412671181e+00, 8.7637264425763934e+00}, + {-8.8701010540232534e+00, -8.2029780727977943e+00, -7.6492795366289874e+00, -7.1539272947757162e+00, -6.6959122110632512e+00, -6.2644130149704740e+00, -5.8529346161254212e+00, -5.4571895556816514e+00, -5.0741554169850653e+00, -4.7015953849679351e+00, -4.3377901884924199e+00, -3.9813772107064693e+00, -3.6312484092926161e+00, -3.2864825713246675e+00, -2.9462986351921705e+00, -2.6100224744061520e+00, -2.2770625758595000e+00, -1.9468917579991860e+00, -1.6190330813590508e+00, -1.2930487170109526e+00, -9.6853092273781483e-01, -6.4509452302768844e-01, -3.2237044915615060e-01, -0.0000000000000000e+00, 3.2237044915615060e-01, 6.4509452302768844e-01, 9.6853092273781483e-01, 1.2930487170109526e+00, 1.6190330813590508e+00, 1.9468917579991860e+00, 2.2770625758595000e+00, 2.6100224744061520e+00, 2.9462986351921705e+00, 3.2864825713246675e+00, 3.6312484092926161e+00, 3.9813772107064693e+00, 4.3377901884924199e+00, 4.7015953849679351e+00, 5.0741554169850653e+00, 5.4571895556816514e+00, 5.8529346161254212e+00, 6.2644130149704740e+00, 6.6959122110632512e+00, 7.1539272947757162e+00, 7.6492795366289874e+00, 8.2029780727977943e+00, 8.8701010540232534e+00}, + {-8.9753150819316865e+00, -8.3107521907047843e+00, -7.7592955197657743e+00, -7.2660465541643502e+00, -6.8100645780741411e+00, -6.3805640961864096e+00, -5.9710722250135460e+00, -5.5773169812237278e+00, -5.1962877187923642e+00, -4.8257572281332095e+00, -4.4640145469344583e+00, -4.1097046035605898e+00, -3.7617264902283578e+00, -3.4191659693638847e+00, -3.0812489886451053e+00, -2.7473086248223830e+00, -2.4167609048732164e+00, -2.0890866609442762e+00, -1.7638175798953000e+00, -1.4405252201375651e+00, -1.1188121524021566e+00, -7.9830462777856215e-01, -4.7864633759449599e-01, -1.5949293584886245e-01, 1.5949293584886245e-01, 4.7864633759449599e-01, 7.9830462777856215e-01, 1.1188121524021566e+00, 1.4405252201375651e+00, 1.7638175798953000e+00, 2.0890866609442762e+00, 2.4167609048732164e+00, 2.7473086248223830e+00, 3.0812489886451053e+00, 3.4191659693638847e+00, 3.7617264902283578e+00, 4.1097046035605898e+00, 4.4640145469344583e+00, 4.8257572281332095e+00, 5.1962877187923642e+00, 5.5773169812237278e+00, 5.9710722250135460e+00, 6.3805640961864096e+00, 6.8100645780741411e+00, 7.2660465541643502e+00, 7.7592955197657743e+00, 8.3107521907047843e+00, 8.9753150819316865e+00}, + {-9.0794053951994336e+00, -8.4173371862679787e+00, -7.8680628640816641e+00, -7.3768593906319282e+00, -6.9228528349597616e+00, -6.4952925650076585e+00, -6.0877272810547556e+00, -5.6958999850352088e+00, -5.3168113741835157e+00, -4.9482434430048912e+00, -4.5884931402744824e+00, -4.2362125300687872e+00, -3.8903074057661615e+00, -3.5498700372120946e+00, -3.2141328684568560e+00, -2.8824356106455995e+00, -2.5542011939519624e+00, -2.2289177453859468e+00, -1.9061247609883607e+00, -1.5854022514550468e+00, -1.2663620236873581e+00, -9.4864050761025742e-01, -6.3189269951096161e-01, -3.1578690052375491e-01, -0.0000000000000000e+00, 3.1578690052375491e-01, 6.3189269951096161e-01, 9.4864050761025742e-01, 1.2663620236873581e+00, 1.5854022514550468e+00, 1.9061247609883607e+00, 2.2289177453859468e+00, 2.5542011939519624e+00, 2.8824356106455995e+00, 3.2141328684568560e+00, 3.5498700372120946e+00, 3.8903074057661615e+00, 4.2362125300687872e+00, 4.5884931402744824e+00, 4.9482434430048912e+00, 5.3168113741835157e+00, 5.6958999850352088e+00, 6.0877272810547556e+00, 6.4952925650076585e+00, 6.9228528349597616e+00, 7.3768593906319282e+00, 7.8680628640816641e+00, 8.4173371862679787e+00, 9.0794053951994336e+00}, + {-9.1824069581293166e+00, -8.5227710309178022e+00, -7.9756223682056362e+00, -7.4864094298641941e+00, -7.0343235097706103e+00, -6.6086479738553576e+00, -6.2029525192746719e+00, -5.8129946754204047e+00, -5.4357860872249475e+00, -5.0691175849172350e+00, -4.7112936661690421e+00, -4.3609731604545781e+00, -4.0170681728581341e+00, -3.6786770625152689e+00, -3.3450383139378910e+00, -3.0154977695745222e+00, -2.6894847022677451e+00, -2.3664939042986637e+00, -2.0460719686864088e+00, -1.7278065475158983e+00, -1.4113177548982998e+00, -1.0962511289576817e+00, -7.8227172955460689e-01, -4.6905905667823600e-01, -1.5630254688946871e-01, 1.5630254688946871e-01, 4.6905905667823600e-01, 7.8227172955460689e-01, 1.0962511289576817e+00, 1.4113177548982998e+00, 1.7278065475158983e+00, 2.0460719686864088e+00, 2.3664939042986637e+00, 2.6894847022677451e+00, 3.0154977695745222e+00, 3.3450383139378910e+00, 3.6786770625152689e+00, 4.0170681728581341e+00, 4.3609731604545781e+00, 4.7112936661690421e+00, 5.0691175849172350e+00, 5.4357860872249475e+00, 5.8129946754204047e+00, 6.2029525192746719e+00, 6.6086479738553576e+00, 7.0343235097706103e+00, 7.4864094298641941e+00, 7.9756223682056362e+00, 8.5227710309178022e+00, 9.1824069581293166e+00}, + {-9.2843529650947954e+00, -8.6270897293636839e+00, -8.0820126735040123e+00, -7.5947379445835947e+00, -7.1445205714796174e+00, -6.7206770958687514e+00, -6.3167976579034049e+00, -5.9286538858731372e+00, -5.5532680052649175e+00, -5.1884393429381372e+00, -4.8324796145780748e+00, -4.4840540790573504e+00, -4.1420808019620621e+00, -3.8056638567519334e+00, -3.4740473616558587e+00, -3.1465828437716956e+00, -2.8227054233054294e+00, -2.5019160040577368e+00, -2.1837676525361926e+00, -1.8678549556995603e+00, -1.5538055294554218e+00, -1.2412730966236114e+00, -9.2993171560017596e-01, -6.1947084974715272e-01, -3.0959104093724038e-01, -0.0000000000000000e+00, 3.0959104093724038e-01, 6.1947084974715272e-01, 9.2993171560017596e-01, 1.2412730966236114e+00, 1.5538055294554218e+00, 1.8678549556995603e+00, 2.1837676525361926e+00, 2.5019160040577368e+00, 2.8227054233054294e+00, 3.1465828437716956e+00, 3.4740473616558587e+00, 3.8056638567519334e+00, 4.1420808019620621e+00, 4.4840540790573504e+00, 4.8324796145780748e+00, 5.1884393429381372e+00, 5.5532680052649175e+00, 5.9286538858731372e+00, 6.3167976579034049e+00, 6.7206770958687514e+00, 7.1445205714796174e+00, 7.5947379445835947e+00, 8.0820126735040123e+00, 8.6270897293636839e+00, 9.2843529650947954e+00}, + {-9.3852749632231376e+00, -8.7303274588209110e+00, -8.1872704197671577e+00, -7.7018840275679166e+00, -7.2534856216969716e+00, -6.8314241370686029e+00, -6.4293096331149808e+00, -6.0429274349196920e+00, -5.6693100068563673e+00, -5.3062648593656414e+00, -4.9521106229353720e+00, -4.6055186799962122e+00, -4.2654127388779193e+00, -3.9309022499573141e+00, -3.6012366010181420e+00, -3.2757726058076915e+00, -2.9539507925538842e+00, -2.6352776875892849e+00, -2.3193122827994568e+00, -2.0056554817328660e+00, -1.6939417005414366e+00, -1.3838320462108629e+00, -1.0750086571198576e+00, -7.6716990012409136e-01, -4.6002619243746073e-01, -1.5329626692045756e-01, 1.5329626692045756e-01, 4.6002619243746073e-01, 7.6716990012409136e-01, 1.0750086571198576e+00, 1.3838320462108629e+00, 1.6939417005414366e+00, 2.0056554817328660e+00, 2.3193122827994568e+00, 2.6352776875892849e+00, 2.9539507925538842e+00, 3.2757726058076915e+00, 3.6012366010181420e+00, 3.9309022499573141e+00, 4.2654127388779193e+00, 4.6055186799962122e+00, 4.9521106229353720e+00, 5.3062648593656414e+00, 5.6693100068563673e+00, 6.0429274349196920e+00, 6.4293096331149808e+00, 6.8314241370686029e+00, 7.2534856216969716e+00, 7.7018840275679166e+00, 8.1872704197671577e+00, 8.7303274588209110e+00, 9.3852749632231376e+00}, + {-9.4852029643727302e+00, -8.8325166958454133e+00, -8.2914303867830093e+00, -7.8078847487003955e+00, -7.3612580683690458e+00, -6.9409309282147520e+00, -6.5405328108757619e+00, -6.1558623601311924e+00, -5.7839619604859447e+00, -5.4226470161614522e+00, -5.0702427937817154e+00, -4.7254265200961152e+00, -4.3871272577720717e+00, -4.0544595295034727e+00, -3.7266776654942122e+00, -3.4031434102599176e+00, -3.0833023089391358e+00, -2.7666660769675384e+00, -2.4527991478588032e+00, -2.1413081984302371e+00, -1.8318338313140423e+00, -1.5240438405087577e+00, -1.2176276482547366e+00, -9.1229161088998856e-01, -6.0775496588729694e-01, -3.0374624334991529e-01, -0.0000000000000000e+00, 3.0374624334991529e-01, 6.0775496588729694e-01, 9.1229161088998856e-01, 1.2176276482547366e+00, 1.5240438405087577e+00, 1.8318338313140423e+00, 2.1413081984302371e+00, 2.4527991478588032e+00, 2.7666660769675384e+00, 3.0833023089391358e+00, 3.4031434102599176e+00, 3.7266776654942122e+00, 4.0544595295034727e+00, 4.3871272577720717e+00, 4.7254265200961152e+00, 5.0702427937817154e+00, 5.4226470161614522e+00, 5.7839619604859447e+00, 6.1558623601311924e+00, 6.5405328108757619e+00, 6.9409309282147520e+00, 7.3612580683690458e+00, 7.8078847487003955e+00, 8.2914303867830093e+00, 8.8325166958454133e+00, 9.4852029643727302e+00}, + {-9.5841655475234688e+00, -8.9336883320961924e+00, -8.3945256233272012e+00, -7.9127752978124946e+00, -7.4678752834836200e+00, -7.0492370986783772e+00, -6.6505091785664918e+00, -6.2675031293697510e+00, -5.8972709576411209e+00, -5.5376356924033008e+00, -5.1869289795928895e+00, -4.8438336345819870e+00, -4.5072838118199003e+00, -4.1763988304784849e+00, -3.8504376683661063e+00, -3.5287666814910854e+00, -3.2108360825282936e+00, -2.8961623904571474e+00, -2.5843150518736273e+00, -2.2749060375416974e+00, -1.9675815973920669e+00, -1.6620156026589967e+00, -1.3579040662442226e+00, -1.0549605418738988e+00, -7.5291217747488703e-01, -4.5149624980624264e-01, -1.5045704292086298e-01, 1.5045704292086298e-01, 4.5149624980624264e-01, 7.5291217747488703e-01, 1.0549605418738988e+00, 1.3579040662442226e+00, 1.6620156026589967e+00, 1.9675815973920669e+00, 2.2749060375416974e+00, 2.5843150518736273e+00, 2.8961623904571474e+00, 3.2108360825282936e+00, 3.5287666814910854e+00, 3.8504376683661063e+00, 4.1763988304784849e+00, 4.5072838118199003e+00, 4.8438336345819870e+00, 5.1869289795928895e+00, 5.5376356924033008e+00, 5.8972709576411209e+00, 6.2675031293697510e+00, 6.6505091785664918e+00, 7.0492370986783772e+00, 7.4678752834836200e+00, 7.9127752978124946e+00, 8.3945256233272012e+00, 8.9336883320961924e+00, 9.5841655475234688e+00}, + {-9.6821899525637249e+00, -9.0338717801824053e+00, -8.4965875649075624e+00, -8.0165891148558295e+00, -7.5733727465411995e+00, -7.1563802343429099e+00, -6.7592785186840851e+00, -6.3778918319127680e+00, -6.0092815232536667e+00, -5.6512779962558639e+00, -5.3022190388457897e+00, -4.9607928202275557e+00, -4.6259383469194120e+00, -4.2967794840336984e+00, -3.9725795904787460e+00, -3.6527093464132974e+00, -3.3366233189341656e+00, -3.0238424864191802e+00, -2.7139409275560999e+00, -2.4065354826206522e+00, -2.1012775733291407e+00, -1.7978466126036980e+00, -1.4959445977962444e+00, -1.1952915904152335e+00, -8.9562186046229086e-01, -5.9668052547571682e-01, -2.9822055049276669e-01, -0.0000000000000000e+00, 2.9822055049276669e-01, 5.9668052547571682e-01, 8.9562186046229086e-01, 1.1952915904152335e+00, 1.4959445977962444e+00, 1.7978466126036980e+00, 2.1012775733291407e+00, 2.4065354826206522e+00, 2.7139409275560999e+00, 3.0238424864191802e+00, 3.3366233189341656e+00, 3.6527093464132974e+00, 3.9725795904787460e+00, 4.2967794840336984e+00, 4.6259383469194120e+00, 4.9607928202275557e+00, 5.3022190388457897e+00, 5.6512779962558639e+00, 6.0092815232536667e+00, 6.3778918319127680e+00, 6.7592785186840851e+00, 7.1563802343429099e+00, 7.5733727465411995e+00, 8.0165891148558295e+00, 8.4965875649075624e+00, 9.0338717801824053e+00, 9.6821899525637249e+00}, + {-9.7793021663403099e+00, -9.1330950706121001e+00, -8.5976461414362131e+00, -8.1193580087474686e+00, -7.6777841753281493e+00, -7.2623960212867891e+00, -6.8668785666252870e+00, -6.4870683517446244e+00, -6.1200358061419919e+00, -5.7636184744715768e+00, -5.4161600667900469e+00, -5.0763538899639924e+00, -4.7431435831181288e+00, -4.4156573291002159e+00, -4.0931626262997982e+00, -3.7750342196411242e+00, -3.4607307491477983e+00, -3.1497773444199684e+00, -2.8417523763809922e+00, -2.5362771776597737e+00, -2.2330079208452407e+00, -1.9316290883640068e+00, -1.6318481297059444e+00, -1.3333910111792098e+00, -1.0359984385570031e+00, -7.3942258523430104e-01, -4.4342419505035346e-01, -1.4776995439420115e-01, 1.4776995439420115e-01, 4.4342419505035346e-01, 7.3942258523430104e-01, 1.0359984385570031e+00, 1.3333910111792098e+00, 1.6318481297059444e+00, 1.9316290883640068e+00, 2.2330079208452407e+00, 2.5362771776597737e+00, 2.8417523763809922e+00, 3.1497773444199684e+00, 3.4607307491477983e+00, 3.7750342196411242e+00, 4.0931626262997982e+00, 4.4156573291002159e+00, 4.7431435831181288e+00, 5.0763538899639924e+00, 5.4161600667900469e+00, 5.7636184744715768e+00, 6.1200358061419919e+00, 6.4870683517446244e+00, 6.8668785666252870e+00, 7.2623960212867891e+00, 7.6777841753281493e+00, 8.1193580087474686e+00, 8.5976461414362131e+00, 9.1330950706121001e+00, 9.7793021663403099e+00}, + {-9.8755270017367671e+00, -9.2313849407386552e+00, -8.6977298758606238e+00, -8.2211122660677169e+00, -7.7811416453357003e+00, -7.3673183767785728e+00, -6.9733451542956244e+00, -6.5950705250038864e+00, -6.2295737517233460e+00, -5.8746993020212539e+00, -5.5287966039093659e+00, -5.1905639023838361e+00, -4.8589492677211483e+00, -4.5330849920738157e+00, -4.2122424936406224e+00, -3.8958003472863840e+00, -3.5832210121368786e+00, -3.2740334921948340e+00, -2.9678201464818930e+00, -2.6642064637087906e+00, -2.3628529934485321e+00, -2.0634488697846303e+00, -1.7657065251132762e+00, -1.4693573011471874e+00, -1.1741477394031905e+00, -8.7983638589173074e-01, -5.8619098157190686e-01, -2.9298593604778866e-01, -0.0000000000000000e+00, 2.9298593604778866e-01, 5.8619098157190686e-01, 8.7983638589173074e-01, 1.1741477394031905e+00, 1.4693573011471874e+00, 1.7657065251132762e+00, 2.0634488697846303e+00, 2.3628529934485321e+00, 2.6642064637087906e+00, 2.9678201464818930e+00, 3.2740334921948340e+00, 3.5832210121368786e+00, 3.8958003472863840e+00, 4.2122424936406224e+00, 4.5330849920738157e+00, 4.8589492677211483e+00, 5.1905639023838361e+00, 5.5287966039093659e+00, 5.8746993020212539e+00, 6.2295737517233460e+00, 6.5950705250038864e+00, 6.9733451542956244e+00, 7.3673183767785728e+00, 7.7811416453357003e+00, 8.2211122660677169e+00, 8.6977298758606238e+00, 9.2313849407386552e+00, 9.8755270017367671e+00}, + {-9.9708881704574601e+00, -9.3287669164964395e+00, -8.7968659746627651e+00, -8.3218807506473613e+00, -7.8834756990041477e+00, -7.4711795689242475e+00, -7.0787123410660744e+00, -6.7019342833176401e+00, -6.3379332589686221e+00, -5.9845604541065045e+00, -5.6401708246496867e+00, -5.3034673690975112e+00, -4.9734024034844930e+00, -4.6491121384000209e+00, -4.3298717115959429e+00, -4.0150633146984989e+00, -3.7041529964080997e+00, -3.3966733857420293e+00, -3.0922105568140124e+00, -2.7903938536440540e+00, -2.4908878695658663e+00, -2.1933860192661303e+00, -1.8976053029060733e+00, -1.6032819710214761e+00, -1.3101678741366003e+00, -1.0180273335786967e+00, -7.2663440704649163e-01, -4.3577044873391346e-01, -1.4522188229810670e-01, 1.4522188229810670e-01, 4.3577044873391346e-01, 7.2663440704649163e-01, 1.0180273335786967e+00, 1.3101678741366003e+00, 1.6032819710214761e+00, 1.8976053029060733e+00, 2.1933860192661303e+00, 2.4908878695658663e+00, 2.7903938536440540e+00, 3.0922105568140124e+00, 3.3966733857420293e+00, 3.7041529964080997e+00, 4.0150633146984989e+00, 4.3298717115959429e+00, 4.6491121384000209e+00, 4.9734024034844930e+00, 5.3034673690975112e+00, 5.6401708246496867e+00, 5.9845604541065045e+00, 6.3379332589686221e+00, 6.7019342833176401e+00, 7.0787123410660744e+00, 7.4711795689242475e+00, 7.8834756990041477e+00, 8.3218807506473613e+00, 8.7968659746627651e+00, 9.3287669164964395e+00, 9.9708881704574601e+00}, + {-1.0065408350118513e+01, -9.4252653876263999e+00, -8.8950804110294346e+00, -8.4216909949586132e+00, -7.9848154458297120e+00, -7.5740103261427940e+00, -7.1830125334106762e+00, -6.8076937845356600e+00, -6.4451503233185363e+00, -6.0932398625106678e+00, -5.7503227086468636e+00, -5.4151064424967945e+00, -5.0865474548246592e+00, -4.7637856994329741e+00, -4.4460998505989417e+00, -4.1328755226679874e+00, -3.8235821457915500e+00, -3.5177557486926583e+00, -3.2149858747990203e+00, -2.9149054536014392e+00, -2.6171828242728932e+00, -2.3215153515122373e+00, -2.0276242346848043e+00, -1.7352502204281328e+00, -1.4441500040985724e+00, -1.1540931580511036e+00, -8.6485946196705754e-01, -5.7623653694114951e-01, -2.8801770388153508e-01, -0.0000000000000000e+00, 2.8801770388153508e-01, 5.7623653694114951e-01, 8.6485946196705754e-01, 1.1540931580511036e+00, 1.4441500040985724e+00, 1.7352502204281328e+00, 2.0276242346848043e+00, 2.3215153515122373e+00, 2.6171828242728932e+00, 2.9149054536014392e+00, 3.2149858747990203e+00, 3.5177557486926583e+00, 3.8235821457915500e+00, 4.1328755226679874e+00, 4.4460998505989417e+00, 4.7637856994329741e+00, 5.0865474548246592e+00, 5.4151064424967945e+00, 5.7503227086468636e+00, 6.0932398625106678e+00, 6.4451503233185363e+00, 6.8076937845356600e+00, 7.1830125334106762e+00, 7.5740103261427940e+00, 7.9848154458297120e+00, 8.4216909949586132e+00, 8.8950804110294346e+00, 9.4252653876263999e+00, 1.0065408350118513e+01}, + {-1.0159109246180085e+01, -9.5209036770133171e+00, -8.9923980014049434e+00, -8.5205692841176308e+00, -8.0851886542490199e+00, -7.6758399375048869e+00, -7.2862765943955985e+00, -6.9123815321893174e+00, -6.5512591670629208e+00, -6.2007735579934371e+00, -5.8592901963942339e+00, -5.5255210861386832e+00, -5.1984265345762939e+00, -4.8771500774731509e+00, -4.5609737579358356e+00, -4.2492864359560061e+00, -3.9415607339261842e+00, -3.6373358761707317e+00, -3.3362046535475867e+00, -3.0378033382307490e+00, -2.7418037480696915e+00, -2.4479069023076856e+00, -2.1558378712292110e+00, -1.8653415312330315e+00, -1.5761790119750203e+00, -1.2881246748688935e+00, -1.0009634995607180e+00, -7.1448878167257845e-01, -4.2850006422062747e-01, -1.4280123870343886e-01, 1.4280123870343886e-01, 4.2850006422062747e-01, 7.1448878167257845e-01, 1.0009634995607180e+00, 1.2881246748688935e+00, 1.5761790119750203e+00, 1.8653415312330315e+00, 2.1558378712292110e+00, 2.4479069023076856e+00, 2.7418037480696915e+00, 3.0378033382307490e+00, 3.3362046535475867e+00, 3.6373358761707317e+00, 3.9415607339261842e+00, 4.2492864359560061e+00, 4.5609737579358356e+00, 4.8771500774731509e+00, 5.1984265345762939e+00, 5.5255210861386832e+00, 5.8592901963942339e+00, 6.2007735579934371e+00, 6.5512591670629208e+00, 6.9123815321893174e+00, 7.2862765943955985e+00, 7.6758399375048869e+00, 8.0851886542490199e+00, 8.5205692841176308e+00, 8.9923980014049434e+00, 9.5209036770133171e+00, 1.0159109246180085e+01}, + {-1.0252011649196143e+01, -9.6157041046875609e+00, -9.0888424760573390e+00, -8.6185407332142496e+00, -8.1846218361099510e+00, -7.7766963448476236e+00, -7.3885339440499829e+00, -7.0160284848388690e+00, -6.6562923584988729e+00, -6.3071958002194259e+00, -5.9671093310413950e+00, -5.6347492296736759e+00, -5.3090795734924505e+00, -4.9892473314939929e+00, -4.6745377615999182e+00, -4.3643428074654231e+00, -4.0581381112767332e+00, -3.7554659075853780e+00, -3.4559220338316390e+00, -3.1591458858192856e+00, -2.8648125198053043e+00, -2.5726263447097191e+00, -2.2823160084101848e+00, -1.9936301908281084e+00, -1.7063340915790624e+00, -1.4202064526026656e+00, -1.1350369935815596e+00, -8.5062416477081448e-01, -5.6677314117022048e-01, -2.8329399584293824e-01, -0.0000000000000000e+00, 2.8329399584293824e-01, 5.6677314117022048e-01, 8.5062416477081448e-01, 1.1350369935815596e+00, 1.4202064526026656e+00, 1.7063340915790624e+00, 1.9936301908281084e+00, 2.2823160084101848e+00, 2.5726263447097191e+00, 2.8648125198053043e+00, 3.1591458858192856e+00, 3.4559220338316390e+00, 3.7554659075853780e+00, 4.0581381112767332e+00, 4.3643428074654231e+00, 4.6745377615999182e+00, 4.9892473314939929e+00, 5.3090795734924505e+00, 5.6347492296736759e+00, 5.9671093310413950e+00, 6.3071958002194259e+00, 6.6562923584988729e+00, 7.0160284848388690e+00, 7.3885339440499829e+00, 7.7766963448476236e+00, 8.1846218361099510e+00, 8.6185407332142496e+00, 9.0888424760573390e+00, 9.6157041046875609e+00, 1.0252011649196143e+01}, + {-1.0344135487806895e+01, -9.7096880469839437e+00, -9.1844365442194498e+00, -8.7156293586041365e+00, -8.2831403244454158e+00, -7.8766062274725090e+00, -7.4898126515277026e+00, -7.1186641563335851e+00, -6.7602809210235622e+00, -6.4125391965266108e+00, -6.0738143878025932e+00, -5.7428269099958227e+00, -5.4185444743952305e+00, -5.1001173457332412e+00, -4.7868338549738239e+00, -4.4780888809091079e+00, -4.1733609279699495e+00, -3.8721950721542884e+00, -3.5741900152128512e+00, -3.2789880784162539e+00, -2.9862673397528621e+00, -2.6957353597041749e+00, -2.4071241008699498e+00, -2.1201857552620891e+00, -1.8346892680544815e+00, -1.5504173991942523e+00, -1.2671642017112603e+00, -9.8473282246759541e-01, -7.0293355055041085e-01, -4.2158205259642756e-01, -1.4049774444160384e-01, 1.4049774444160384e-01, 4.2158205259642756e-01, 7.0293355055041085e-01, 9.8473282246759541e-01, 1.2671642017112603e+00, 1.5504173991942523e+00, 1.8346892680544815e+00, 2.1201857552620891e+00, 2.4071241008699498e+00, 2.6957353597041749e+00, 2.9862673397528621e+00, 3.2789880784162539e+00, 3.5741900152128512e+00, 3.8721950721542884e+00, 4.1733609279699495e+00, 4.4780888809091079e+00, 4.7868338549738239e+00, 5.1001173457332412e+00, 5.4185444743952305e+00, 5.7428269099958227e+00, 6.0738143878025932e+00, 6.4125391965266108e+00, 6.7602809210235622e+00, 7.1186641563335851e+00, 7.4898126515277026e+00, 7.8766062274725090e+00, 8.2831403244454158e+00, 8.7156293586041365e+00, 9.1844365442194498e+00, 9.7096880469839437e+00, 1.0344135487806895e+01}, + {-1.0435499877854168e+01, -9.8028759912974959e+00, -9.2792019543050390e+00, -8.8118581437284540e+00, -8.3807683451863202e+00, -7.9755950801420372e+00, -7.5901395198641071e+00, -7.2203167078889665e+00, -6.8632544331795353e+00, -6.5168348106821155e+00, -6.1794379922705955e+00, -5.8497884000810672e+00, -5.5268572526403030e+00, -5.2097979830408345e+00, -4.8979018644975740e+00, -4.5905665744435185e+00, -4.2872733352824408e+00, -3.9875699104197153e+00, -3.6910577000963465e+00, -3.3973817713303909e+00, -3.1062230279282566e+00, -2.8172919672837975e+00, -2.5303236304712007e+00, -2.2450734604812066e+00, -1.9613138583081484e+00, -1.6788312791720135e+00, -1.3974237486049623e+00, -1.1168987050996462e+00, -8.3707109558947612e-01, -5.5776166427908214e-01, -2.7879538567115225e-01, -0.0000000000000000e+00, 2.7879538567115225e-01, 5.5776166427908214e-01, 8.3707109558947612e-01, 1.1168987050996462e+00, 1.3974237486049623e+00, 1.6788312791720135e+00, 1.9613138583081484e+00, 2.2450734604812066e+00, 2.5303236304712007e+00, 2.8172919672837975e+00, 3.1062230279282566e+00, 3.3973817713303909e+00, 3.6910577000963465e+00, 3.9875699104197153e+00, 4.2872733352824408e+00, 4.5905665744435185e+00, 4.8979018644975740e+00, 5.2097979830408345e+00, 5.5268572526403030e+00, 5.8497884000810672e+00, 6.1794379922705955e+00, 6.5168348106821155e+00, 6.8632544331795353e+00, 7.2203167078889665e+00, 7.5901395198641071e+00, 7.9755950801420372e+00, 8.3807683451863202e+00, 8.8118581437284540e+00, 9.2792019543050390e+00, 9.8028759912974959e+00, 1.0435499877854168e+01}, + {-1.0526123167960545e+01, -9.8952875868295376e+00, -9.3731595496467204e+00, -8.9072490999647691e+00, -8.4775290833798636e+00, -8.0736872850102248e+00, -7.6895401640404968e+00, -7.3210130327809484e+00, -6.9652411205511076e+00, -6.6201122626360274e+00, -6.2840112287748280e+00, -5.9556663267994852e+00, -5.6340521643499724e+00, -5.3183252246332708e+00, -5.0077796021987675e+00, -4.7018156474074990e+00, -4.3999171682281375e+00, -4.1016344745666560e+00, -3.8065715139453600e+00, -3.5143759357409059e+00, -3.2247312919920357e+00, -2.9373508230046212e+00, -2.6519724354306349e+00, -2.3683545886324011e+00, -2.0862728798817618e+00, -1.8055171714655447e+00, -1.5258891402098638e+00, -1.2472001569431179e+00, -9.6926942307117792e-01, -6.9192230581004455e-01, -4.1498882412107863e-01, -1.3830224498700971e-01, 1.3830224498700971e-01, 4.1498882412107863e-01, 6.9192230581004455e-01, 9.6926942307117792e-01, 1.2472001569431179e+00, 1.5258891402098638e+00, 1.8055171714655447e+00, 2.0862728798817618e+00, 2.3683545886324011e+00, 2.6519724354306349e+00, 2.9373508230046212e+00, 3.2247312919920357e+00, 3.5143759357409059e+00, 3.8065715139453600e+00, 4.1016344745666560e+00, 4.3999171682281375e+00, 4.7018156474074990e+00, 5.0077796021987675e+00, 5.3183252246332708e+00, 5.6340521643499724e+00, 5.9556663267994852e+00, 6.2840112287748280e+00, 6.6201122626360274e+00, 6.9652411205511076e+00, 7.3210130327809484e+00, 7.6895401640404968e+00, 8.0736872850102248e+00, 8.4775290833798636e+00, 8.9072490999647691e+00, 9.3731595496467204e+00, 9.8952875868295376e+00, 1.0526123167960545e+01}, + {-1.0616022981878281e+01, -9.9869416916766838e+00, -9.4663293201553849e+00, -9.0018233229591331e+00, -8.5734447444179089e+00, -8.1709061780525847e+00, -7.7880390829895703e+00, -7.4207788343663230e+00, -7.0662679403068926e+00, -6.7223998201657338e+00, -6.3875637397870904e+00, -6.0604917788315049e+00, -5.7401618236902250e+00, -5.4257332976973487e+00, -5.1165030047214124e+00, -4.8118738520274640e+00, -4.5113321113682128e+00, -4.2144305099719546e+00, -3.9207754044447234e+00, -3.6300168776328952e+00, -3.3418409684468302e+00, -3.0559634843286707e+00, -2.7721250051570916e+00, -2.4900867953039354e+00, -2.2096274151691842e+00, -1.9305398759772254e+00, -1.6526292190403253e+00, -1.3757104277236682e+00, -1.0996066000569449e+00, -8.2414732440241278e-01, -5.4916721122159917e-01, -2.7450454175394473e-01, -0.0000000000000000e+00, 2.7450454175394473e-01, 5.4916721122159917e-01, 8.2414732440241278e-01, 1.0996066000569449e+00, 1.3757104277236682e+00, 1.6526292190403253e+00, 1.9305398759772254e+00, 2.2096274151691842e+00, 2.4900867953039354e+00, 2.7721250051570916e+00, 3.0559634843286707e+00, 3.3418409684468302e+00, 3.6300168776328952e+00, 3.9207754044447234e+00, 4.2144305099719546e+00, 4.5113321113682128e+00, 4.8118738520274640e+00, 5.1165030047214124e+00, 5.4257332976973487e+00, 5.7401618236902250e+00, 6.0604917788315049e+00, 6.3875637397870904e+00, 6.7223998201657338e+00, 7.0662679403068926e+00, 7.4207788343663230e+00, 7.7880390829895703e+00, 8.1709061780525847e+00, 8.5734447444179089e+00, 9.0018233229591331e+00, 9.4663293201553849e+00, 9.9869416916766838e+00, 1.0616022981878281e+01}, + {-1.0705216257883158e+01, -1.0077856416579301e+01, -9.5587304502592971e+00, -9.0956010448419295e+00, -8.6685366107264805e+00, -8.2672741104998497e+00, -7.8856597261055059e+00, -7.5196386980596541e+00, -7.1663606590936650e+00, -6.8237244832006141e+00, -6.4901238172609474e+00, -6.1642944056838216e+00, -5.8452173103130356e+00, -5.5320547921086867e+00, -5.2241062602848638e+00, -4.9207770717124939e+00, -4.6215558496899147e+00, -4.3259976200905568e+00, -4.0337110220232306e+00, -3.7443484358240933e+00, -3.4575982403178411e+00, -3.1731786504386261e+00, -2.8908327450724003e+00, -2.6103244026894505e+00, -2.3314349368154352e+00, -2.0539602757725310e+00, -1.7777085685161123e+00, -1.5024981254275005e+00, -1.2281556226723449e+00, -9.5451451326831394e-01, -6.8141359873982055e-01, -4.0869572314721075e-01, -1.3620655703952730e-01, 1.3620655703952730e-01, 4.0869572314721075e-01, 6.8141359873982055e-01, 9.5451451326831394e-01, 1.2281556226723449e+00, 1.5024981254275005e+00, 1.7777085685161123e+00, 2.0539602757725310e+00, 2.3314349368154352e+00, 2.6103244026894505e+00, 2.8908327450724003e+00, 3.1731786504386261e+00, 3.4575982403178411e+00, 3.7443484358240933e+00, 4.0337110220232306e+00, 4.3259976200905568e+00, 4.6215558496899147e+00, 4.9207770717124939e+00, 5.2241062602848638e+00, 5.5320547921086867e+00, 5.8452173103130356e+00, 6.1642944056838216e+00, 6.4901238172609474e+00, 6.8237244832006141e+00, 7.1663606590936650e+00, 7.5196386980596541e+00, 7.8856597261055059e+00, 8.2672741104998497e+00, 8.6685366107264805e+00, 9.0956010448419295e+00, 9.5587304502592971e+00, 1.0077856416579301e+01, 1.0705216257883158e+01}, + {-1.0793719285461286e+01, -1.0168049165614175e+01, -9.6503813634446356e+00, -9.1886016826884820e+00, -8.7628250943199557e+00, -8.3628125057261151e+00, -7.9824245547615575e+00, -7.6176161578278192e+00, -7.2655439249081999e+00, -6.9241120615277021e+00, -6.5917184866891132e+00, -6.2671025086846086e+00, -5.9492482679521004e+00, -5.6373207673775578e+00, -5.3306219248283462e+00, -5.0285594473595783e+00, -4.7306242061652037e+00, -4.4363734165111914e+00, -4.1454178838251625e+00, -3.8574121614750752e+00, -3.5720468340630473e+00, -3.2890423786892447e+00, -3.0081442150749433e+00, -2.7291186629245998e+00, -2.4517495992505411e+00, -2.1758356606878357e+00, -1.9011878731830645e+00, -1.6276276184711236e+00, -1.3549848665269235e+00, -1.0830966177633830e+00, -8.1180550955890352e-01, -5.4095854971511481e-01, -2.7040594535031914e-01, -0.0000000000000000e+00, 2.7040594535031914e-01, 5.4095854971511481e-01, 8.1180550955890352e-01, 1.0830966177633830e+00, 1.3549848665269235e+00, 1.6276276184711236e+00, 1.9011878731830645e+00, 2.1758356606878357e+00, 2.4517495992505411e+00, 2.7291186629245998e+00, 3.0081442150749433e+00, 3.2890423786892447e+00, 3.5720468340630473e+00, 3.8574121614750752e+00, 4.1454178838251625e+00, 4.4363734165111914e+00, 4.7306242061652037e+00, 5.0285594473595783e+00, 5.3306219248283462e+00, 5.6373207673775578e+00, 5.9492482679521004e+00, 6.2671025086846086e+00, 6.5917184866891132e+00, 6.9241120615277021e+00, 7.2655439249081999e+00, 7.6176161578278192e+00, 7.9824245547615575e+00, 8.3628125057261151e+00, 8.7628250943199557e+00, 9.1886016826884820e+00, 9.6503813634446356e+00, 1.0168049165614175e+01, 1.0793719285461286e+01}, + {-1.0881547739512506e+01, -1.0257536674087854e+01, -9.7412997636867704e+00, -9.2808438835486236e+00, -8.8563297855819929e+00, -8.4575419119948716e+00, -8.0783550992846092e+00, -7.7147337577029216e+00, -7.3638413335052801e+00, -7.0235872465011688e+00, -6.6923735845747432e+00, -6.3689431247367301e+00, -6.0522829950450374e+00, -5.7415608508027303e+00, -5.4360810284450567e+00, -5.1352534929147948e+00, -4.8385712673985131e+00, -4.5455936557800598e+00, -4.2559335229494488e+00, -3.9692474811577245e+00, -3.6852281980879265e+00, -3.4035982804227491e+00, -3.1241053447888532e+00, -2.8465179952316144e+00, -2.5706225005795180e+00, -2.2962200172773377e+00, -2.0231242405790431e+00, -1.7511593940081669e+00, -1.4801584867781896e+00, -1.2099617834856000e+00, -9.4041544125892573e-01, -6.7137027764848267e-01, -4.0268063855845554e-01, -1.3420333993493833e-01, 1.3420333993493833e-01, 4.0268063855845554e-01, 6.7137027764848267e-01, 9.4041544125892573e-01, 1.2099617834856000e+00, 1.4801584867781896e+00, 1.7511593940081669e+00, 2.0231242405790431e+00, 2.2962200172773377e+00, 2.5706225005795180e+00, 2.8465179952316144e+00, 3.1241053447888532e+00, 3.4035982804227491e+00, 3.6852281980879265e+00, 3.9692474811577245e+00, 4.2559335229494488e+00, 4.5455936557800598e+00, 4.8385712673985131e+00, 5.1352534929147948e+00, 5.4360810284450567e+00, 5.7415608508027303e+00, 6.0522829950450374e+00, 6.3689431247367301e+00, 6.6923735845747432e+00, 7.0235872465011688e+00, 7.3638413335052801e+00, 7.7147337577029216e+00, 8.0783550992846092e+00, 8.4575419119948716e+00, 8.8563297855819929e+00, 9.2808438835486236e+00, 9.7412997636867704e+00, 1.0257536674087854e+01, 1.0881547739512506e+01}, + {-1.0968716712272720e+01, -1.0346335043862190e+01, -9.8315026740330858e+00, -9.3723455663368824e+00, -8.9490694985983303e+00, -8.5514820514248040e+00, -8.1734720117891584e+00, -7.8110131087611858e+00, -7.4612754898399762e+00, -7.1221736773103954e+00, -6.7921138299353210e+00, -6.4698421035199560e+00, -6.1543485281550758e+00, -5.8448033276997977e+00, -5.5405131730790877e+00, -5.2408902012860343e+00, -4.9454294985999852e+00, -4.6536923643912962e+00, -4.3652936245432166e+00, -4.0798918452871904e+00, -3.7971816649246475e+00, -3.5168876985063164e+00, -3.2387596283073630e+00, -2.9625681999937008e+00, -2.6881019184401618e+00, -2.4151642892936240e+00, -2.1435714896364328e+00, -1.8731503781015579e+00, -1.6037367745786486e+00, -1.3351739542940309e+00, -1.0673113119622561e+00, -8.0000315987311321e-01, -5.3310762988307847e-01, -2.6648565380755118e-01, -0.0000000000000000e+00, 2.6648565380755118e-01, 5.3310762988307847e-01, 8.0000315987311321e-01, 1.0673113119622561e+00, 1.3351739542940309e+00, 1.6037367745786486e+00, 1.8731503781015579e+00, 2.1435714896364328e+00, 2.4151642892936240e+00, 2.6881019184401618e+00, 2.9625681999937008e+00, 3.2387596283073630e+00, 3.5168876985063164e+00, 3.7971816649246475e+00, 4.0798918452871904e+00, 4.3652936245432166e+00, 4.6536923643912962e+00, 4.9454294985999852e+00, 5.2408902012860343e+00, 5.5405131730790877e+00, 5.8448033276997977e+00, 6.1543485281550758e+00, 6.4698421035199560e+00, 6.7921138299353210e+00, 7.1221736773103954e+00, 7.4612754898399762e+00, 7.8110131087611858e+00, 8.1734720117891584e+00, 8.5514820514248040e+00, 8.9490694985983303e+00, 9.3723455663368824e+00, 9.8315026740330858e+00, 1.0346335043862190e+01, 1.0968716712272720e+01}, + {-1.1055240743138121e+01, -1.0434459776321237e+01, -9.9210064725726337e+00, -9.4631239608462057e+00, -9.0410623133341144e+00, -8.6446518655005491e+00, -8.2677951152318059e+00, -7.9064749419687779e+00, -7.5578680649896128e+00, -7.2198940023018814e+00, -6.8909628903904032e+00, -6.5698241787566660e+00, -6.2554707188783159e+00, -5.9470752244713703e+00, -5.6439466223452381e+00, -5.3454991415732502e+00, -5.0512298489716008e+00, -4.7607019531713526e+00, -4.4735321501381859e+00, -4.1893808634925733e+00, -3.9079445988680890e+00, -3.6289498686372541e+00, -3.3521483007723556e+00, -3.0773126524497552e+00, -2.8042335229302870e+00, -2.5327166122907285e+00, -2.2625804097899467e+00, -1.9936542226231451e+00, -1.7257764756009522e+00, -1.4587932269483976e+00, -1.1925568563654070e+00, -9.2692488970661657e-01, -6.6175893081256654e-01, -3.9692367564298847e-01, -1.3228598727031571e-01, 1.3228598727031571e-01, 3.9692367564298847e-01, 6.6175893081256654e-01, 9.2692488970661657e-01, 1.1925568563654070e+00, 1.4587932269483976e+00, 1.7257764756009522e+00, 1.9936542226231451e+00, 2.2625804097899467e+00, 2.5327166122907285e+00, 2.8042335229302870e+00, 3.0773126524497552e+00, 3.3521483007723556e+00, 3.6289498686372541e+00, 3.9079445988680890e+00, 4.1893808634925733e+00, 4.4735321501381859e+00, 4.7607019531713526e+00, 5.0512298489716008e+00, 5.3454991415732502e+00, 5.6439466223452381e+00, 5.9470752244713703e+00, 6.2554707188783159e+00, 6.5698241787566660e+00, 6.8909628903904032e+00, 7.2198940023018814e+00, 7.5578680649896128e+00, 7.9064749419687779e+00, 8.2677951152318059e+00, 8.6446518655005491e+00, 9.0410623133341144e+00, 9.4631239608462057e+00, 9.9210064725726337e+00, 1.0434459776321237e+01, 1.1055240743138121e+01}, + {-1.1141133846557336e+01, -1.0521925803168939e+01, -1.0009826926005323e+01, -9.5531956441224679e+00, -9.1323256149194787e+00, -8.7370695574210657e+00, -8.3613434490107519e+00, -8.0011391572542987e+00, -7.6536398489544064e+00, -7.3167699357978755e+00, -6.9889434433253230e+00, -6.6689130340885914e+00, -6.3556743048467315e+00, -6.0484023852002728e+00, -5.7464083842334572e+00, -5.4491085484699262e+00, -5.1560018484650616e+00, -4.8666533221367576e+00, -4.5806814514481742e+00, -4.2977484283048772e+00, -4.0175525306328757e+00, -3.7398220661958628e+00, -3.4643104988218911e+00, -3.1907924783359922e+00, -2.9190605692775651e+00, -2.6489225254318436e+00, -2.3801989943566357e+00, -2.1127215630246923e+00, -1.8463310754751214e+00, -1.5808761680325296e+00, -1.3162119786216788e+00, -1.0521989949595671e+00, -7.8870201263520334e-01, -5.2558917877833533e-01, -2.6273110051935877e-01, -0.0000000000000000e+00, 2.6273110051935877e-01, 5.2558917877833533e-01, 7.8870201263520334e-01, 1.0521989949595671e+00, 1.3162119786216788e+00, 1.5808761680325296e+00, 1.8463310754751214e+00, 2.1127215630246923e+00, 2.3801989943566357e+00, 2.6489225254318436e+00, 2.9190605692775651e+00, 3.1907924783359922e+00, 3.4643104988218911e+00, 3.7398220661958628e+00, 4.0175525306328757e+00, 4.2977484283048772e+00, 4.5806814514481742e+00, 4.8666533221367576e+00, 5.1560018484650616e+00, 5.4491085484699262e+00, 5.7464083842334572e+00, 6.0484023852002728e+00, 6.3556743048467315e+00, 6.6689130340885914e+00, 6.9889434433253230e+00, 7.3167699357978755e+00, 7.6536398489544064e+00, 8.0011391572542987e+00, 8.3613434490107519e+00, 8.7370695574210657e+00, 9.1323256149194787e+00, 9.5531956441224679e+00, 1.0009826926005323e+01, 1.0521925803168939e+01, 1.1141133846557336e+01}, + {-1.1226409538142136e+01, -1.0608747515229252e+01, -1.0097979221003259e+01, -9.6425765744143064e+00, -9.2228761302815698e+00, -8.8287526315494791e+00, -8.4541353114024211e+00, -8.0950248691313433e+00, -7.7486107996948919e+00, -7.4128223108085409e+00, -7.0860772325710890e+00, -6.7671313640535109e+00, -6.4549829753707284e+00, -6.1488095423716089e+00, -5.8479242873741697e+00, -5.5517454045920136e+00, -5.2597736967589261e+00, -4.9715759567771789e+00, -4.6867723746994256e+00, -4.4050268283718435e+00, -4.1260392804003079e+00, -3.8495397401994360e+00, -3.5752834066737424e+00, -3.3030467134928974e+00, -3.0326240725636300e+00, -2.7638251631581228e+00, -2.4964726512514903e+00, -2.2304002505260021e+00, -1.9654510562578547e+00, -1.7014760979685193e+00, -1.4383330677067736e+00, -1.1758851891099782e+00, -9.1400019866369742e-01, -6.5254941532698807e-01, -3.9140687826621273e-01, -1.3044853509282020e-01, 1.3044853509282020e-01, 3.9140687826621273e-01, 6.5254941532698807e-01, 9.1400019866369742e-01, 1.1758851891099782e+00, 1.4383330677067736e+00, 1.7014760979685193e+00, 1.9654510562578547e+00, 2.2304002505260021e+00, 2.4964726512514903e+00, 2.7638251631581228e+00, 3.0326240725636300e+00, 3.3030467134928974e+00, 3.5752834066737424e+00, 3.8495397401994360e+00, 4.1260392804003079e+00, 4.4050268283718435e+00, 4.6867723746994256e+00, 4.9715759567771789e+00, 5.2597736967589261e+00, 5.5517454045920136e+00, 5.8479242873741697e+00, 6.1488095423716089e+00, 6.4549829753707284e+00, 6.7671313640535109e+00, 7.0860772325710890e+00, 7.4128223108085409e+00, 7.7486107996948919e+00, 8.0950248691313433e+00, 8.4541353114024211e+00, 8.8287526315494791e+00, 9.2228761302815698e+00, 9.6425765744143064e+00, 1.0097979221003259e+01, 1.0608747515229252e+01, 1.1226409538142136e+01}, + {-1.1311080859133723e+01, -1.0694938789404631e+01, -1.0185477993538820e+01, -9.7312821228925461e+00, -9.3127299623383131e+00, -8.9197179302027116e+00, -8.5461882990986897e+00, -8.1881504491623041e+00, -7.8428000887281044e+00, -7.5080711279939001e+00, -7.1823851209949314e+00, -6.8645009305993021e+00, -6.5534194322069030e+00, -6.2483203822637563e+00, -5.9485190514660768e+00, -5.6534355164057573e+00, -5.3625723452058249e+00, -5.0754980166052253e+00, -4.7918343564389145e+00, -4.5112468522638922e+00, -4.2334370704564908e+00, -3.9581366357170062e+00, -3.6851023893880592e+00, -3.4141124491940373e+00, -3.1449629665080243e+00, -2.8774654290158654e+00, -2.6114443936789562e+00, -2.3467355617654575e+00, -2.0831841274592904e+00, -1.8206433462185645e+00, -1.5589732800480507e+00, -1.2980396851534748e+00, -1.0377130137484731e+00, -7.7786750657853077e-01, -5.1838035636125168e-01, -2.5913092507112634e-01, -0.0000000000000000e+00, 2.5913092507112634e-01, 5.1838035636125168e-01, 7.7786750657853077e-01, 1.0377130137484731e+00, 1.2980396851534748e+00, 1.5589732800480507e+00, 1.8206433462185645e+00, 2.0831841274592904e+00, 2.3467355617654575e+00, 2.6114443936789562e+00, 2.8774654290158654e+00, 3.1449629665080243e+00, 3.4141124491940373e+00, 3.6851023893880592e+00, 3.9581366357170062e+00, 4.2334370704564908e+00, 4.5112468522638922e+00, 4.7918343564389145e+00, 5.0754980166052253e+00, 5.3625723452058249e+00, 5.6534355164057573e+00, 5.9485190514660768e+00, 6.2483203822637563e+00, 6.5534194322069030e+00, 6.8645009305993021e+00, 7.1823851209949314e+00, 7.5080711279939001e+00, 7.8428000887281044e+00, 8.1881504491623041e+00, 8.5461882990986897e+00, 8.9197179302027116e+00, 9.3127299623383131e+00, 9.7312821228925461e+00, 1.0185477993538820e+01, 1.0694938789404631e+01, 1.1311080859133723e+01}, + {-1.1395160399349303e+01, -1.0780513013934538e+01, -1.0272337356338001e+01, -9.8193271033153593e+00, -9.4019026219489774e+00, -9.0099816679963673e+00, -8.6375193440825591e+00, -8.2805335655260475e+00, -7.9362261435724362e+00, -7.6025356011958438e+00, -7.2778871393556734e+00, -6.9610426155273659e+00, -6.6510054458855254e+00, -6.3469576054906103e+00, -6.0482163524027337e+00, -5.7542035843517603e+00, -5.4644235724164387e+00, -5.1784464167185336e+00, -4.8958955116562031e+00, -4.6164378838097413e+00, -4.3397766284785542e+00, -4.0656449059380266e+00, -3.7938011146597774e+00, -3.5240249647298416e+00, -3.2561142480573673e+00, -2.9898821536352491e+00, -2.7251550130837989e+00, -2.4617703885377660e+00, -2.1995754346550642e+00, -1.9384254811801831e+00, -1.6781827934921525e+00, -1.4187154768845949e+00, -1.1598964966533338e+00, -9.0160279089609208e-01, -6.4371445661134197e-01, -3.8611399247334727e-01, -1.2868558374092035e-01, 1.2868558374092035e-01, 3.8611399247334727e-01, 6.4371445661134197e-01, 9.0160279089609208e-01, 1.1598964966533338e+00, 1.4187154768845949e+00, 1.6781827934921525e+00, 1.9384254811801831e+00, 2.1995754346550642e+00, 2.4617703885377660e+00, 2.7251550130837989e+00, 2.9898821536352491e+00, 3.2561142480573673e+00, 3.5240249647298416e+00, 3.7938011146597774e+00, 4.0656449059380266e+00, 4.3397766284785542e+00, 4.6164378838097413e+00, 4.8958955116562031e+00, 5.1784464167185336e+00, 5.4644235724164387e+00, 5.7542035843517603e+00, 6.0482163524027337e+00, 6.3469576054906103e+00, 6.6510054458855254e+00, 6.9610426155273659e+00, 7.2778871393556734e+00, 7.6025356011958438e+00, 7.9362261435724362e+00, 8.2805335655260475e+00, 8.6375193440825591e+00, 9.0099816679963673e+00, 9.4019026219489774e+00, 9.8193271033153593e+00, 1.0272337356338001e+01, 1.0780513013934538e+01, 1.1395160399349303e+01}, + {-1.1478660318722643e+01, -1.0865483112083050e+01, -1.0358570924603207e+01, -9.9067257997991209e+00, -9.4904090577984004e+00, -9.0995594639401105e+00, -8.7281447480576215e+00, -8.3721912199266999e+00, -8.0289066873027544e+00, -7.6962341998287283e+00, -7.3726025317424613e+00, -7.0567764692174766e+00, -6.7477619079872566e+00, -6.4447429831267424e+00, -6.1470388825769424e+00, -5.8540732676978866e+00, -5.5653520540734327e+00, -5.2804469030361734e+00, -4.9989827149592099e+00, -4.7206279897915646e+00, -4.4450872824012313e+00, -4.1720952149448500e+00, -3.9014116643261456e+00, -3.6328178485882909e+00, -3.3661131093032384e+00, -3.1011122385952579e+00, -2.8376432363425028e+00, -2.5755454098889712e+00, -2.3146677482934548e+00, -2.0548675177858016e+00, -1.7960090360977110e+00, -1.5379625916624640e+00, -1.2806034800245349e+00, -1.0238111346569745e+00, -7.6746833310481610e-01, -5.1146046221189689e-01, -2.5567482833134803e-01, -0.0000000000000000e+00, 2.5567482833134803e-01, 5.1146046221189689e-01, 7.6746833310481610e-01, 1.0238111346569745e+00, 1.2806034800245349e+00, 1.5379625916624640e+00, 1.7960090360977110e+00, 2.0548675177858016e+00, 2.3146677482934548e+00, 2.5755454098889712e+00, 2.8376432363425028e+00, 3.1011122385952579e+00, 3.3661131093032384e+00, 3.6328178485882909e+00, 3.9014116643261456e+00, 4.1720952149448500e+00, 4.4450872824012313e+00, 4.7206279897915646e+00, 4.9989827149592099e+00, 5.2804469030361734e+00, 5.5653520540734327e+00, 5.8540732676978866e+00, 6.1470388825769424e+00, 6.4447429831267424e+00, 6.7477619079872566e+00, 7.0567764692174766e+00, 7.3726025317424613e+00, 7.6962341998287283e+00, 8.0289066873027544e+00, 8.3721912199266999e+00, 8.7281447480576215e+00, 9.0995594639401105e+00, 9.4904090577984004e+00, 9.9067257997991209e+00, 1.0358570924603207e+01, 1.0865483112083050e+01, 1.1478660318722643e+01}, + {-1.1561592367542413e+01, -1.0949861564373141e+01, -1.0444191840136728e+01, -9.9934919928404522e+00, -9.5782636843755515e+00, -9.1884663714605921e+00, -8.8180802146261925e+00, -8.4631397820581817e+00, -8.1208587754520742e+00, -7.7891846883888824e+00, -7.4665497978837827e+00, -7.1517217559506374e+00, -6.8437088797189292e+00, -6.5416974088024276e+00, -6.2450084067917304e+00, -5.9530672445968058e+00, -5.6653814275042969e+00, -5.3815241217984982e+00, -5.1011216754614015e+00, -4.8238440007350292e+00, -4.5493970476880525e+00, -4.2775168321151087e+00, -4.0079646366324129e+00, -3.7405231094103377e+00, -3.4749930580623096e+00, -3.2111907876889831e+00, -2.9489458689195023e+00, -2.6880992485383528e+00, -2.4285016349547641e+00, -2.1700121054020434e+00, -1.9124968927478689e+00, -1.6558283181292228e+00, -1.3998838419857680e+00, -1.1445452109440197e+00, -8.8969768175512143e-01, -6.3522930636766928e-01, -3.8103026441027604e-01, -1.2699223100184112e-01, 1.2699223100184112e-01, 3.8103026441027604e-01, 6.3522930636766928e-01, 8.8969768175512143e-01, 1.1445452109440197e+00, 1.3998838419857680e+00, 1.6558283181292228e+00, 1.9124968927478689e+00, 2.1700121054020434e+00, 2.4285016349547641e+00, 2.6880992485383528e+00, 2.9489458689195023e+00, 3.2111907876889831e+00, 3.4749930580623096e+00, 3.7405231094103377e+00, 4.0079646366324129e+00, 4.2775168321151087e+00, 4.5493970476880525e+00, 4.8238440007350292e+00, 5.1011216754614015e+00, 5.3815241217984982e+00, 5.6653814275042969e+00, 5.9530672445968058e+00, 6.2450084067917304e+00, 6.5416974088024276e+00, 6.8437088797189292e+00, 7.1517217559506374e+00, 7.4665497978837827e+00, 7.7891846883888824e+00, 8.1208587754520742e+00, 8.4631397820581817e+00, 8.8180802146261925e+00, 9.1884663714605921e+00, 9.5782636843755515e+00, 9.9934919928404522e+00, 1.0444191840136728e+01, 1.0949861564373141e+01, 1.1561592367542413e+01}, + {-1.1643967905483196e+01, -1.1033660429475029e+01, -1.0529212793984577e+01, -1.0079638983721908e+01, -9.6654804081925363e+00, -9.2767169065128172e+00, -8.9073408793931357e+00, -8.5533950218190302e+00, -8.2120988304736517e+00, -7.8814041633182299e+00, -7.5597467325857197e+00, -7.2458969961152926e+00, -6.9388656371030670e+00, -6.6378409471161133e+00, -6.3421458141623201e+00, -6.0512072677740329e+00, -5.7645343514856853e+00, -5.4817016838558219e+00, -5.2023370059655702e+00, -4.9261115854472983e+00, -4.6527327077376199e+00, -4.3819377189728366e+00, -4.1134892401757890e+00, -3.8471712777564733e+00, -3.5827860282892376e+00, -3.3201512269147213e+00, -3.0590979254933970e+00, -2.7994686133415088e+00, -2.5411156130214039e+00, -2.2838996982733861e+00, -2.0276888921639609e+00, -1.7723574118602183e+00, -1.5177847328096994e+00, -1.2638547500001409e+00, -1.0104550177477929e+00, -7.5747605237336058e-01, -5.0481068435860232e-01, -2.5235344827118406e-01, -0.0000000000000000e+00, 2.5235344827118406e-01, 5.0481068435860232e-01, 7.5747605237336058e-01, 1.0104550177477929e+00, 1.2638547500001409e+00, 1.5177847328096994e+00, 1.7723574118602183e+00, 2.0276888921639609e+00, 2.2838996982733861e+00, 2.5411156130214039e+00, 2.7994686133415088e+00, 3.0590979254933970e+00, 3.3201512269147213e+00, 3.5827860282892376e+00, 3.8471712777564733e+00, 4.1134892401757890e+00, 4.3819377189728366e+00, 4.6527327077376199e+00, 4.9261115854472983e+00, 5.2023370059655702e+00, 5.4817016838558219e+00, 5.7645343514856853e+00, 6.0512072677740329e+00, 6.3421458141623201e+00, 6.6378409471161133e+00, 6.9388656371030670e+00, 7.2458969961152926e+00, 7.5597467325857197e+00, 7.8814041633182299e+00, 8.2120988304736517e+00, 8.5533950218190302e+00, 8.9073408793931357e+00, 9.2767169065128172e+00, 9.6654804081925363e+00, 1.0079638983721908e+01, 1.0529212793984577e+01, 1.1033660429475029e+01, 1.1643967905483196e+01}, + {-1.1725797919515925e+01, -1.1116891363846698e+01, -1.0613646047709890e+01, -1.0165179617422121e+01, -9.7520726523771355e+00, -9.3643250739262687e+00, -8.9959413381560331e+00, -8.6429721394539492e+00, -8.3026426739573083e+00, -7.9729090874349415e+00, -7.6522104625334553e+00, -7.3393200055543293e+00, -7.0332507130647253e+00, -6.7331928786770474e+00, -6.4384711663544172e+00, -6.1485142162283823e+00, -5.8628325617022545e+00, -5.5810022242153172e+00, -5.3026522869660511e+00, -5.0274553198842957e+00, -4.7551198880737857e+00, -4.4853846092140870e+00, -4.2180133803413131e+00, -3.9527914995987943e+00, -3.6895224813523542e+00, -3.4280254143563189e+00, -3.1681327493707792e+00, -2.9096884292910694e+00, -2.6525462944632925e+00, -2.3965687104578790e+00, -2.1416253765529731e+00, -1.8875922815137989e+00, -1.6343507796298868e+00, -1.3817867648795250e+00, -1.1297899248837724e+00, -8.7825305924819486e-01, -6.2707144915742807e-01, -3.7614226682388563e-01, -1.2536401469850444e-01, 1.2536401469850444e-01, 3.7614226682388563e-01, 6.2707144915742807e-01, 8.7825305924819486e-01, 1.1297899248837724e+00, 1.3817867648795250e+00, 1.6343507796298868e+00, 1.8875922815137989e+00, 2.1416253765529731e+00, 2.3965687104578790e+00, 2.6525462944632925e+00, 2.9096884292910694e+00, 3.1681327493707792e+00, 3.4280254143563189e+00, 3.6895224813523542e+00, 3.9527914995987943e+00, 4.2180133803413131e+00, 4.4853846092140870e+00, 4.7551198880737857e+00, 5.0274553198842957e+00, 5.3026522869660511e+00, 5.5810022242153172e+00, 5.8628325617022545e+00, 6.1485142162283823e+00, 6.4384711663544172e+00, 6.7331928786770474e+00, 7.0332507130647253e+00, 7.3393200055543293e+00, 7.6522104625334553e+00, 7.9729090874349415e+00, 8.3026426739573083e+00, 8.6429721394539492e+00, 8.9959413381560331e+00, 9.3643250739262687e+00, 9.7520726523771355e+00, 1.0165179617422121e+01, 1.0613646047709890e+01, 1.1116891363846698e+01, 1.1725797919515925e+01}, + {-1.1807093040777294e+01, -1.1199565640216381e+01, -1.0697503453395814e+01, -1.0250126304140645e+01, -9.8380533797602858e+00, -9.4513043921191180e+00, -9.0838956733280174e+00, -8.7318857937825296e+00, -8.3925055567758680e+00, -8.0637153221240894e+00, -7.7439574806678753e+00, -7.4320079322856305e+00, -7.1268819366716176e+00, -6.8277717420599027e+00, -6.5340037424695643e+00, -6.2450081432878877e+00, -5.9602969222394462e+00, -5.6794474572664067e+00, -5.4020901259356995e+00, -5.1278987508656595e+00, -4.8565831248972122e+00, -4.5878830825516648e+00, -4.3215637389507622e+00, -4.0574116223471224e+00, -3.7952314990808915e+00, -3.5348437409765978e+00, -3.2760821218442313e+00, -3.0187919563650998e+00, -2.7628285142266278e+00, -2.5080556569501704e+00, -2.2543446558260460e+00, -2.0015731577016731e+00, -1.7496242717478425e+00, -1.4983857552446240e+00, -1.2477492802359769e+00, -9.9760976585826833e-01, -7.4786476344152575e-01, -4.9841388325234109e-01, -2.4915825309625725e-01, -0.0000000000000000e+00, 2.4915825309625725e-01, 4.9841388325234109e-01, 7.4786476344152575e-01, 9.9760976585826833e-01, 1.2477492802359769e+00, 1.4983857552446240e+00, 1.7496242717478425e+00, 2.0015731577016731e+00, 2.2543446558260460e+00, 2.5080556569501704e+00, 2.7628285142266278e+00, 3.0187919563650998e+00, 3.2760821218442313e+00, 3.5348437409765978e+00, 3.7952314990808915e+00, 4.0574116223471224e+00, 4.3215637389507622e+00, 4.5878830825516648e+00, 4.8565831248972122e+00, 5.1278987508656595e+00, 5.4020901259356995e+00, 5.6794474572664067e+00, 5.9602969222394462e+00, 6.2450081432878877e+00, 6.5340037424695643e+00, 6.8277717420599027e+00, 7.1268819366716176e+00, 7.4320079322856305e+00, 7.7439574806678753e+00, 8.0637153221240894e+00, 8.3925055567758680e+00, 8.7318857937825296e+00, 9.0838956733280174e+00, 9.4513043921191180e+00, 9.8380533797602858e+00, 1.0250126304140645e+01, 1.0697503453395814e+01, 1.1199565640216381e+01, 1.1807093040777294e+01}, + {-1.1887863560471148e+01, -1.1281694164989270e+01, -1.0780796472469154e+01, -1.0334491039538371e+01, -9.9234351145692425e+00, -9.5376679163020608e+00, -9.1712174787264829e+00, -8.8201501286610533e+00, -8.4817021873215737e+00, -8.1538381574634560e+00, -7.8350036783292891e+00, -7.5239772908068669e+00, -7.2197764697589237e+00, -6.9215953729258182e+00, -6.6287620808575998e+00, -6.3407083213299842e+00, -6.0569474734510278e+00, -5.7770582280615690e+00, -5.5006722123151564e+00, -5.2274644551006757e+00, -4.9571459285134285e+00, -4.6894576329528137e+00, -4.4241658477651837e+00, -4.1610582741258364e+00, -3.8999408693873892e+00, -3.6406352232272088e+00, -3.3829763625124016e+00, -3.1268108983731295e+00, -2.8719954485287333e+00, -2.6183952824717842e+00, -2.3658831480742251e+00, -2.1143382465070100e+00, -1.8636453287449284e+00, -1.6136938918510606e+00, -1.3643774570540068e+00, -1.1155929146033490e+00, -8.6723992270397532e-01, -6.1922034962756711e-01, -3.7143774948304431e-01, -1.2379686317313206e-01, 1.2379686317313206e-01, 3.7143774948304431e-01, 6.1922034962756711e-01, 8.6723992270397532e-01, 1.1155929146033490e+00, 1.3643774570540068e+00, 1.6136938918510606e+00, 1.8636453287449284e+00, 2.1143382465070100e+00, 2.3658831480742251e+00, 2.6183952824717842e+00, 2.8719954485287333e+00, 3.1268108983731295e+00, 3.3829763625124016e+00, 3.6406352232272088e+00, 3.8999408693873892e+00, 4.1610582741258364e+00, 4.4241658477651837e+00, 4.6894576329528137e+00, 4.9571459285134285e+00, 5.2274644551006757e+00, 5.5006722123151564e+00, 5.7770582280615690e+00, 6.0569474734510278e+00, 6.3407083213299842e+00, 6.6287620808575998e+00, 6.9215953729258182e+00, 7.2197764697589237e+00, 7.5239772908068669e+00, 7.8350036783292891e+00, 8.1538381574634560e+00, 8.4817021873215737e+00, 8.8201501286610533e+00, 9.1712174787264829e+00, 9.5376679163020608e+00, 9.9234351145692425e+00, 1.0334491039538371e+01, 1.0780796472469154e+01, 1.1281694164989270e+01, 1.1887863560471148e+01}, + {-1.1968119444868723e+01, -1.1363287494653905e+01, -1.0863536193428574e+01, -1.0418285423785731e+01, -1.0008229962827862e+01, -9.6234282602828909e+00, -9.2579198828492224e+00, -8.9077787978104048e+00, -8.5702467579780226e+00, -8.2432923404437446e+00, -7.9253643753426406e+00, -7.6152439941755770e+00, -7.3119508411483105e+00, -7.0146809405398773e+00, -6.7227640181091326e+00, -6.4356332834442265e+00, -6.1528034765082218e+00, -5.8738545599912273e+00, -5.5984193685789059e+00, -5.3261740939400637e+00, -5.0568308420977290e+00, -4.7901317317816865e+00, -4.5258441564113081e+00, -4.2637569369381021e+00, -4.0036771651776295e+00, -3.7454275882737633e+00, -3.4888444214602070e+00, -3.2337755028119282e+00, -2.9800787232025514e+00, -2.7276206792242430e+00, -2.4762755077735275e+00, -2.2259238693277426e+00, -1.9764520533164986e+00, -1.7277511839192137e+00, -1.4797165084468731e+00, -1.2322467534512360e+00, -9.8524353603723147e-01, -7.3861081967444187e-01, -4.9225440521533759e-01, -2.4608144890838049e-01, -0.0000000000000000e+00, 2.4608144890838049e-01, 4.9225440521533759e-01, 7.3861081967444187e-01, 9.8524353603723147e-01, 1.2322467534512360e+00, 1.4797165084468731e+00, 1.7277511839192137e+00, 1.9764520533164986e+00, 2.2259238693277426e+00, 2.4762755077735275e+00, 2.7276206792242430e+00, 2.9800787232025514e+00, 3.2337755028119282e+00, 3.4888444214602070e+00, 3.7454275882737633e+00, 4.0036771651776295e+00, 4.2637569369381021e+00, 4.5258441564113081e+00, 4.7901317317816865e+00, 5.0568308420977290e+00, 5.3261740939400637e+00, 5.5984193685789059e+00, 5.8738545599912273e+00, 6.1528034765082218e+00, 6.4356332834442265e+00, 6.7227640181091326e+00, 7.0146809405398773e+00, 7.3119508411483105e+00, 7.6152439941755770e+00, 7.9253643753426406e+00, 8.2432923404437446e+00, 8.5702467579780226e+00, 8.9077787978104048e+00, 9.2579198828492224e+00, 9.6234282602828909e+00, 1.0008229962827862e+01, 1.0418285423785731e+01, 1.0863536193428574e+01, 1.1363287494653905e+01, 1.1968119444868723e+01}, + {-1.2047870349469452e+01, -1.1444355851257512e+01, -1.0945733348554121e+01, -1.0501520679503271e+01, -1.0092449631556644e+01, -9.7085976169732788e+00, -9.3440155707490522e+00, -8.9947849881314195e+00, -8.6581529699601738e+00, -8.3320921014281222e+00, -8.0150543482026926e+00, -7.7058233840379780e+00, -7.4034209786511349e+00, -7.1070449818933454e+00, -6.8160267254566378e+00, -6.5298008622888712e+00, -6.2478834549069706e+00, -5.9698556991575886e+00, -5.6953515977146445e+00, -5.4240484642257165e+00, -5.1556594962091573e+00, -4.8899278863041147e+00, -4.6266220952405250e+00, -4.3655320142842475e+00, -4.1064658171809416e+00, -3.8492473525444271e+00, -3.5937139640934332e+00, -3.3397146526239907e+00, -3.0871085130972600e+00, -2.8357633947424321e+00, -2.5855547430080739e+00, -2.3363645905095152e+00, -2.0880806704972801e+00, -1.8405956313004481e+00, -1.5938063340319311e+00, -1.3476132188376881e+00, -1.1019197273183625e+00, -8.5663177059026308e-01, -6.1165723388752291e-01, -3.6690550971654429e-01, -1.2228705241518351e-01, 1.2228705241518351e-01, 3.6690550971654429e-01, 6.1165723388752291e-01, 8.5663177059026308e-01, 1.1019197273183625e+00, 1.3476132188376881e+00, 1.5938063340319311e+00, 1.8405956313004481e+00, 2.0880806704972801e+00, 2.3363645905095152e+00, 2.5855547430080739e+00, 2.8357633947424321e+00, 3.0871085130972600e+00, 3.3397146526239907e+00, 3.5937139640934332e+00, 3.8492473525444271e+00, 4.1064658171809416e+00, 4.3655320142842475e+00, 4.6266220952405250e+00, 4.8899278863041147e+00, 5.1556594962091573e+00, 5.4240484642257165e+00, 5.6953515977146445e+00, 5.9698556991575886e+00, 6.2478834549069706e+00, 6.5298008622888712e+00, 6.8160267254566378e+00, 7.1070449818933454e+00, 7.4034209786511349e+00, 7.7058233840379780e+00, 8.0150543482026926e+00, 8.3320921014281222e+00, 8.6581529699601738e+00, 8.9947849881314195e+00, 9.3440155707490522e+00, 9.7085976169732788e+00, 1.0092449631556644e+01, 1.0501520679503271e+01, 1.0945733348554121e+01, 1.1444355851257512e+01, 1.2047870349469452e+01}, + {-1.2127125632378913e+01, -1.1524909137013976e+01, -1.1027398329668573e+01, -1.0584207668672128e+01, -1.0176105446857637e+01, -9.7931877776907488e+00, -9.4295168046084115e+00, -9.0811814416185097e+00, -8.7454340566434574e+00, -8.4202511789832108e+00, -8.1040878565034831e+00, -7.7957302587642490e+00, -7.4942022390283798e+00, -7.1987034336195581e+00, -6.9085667427912707e+00, -6.6232282263685835e+00, -6.3422052331830958e+00, -6.0650801557222689e+00, -5.7914881274189227e+00, -5.5211075455728480e+00, -5.2536526594233770e+00, -4.9888676939643233e+00, -4.7265221335751297e+00, -4.4664068937399284e+00, -4.2083311812642945e+00, -3.9521198942311013e+00, -3.6976114493318364e+00, -3.4446559506485350e+00, -3.1931136334230796e+00, -2.9428535308492294e+00, -2.6937523228426583e+00, -2.4456933340503899e+00, -2.1985656547350549e+00, -1.9522633630987765e+00, -1.7066848314488341e+00, -1.4617321016098621e+00, -1.2173103173449662e+00, -9.7332720340140344e-01, -7.2969258225037825e-01, -4.8631792072343311e-01, -2.4311589961848629e-01, -0.0000000000000000e+00, 2.4311589961848629e-01, 4.8631792072343311e-01, 7.2969258225037825e-01, 9.7332720340140344e-01, 1.2173103173449662e+00, 1.4617321016098621e+00, 1.7066848314488341e+00, 1.9522633630987765e+00, 2.1985656547350549e+00, 2.4456933340503899e+00, 2.6937523228426583e+00, 2.9428535308492294e+00, 3.1931136334230796e+00, 3.4446559506485350e+00, 3.6976114493318364e+00, 3.9521198942311013e+00, 4.2083311812642945e+00, 4.4664068937399284e+00, 4.7265221335751297e+00, 4.9888676939643233e+00, 5.2536526594233770e+00, 5.5211075455728480e+00, 5.7914881274189227e+00, 6.0650801557222689e+00, 6.3422052331830958e+00, 6.6232282263685835e+00, 6.9085667427912707e+00, 7.1987034336195581e+00, 7.4942022390283798e+00, 7.7957302587642490e+00, 8.1040878565034831e+00, 8.4202511789832108e+00, 8.7454340566434574e+00, 9.0811814416185097e+00, 9.4295168046084115e+00, 9.7931877776907488e+00, 1.0176105446857637e+01, 1.0584207668672128e+01, 1.1027398329668573e+01, 1.1524909137013976e+01, 1.2127125632378913e+01}, + {-1.2205894366956139e+01, -1.1604956948103077e+01, -1.1108541203015454e+01, -1.0666356908585685e+01, -1.0259208370962089e+01, -9.8772101503410621e+00, -9.5144354431069669e+00, -9.1669804759729860e+00, -8.8321028054925428e+00, -8.5077828432020937e+00, -8.1924786677436181e+00, -7.8849788998338592e+00, -7.5843094360641796e+00, -7.2896716618750510e+00, -7.0004000104832143e+00, -6.7159319139391096e+00, -6.4357859730612450e+00, -6.1595457424759266e+00, -5.8868474512821898e+00, -5.6173705443855964e+00, -5.3508302854168104e+00, -5.0869718928011789e+00, -4.8255658337490095e+00, -4.5664040049460510e+00, -4.3092966007328037e+00, -4.0540695203033383e+00, -3.8005622017862843e+00, -3.5486257974651720e+00, -3.2981216238257258e+00, -3.0489198345947157e+00, -2.8008982758405363e+00, -2.5539414905028606e+00, -2.3079398460883205e+00, -2.0627887641978626e+00, -1.8183880343913310e+00, -1.5746411979031998e+00, -1.3314549890897636e+00, -1.0887388243534069e+00, -8.4640432975900237e-01, -6.0436489970992124e-01, -3.6253527994578344e-01, -1.2083116880501313e-01, 1.2083116880501313e-01, 3.6253527994578344e-01, 6.0436489970992124e-01, 8.4640432975900237e-01, 1.0887388243534069e+00, 1.3314549890897636e+00, 1.5746411979031998e+00, 1.8183880343913310e+00, 2.0627887641978626e+00, 2.3079398460883205e+00, 2.5539414905028606e+00, 2.8008982758405363e+00, 3.0489198345947157e+00, 3.2981216238257258e+00, 3.5486257974651720e+00, 3.8005622017862843e+00, 4.0540695203033383e+00, 4.3092966007328037e+00, 4.5664040049460510e+00, 4.8255658337490095e+00, 5.0869718928011789e+00, 5.3508302854168104e+00, 5.6173705443855964e+00, 5.8868474512821898e+00, 6.1595457424759266e+00, 6.4357859730612450e+00, 6.7159319139391096e+00, 7.0004000104832143e+00, 7.2896716618750510e+00, 7.5843094360641796e+00, 7.8849788998338592e+00, 8.1924786677436181e+00, 8.5077828432020937e+00, 8.8321028054925428e+00, 9.1669804759729860e+00, 9.5144354431069669e+00, 9.8772101503410621e+00, 1.0259208370962089e+01, 1.0666356908585685e+01, 1.1108541203015454e+01, 1.1604956948103077e+01, 1.2205894366956139e+01}, + {-1.2284185353778504e+01, -1.1684508587714936e+01, -1.1189171723313381e+01, -1.0747978586907845e+01, -1.0341769018312585e+01, -9.9606757765591638e+00, -9.5987829596674032e+00, -9.2521940040089010e+00, -8.9181715786909077e+00, -8.5946999176295051e+00, -8.2802400806274559e+00, -7.9735830966018995e+00, -7.6737568668958440e+00, -7.3799644903419361e+00, -7.0915418991761436e+00, -6.8079278647256025e+00, -6.5286422072422212e+00, -6.2532696108544226e+00, -5.9814473672099631e+00, -5.7128559348775809e+00, -5.4472115568012640e+00, -5.1842604083343016e+00, -4.9237739013081612e+00, -4.6655448734152234e+00, -4.4093844640660000e+00, -4.1551195285347458e+00, -3.9025904784769208e+00, -3.6516494632523195e+00, -3.4021588258868611e+00, -3.1539897819612150e+00, -2.9070212806051177e+00, -2.6611390150638674e+00, -2.4162345566678476e+00, -2.1722045909628105e+00, -1.9289502385999013e+00, -1.6863764465968691e+00, -1.4443914379551996e+00, -1.2029062094928866e+00, -9.6183406923470449e-01, -7.2109020587034223e-01, -4.8059128370529336e-01, -2.4025505723472676e-01, -0.0000000000000000e+00, 2.4025505723472676e-01, 4.8059128370529336e-01, 7.2109020587034223e-01, 9.6183406923470449e-01, 1.2029062094928866e+00, 1.4443914379551996e+00, 1.6863764465968691e+00, 1.9289502385999013e+00, 2.1722045909628105e+00, 2.4162345566678476e+00, 2.6611390150638674e+00, 2.9070212806051177e+00, 3.1539897819612150e+00, 3.4021588258868611e+00, 3.6516494632523195e+00, 3.9025904784769208e+00, 4.1551195285347458e+00, 4.4093844640660000e+00, 4.6655448734152234e+00, 4.9237739013081612e+00, 5.1842604083343016e+00, 5.4472115568012640e+00, 5.7128559348775809e+00, 5.9814473672099631e+00, 6.2532696108544226e+00, 6.5286422072422212e+00, 6.8079278647256025e+00, 7.0915418991761436e+00, 7.3799644903419361e+00, 7.6737568668958440e+00, 7.9735830966018995e+00, 8.2802400806274559e+00, 8.5946999176295051e+00, 8.9181715786909077e+00, 9.2521940040089010e+00, 9.5987829596674032e+00, 9.9606757765591638e+00, 1.0341769018312585e+01, 1.0747978586907845e+01, 1.1189171723313381e+01, 1.1684508587714936e+01, 1.2284185353778504e+01}, + {-1.2362007131968511e+01, -1.1763573078389516e+01, -1.1269299347041693e+01, -1.0829082575898250e+01, -1.0423797670745445e+01, -1.0043595347880535e+01, -9.6825704596576454e+00, -9.3368335519365662e+00, -9.0036523325638047e+00, -8.6810147998900291e+00, -8.3673849469719066e+00, -8.0615561695659022e+00, -7.7625583367306144e+00, -7.4695962264936551e+00, -7.1820072377109705e+00, -6.8992314496242599e+00, -6.6207898710143054e+00, -6.3462682846048741e+00, -6.0753050133032716e+00, -5.8075814973426141e+00, -5.5428149259789015e+00, -5.2807523972174923e+00, -5.0211662316993868e+00, -4.7638501705179523e+00, -4.5086162584922675e+00, -4.2552922649886131e+00, -4.0037195305892794e+00, -3.7537511542142386e+00, -3.5052504546692158e+00, -3.2580896550268070e+00, -3.0121487491227401e+00, -2.7673145177270055e+00, -2.5234796683078762e+00, -2.2805420772311842e+00, -2.0384041170786049e+00, -1.7969720547840342e+00, -1.5561555086656726e+00, -1.3158669543141910e+00, -1.0760212707898533e+00, -8.3653531976321294e-01, -5.9732755116498426e-01, -3.5831762963623587e-01, -1.1942607662410318e-01, 1.1942607662410318e-01, 3.5831762963623587e-01, 5.9732755116498426e-01, 8.3653531976321294e-01, 1.0760212707898533e+00, 1.3158669543141910e+00, 1.5561555086656726e+00, 1.7969720547840342e+00, 2.0384041170786049e+00, 2.2805420772311842e+00, 2.5234796683078762e+00, 2.7673145177270055e+00, 3.0121487491227401e+00, 3.2580896550268070e+00, 3.5052504546692158e+00, 3.7537511542142386e+00, 4.0037195305892794e+00, 4.2552922649886131e+00, 4.5086162584922675e+00, 4.7638501705179523e+00, 5.0211662316993868e+00, 5.2807523972174923e+00, 5.5428149259789015e+00, 5.8075814973426141e+00, 6.0753050133032716e+00, 6.3462682846048741e+00, 6.6207898710143054e+00, 6.8992314496242599e+00, 7.1820072377109705e+00, 7.4695962264936551e+00, 7.7625583367306144e+00, 8.0615561695659022e+00, 8.3673849469719066e+00, 8.6810147998900291e+00, 9.0036523325638047e+00, 9.3368335519365662e+00, 9.6825704596576454e+00, 1.0043595347880535e+01, 1.0423797670745445e+01, 1.0829082575898250e+01, 1.1269299347041693e+01, 1.1763573078389516e+01, 1.2362007131968511e+01}, + {-1.2439367989923680e+01, -1.1842159173697059e+01, -1.1348933245008068e+01, -1.0909678445859965e+01, -1.0505304291834085e+01, -1.0125979221008995e+01, -9.7658086966213720e+00, -9.4209102766018642e+00, -9.0885566358796162e+00, -8.7667394811116139e+00, -8.4539256923192720e+00, -8.1489109922424241e+00, -7.8507271820680931e+00, -7.5585806862536904e+00, -7.2718103393202060e+00, -6.9898574985414994e+00, -6.7122443318572111e+00, -6.4385576912861495e+00, -6.1684369014005451e+00, -5.9015643538974087e+00, -5.6376581532613121e+00, -5.3764662879277241e+00, -5.1177619537428889e+00, -4.8613397599750519e+00, -4.6070126197625800e+00, -4.3546091773629314e+00, -4.1039716607125998e+00, -3.8549540740709145e+00, -3.6074206648573135e+00, -3.3612446132027243e+00, -3.1163069035955786e+00, -2.8724953462701670e+00, -2.6297037223368069e+00, -2.3878310315742213e+00, -2.1467808256453083e+00, -1.9064606125144659e+00, -1.6667813202271460e+00, -1.4276568101012006e+00, -1.1890034308805355e+00, -9.5073960659419110e-01, -7.1278545180861597e-01, -4.7506240870319627e-01, -2.3749290097360490e-01, -0.0000000000000000e+00, 2.3749290097360490e-01, 4.7506240870319627e-01, 7.1278545180861597e-01, 9.5073960659419110e-01, 1.1890034308805355e+00, 1.4276568101012006e+00, 1.6667813202271460e+00, 1.9064606125144659e+00, 2.1467808256453083e+00, 2.3878310315742213e+00, 2.6297037223368069e+00, 2.8724953462701670e+00, 3.1163069035955786e+00, 3.3612446132027243e+00, 3.6074206648573135e+00, 3.8549540740709145e+00, 4.1039716607125998e+00, 4.3546091773629314e+00, 4.6070126197625800e+00, 4.8613397599750519e+00, 5.1177619537428889e+00, 5.3764662879277241e+00, 5.6376581532613121e+00, 5.9015643538974087e+00, 6.1684369014005451e+00, 6.4385576912861495e+00, 6.7122443318572111e+00, 6.9898574985414994e+00, 7.2718103393202060e+00, 7.5585806862536904e+00, 7.8507271820680931e+00, 8.1489109922424241e+00, 8.4539256923192720e+00, 8.7667394811116139e+00, 9.0885566358796162e+00, 9.4209102766018642e+00, 9.7658086966213720e+00, 1.0125979221008995e+01, 1.0505304291834085e+01, 1.0909678445859965e+01, 1.1348933245008068e+01, 1.1842159173697059e+01, 1.2439367989923680e+01}, + {-1.2516275975487387e+01, -1.1920275369301974e+01, -1.1428082314244874e+01, -1.0989775477860821e+01, -1.0586298540449153e+01, -1.0207837432241758e+01, -9.8485080876029141e+00, -9.5044349817531568e+00, -9.1728956871075304e+00, -8.8518855642291054e+00, -8.5398743353481130e+00, -8.2356600117533336e+00, -7.9382762925370942e+00, -7.6469312171655428e+00, -7.3609650262218116e+00, -7.0798203265112649e+00, -6.8030204171920579e+00, -6.5301531917714213e+00, -6.2608589484644162e+00, -5.9948210018972574e+00, -5.7317583424731948e+00, -5.4714198187320084e+00, -5.2135794701554339e+00, -4.9580327411502472e+00, -4.7045933784481448e+00, -4.4530908645538636e+00, -4.2033682759582804e+00, -3.9552804810525908e+00, -3.7086926119853119e+00, -3.4634787590926437e+00, -3.2195208473769141e+00, -2.9767076627641722e+00, -2.7349340022167890e+00, -2.4940999266938628e+00, -2.2541100997915855e+00, -2.0148731979134999e+00, -1.7763013802059482e+00, -1.5383098083876734e+00, -1.3008162081103343e+00, -1.0637404646882309e+00, -8.2700424699148045e-01, -5.9053065405312266e-01, -3.5424387953214642e-01, -1.1806888962751633e-01, 1.1806888962751633e-01, 3.5424387953214642e-01, 5.9053065405312266e-01, 8.2700424699148045e-01, 1.0637404646882309e+00, 1.3008162081103343e+00, 1.5383098083876734e+00, 1.7763013802059482e+00, 2.0148731979134999e+00, 2.2541100997915855e+00, 2.4940999266938628e+00, 2.7349340022167890e+00, 2.9767076627641722e+00, 3.2195208473769141e+00, 3.4634787590926437e+00, 3.7086926119853119e+00, 3.9552804810525908e+00, 4.2033682759582804e+00, 4.4530908645538636e+00, 4.7045933784481448e+00, 4.9580327411502472e+00, 5.2135794701554339e+00, 5.4714198187320084e+00, 5.7317583424731948e+00, 5.9948210018972574e+00, 6.2608589484644162e+00, 6.5301531917714213e+00, 6.8030204171920579e+00, 7.0798203265112649e+00, 7.3609650262218116e+00, 7.6469312171655428e+00, 7.9382762925370942e+00, 8.2356600117533336e+00, 8.5398743353481130e+00, 8.8518855642291054e+00, 9.1728956871075304e+00, 9.5044349817531568e+00, 9.8485080876029141e+00, 1.0207837432241758e+01, 1.0586298540449153e+01, 1.0989775477860821e+01, 1.1428082314244874e+01, 1.1920275369301974e+01, 1.2516275975487387e+01}, + {-1.2592738905595901e+01, -1.1997929913449418e+01, -1.1506755189277548e+01, -1.1069382675775751e+01, -1.0666789783587026e+01, -1.0289179711107796e+01, -9.9306787276273880e+00, -9.5874181334018580e+00, -9.2566803307032135e+00, -8.9364642812455379e+00, -8.6252425061665043e+00, -8.3218152682134434e+00, -8.0252181314463780e+00, -7.7346607201821760e+00, -7.4494846527302592e+00, -7.1691337582185994e+00, -6.8931324404171299e+00, -6.6210696079053228e+00, -6.3525865059800601e+00, -6.0873673452070678e+00, -5.8251319742404801e+00, -5.5656300731513921e+00, -5.3086364953650067e+00, -5.0539474894081309e+00, -4.8013776030542550e+00, -4.5507571227604720e+00, -4.3019299373155544e+00, -4.0547517407947415e+00, -3.8090885091914664e+00, -3.5648151994628399e+00, -3.3218146305539729e+00, -3.0799765142115443e+00, -2.8391966097343762e+00, -2.5993759817212956e+00, -2.3604203437138307e+00, -2.1222394736491395e+00, -1.8847466894257894e+00, -1.6478583747824140e+00, -1.4114935472024899e+00, -1.1755734607673940e+00, -9.4002123784514680e-01, -7.0476152427011995e-01, -4.6972016327466942e-01, -2.3482388390393241e-01, -0.0000000000000000e+00, 2.3482388390393241e-01, 4.6972016327466942e-01, 7.0476152427011995e-01, 9.4002123784514680e-01, 1.1755734607673940e+00, 1.4114935472024899e+00, 1.6478583747824140e+00, 1.8847466894257894e+00, 2.1222394736491395e+00, 2.3604203437138307e+00, 2.5993759817212956e+00, 2.8391966097343762e+00, 3.0799765142115443e+00, 3.3218146305539729e+00, 3.5648151994628399e+00, 3.8090885091914664e+00, 4.0547517407947415e+00, 4.3019299373155544e+00, 4.5507571227604720e+00, 4.8013776030542550e+00, 5.0539474894081309e+00, 5.3086364953650067e+00, 5.5656300731513921e+00, 5.8251319742404801e+00, 6.0873673452070678e+00, 6.3525865059800601e+00, 6.6210696079053228e+00, 6.8931324404171299e+00, 7.1691337582185994e+00, 7.4494846527302592e+00, 7.7346607201821760e+00, 8.0252181314463780e+00, 8.3218152682134434e+00, 8.6252425061665043e+00, 8.9364642812455379e+00, 9.2566803307032135e+00, 9.5874181334018580e+00, 9.9306787276273880e+00, 1.0289179711107796e+01, 1.0666789783587026e+01, 1.1069382675775751e+01, 1.1506755189277548e+01, 1.1997929913449418e+01, 1.2592738905595901e+01}, + {-1.2668764375434174e+01, -1.2075130816910921e+01, -1.1584960252804917e+01, -1.1148508777693781e+01, -1.0746787108514194e+01, -1.0370015493271170e+01, -1.0012330403392184e+01, -9.6698698743374543e+00, -9.3399210724883908e+00, -9.0204865095226339e+00, -8.7100414635651475e+00, -8.4073884130034546e+00, -8.1115647551404777e+00, -7.8217816701739293e+00, -7.5373821269924042e+00, -7.2578111510465870e+00, -6.9825942253568725e+00, -6.7113212484546603e+00, -6.4436343875167896e+00, -6.1792187234934586e+00, -5.9177949371442047e+00, -5.6591135131207473e+00, -5.4029500908349490e+00, -5.1491016937770269e+00, -4.8973836402140369e+00, -4.6476269884213890e+00, -4.3996764055654278e+00, -4.1533883754886318e+00, -3.9086296798928606e+00, -3.6652761017603779e+00, -3.4232113106647768e+00, -3.1823258978578806e+00, -2.9425165353484215e+00, -2.7036852380958849e+00, -2.4657387122776617e+00, -2.2285877756048471e+00, -1.9921468380503871e+00, -1.7563334332534348e+00, -1.5210677923813427e+00, -1.2862724534455954e+00, -1.0518719000409926e+00, -8.1779222425489551e-01, -5.8396080911088377e-01, -3.5030602639582364e-01, -1.1675694609164179e-01, 1.1675694609164179e-01, 3.5030602639582364e-01, 5.8396080911088377e-01, 8.1779222425489551e-01, 1.0518719000409926e+00, 1.2862724534455954e+00, 1.5210677923813427e+00, 1.7563334332534348e+00, 1.9921468380503871e+00, 2.2285877756048471e+00, 2.4657387122776617e+00, 2.7036852380958849e+00, 2.9425165353484215e+00, 3.1823258978578806e+00, 3.4232113106647768e+00, 3.6652761017603779e+00, 3.9086296798928606e+00, 4.1533883754886318e+00, 4.3996764055654278e+00, 4.6476269884213890e+00, 4.8973836402140369e+00, 5.1491016937770269e+00, 5.4029500908349490e+00, 5.6591135131207473e+00, 5.9177949371442047e+00, 6.1792187234934586e+00, 6.4436343875167896e+00, 6.7113212484546603e+00, 6.9825942253568725e+00, 7.2578111510465870e+00, 7.5373821269924042e+00, 7.8217816701739293e+00, 8.1115647551404777e+00, 8.4073884130034546e+00, 8.7100414635651475e+00, 9.0204865095226339e+00, 9.3399210724883908e+00, 9.6698698743374543e+00, 1.0012330403392184e+01, 1.0370015493271170e+01, 1.0746787108514194e+01, 1.1148508777693781e+01, 1.1584960252804917e+01, 1.2075130816910921e+01, 1.2668764375434174e+01}, + {-1.2744359767130547e+01, -1.2151885862422731e+01, -1.1662705645828531e+01, -1.1227162266730099e+01, -1.0826299334271541e+01, -1.0450353932747101e+01, -1.0093472606221523e+01, -9.7518000378530658e+00, -9.4226280941850682e+00, -9.1039627871662461e+00, -8.7942821113015697e+00, -8.4923907260054339e+00, -8.1973278312442819e+00, -7.9083061352456419e+00, -7.6246699314466770e+00, -7.3458654167536865e+00, -7.0714191292405717e+00, -6.8009219334794446e+00, -6.5340168945910211e+00, -6.2703899396887248e+00, -6.0097625569049269e+00, -5.7518860100246414e+00, -5.4965366980951300e+00, -5.2435123921335229e+00, -4.9926291522002995e+00, -4.7437187782456505e+00, -4.4966266840419751e+00, -4.2512101096067996e+00, -4.0073366067337117e+00, -3.7648827465709873e+00, -3.5237330089839838e+00, -3.2837788216598618e+00, -3.0449177232349895e+00, -2.8070526296277643e+00, -2.5700911865913141e+00, -2.3339451945166196e+00, -2.0985300939053997e+00, -1.8637645018342535e+00, -1.6295697912525116e+00, -1.3958697061759588e+00, -1.1625900068179993e+00, -9.2965813948535503e-01, -6.9700292669283159e-01, -4.6455427344836053e-01, -2.3224288604634152e-01, -0.0000000000000000e+00, 2.3224288604634152e-01, 4.6455427344836053e-01, 6.9700292669283159e-01, 9.2965813948535503e-01, 1.1625900068179993e+00, 1.3958697061759588e+00, 1.6295697912525116e+00, 1.8637645018342535e+00, 2.0985300939053997e+00, 2.3339451945166196e+00, 2.5700911865913141e+00, 2.8070526296277643e+00, 3.0449177232349895e+00, 3.2837788216598618e+00, 3.5237330089839838e+00, 3.7648827465709873e+00, 4.0073366067337117e+00, 4.2512101096067996e+00, 4.4966266840419751e+00, 4.7437187782456505e+00, 4.9926291522002995e+00, 5.2435123921335229e+00, 5.4965366980951300e+00, 5.7518860100246414e+00, 6.0097625569049269e+00, 6.2703899396887248e+00, 6.5340168945910211e+00, 6.8009219334794446e+00, 7.0714191292405717e+00, 7.3458654167536865e+00, 7.6246699314466770e+00, 7.9083061352456419e+00, 8.1973278312442819e+00, 8.4923907260054339e+00, 8.7942821113015697e+00, 9.1039627871662461e+00, 9.4226280941850682e+00, 9.7518000378530658e+00, 1.0093472606221523e+01, 1.0450353932747101e+01, 1.0826299334271541e+01, 1.1227162266730099e+01, 1.1662705645828531e+01, 1.2151885862422731e+01, 1.2744359767130547e+01}, + {-1.2819532258018480e+01, -1.2228202613648115e+01, -1.1739999277265277e+01, -1.1305351381280618e+01, -1.0905335022579179e+01, -1.0530203913474873e+01, -1.0174114544331893e+01, -9.8332181607332707e+00, -9.5048112671603402e+00, -9.1869033275673413e+00, -8.8779750134809063e+00, -8.5768331318717053e+00, -8.2825186558731350e+00, -7.9942457949462566e+00, -7.7113601420959172e+00, -7.4333090418794825e+00, -7.1596200643171857e+00, -6.8898850172400419e+00, -6.6237478409567272e+00, -6.3608952857640544e+00, -6.1010496237476017e+00, -5.8439628737731484e+00, -5.5894121696594157e+00, -5.3371960041051256e+00, -5.0871311519710600e+00, -4.8390501265746098e+00, -4.5927990585018197e+00, -4.3482359124910070e+00, -4.1052289771248800e+00, -3.8636555763680760e+00, -3.6234009627673571e+00, -3.3843573603426855e+00, -3.1464231315109763e+00, -2.9095020472812747e+00, -2.6735026437884462e+00, -2.4383376512469250e+00, -2.2039234837948438e+00, -1.9701797806022634e+00, -1.7370289901408089e+00, -1.5043959907356530e+00, -1.2722077415053921e+00, -1.0403929585875988e+00, -8.0888181218354049e-01, -5.7760564046232032e-01, -3.4649667676368101e-01, -1.1548778684603313e-01, 1.1548778684603313e-01, 3.4649667676368101e-01, 5.7760564046232032e-01, 8.0888181218354049e-01, 1.0403929585875988e+00, 1.2722077415053921e+00, 1.5043959907356530e+00, 1.7370289901408089e+00, 1.9701797806022634e+00, 2.2039234837948438e+00, 2.4383376512469250e+00, 2.6735026437884462e+00, 2.9095020472812747e+00, 3.1464231315109763e+00, 3.3843573603426855e+00, 3.6234009627673571e+00, 3.8636555763680760e+00, 4.1052289771248800e+00, 4.3482359124910070e+00, 4.5927990585018197e+00, 4.8390501265746098e+00, 5.0871311519710600e+00, 5.3371960041051256e+00, 5.5894121696594157e+00, 5.8439628737731484e+00, 6.1010496237476017e+00, 6.3608952857640544e+00, 6.6237478409567272e+00, 6.8898850172400419e+00, 7.1596200643171857e+00, 7.4333090418794825e+00, 7.7113601420959172e+00, 7.9942457949462566e+00, 8.2825186558731350e+00, 8.5768331318717053e+00, 8.8779750134809063e+00, 9.1869033275673413e+00, 9.5048112671603402e+00, 9.8332181607332707e+00, 1.0174114544331893e+01, 1.0530203913474873e+01, 1.0905335022579179e+01, 1.1305351381280618e+01, 1.1739999277265277e+01, 1.2228202613648115e+01, 1.2819532258018480e+01}, + {-1.2894288828491323e+01, -1.2304088423692580e+01, -1.1816848833075053e+01, -1.1383084124753704e+01, -1.0983902488179488e+01, -1.0609574060288383e+01, -1.0254265154452550e+01, -9.9141334955519440e+00, -9.5864801654334606e+00, -9.2693180331543115e+00, -8.9611304090936645e+00, -8.6607262153924776e+00, -8.3671481698791865e+00, -8.0796119574473497e+00, -7.7974644466766474e+00, -7.5201541069686444e+00, -7.2472095182038041e+00, -6.9782234097463292e+00, -6.7128405754384817e+00, -6.4507485669373850e+00, -6.1916704180836000e+00, -5.9353588800666905e+00, -5.6815917979923949e+00, -5.4301683618693133e+00, -5.1809060359441155e+00, -4.9336380202893313e+00, -4.6882111343374202e+00, -4.4444840380621056e+00, -4.2023257256606739e+00, -3.9616142408689083e+00, -3.7222355738045620e+00, -3.4840827074346534e+00, -3.2470547880671274e+00, -3.0110563991586603e+00, -2.7759969215550591e+00, -2.5417899662931847e+00, -2.3083528684815695e+00, -2.0756062326810416e+00, -1.8434735217321803e+00, -1.6118806822031735e+00, -1.3807558006205385e+00, -1.1500287854429532e+00, -9.1963107038107428e-01, -6.8949533518145145e-01, -4.5955524040186729e-01, -2.2974517302503578e-01, -0.0000000000000000e+00, 2.2974517302503578e-01, 4.5955524040186729e-01, 6.8949533518145145e-01, 9.1963107038107428e-01, 1.1500287854429532e+00, 1.3807558006205385e+00, 1.6118806822031735e+00, 1.8434735217321803e+00, 2.0756062326810416e+00, 2.3083528684815695e+00, 2.5417899662931847e+00, 2.7759969215550591e+00, 3.0110563991586603e+00, 3.2470547880671274e+00, 3.4840827074346534e+00, 3.7222355738045620e+00, 3.9616142408689083e+00, 4.2023257256606739e+00, 4.4444840380621056e+00, 4.6882111343374202e+00, 4.9336380202893313e+00, 5.1809060359441155e+00, 5.4301683618693133e+00, 5.6815917979923949e+00, 5.9353588800666905e+00, 6.1916704180836000e+00, 6.4507485669373850e+00, 6.7128405754384817e+00, 6.9782234097463292e+00, 7.2472095182038041e+00, 7.5201541069686444e+00, 7.7974644466766474e+00, 8.0796119574473497e+00, 8.3671481698791865e+00, 8.6607262153924776e+00, 8.9611304090936645e+00, 9.2693180331543115e+00, 9.5864801654334606e+00, 9.9141334955519440e+00, 1.0254265154452550e+01, 1.0609574060288383e+01, 1.0983902488179488e+01, 1.1383084124753704e+01, 1.1816848833075053e+01, 1.2304088423692580e+01, 1.2894288828491323e+01}, + {-1.2968636269474320e+01, -1.2379550443198964e+01, -1.1893261784933093e+01, -1.1460368274811241e+01, -1.1062009808653285e+01, -1.0688472749322155e+01, -1.0333933112841928e+01, -9.9945550223243256e+00, -9.6676440779928683e+00, -9.3512165084081822e+00, -9.0437582257661120e+00, -8.7440802360223131e+00, -8.4512269741988870e+00, -8.1644155757609358e+00, -7.8829941618009407e+00, -7.6064123046955778e+00, -7.3341995730571172e+00, -7.0659495970458304e+00, -6.8013080034124762e+00, -6.5399631244304128e+00, -6.2816387346344911e+00, -6.0260882959858302e+00, -5.7730903426736297e+00, -5.5224447390110498e+00, -5.2739696146779718e+00, -5.0274988314577831e+00, -4.7828798713474461e+00, -4.5399720618862149e+00, -4.2986450736710040e+00, -4.0587776392825550e+00, -3.8202564535947250e+00, -3.5829752236268817e+00, -3.3468338423962911e+00, -3.1117376661126466e+00, -2.8775968778776946e+00, -2.6443259240630739e+00, -2.4118430119268002e+00, -2.1800696589332400e+00, -1.9489302857683151e+00, -1.7183518462708216e+00, -1.4882634884931585e+00, -1.2585962419071162e+00, -1.0292827264188049e+00, -8.0025687937913981e-01, -5.7145369719413508e-01, -3.4280898846921665e-01, -1.1425913587653955e-01, 1.1425913587653955e-01, 3.4280898846921665e-01, 5.7145369719413508e-01, 8.0025687937913981e-01, 1.0292827264188049e+00, 1.2585962419071162e+00, 1.4882634884931585e+00, 1.7183518462708216e+00, 1.9489302857683151e+00, 2.1800696589332400e+00, 2.4118430119268002e+00, 2.6443259240630739e+00, 2.8775968778776946e+00, 3.1117376661126466e+00, 3.3468338423962911e+00, 3.5829752236268817e+00, 3.8202564535947250e+00, 4.0587776392825550e+00, 4.2986450736710040e+00, 4.5399720618862149e+00, 4.7828798713474461e+00, 5.0274988314577831e+00, 5.2739696146779718e+00, 5.5224447390110498e+00, 5.7730903426736297e+00, 6.0260882959858302e+00, 6.2816387346344911e+00, 6.5399631244304128e+00, 6.8013080034124762e+00, 7.0659495970458304e+00, 7.3341995730571172e+00, 7.6064123046955778e+00, 7.8829941618009407e+00, 8.1644155757609358e+00, 8.4512269741988870e+00, 8.7440802360223131e+00, 9.0437582257661120e+00, 9.3512165084081822e+00, 9.6676440779928683e+00, 9.9945550223243256e+00, 1.0333933112841928e+01, 1.0688472749322155e+01, 1.1062009808653285e+01, 1.1460368274811241e+01, 1.1893261784933093e+01, 1.2379550443198964e+01, 1.2968636269474320e+01}, + {-1.3042581189536424e+01, -1.2454595628047418e+01, -1.1969245398474266e+01, -1.1537211392148828e+01, -1.1139664833741461e+01, -1.0766908117887827e+01, -1.0413126845737839e+01, -1.0074491459554146e+01, -9.7483120204672815e+00, -9.4326080721882803e+00, -9.1258680927746667e+00, -8.8269051416209461e+00, -8.5347653443616345e+00, -8.2486672630612325e+00, -7.9679602491408312e+00, -7.6920949569654464e+00, -7.4206019236498832e+00, -7.1530756603397334e+00, -6.8891626070319019e+00, -6.6285518568795139e+00, -6.3709679051115460e+00, -6.1161649040299730e+00, -5.8639220558946130e+00, -5.6140398775862348e+00, -5.3663371416203249e+00, -5.1206483478982010e+00, -4.8768216162575175e+00, -4.6347169158093715e+00, -4.3942045661421210e+00, -4.1551639597063925e+00, -3.9174824654279452e+00, -3.6810544817710307e+00, -3.4457806137632216e+00, -3.2115669533719382e+00, -2.9783244464395575e+00, -2.7459683323916124e+00, -2.5144176453186349e+00, -2.2835947669364720e+00, -2.0534250234577174e+00, -1.8238363196378788e+00, -1.5947588042551295e+00, -1.3661245620886429e+00, -1.1378673281137517e+00, -9.0992222016050861e-01, -6.8222548670729899e-01, -4.5471426681985894e-01, -2.2732635951125563e-01, -0.0000000000000000e+00, 2.2732635951125563e-01, 4.5471426681985894e-01, 6.8222548670729899e-01, 9.0992222016050861e-01, 1.1378673281137517e+00, 1.3661245620886429e+00, 1.5947588042551295e+00, 1.8238363196378788e+00, 2.0534250234577174e+00, 2.2835947669364720e+00, 2.5144176453186349e+00, 2.7459683323916124e+00, 2.9783244464395575e+00, 3.2115669533719382e+00, 3.4457806137632216e+00, 3.6810544817710307e+00, 3.9174824654279452e+00, 4.1551639597063925e+00, 4.3942045661421210e+00, 4.6347169158093715e+00, 4.8768216162575175e+00, 5.1206483478982010e+00, 5.3663371416203249e+00, 5.6140398775862348e+00, 5.8639220558946130e+00, 6.1161649040299730e+00, 6.3709679051115460e+00, 6.6285518568795139e+00, 6.8891626070319019e+00, 7.1530756603397334e+00, 7.4206019236498832e+00, 7.6920949569654464e+00, 7.9679602491408312e+00, 8.2486672630612325e+00, 8.5347653443616345e+00, 8.8269051416209461e+00, 9.1258680927746667e+00, 9.4326080721882803e+00, 9.7483120204672815e+00, 1.0074491459554146e+01, 1.0413126845737839e+01, 1.0766908117887827e+01, 1.1139664833741461e+01, 1.1537211392148828e+01, 1.1969245398474266e+01, 1.2454595628047418e+01, 1.3042581189536424e+01}, + {-1.3116130021662876e+01, -1.2529230746683540e+01, -1.2044806741134924e+01, -1.1613620828842913e+01, -1.1216875194202160e+01, -1.0844888073853586e+01, -1.0491854539276538e+01, -1.0153951274713688e+01, -9.8284927461917118e+00, -9.5135017694124251e+00, -9.2074693533717600e+00, -8.9092105814595968e+00, -8.6177732442147459e+00, -8.3323773071700593e+00, -8.0523733307197105e+00, -7.7772130310612386e+00, -7.5064278944277563e+00, -7.2396132940083531e+00, -6.9764164642851814e+00, -6.7165272404965179e+00, -6.4596708195551207e+00, -6.2056020247183090e+00, -5.9541007064117260e+00, -5.7049680135255354e+00, -5.4580233400707856e+00, -5.2131018018189597e+00, -4.9700521331667717e+00, -4.7287349203529301e+00, -4.4890211062169945e+00, -4.2507907159031859e+00, -4.0139317636282685e+00, -3.7783393087968626e+00, -3.5439146360273117e+00, -3.3105645385243054e+00, -3.0782006880468189e+00, -2.8467390777247825e+00, -2.6160995263623885e+00, -2.3862052347697795e+00, -2.1569823861931283e+00, -1.9283597841455022e+00, -1.7002685219383502e+00, -1.4726416790227095e+00, -1.2454140399065079e+00, -1.0185218319476799e+00, -7.9190247875401665e-01, -5.6549436626674887e-01, -3.3923661887888523e-01, -1.1306888315145193e-01, 1.1306888315145193e-01, 3.3923661887888523e-01, 5.6549436626674887e-01, 7.9190247875401665e-01, 1.0185218319476799e+00, 1.2454140399065079e+00, 1.4726416790227095e+00, 1.7002685219383502e+00, 1.9283597841455022e+00, 2.1569823861931283e+00, 2.3862052347697795e+00, 2.6160995263623885e+00, 2.8467390777247825e+00, 3.0782006880468189e+00, 3.3105645385243054e+00, 3.5439146360273117e+00, 3.7783393087968626e+00, 4.0139317636282685e+00, 4.2507907159031859e+00, 4.4890211062169945e+00, 4.7287349203529301e+00, 4.9700521331667717e+00, 5.2131018018189597e+00, 5.4580233400707856e+00, 5.7049680135255354e+00, 5.9541007064117260e+00, 6.2056020247183090e+00, 6.4596708195551207e+00, 6.7165272404965179e+00, 6.9764164642851814e+00, 7.2396132940083531e+00, 7.5064278944277563e+00, 7.7772130310612386e+00, 8.0523733307197105e+00, 8.3323773071700593e+00, 8.6177732442147459e+00, 8.9092105814595968e+00, 9.2074693533717600e+00, 9.5135017694124251e+00, 9.8284927461917118e+00, 1.0153951274713688e+01, 1.0491854539276538e+01, 1.0844888073853586e+01, 1.1216875194202160e+01, 1.1613620828842913e+01, 1.2044806741134924e+01, 1.2529230746683540e+01, 1.3116130021662876e+01}, + {-1.3189289029708117e+01, -1.2603462387096409e+01, -1.2119952689615966e+01, -1.1689603736290559e+01, -1.1293648310231410e+01, -1.0922420304556775e+01, -1.0570124148913189e+01, -1.0232942694191875e+01, -9.9081947567061555e+00, -9.5939063821323529e+00, -9.2885710764670684e+00, -8.9910059185401376e+00, -8.7002603389157791e+00, -8.4155556842608696e+00, -8.1362437033700719e+00, -7.8617771549009925e+00, -7.5916884556157704e+00, -7.3255738226210259e+00, -7.0630812669681537e+00, -6.8039013480672903e+00, -6.5477599464293741e+00, -6.2944125378566032e+00, -6.0436396020679171e+00, -5.7952429005012469e+00, -5.5490424284915560e+00, -5.3048738966808706e+00, -5.0625866320797561e+00, -4.8220418150442850e+00, -4.5831109874666334e+00, -4.3456747816687633e+00, -4.1096218301890062e+00, -3.8748478248038931e+00, -3.6412546993987251e+00, -3.4087499161671784e+00, -3.1772458384281856e+00, -2.9466591763501873e+00, -2.7169104942556110e+00, -2.4879237700815029e+00, -2.2596259991006340e+00, -2.0319468352407690e+00, -1.8048182643389761e+00, -1.5781743044796297e+00, -1.3519507292254074e+00, -1.1260848100881036e+00, -9.0051507502248329e-01, -6.7518108007869271e-01, -4.5002319163025301e-01, -2.2498237681566594e-01, -0.0000000000000000e+00, 2.2498237681566594e-01, 4.5002319163025301e-01, 6.7518108007869271e-01, 9.0051507502248329e-01, 1.1260848100881036e+00, 1.3519507292254074e+00, 1.5781743044796297e+00, 1.8048182643389761e+00, 2.0319468352407690e+00, 2.2596259991006340e+00, 2.4879237700815029e+00, 2.7169104942556110e+00, 2.9466591763501873e+00, 3.1772458384281856e+00, 3.4087499161671784e+00, 3.6412546993987251e+00, 3.8748478248038931e+00, 4.1096218301890062e+00, 4.3456747816687633e+00, 4.5831109874666334e+00, 4.8220418150442850e+00, 5.0625866320797561e+00, 5.3048738966808706e+00, 5.5490424284915560e+00, 5.7952429005012469e+00, 6.0436396020679171e+00, 6.2944125378566032e+00, 6.5477599464293741e+00, 6.8039013480672903e+00, 7.0630812669681537e+00, 7.3255738226210259e+00, 7.5916884556157704e+00, 7.8617771549009925e+00, 8.1362437033700719e+00, 8.4155556842608696e+00, 8.7002603389157791e+00, 8.9910059185401376e+00, 9.2885710764670684e+00, 9.5939063821323529e+00, 9.9081947567061555e+00, 1.0232942694191875e+01, 1.0570124148913189e+01, 1.0922420304556775e+01, 1.1293648310231410e+01, 1.1689603736290559e+01, 1.2119952689615966e+01, 1.2603462387096409e+01, 1.3189289029708117e+01}, + {-1.3262064314547260e+01, -1.2677296963466635e+01, -1.2194689936989255e+01, -1.1765167072765909e+01, -1.1369991399473138e+01, -1.0999512285277628e+01, -1.0647943408373985e+01, -1.0311473712742933e+01, -9.9874263117220838e+00, -9.6738304400421331e+00, -9.3691820677047506e+00, -9.0723002412708205e+00, -8.7822360072393444e+00, -8.4982120718321887e+00, -8.2195813524123764e+00, -7.9457976314642735e+00, -7.6763942384382915e+00, -7.4109682169993913e+00, -7.1491683376448565e+00, -6.8906858668688686e+00, -6.6352473515597925e+00, -6.3826089025647779e+00, -6.1325516109861775e+00, -5.8848778323693072e+00, -5.6394081442881152e+00, -5.3959788324149320e+00, -5.1544397956688064e+00, -4.9146527868415708e+00, -4.6764899241060425e+00, -4.4398324229806452e+00, -4.2045695090093798e+00, -3.9705974795569130e+00, -3.7378188893809927e+00, -3.5061418395049322e+00, -3.2754793527162449e+00, -3.0457488220163000e+00, -2.8168715207266257e+00, -2.5887721648595683e+00, -2.3613785198892869e+00, -2.1346210452930161e+00, -1.9084325712330619e+00, -1.6827480025638228e+00, -1.4575040460115227e+00, -1.2326389569154106e+00, -1.0080923023599291e+00, -7.8380473788493388e-01, -5.5971779524889242e-01, -3.3577367894853466e-01, -1.1191506937570589e-01, 1.1191506937570589e-01, 3.3577367894853466e-01, 5.5971779524889242e-01, 7.8380473788493388e-01, 1.0080923023599291e+00, 1.2326389569154106e+00, 1.4575040460115227e+00, 1.6827480025638228e+00, 1.9084325712330619e+00, 2.1346210452930161e+00, 2.3613785198892869e+00, 2.5887721648595683e+00, 2.8168715207266257e+00, 3.0457488220163000e+00, 3.2754793527162449e+00, 3.5061418395049322e+00, 3.7378188893809927e+00, 3.9705974795569130e+00, 4.2045695090093798e+00, 4.4398324229806452e+00, 4.6764899241060425e+00, 4.9146527868415708e+00, 5.1544397956688064e+00, 5.3959788324149320e+00, 5.6394081442881152e+00, 5.8848778323693072e+00, 6.1325516109861775e+00, 6.3826089025647779e+00, 6.6352473515597925e+00, 6.8906858668688686e+00, 7.1491683376448565e+00, 7.4109682169993913e+00, 7.6763942384382915e+00, 7.9457976314642735e+00, 8.2195813524123764e+00, 8.4982120718321887e+00, 8.7822360072393444e+00, 9.0723002412708205e+00, 9.3691820677047506e+00, 9.6738304400421331e+00, 9.9874263117220838e+00, 1.0311473712742933e+01, 1.0647943408373985e+01, 1.0999512285277628e+01, 1.1369991399473138e+01, 1.1765167072765909e+01, 1.2194689936989255e+01, 1.2677296963466635e+01, 1.3262064314547260e+01}, + {-1.3334461819943153e+01, -1.2750740722503373e+01, -1.2269024999467902e+01, -1.1840317610615624e+01, -1.1445911484642805e+01, -1.1076171287300262e+01, -1.0725319838167971e+01, -1.0389552102465858e+01, -1.0066195438589224e+01, -9.7532822304545537e+00, -9.4493108799743251e+00, -9.1531023745391185e+00, -8.8637093532419815e+00, -8.5803558609974342e+00, -8.3023959646056102e+00, -8.0292844524423987e+00, -7.7605555495112331e+00, -7.4958071093975249e+00, -7.2346886456654547e+00, -6.9768921155793651e+00, -6.7221447159938794e+00, -6.4702031761523404e+00, -6.2208491815292408e+00, -5.9738856642890008e+00, -5.7291337661713966e+00, -5.4864303291169465e+00, -5.2456258043992712e+00, -5.0065824967968044e+00, -4.7691730793126910e+00, -4.5332793281004458e+00, -4.2987910379219327e+00, -4.0656050865933535e+00, -3.8336246231287601e+00, -3.6027583591447181e+00, -3.3729199468884627e+00, -3.1440274302474247e+00, -2.9160027574766345e+00, -2.6887713462813925e+00, -2.4622616934204693e+00, -2.2364050222293588e+00, -2.0111349624646375e+00, -1.7863872576859270e+00, -1.5620994960576213e+00, -1.3382108609965631e+00, -1.1146618985362737e+00, -8.9139429864040043e-01, -6.6835068799126329e-01, -4.4547443201433412e-01, -2.2270944408436802e-01, -0.0000000000000000e+00, 2.2270944408436802e-01, 4.4547443201433412e-01, 6.6835068799126329e-01, 8.9139429864040043e-01, 1.1146618985362737e+00, 1.3382108609965631e+00, 1.5620994960576213e+00, 1.7863872576859270e+00, 2.0111349624646375e+00, 2.2364050222293588e+00, 2.4622616934204693e+00, 2.6887713462813925e+00, 2.9160027574766345e+00, 3.1440274302474247e+00, 3.3729199468884627e+00, 3.6027583591447181e+00, 3.8336246231287601e+00, 4.0656050865933535e+00, 4.2987910379219327e+00, 4.5332793281004458e+00, 4.7691730793126910e+00, 5.0065824967968044e+00, 5.2456258043992712e+00, 5.4864303291169465e+00, 5.7291337661713966e+00, 5.9738856642890008e+00, 6.2208491815292408e+00, 6.4702031761523404e+00, 6.7221447159938794e+00, 6.9768921155793651e+00, 7.2346886456654547e+00, 7.4958071093975249e+00, 7.7605555495112331e+00, 8.0292844524423987e+00, 8.3023959646056102e+00, 8.5803558609974342e+00, 8.8637093532419815e+00, 9.1531023745391185e+00, 9.4493108799743251e+00, 9.7532822304545537e+00, 1.0066195438589224e+01, 1.0389552102465858e+01, 1.0725319838167971e+01, 1.1076171287300262e+01, 1.1445911484642805e+01, 1.1840317610615624e+01, 1.2269024999467902e+01, 1.2750740722503373e+01, 1.3334461819943153e+01}, + {-1.3406487338144908e+01, -1.2823799749487808e+01, -1.2342964222859672e+01, -1.1915061943114164e+01, -1.1521415400787030e+01, -1.1152404385585125e+01, -1.0802260753684713e+01, -1.0467185421342810e+01, -1.0144509941292846e+01, -9.8322698077779673e+00, -9.5289658233901147e+00, -9.2334208902191612e+00, -8.9446892173254735e+00, -8.6619961681345181e+00, -8.3846969404162657e+00, -8.1122473111627915e+00, -7.8441823844608196e+00, -7.5801008078574874e+00, -7.3196528223045343e+00, -7.0625310602488653e+00, -6.8084633528587952e+00, -6.5572070319215392e+00, -6.3085443611121343e+00, -6.0622788326143020e+00, -5.8182321352035169e+00, -5.5762416493299236e+00, -5.3361583601383602e+00, -5.0978451050891360e+00, -4.8611750917912095e+00, -4.6260306357871555e+00, -4.3923020786826834e+00, -4.1598868551310302e+00, -3.9286886834276706e+00, -3.6986168593184914e+00, -3.4695856364185889e+00, -3.2415136796310131e+00, -3.0143235803311552e+00, -2.7879414239819891e+00, -2.5622964023726080e+00, -2.3373204639068783e+00, -2.1129479963711879e+00, -1.8891155374270083e+00, -1.6657615087415094e+00, -1.4428259702159327e+00, -1.2202503912189531e+00, -9.9797743609810530e-01, -7.7595076154014564e-01, -5.5411482359161690e-01, -3.3241469234223181e-01, -1.1079587242243949e-01, 1.1079587242243949e-01, 3.3241469234223181e-01, 5.5411482359161690e-01, 7.7595076154014564e-01, 9.9797743609810530e-01, 1.2202503912189531e+00, 1.4428259702159327e+00, 1.6657615087415094e+00, 1.8891155374270083e+00, 2.1129479963711879e+00, 2.3373204639068783e+00, 2.5622964023726080e+00, 2.7879414239819891e+00, 3.0143235803311552e+00, 3.2415136796310131e+00, 3.4695856364185889e+00, 3.6986168593184914e+00, 3.9286886834276706e+00, 4.1598868551310302e+00, 4.3923020786826834e+00, 4.6260306357871555e+00, 4.8611750917912095e+00, 5.0978451050891360e+00, 5.3361583601383602e+00, 5.5762416493299236e+00, 5.8182321352035169e+00, 6.0622788326143020e+00, 6.3085443611121343e+00, 6.5572070319215392e+00, 6.8084633528587952e+00, 7.0625310602488653e+00, 7.3196528223045343e+00, 7.5801008078574874e+00, 7.8441823844608196e+00, 8.1122473111627915e+00, 8.3846969404162657e+00, 8.6619961681345181e+00, 8.9446892173254735e+00, 9.2334208902191612e+00, 9.5289658233901147e+00, 9.8322698077779673e+00, 1.0144509941292846e+01, 1.0467185421342810e+01, 1.0802260753684713e+01, 1.1152404385585125e+01, 1.1521415400787030e+01, 1.1915061943114164e+01, 1.2342964222859672e+01, 1.2823799749487808e+01, 1.3406487338144908e+01}, + {-1.3478146515232797e+01, -1.2896479974039561e+01, -1.2416513788721415e+01, -1.1989406490998284e+01, -1.1596509802200323e+01, -1.1228218466075560e+01, -1.0878773272902121e+01, -1.0544381021362536e+01, -1.0222377409009630e+01, -9.9108010025237636e+00, -9.6081549747716188e+00, -9.3132641171485986e+00, -9.0251841867360021e+00, -8.7431418459354120e+00, -8.4664934056489916e+00, -8.1946956148339627e+00, -7.9272844408189824e+00, -7.6638593097942502e+00, -7.4040711750779735e+00, -7.1476133293942068e+00, -6.8942142232839023e+00, -6.6436317759717189e+00, -6.3956488139470400e+00, -6.1500693736430252e+00, -5.9067156746204947e+00, -5.6654256190158065e+00, -5.4260507083580034e+00, -5.1884542945483902e+00, -4.9525101007153634e+00, -4.7181009617643239e+00, -4.4851177450803661e+00, -4.2534584199474237e+00, -4.0230272504840583e+00, -3.7937340917372753e+00, -3.5654937723650511e+00, -3.3382255503269591e+00, -3.1118526303762444e+00, -2.8863017340447339e+00, -2.6615027143383925e+00, -2.4373882085955381e+00, -2.2138933239623526e+00, -1.9909553507579980e+00, -1.7685134996706828e+00, -1.5465086592745161e+00, -1.3248831708071216e+00, -1.1035806175170297e+00, -8.8254562619156474e-01, -6.6172367872096116e-01, -4.4106093175132588e-01, -2.2050404263430215e-01, -0.0000000000000000e+00, 2.2050404263430215e-01, 4.4106093175132588e-01, 6.6172367872096116e-01, 8.8254562619156474e-01, 1.1035806175170297e+00, 1.3248831708071216e+00, 1.5465086592745161e+00, 1.7685134996706828e+00, 1.9909553507579980e+00, 2.2138933239623526e+00, 2.4373882085955381e+00, 2.6615027143383925e+00, 2.8863017340447339e+00, 3.1118526303762444e+00, 3.3382255503269591e+00, 3.5654937723650511e+00, 3.7937340917372753e+00, 4.0230272504840583e+00, 4.2534584199474237e+00, 4.4851177450803661e+00, 4.7181009617643239e+00, 4.9525101007153634e+00, 5.1884542945483902e+00, 5.4260507083580034e+00, 5.6654256190158065e+00, 5.9067156746204947e+00, 6.1500693736430252e+00, 6.3956488139470400e+00, 6.6436317759717189e+00, 6.8942142232839023e+00, 7.1476133293942068e+00, 7.4040711750779735e+00, 7.6638593097942502e+00, 7.9272844408189824e+00, 8.1946956148339627e+00, 8.4664934056489916e+00, 8.7431418459354120e+00, 9.0251841867360021e+00, 9.3132641171485986e+00, 9.6081549747716188e+00, 9.9108010025237636e+00, 1.0222377409009630e+01, 1.0544381021362536e+01, 1.0878773272902121e+01, 1.1228218466075560e+01, 1.1596509802200323e+01, 1.1989406490998284e+01, 1.2416513788721415e+01, 1.2896479974039561e+01, 1.3478146515232797e+01}, + {-1.3549444856223355e+01, -1.2968787175621387e+01, -1.2489679720231214e+01, -1.2063357508698903e+01, -1.1671201169018351e+01, -1.1303620232659483e+01, -1.0954864323727046e+01, -1.0621146056253156e+01, -1.0299805224248269e+01, -9.9888834298724642e+00, -9.6868861866549612e+00, -9.3926401506071997e+00, -9.1052026055338082e+00, -8.8238014938930043e+00, -8.5477942224789647e+00, -8.2766384961541863e+00, -8.0098711302417200e+00, -7.7470923148599020e+00, -7.4879537012921364e+00, -7.2321492282755919e+00, -6.9794079514507139e+00, -6.7294883630724422e+00, -6.4821738377935736e+00, -6.2372689413028590e+00, -5.9945964085177108e+00, -5.7539946473095069e+00, -5.5153156590327264e+00, -5.2784232927787453e+00, -5.0431917691668700e+00, -4.8095044235715418e+00, -4.5772526293071110e+00, -4.3463348693861139e+00, -4.1166559316947993e+00, -3.8881262072644476e+00, -3.6606610751014688e+00, -3.4341803600244734e+00, -3.2086078523280142e+00, -2.9838708799890519e+00, -2.7598999256576846e+00, -2.5366282819075883e+00, -2.3139917392243752e+00, -2.0919283020285095e+00, -1.8703779286996216e+00, -1.6492822921192409e+00, -1.4285845577012724e+00, -1.2082291762513240e+00, -9.8816168930097070e-01, -7.6832854481204382e-01, -5.4867692134760149e-01, -3.2915455896704260e-01, -1.0970959522807897e-01, 1.0970959522807897e-01, 3.2915455896704260e-01, 5.4867692134760149e-01, 7.6832854481204382e-01, 9.8816168930097070e-01, 1.2082291762513240e+00, 1.4285845577012724e+00, 1.6492822921192409e+00, 1.8703779286996216e+00, 2.0919283020285095e+00, 2.3139917392243752e+00, 2.5366282819075883e+00, 2.7598999256576846e+00, 2.9838708799890519e+00, 3.2086078523280142e+00, 3.4341803600244734e+00, 3.6606610751014688e+00, 3.8881262072644476e+00, 4.1166559316947993e+00, 4.3463348693861139e+00, 4.5772526293071110e+00, 4.8095044235715418e+00, 5.0431917691668700e+00, 5.2784232927787453e+00, 5.5153156590327264e+00, 5.7539946473095069e+00, 5.9945964085177108e+00, 6.2372689413028590e+00, 6.4821738377935736e+00, 6.7294883630724422e+00, 6.9794079514507139e+00, 7.2321492282755919e+00, 7.4879537012921364e+00, 7.7470923148599020e+00, 8.0098711302417200e+00, 8.2766384961541863e+00, 8.5477942224789647e+00, 8.8238014938930043e+00, 9.1052026055338082e+00, 9.3926401506071997e+00, 9.6868861866549612e+00, 9.9888834298724642e+00, 1.0299805224248269e+01, 1.0621146056253156e+01, 1.0954864323727046e+01, 1.1303620232659483e+01, 1.1671201169018351e+01, 1.2063357508698903e+01, 1.2489679720231214e+01, 1.2968787175621387e+01, 1.3549444856223355e+01}, + {-1.3620387729947742e+01, -1.3040726988796493e+01, -1.2562467887793943e+01, -1.2136921090287251e+01, -1.1745495813506075e+01, -1.1378616213805854e+01, -1.1030540650989794e+01, -1.0697487488847003e+01, -1.0376800570599057e+01, -1.0066524497824579e+01, -9.7651670958633421e+00, -9.4715568613271639e+00, -9.1847525840655759e+00, -8.9039834682597192e+00, -8.6286079999230569e+00, -8.3580848243237309e+00, -8.0919515900932844e+00, -7.8298092371332197e+00, -7.5713101008750368e+00, -7.3161487524084921e+00, -7.0640548388279587e+00, -6.8147874116676039e+00, -6.5681303797817083e+00, -6.3238888238470219e+00, -6.0818859794767741e+00, -5.8419607451405371e+00, -5.6039656063250805e+00, -5.3677648929830539e+00, -5.1332333061803963e+00, -4.9002546639192408e+00, -4.6687208267203344e+00, -4.4385307716320357e+00, -4.2095897895522105e+00, -3.9818087855776474e+00, -3.7551036658752275e+00, -3.5293947975507334e+00, -3.3046065303600929e+00, -3.0806667710024973e+00, -2.8575066022592246e+00, -2.6350599404753994e+00, -2.4132632258847226e+00, -2.1920551410961067e+00, -1.9713763537322730e+00, -1.7511692797619354e+00, -1.5313778645213059e+00, -1.3119473787947484e+00, -1.0928242276321787e+00, -8.7395576983320977e-01, -6.5529014623361903e-01, -4.3677611509527065e-01, -2.1836289303147782e-01, -0.0000000000000000e+00, 2.1836289303147782e-01, 4.3677611509527065e-01, 6.5529014623361903e-01, 8.7395576983320977e-01, 1.0928242276321787e+00, 1.3119473787947484e+00, 1.5313778645213059e+00, 1.7511692797619354e+00, 1.9713763537322730e+00, 2.1920551410961067e+00, 2.4132632258847226e+00, 2.6350599404753994e+00, 2.8575066022592246e+00, 3.0806667710024973e+00, 3.3046065303600929e+00, 3.5293947975507334e+00, 3.7551036658752275e+00, 3.9818087855776474e+00, 4.2095897895522105e+00, 4.4385307716320357e+00, 4.6687208267203344e+00, 4.9002546639192408e+00, 5.1332333061803963e+00, 5.3677648929830539e+00, 5.6039656063250805e+00, 5.8419607451405371e+00, 6.0818859794767741e+00, 6.3238888238470219e+00, 6.5681303797817083e+00, 6.8147874116676039e+00, 7.0640548388279587e+00, 7.3161487524084921e+00, 7.5713101008750368e+00, 7.8298092371332197e+00, 8.0919515900932844e+00, 8.3580848243237309e+00, 8.6286079999230569e+00, 8.9039834682597192e+00, 9.1847525840655759e+00, 9.4715568613271639e+00, 9.7651670958633421e+00, 1.0066524497824579e+01, 1.0376800570599057e+01, 1.0697487488847003e+01, 1.1030540650989794e+01, 1.1378616213805854e+01, 1.1745495813506075e+01, 1.2136921090287251e+01, 1.2562467887793943e+01, 1.3040726988796493e+01, 1.3620387729947742e+01}, + {-1.3690980373715535e+01, -1.3112304908251922e+01, -1.2634884014394832e+01, -1.2210103175151124e+01, -1.1819399886057777e+01, -1.1453212768894272e+01, -1.1105808823112232e+01, -1.0773412098098593e+01, -1.0453370440115185e+01, -1.0143731414960465e+01, -9.8430051316625278e+00, -9.5500219040630885e+00, -9.2638420079694495e+00, -8.9836958915100507e+00, -8.7089431037842626e+00, -8.4390432154976232e+00, -8.1735346944358760e+00, -7.9120192166772831e+00, -7.6541497885353431e+00, -7.3996216003602537e+00, -7.1481648776449447e+00, -6.8995392180679298e+00, -6.6535290513692580e+00, -6.4099399596264091e+00, -6.1685956652061904e+00, -5.9293355428005707e+00, -5.6920125471434968e+00, -5.4564914735798906e+00, -5.2226474874947222e+00, -4.9903648726555803e+00, -4.7595359591142765e+00, -4.5300601993847316e+00, -4.3018433678250396e+00, -4.0747968629734785e+00, -3.8488370963629586e+00, -3.6238849543164635e+00, -3.3998653215923187e+00, -3.1767066576408891e+00, -2.9543406177575795e+00, -2.7327017126497148e+00, -2.5117270009375883e+00, -2.2913558099291085e+00, -2.0715294806793496e+00, -1.8521911338989445e+00, -1.6332854537309136e+00, -1.4147584867915231e+00, -1.1965574541809449e+00, -9.7863057442477308e-01, -7.6092689551645798e-01, -5.4339613440036172e-01, -3.2598852237076159e-01, -1.0865465496797615e-01, 1.0865465496797615e-01, 3.2598852237076159e-01, 5.4339613440036172e-01, 7.6092689551645798e-01, 9.7863057442477308e-01, 1.1965574541809449e+00, 1.4147584867915231e+00, 1.6332854537309136e+00, 1.8521911338989445e+00, 2.0715294806793496e+00, 2.2913558099291085e+00, 2.5117270009375883e+00, 2.7327017126497148e+00, 2.9543406177575795e+00, 3.1767066576408891e+00, 3.3998653215923187e+00, 3.6238849543164635e+00, 3.8488370963629586e+00, 4.0747968629734785e+00, 4.3018433678250396e+00, 4.5300601993847316e+00, 4.7595359591142765e+00, 4.9903648726555803e+00, 5.2226474874947222e+00, 5.4564914735798906e+00, 5.6920125471434968e+00, 5.9293355428005707e+00, 6.1685956652061904e+00, 6.4099399596264091e+00, 6.6535290513692580e+00, 6.8995392180679298e+00, 7.1481648776449447e+00, 7.3996216003602537e+00, 7.6541497885353431e+00, 7.9120192166772831e+00, 8.1735346944358760e+00, 8.4390432154976232e+00, 8.7089431037842626e+00, 8.9836958915100507e+00, 9.2638420079694495e+00, 9.5500219040630885e+00, 9.8430051316625278e+00, 1.0143731414960465e+01, 1.0453370440115185e+01, 1.0773412098098593e+01, 1.1105808823112232e+01, 1.1453212768894272e+01, 1.1819399886057777e+01, 1.2210103175151124e+01, 1.2634884014394832e+01, 1.3112304908251922e+01, 1.3690980373715535e+01}, + {-1.3761227897775342e+01, -1.3183526293600599e+01, -1.2706933680714704e+01, -1.2282909553416038e+01, -1.1892919380924928e+01, -1.1527416094254811e+01, -1.1180675238467860e+01, -1.0848926485775479e+01, -1.0529521640346799e+01, -1.0220511197831829e+01, -9.9204075235256379e+00, -9.6280427257475036e+00, -9.3424785467404909e+00, -9.0629466613367704e+00, -8.7888076661013130e+00, -8.5195220427131719e+00, -8.2546290644616640e+00, -7.9937311305046359e+00, -7.7364819052916909e+00, -7.4825771858770791e+00, -7.2317477636524030e+00, -6.9837537698848138e+00, -6.7383801424910441e+00, -6.4954329519998799e+00, -6.2547363942623555e+00, -6.0161303065289111e+00, -5.7794680986505123e+00, -5.5446150166977928e+00, -5.3114466751017559e+00, -5.0798478074449882e+00, -4.8497111966094790e+00, -4.6209367530474879e+00, -4.3934307161440911e+00, -4.1671049584554103e+00, -3.9418763763764075e+00, -3.7176663537665213e+00, -3.4944002874250444e+00, -3.2720071651989722e+00, -3.0504191890280565e+00, -2.8295714364637563e+00, -2.6094015552011851e+00, -2.3898494859824693e+00, -2.1708572099022447e+00, -1.9523685166996116e+00, -1.7343287910777165e+00, -1.5166848144697649e+00, -1.2993845799825059e+00, -1.0823771185059250e+00, -8.6561233418988326e-01, -6.4904084766152925e-01, -4.3261384549707677e-01, -2.1628293457217421e-01, -0.0000000000000000e+00, 2.1628293457217421e-01, 4.3261384549707677e-01, 6.4904084766152925e-01, 8.6561233418988326e-01, 1.0823771185059250e+00, 1.2993845799825059e+00, 1.5166848144697649e+00, 1.7343287910777165e+00, 1.9523685166996116e+00, 2.1708572099022447e+00, 2.3898494859824693e+00, 2.6094015552011851e+00, 2.8295714364637563e+00, 3.0504191890280565e+00, 3.2720071651989722e+00, 3.4944002874250444e+00, 3.7176663537665213e+00, 3.9418763763764075e+00, 4.1671049584554103e+00, 4.3934307161440911e+00, 4.6209367530474879e+00, 4.8497111966094790e+00, 5.0798478074449882e+00, 5.3114466751017559e+00, 5.5446150166977928e+00, 5.7794680986505123e+00, 6.0161303065289111e+00, 6.2547363942623555e+00, 6.4954329519998799e+00, 6.7383801424910441e+00, 6.9837537698848138e+00, 7.2317477636524030e+00, 7.4825771858770791e+00, 7.7364819052916909e+00, 7.9937311305046359e+00, 8.2546290644616640e+00, 8.5195220427131719e+00, 8.7888076661013130e+00, 9.0629466613367704e+00, 9.3424785467404909e+00, 9.6280427257475036e+00, 9.9204075235256379e+00, 1.0220511197831829e+01, 1.0529521640346799e+01, 1.0848926485775479e+01, 1.1180675238467860e+01, 1.1527416094254811e+01, 1.1892919380924928e+01, 1.2282909553416038e+01, 1.2706933680714704e+01, 1.3183526293600599e+01, 1.3761227897775342e+01}, + {-1.3831135289582965e+01, -1.3254396373973801e+01, -1.2778622330019754e+01, -1.2355345871125120e+01, -1.1966060141686793e+01, -1.1601232228934139e+01, -1.1255146131451047e+01, -1.0924037082840369e+01, -1.0605260801047601e+01, -1.0296870678005966e+01, -9.9973813085297891e+00, -9.7056265732561915e+00, -9.4206696618824566e+00, -9.1417434592085591e+00, -8.8682095941331820e+00, -8.5995294453241531e+00, -8.3352430784012270e+00, -8.0749536029866285e+00, -7.8183153294116643e+00, -7.5650246493836404e+00, -7.3148129082162541e+00, -7.0674407587544215e+00, -6.8226936349524259e+00, -6.5803780834395011e+00, -6.3403187609122504e+00, -6.1023559541821202e+00, -5.8663435147929848e+00, -5.6321471256242530e+00, -5.3996428356774224e+00, -5.1687158132495581e+00, -4.9392592782592839e+00, -4.7111735825401517e+00, -4.4843654131098756e+00, -4.2587470982328570e+00, -4.0342359998584794e+00, -3.8107539789883282e+00, -3.5882269228863879e+00, -3.3665843249351557e+00, -3.1457589094612213e+00, -2.9256862950849976e+00, -2.7063046911512725e+00, -2.4875546226165683e+00, -2.2693786794419482e+00, -2.0517212870941761e+00, -1.8345284952160181e+00, -1.6177477819054702e+00, -1.4013278713576325e+00, -1.1852185628827800e+00, -9.6937056952866862e-01, -7.5373536471122926e-01, -5.3826503540107018e-01, -3.2291214052800010e-01, -1.0762957335551564e-01, 1.0762957335551564e-01, 3.2291214052800010e-01, 5.3826503540107018e-01, 7.5373536471122926e-01, 9.6937056952866862e-01, 1.1852185628827800e+00, 1.4013278713576325e+00, 1.6177477819054702e+00, 1.8345284952160181e+00, 2.0517212870941761e+00, 2.2693786794419482e+00, 2.4875546226165683e+00, 2.7063046911512725e+00, 2.9256862950849976e+00, 3.1457589094612213e+00, 3.3665843249351557e+00, 3.5882269228863879e+00, 3.8107539789883282e+00, 4.0342359998584794e+00, 4.2587470982328570e+00, 4.4843654131098756e+00, 4.7111735825401517e+00, 4.9392592782592839e+00, 5.1687158132495581e+00, 5.3996428356774224e+00, 5.6321471256242530e+00, 5.8663435147929848e+00, 6.1023559541821202e+00, 6.3403187609122504e+00, 6.5803780834395011e+00, 6.8226936349524259e+00, 7.0674407587544215e+00, 7.3148129082162541e+00, 7.5650246493836404e+00, 7.8183153294116643e+00, 8.0749536029866285e+00, 8.3352430784012270e+00, 8.5995294453241531e+00, 8.8682095941331820e+00, 9.1417434592085591e+00, 9.4206696618824566e+00, 9.7056265732561915e+00, 9.9973813085297891e+00, 1.0296870678005966e+01, 1.0605260801047601e+01, 1.0924037082840369e+01, 1.1255146131451047e+01, 1.1601232228934139e+01, 1.1966060141686793e+01, 1.2355345871125120e+01, 1.2778622330019754e+01, 1.3254396373973801e+01, 1.3831135289582965e+01}, + {-1.3900707417887173e+01, -1.3324920252415142e+01, -1.2849955272837832e+01, -1.2427417635190753e+01, -1.2038827866477725e+01, -1.1674667060202870e+01, -1.1329227578271460e+01, -1.0998750155541702e+01, -1.0680594380572309e+01, -1.0372816508782414e+01, -1.0073933338405658e+01, -9.7827805008057851e+00, -9.4984226146699928e+00, -9.2200937585148388e+00, -8.9471565789061032e+00, -8.6790733379711611e+00, -8.4153848809401453e+00, -8.1556950157409371e+00, -7.8996586867968652e+00, -7.6469728688944967e+00, -7.3973694497863685e+00, -7.1506095923972852e+00, -6.9064792151159047e+00, -6.6647853288831929e+00, -6.4253530391943388e+00, -6.1880230700488541e+00, -5.9526497019202820e+00, -5.7190990412807672e+00, -5.4872475579716511e+00, -5.2569808406969596e+00, -5.0281925314641187e+00, -4.8007834078342349e+00, -4.5746605880295625e+00, -4.3497368387482860e+00, -4.1259299692968714e+00, -3.9031622986173096e+00, -3.6813601841446331e+00, -3.4604536033170050e+00, -3.2403757800798094e+00, -3.0210628499554302e+00, -2.8024535582518539e+00, -2.5844889868023952e+00, -2.3671123053017529e+00, -2.1502685438583309e+00, -1.9339043838414955e+00, -1.7179679644825636e+00, -1.5024087030036999e+00, -1.2871771263105225e+00, -1.0722247125008730e+00, -8.5750374062088575e-01, -6.4296714724579429e-01, -4.2856838858126434e-01, -2.1426130687493608e-01, -0.0000000000000000e+00, 2.1426130687493608e-01, 4.2856838858126434e-01, 6.4296714724579429e-01, 8.5750374062088575e-01, 1.0722247125008730e+00, 1.2871771263105225e+00, 1.5024087030036999e+00, 1.7179679644825636e+00, 1.9339043838414955e+00, 2.1502685438583309e+00, 2.3671123053017529e+00, 2.5844889868023952e+00, 2.8024535582518539e+00, 3.0210628499554302e+00, 3.2403757800798094e+00, 3.4604536033170050e+00, 3.6813601841446331e+00, 3.9031622986173096e+00, 4.1259299692968714e+00, 4.3497368387482860e+00, 4.5746605880295625e+00, 4.8007834078342349e+00, 5.0281925314641187e+00, 5.2569808406969596e+00, 5.4872475579716511e+00, 5.7190990412807672e+00, 5.9526497019202820e+00, 6.1880230700488541e+00, 6.4253530391943388e+00, 6.6647853288831929e+00, 6.9064792151159047e+00, 7.1506095923972852e+00, 7.3973694497863685e+00, 7.6469728688944967e+00, 7.8996586867968652e+00, 8.1556950157409371e+00, 8.4153848809401453e+00, 8.6790733379711611e+00, 8.9471565789061032e+00, 9.2200937585148388e+00, 9.4984226146699928e+00, 9.7827805008057851e+00, 1.0073933338405658e+01, 1.0372816508782414e+01, 1.0680594380572309e+01, 1.0998750155541702e+01, 1.1329227578271460e+01, 1.1674667060202870e+01, 1.2038827866477725e+01, 1.2427417635190753e+01, 1.2849955272837832e+01, 1.3324920252415142e+01, 1.3900707417887173e+01}, + {-1.3969949036642459e+01, -1.3395102910086411e+01, -1.2920937691432538e+01, -1.2499130218130038e+01, -1.2111228112984248e+01, -1.1747726328818176e+01, -1.1402925502488745e+01, -1.1073071811228770e+01, -1.0755528671982248e+01, -1.0448355171600436e+01, -1.0150070286259611e+01, -9.8595113770046634e+00, -9.5757444735437325e+00, -9.2980048323218245e+00, -9.0256561033487941e+00, -8.7581614191156962e+00, -8.4950623921731907e+00, -8.2359635170287859e+00, -7.9805203608479554e+00, -7.7284304703735840e+00, -7.4794262647792982e+00, -7.2332694060552951e+00, -6.9897462859257979e+00, -6.7486643683832410e+00, -6.5098491962299123e+00, -6.2731419188661652e+00, -6.0383972335511160e+00, -5.8054816577895725e+00, -5.5742720692284102e+00, -5.3446544634117208e+00, -5.1165228902768884e+00, -4.8897785383006882e+00, -4.6643289413814166e+00, -4.4400872883391642e+00, -4.2169718186716345e+00, -3.9949052911662122e+00, -3.7738145143243407e+00, -3.5536299294390266e+00, -3.3342852386840143e+00, -3.1157170718023619e+00, -2.8978646859830590e+00, -2.6806696943332091e+00, -2.4640758190263061e+00, -2.2480286657622290e+00, -2.0324755166339639e+00, -1.8173651388771286e+00, -1.6026476072949805e+00, -1.3882741384147259e+00, -1.1741969346494687e+00, -9.6036903692102105e-01, -7.4674418434770939e-01, -5.3327667972273107e-01, -3.1992125960608508e-01, -1.0663296792943616e-01, 1.0663296792943616e-01, 3.1992125960608508e-01, 5.3327667972273107e-01, 7.4674418434770939e-01, 9.6036903692102105e-01, 1.1741969346494687e+00, 1.3882741384147259e+00, 1.6026476072949805e+00, 1.8173651388771286e+00, 2.0324755166339639e+00, 2.2480286657622290e+00, 2.4640758190263061e+00, 2.6806696943332091e+00, 2.8978646859830590e+00, 3.1157170718023619e+00, 3.3342852386840143e+00, 3.5536299294390266e+00, 3.7738145143243407e+00, 3.9949052911662122e+00, 4.2169718186716345e+00, 4.4400872883391642e+00, 4.6643289413814166e+00, 4.8897785383006882e+00, 5.1165228902768884e+00, 5.3446544634117208e+00, 5.5742720692284102e+00, 5.8054816577895725e+00, 6.0383972335511160e+00, 6.2731419188661652e+00, 6.5098491962299123e+00, 6.7486643683832410e+00, 6.9897462859257979e+00, 7.2332694060552951e+00, 7.4794262647792982e+00, 7.7284304703735840e+00, 7.9805203608479554e+00, 8.2359635170287859e+00, 8.4950623921731907e+00, 8.7581614191156962e+00, 9.0256561033487941e+00, 9.2980048323218245e+00, 9.5757444735437325e+00, 9.8595113770046634e+00, 1.0150070286259611e+01, 1.0448355171600436e+01, 1.0755528671982248e+01, 1.1073071811228770e+01, 1.1402925502488745e+01, 1.1747726328818176e+01, 1.2111228112984248e+01, 1.2499130218130038e+01, 1.2920937691432538e+01, 1.3395102910086411e+01, 1.3969949036642459e+01}, + {-1.4038864788757728e+01, -1.3464949210295044e+01, -1.2991574644085651e+01, -1.2570488862595592e+01, -1.2183266303224141e+01, -1.1820415634054809e+01, -1.1476245680301457e+01, -1.1147008003906418e+01, -1.0830069808875091e+01, -1.0523492982154455e+01, -1.0225798652986768e+01, -9.9358258915767603e+00, -9.6526421211592019e+00, -9.3754837607621955e+00, -9.1037154500398181e+00, -8.8368011791635279e+00, -8.5742833161234948e+00, -8.3157670306912532e+00, -8.0609085018410500e+00, -7.8094058375754942e+00, -7.5609919779111072e+00, -7.3154290733448306e+00, -7.0725039783127066e+00, -6.8320245990954787e+00, -6.5938169048330693e+00, -6.3577224590892367e+00, -6.1235963643451115e+00, -5.8913055371925065e+00, -5.6607272507011190e+00, -5.4317478943805018e+00, -5.2042619126759186e+00, -4.9781708909532618e+00, -4.7533827640966910e+00, -4.5298111276324908e+00, -4.3073746350430024e+00, -4.0859964678941409e+00, -3.8656038677524993e+00, -3.6461277207507310e+00, -3.4275021871760831e+00, -3.2096643696850733e+00, -2.9925540147475451e+00, -2.7761132427418982e+00, -2.5602863027962388e+00, -2.3450193490255717e+00, -2.1302602352750175e+00, -1.9159583258608970e+00, -1.7020643201191179e+00, -1.4885300888347839e+00, -1.2753085208470012e+00, -1.0623533783056693e+00, -8.4961915920820152e-01, -6.3706096596817285e-01, -4.2463437886846966e-01, -2.1229533333143397e-01, -0.0000000000000000e+00, 2.1229533333143397e-01, 4.2463437886846966e-01, 6.3706096596817285e-01, 8.4961915920820152e-01, 1.0623533783056693e+00, 1.2753085208470012e+00, 1.4885300888347839e+00, 1.7020643201191179e+00, 1.9159583258608970e+00, 2.1302602352750175e+00, 2.3450193490255717e+00, 2.5602863027962388e+00, 2.7761132427418982e+00, 2.9925540147475451e+00, 3.2096643696850733e+00, 3.4275021871760831e+00, 3.6461277207507310e+00, 3.8656038677524993e+00, 4.0859964678941409e+00, 4.3073746350430024e+00, 4.5298111276324908e+00, 4.7533827640966910e+00, 4.9781708909532618e+00, 5.2042619126759186e+00, 5.4317478943805018e+00, 5.6607272507011190e+00, 5.8913055371925065e+00, 6.1235963643451115e+00, 6.3577224590892367e+00, 6.5938169048330693e+00, 6.8320245990954787e+00, 7.0725039783127066e+00, 7.3154290733448306e+00, 7.5609919779111072e+00, 7.8094058375754942e+00, 8.0609085018410500e+00, 8.3157670306912532e+00, 8.5742833161234948e+00, 8.8368011791635279e+00, 9.1037154500398181e+00, 9.3754837607621955e+00, 9.6526421211592019e+00, 9.9358258915767603e+00, 1.0225798652986768e+01, 1.0523492982154455e+01, 1.0830069808875091e+01, 1.1147008003906418e+01, 1.1476245680301457e+01, 1.1820415634054809e+01, 1.2183266303224141e+01, 1.2570488862595592e+01, 1.2991574644085651e+01, 1.3464949210295044e+01, 1.4038864788757728e+01}, + {-1.4107459209689143e+01, -1.3534463902352346e+01, -1.3061871069197858e+01, -1.2641498685712268e+01, -1.2254947728119026e+01, -1.1892740438516830e+01, -1.1549193745603484e+01, -1.1220564539543394e+01, -1.0904223770953831e+01, -1.0598236096233554e+01, -1.0301124773392132e+01, -1.0011730561776583e+01, -9.7291222611091452e+00, -9.4525374380792577e+00, -9.1813417085894020e+00, -8.9149999082012474e+00, -8.6530551488522143e+00, -8.3951132646519024e+00, -8.1408310358446965e+00, -7.8899071213998058e+00, -7.6420749720138357e+00, -7.3970972165620390e+00, -7.1547611620163289e+00, -6.9148751466506351e+00, -6.6772655554639746e+00, -6.4417743554625506e+00, -6.2082570433307618e+00, -5.9765809233777674e+00, -5.7466236523236125e+00, -5.5182720014163928e+00, -5.2914207968757996e+00, -5.0659720076635653e+00, -4.8418339557415173e+00, -4.6189206287614857e+00, -4.3971510788768189e+00, -4.1764488943211937e+00, -3.9567417327500811e+00, -3.7379609072207938e+00, -3.5200410172016268e+00, -3.3029196182276346e+00, -3.0865369248200669e+00, -2.8708355421046665e+00, -2.6557602222368328e+00, -2.4412576422971846e+00, -2.2272762007812905e+00, -2.0137658301898180e+00, -1.8006778235437944e+00, -1.5879646729152568e+00, -1.3755799182849759e+00, -1.1634780052233955e+00, -9.5161415004400396e-01, -7.3994421120471532e-01, -5.2842456583606134e-01, -3.1701199035803573e-01, -1.0566354421255454e-01, 1.0566354421255454e-01, 3.1701199035803573e-01, 5.2842456583606134e-01, 7.3994421120471532e-01, 9.5161415004400396e-01, 1.1634780052233955e+00, 1.3755799182849759e+00, 1.5879646729152568e+00, 1.8006778235437944e+00, 2.0137658301898180e+00, 2.2272762007812905e+00, 2.4412576422971846e+00, 2.6557602222368328e+00, 2.8708355421046665e+00, 3.0865369248200669e+00, 3.3029196182276346e+00, 3.5200410172016268e+00, 3.7379609072207938e+00, 3.9567417327500811e+00, 4.1764488943211937e+00, 4.3971510788768189e+00, 4.6189206287614857e+00, 4.8418339557415173e+00, 5.0659720076635653e+00, 5.2914207968757996e+00, 5.5182720014163928e+00, 5.7466236523236125e+00, 5.9765809233777674e+00, 6.2082570433307618e+00, 6.4417743554625506e+00, 6.6772655554639746e+00, 6.9148751466506351e+00, 7.1547611620163289e+00, 7.3970972165620390e+00, 7.6420749720138357e+00, 7.8899071213998058e+00, 8.1408310358446965e+00, 8.3951132646519024e+00, 8.6530551488522143e+00, 8.9149999082012474e+00, 9.1813417085894020e+00, 9.4525374380792577e+00, 9.7291222611091452e+00, 1.0011730561776583e+01, 1.0301124773392132e+01, 1.0598236096233554e+01, 1.0904223770953831e+01, 1.1220564539543394e+01, 1.1549193745603484e+01, 1.1892740438516830e+01, 1.2254947728119026e+01, 1.2641498685712268e+01, 1.3061871069197858e+01, 1.3534463902352346e+01, 1.4107459209689143e+01}, + {-1.4175736730885069e+01, -1.3603651625271072e+01, -1.3131831789217085e+01, -1.2712164683229908e+01, -1.2326277551871243e+01, -1.1964706072741592e+01, -1.1621775194820279e+01, -1.1293747081147552e+01, -1.0977996389349029e+01, -1.0672590515300062e+01, -1.0376054822035842e+01, -1.0087231738512564e+01, -9.8051914243374672e+00, -9.5291725793451221e+00, -9.2585417826765291e+00, -8.9927647033681737e+00, -8.7313851861824325e+00, -8.4740097190111463e+00, -8.2202956732045873e+00, -7.9699422487875475e+00, -7.7226833973667368e+00, -7.4782822164736231e+00, -7.2365264558624682e+00, -6.9972248759462685e+00, -6.7602042675666434e+00, -6.5253069909368815e+00, -6.2923889264375843e+00, -6.0613177552660416e+00, -5.8319715065921489e+00, -5.6042373217821275e+00, -5.3780103967408355e+00, -5.1531930714178591e+00, -4.9296940416745816e+00, -4.7074276734866194e+00, -4.4863134031967471e+00, -4.2662752104856114e+00, -4.0472411530744239e+00, -3.8291429540521795e+00, -3.6119156342329615e+00, -3.3954971831747680e+00, -3.1798282634899460e+00, -2.9648519438950705e+00, -2.7505134571206762e+00, -2.5367599793568107e+00, -2.3235404283709329e+00, -2.1108052778175836e+00, -1.8985063855784825e+00, -1.6865968342381339e+00, -1.4750307820226600e+00, -1.2637633227153910e+00, -1.0527503532175146e+00, -8.4194844755040910e-01, -6.3131473620181966e-01, -4.2080678980376768e-01, -2.1038250619832910e-01, -0.0000000000000000e+00, 2.1038250619832910e-01, 4.2080678980376768e-01, 6.3131473620181966e-01, 8.4194844755040910e-01, 1.0527503532175146e+00, 1.2637633227153910e+00, 1.4750307820226600e+00, 1.6865968342381339e+00, 1.8985063855784825e+00, 2.1108052778175836e+00, 2.3235404283709329e+00, 2.5367599793568107e+00, 2.7505134571206762e+00, 2.9648519438950705e+00, 3.1798282634899460e+00, 3.3954971831747680e+00, 3.6119156342329615e+00, 3.8291429540521795e+00, 4.0472411530744239e+00, 4.2662752104856114e+00, 4.4863134031967471e+00, 4.7074276734866194e+00, 4.9296940416745816e+00, 5.1531930714178591e+00, 5.3780103967408355e+00, 5.6042373217821275e+00, 5.8319715065921489e+00, 6.0613177552660416e+00, 6.2923889264375843e+00, 6.5253069909368815e+00, 6.7602042675666434e+00, 6.9972248759462685e+00, 7.2365264558624682e+00, 7.4782822164736231e+00, 7.7226833973667368e+00, 7.9699422487875475e+00, 8.2202956732045873e+00, 8.4740097190111463e+00, 8.7313851861824325e+00, 8.9927647033681737e+00, 9.2585417826765291e+00, 9.5291725793451221e+00, 9.8051914243374672e+00, 1.0087231738512564e+01, 1.0376054822035842e+01, 1.0672590515300062e+01, 1.0977996389349029e+01, 1.1293747081147552e+01, 1.1621775194820279e+01, 1.1964706072741592e+01, 1.2326277551871243e+01, 1.2712164683229908e+01, 1.3131831789217085e+01, 1.3603651625271072e+01, 1.4175736730885069e+01}, + {-1.4243701683090396e+01, -1.3672516911310485e+01, -1.3201461514403192e+01, -1.2782491733501539e+01, -1.2397260816155137e+01, -1.2036317739606817e+01, -1.1693995391536458e+01, -1.1366561153620273e+01, -1.1051393351707578e+01, -1.0746562091821255e+01, -1.0450594818817532e+01, -1.0162335612194752e+01, -9.8808559752619285e+00, -9.6053957268710537e+00, -9.3353223967607271e+00, -9.0701024758844149e+00, -8.8092805310594660e+00, -8.5524636937560086e+00, -8.2993099166213113e+00, -8.0495189311868405e+00, -7.8028251805712348e+00, -7.5589922216241447e+00, -7.3178082375274442e+00, -7.0790824013949303e+00, -6.8426419003295491e+00, -6.6083294779732258e+00, -6.3760013883766673e+00, -6.1455256793035486e+00, -5.9167807417097054e+00, -5.6896540760274723e+00, -5.4640412363607487e+00, -5.2398449216799987e+00, -5.0169741892502993e+00, -4.7953437702964461e+00, -4.5748734716450743e+00, -4.3554876500322477e+00, -4.1371147481089601e+00, -3.9196868830532363e+00, -3.7031394802088755e+00, -3.4874109453955420e+00, -3.2724423705327612e+00, -3.0581772680375412e+00, -2.8445613301276866e+00, -2.6315422097183796e+00, -2.4190693200603040e+00, -2.2070936506509247e+00, -1.9955675972702900e+00, -1.7844448042599628e+00, -1.5736800173872914e+00, -1.3632289458242499e+00, -1.1530481319262951e+00, -9.4309482762671593e-01, -7.3332687636947402e-01, -5.2370259959160714e-01, -3.1418068683720984e-01, -1.0472008864073033e-01, 1.0472008864073033e-01, 3.1418068683720984e-01, 5.2370259959160714e-01, 7.3332687636947402e-01, 9.4309482762671593e-01, 1.1530481319262951e+00, 1.3632289458242499e+00, 1.5736800173872914e+00, 1.7844448042599628e+00, 1.9955675972702900e+00, 2.2070936506509247e+00, 2.4190693200603040e+00, 2.6315422097183796e+00, 2.8445613301276866e+00, 3.0581772680375412e+00, 3.2724423705327612e+00, 3.4874109453955420e+00, 3.7031394802088755e+00, 3.9196868830532363e+00, 4.1371147481089601e+00, 4.3554876500322477e+00, 4.5748734716450743e+00, 4.7953437702964461e+00, 5.0169741892502993e+00, 5.2398449216799987e+00, 5.4640412363607487e+00, 5.6896540760274723e+00, 5.9167807417097054e+00, 6.1455256793035486e+00, 6.3760013883766673e+00, 6.6083294779732258e+00, 6.8426419003295491e+00, 7.0790824013949303e+00, 7.3178082375274442e+00, 7.5589922216241447e+00, 7.8028251805712348e+00, 8.0495189311868405e+00, 8.2993099166213113e+00, 8.5524636937560086e+00, 8.8092805310594660e+00, 9.0701024758844149e+00, 9.3353223967607271e+00, 9.6053957268710537e+00, 9.8808559752619285e+00, 1.0162335612194752e+01, 1.0450594818817532e+01, 1.0746562091821255e+01, 1.1051393351707578e+01, 1.1366561153620273e+01, 1.1693995391536458e+01, 1.2036317739606817e+01, 1.2397260816155137e+01, 1.2782491733501539e+01, 1.3201461514403192e+01, 1.3672516911310485e+01, 1.4243701683090396e+01}, + {-1.4311358299517268e+01, -1.3741064189376445e+01, -1.3270764846437274e+01, -1.2852484601295865e+01, -1.2467902444132251e+01, -1.2107580518550922e+01, -1.1765859570925668e+01, -1.1439012148401694e+01, -1.1124420207060311e+01, -1.0820156534367447e+01, -1.0524750634313888e+01, -1.0237048218321810e+01, -9.9561221176215060e+00, -9.6812132563270588e+00, -9.4116901024866948e+00, -9.1470199577543809e+00, -8.8867481005681856e+00, -8.6304822961073278e+00, -8.3778810688446761e+00, -8.1286446726129125e+00, -7.8825080329965438e+00, -7.6392351571886659e+00, -7.3986146528207790e+00, -7.1604560966616368e+00, -6.9245870629045054e+00, -6.6908506692717395e+00, -6.4591035339104934e+00, -6.2292140613060107e+00, -6.0010609940399187e+00, -5.7745321810917920e+00, -5.5495235238436296e+00, -5.3259380689199052e+00, -5.1036852231316345e+00, -4.8826800705576368e+00, -4.6628427755272810e+00, -4.4440980582138394e+00, -4.2263747318887201e+00, -4.0096052927608685e+00, -3.7937255548353970e+00, -3.5786743234488534e+00, -3.3643931021355877e+00, -3.1508258282961985e+00, -2.9379186338110879e+00, -2.7256196272975335e+00, -2.5138786951694905e+00, -2.3026473190429599e+00, -2.0918784073499572e+00, -1.8815261392920377e+00, -1.6715458194887483e+00, -1.4618937418644296e+00, -1.2525270614742765e+00, -1.0434036731020315e+00, -8.3448209557097697e-01, -6.2572136079995633e-01, -4.1708090670945613e-01, -2.0852047314122538e-01, -0.0000000000000000e+00, 2.0852047314122538e-01, 4.1708090670945613e-01, 6.2572136079995633e-01, 8.3448209557097697e-01, 1.0434036731020315e+00, 1.2525270614742765e+00, 1.4618937418644296e+00, 1.6715458194887483e+00, 1.8815261392920377e+00, 2.0918784073499572e+00, 2.3026473190429599e+00, 2.5138786951694905e+00, 2.7256196272975335e+00, 2.9379186338110879e+00, 3.1508258282961985e+00, 3.3643931021355877e+00, 3.5786743234488534e+00, 3.7937255548353970e+00, 4.0096052927608685e+00, 4.2263747318887201e+00, 4.4440980582138394e+00, 4.6628427755272810e+00, 4.8826800705576368e+00, 5.1036852231316345e+00, 5.3259380689199052e+00, 5.5495235238436296e+00, 5.7745321810917920e+00, 6.0010609940399187e+00, 6.2292140613060107e+00, 6.4591035339104934e+00, 6.6908506692717395e+00, 6.9245870629045054e+00, 7.1604560966616368e+00, 7.3986146528207790e+00, 7.6392351571886659e+00, 7.8825080329965438e+00, 8.1286446726129125e+00, 8.3778810688446761e+00, 8.6304822961073278e+00, 8.8867481005681856e+00, 9.1470199577543809e+00, 9.4116901024866948e+00, 9.6812132563270588e+00, 9.9561221176215060e+00, 1.0237048218321810e+01, 1.0524750634313888e+01, 1.0820156534367447e+01, 1.1124420207060311e+01, 1.1439012148401694e+01, 1.1765859570925668e+01, 1.2107580518550922e+01, 1.2467902444132251e+01, 1.2852484601295865e+01, 1.3270764846437274e+01, 1.3741064189376445e+01, 1.4311358299517268e+01}, + {-1.4378710718888687e+01, -1.3809297788283777e+01, -1.3339746281883333e+01, -1.2922147941452449e+01, -1.2538207244299381e+01, -1.2178499369616199e+01, -1.1837372843992933e+01, -1.1511105327917651e+01, -1.1197082370480098e+01, -1.0893379412488740e+01, -1.0598527994882549e+01, -1.0311375442821380e+01, -1.0030995900063404e+01, -9.7566313825866331e+00, -9.4876512847987584e+00, -9.2235237081638886e+00, -8.9637946326267190e+00, -8.7080724475249998e+00, -8.4560162400066048e+00, -8.2073267773259264e+00, -7.9617394588210120e+00, -7.7190187333975366e+00, -7.4789536245148378e+00, -7.2413541039213873e+00, -7.0060481241167620e+00, -6.7728791679610003e+00, -6.5417042085499943e+00, -6.3123919976942711e+00, -6.0848216199144423e+00, -5.8588812627189206e+00, -5.6344671643769209e+00, -5.4114827083623283e+00, -5.1898376397716799e+00, -4.9694473837781068e+00, -4.7502324499094550e+00, -4.5321179088799042e+00, -4.3150329310427544e+00, -4.0989103774038682e+00, -3.8836864356433058e+00, -3.6693002948148599e+00, -3.4556938533892665e+00, -3.2428114561228023e+00, -3.0305996559046307e+00, -2.8190069972914444e+00, -2.6079838188988345e+00, -2.3974820722025694e+00, -2.1874551546235876e+00, -1.9778577550389427e+00, -1.7686457100860522e+00, -1.5597758698165716e+00, -1.3512059714147289e+00, -1.1428945198277283e+00, -9.3480067426661317e-01, -7.2688413962779108e-01, -5.1910506196077233e-01, -3.1142392716846806e-01, -1.0380146217422165e-01, 1.0380146217422165e-01, 3.1142392716846806e-01, 5.1910506196077233e-01, 7.2688413962779108e-01, 9.3480067426661317e-01, 1.1428945198277283e+00, 1.3512059714147289e+00, 1.5597758698165716e+00, 1.7686457100860522e+00, 1.9778577550389427e+00, 2.1874551546235876e+00, 2.3974820722025694e+00, 2.6079838188988345e+00, 2.8190069972914444e+00, 3.0305996559046307e+00, 3.2428114561228023e+00, 3.4556938533892665e+00, 3.6693002948148599e+00, 3.8836864356433058e+00, 4.0989103774038682e+00, 4.3150329310427544e+00, 4.5321179088799042e+00, 4.7502324499094550e+00, 4.9694473837781068e+00, 5.1898376397716799e+00, 5.4114827083623283e+00, 5.6344671643769209e+00, 5.8588812627189206e+00, 6.0848216199144423e+00, 6.3123919976942711e+00, 6.5417042085499943e+00, 6.7728791679610003e+00, 7.0060481241167620e+00, 7.2413541039213873e+00, 7.4789536245148378e+00, 7.7190187333975366e+00, 7.9617394588210120e+00, 8.2073267773259264e+00, 8.4560162400066048e+00, 8.7080724475249998e+00, 8.9637946326267190e+00, 9.2235237081638886e+00, 9.4876512847987584e+00, 9.7566313825866331e+00, 1.0030995900063404e+01, 1.0311375442821380e+01, 1.0598527994882549e+01, 1.0893379412488740e+01, 1.1197082370480098e+01, 1.1511105327917651e+01, 1.1837372843992933e+01, 1.2178499369616199e+01, 1.2538207244299381e+01, 1.2922147941452449e+01, 1.3339746281883333e+01, 1.3809297788283777e+01, 1.4378710718888687e+01}, + {-1.4445762988361196e+01, -1.3877221939887596e+01, -1.3408410215509624e+01, -1.2991486302387372e+01, -1.2608179914177892e+01, -1.2249079137323781e+01, -1.1908540201639026e+01, -1.1582845829838529e+01, -1.1269385127541279e+01, -1.0966236161382101e+01, -1.0671932487544689e+01, -1.0385323027156920e+01, -1.0105483221483672e+01, -9.8316561653115180e+00, -9.5632121677809998e+00, -9.2996201195877468e+00, -9.0404266923744707e+00, -8.7852408903904529e+00, -8.5337223546130900e+00, -8.2855723571485260e+00, -8.0405267626925543e+00, -7.7983504535582933e+00, -7.5588328607481419e+00, -7.3217843426652625e+00, -7.0870332216969052e+00, -6.8544233372804051e+00, -6.6238120087139674e+00, -6.3950683261592980e+00, -6.1680717068342963e+00, -5.9427106672279626e+00, -5.7188817726033569e+00, -5.4964887330064514e+00, -5.2754416211185129e+00, -5.0556561920420737e+00, -4.8370532888321796e+00, -4.6195583205220858e+00, -4.4031008017280051e+00, -4.1876139447872083e+00, -3.9730342968900869e+00, -3.7593014158877045e+00, -3.5463575794514748e+00, -3.3341475230768891e+00, -3.1226182030944165e+00, -2.9117185814056987e+00, -2.7013994291239474e+00, -2.4916131466813880e+00, -2.2823135982874576e+00, -2.0734559588903583e+00, -1.8649965720202712e+00, -1.6568928170822563e+00, -1.4491029848262951e+00, -1.2415861598558324e+00, -1.0343021091482230e+00, -8.2721117565385283e-01, -6.2027417611781133e-01, -4.1345230233083557e-01, -2.0670702506645103e-01, -0.0000000000000000e+00, 2.0670702506645103e-01, 4.1345230233083557e-01, 6.2027417611781133e-01, 8.2721117565385283e-01, 1.0343021091482230e+00, 1.2415861598558324e+00, 1.4491029848262951e+00, 1.6568928170822563e+00, 1.8649965720202712e+00, 2.0734559588903583e+00, 2.2823135982874576e+00, 2.4916131466813880e+00, 2.7013994291239474e+00, 2.9117185814056987e+00, 3.1226182030944165e+00, 3.3341475230768891e+00, 3.5463575794514748e+00, 3.7593014158877045e+00, 3.9730342968900869e+00, 4.1876139447872083e+00, 4.4031008017280051e+00, 4.6195583205220858e+00, 4.8370532888321796e+00, 5.0556561920420737e+00, 5.2754416211185129e+00, 5.4964887330064514e+00, 5.7188817726033569e+00, 5.9427106672279626e+00, 6.1680717068342963e+00, 6.3950683261592980e+00, 6.6238120087139674e+00, 6.8544233372804051e+00, 7.0870332216969052e+00, 7.3217843426652625e+00, 7.5588328607481419e+00, 7.7983504535582933e+00, 8.0405267626925543e+00, 8.2855723571485260e+00, 8.5337223546130900e+00, 8.7852408903904529e+00, 9.0404266923744707e+00, 9.2996201195877468e+00, 9.5632121677809998e+00, 9.8316561653115180e+00, 1.0105483221483672e+01, 1.0385323027156920e+01, 1.0671932487544689e+01, 1.0966236161382101e+01, 1.1269385127541279e+01, 1.1582845829838529e+01, 1.1908540201639026e+01, 1.2249079137323781e+01, 1.2608179914177892e+01, 1.2991486302387372e+01, 1.3408410215509624e+01, 1.3877221939887596e+01, 1.4445762988361196e+01}, + {-1.4512519066332473e+01, -1.3944840782089997e+01, -1.3476760943476538e+01, -1.3060504129456817e+01, -1.2677825043852227e+01, -1.2319324554388889e+01, -1.1979366518555956e+01, -1.1654238671159664e+01, -1.1341333638590701e+01, -1.1038732086359635e+01, -1.0744969564657922e+01, -1.0458896573213373e+01, -1.0179589836134598e+01, -9.9062935142905033e+00, -9.6383788202379357e+00, -9.3753154236236274e+00, -9.1166506782713626e+00, -8.8619941943843266e+00, -8.6110061582143160e+00, -8.3633883384434800e+00, -8.1188770570299589e+00, -7.8772376216979518e+00, -7.6382598630271916e+00, -7.4017545180817317e+00, -7.1675502710629999e+00, -6.9354913097861042e+00, -6.7054352913834911e+00, -6.4772516357915970e+00, -6.2508200841027559e+00, -6.0260294726803698e+00, -5.8027766843552886e+00, -5.5809657459630806e+00, -5.3605070475936927e+00, -5.1413166636713479e+00, -4.9233157596994808e+00, -4.7064300714392884e+00, -4.4905894456231428e+00, -4.2757274331715260e+00, -4.0617809273868284e+00, -3.8486898408169177e+00, -3.6363968154755777e+00, -3.4248469619214639e+00, -3.2139876233679749e+00, -3.0037681615511667e+00, -2.7941397615435219e+00, -2.5850552530853812e+00, -2.3764689463269284e+00, -2.1683364801428588e+00, -1.9606146814080672e+00, -1.7532614338130410e+00, -1.5462355549578937e+00, -1.3394966805987920e+00, -1.1330051550337377e+00, -9.2672192670934395e-01, -7.2060844820888659e-01, -5.1462657984655003e-01, -3.0873849614504811e-01, -1.0290659451494534e-01, 1.0290659451494534e-01, 3.0873849614504811e-01, 5.1462657984655003e-01, 7.2060844820888659e-01, 9.2672192670934395e-01, 1.1330051550337377e+00, 1.3394966805987920e+00, 1.5462355549578937e+00, 1.7532614338130410e+00, 1.9606146814080672e+00, 2.1683364801428588e+00, 2.3764689463269284e+00, 2.5850552530853812e+00, 2.7941397615435219e+00, 3.0037681615511667e+00, 3.2139876233679749e+00, 3.4248469619214639e+00, 3.6363968154755777e+00, 3.8486898408169177e+00, 4.0617809273868284e+00, 4.2757274331715260e+00, 4.4905894456231428e+00, 4.7064300714392884e+00, 4.9233157596994808e+00, 5.1413166636713479e+00, 5.3605070475936927e+00, 5.5809657459630806e+00, 5.8027766843552886e+00, 6.0260294726803698e+00, 6.2508200841027559e+00, 6.4772516357915970e+00, 6.7054352913834911e+00, 6.9354913097861042e+00, 7.1675502710629999e+00, 7.4017545180817317e+00, 7.6382598630271916e+00, 7.8772376216979518e+00, 8.1188770570299589e+00, 8.3633883384434800e+00, 8.6110061582143160e+00, 8.8619941943843266e+00, 9.1166506782713626e+00, 9.3753154236236274e+00, 9.6383788202379357e+00, 9.9062935142905033e+00, 1.0179589836134598e+01, 1.0458896573213373e+01, 1.0744969564657922e+01, 1.1038732086359635e+01, 1.1341333638590701e+01, 1.1654238671159664e+01, 1.1979366518555956e+01, 1.2319324554388889e+01, 1.2677825043852227e+01, 1.3060504129456817e+01, 1.3476760943476538e+01, 1.3944840782089997e+01, 1.4512519066332473e+01}, + {-1.4578982825139288e+01, -1.4012158361728110e+01, -1.3544802666397535e+01, -1.3129205768185479e+01, -1.2747147119365039e+01, -1.2389240245284292e+01, -1.2049856556961975e+01, -1.1725288752112307e+01, -1.1412932942839976e+01, -1.1110872367128264e+01, -1.0817644548390337e+01, -1.0532101547973223e+01, -1.0253321358511124e+01, -9.9805491945452847e+00, -9.7131571610296650e+00, -9.4506156965670485e+00, -9.1924728279240568e+00, -8.9383387625761230e+00, -8.6878742237708870e+00, -8.4407814687705134e+00, -8.1967972689854154e+00, -7.9556873498473575e+00, -7.7172419338499774e+00, -7.4812721290378645e+00, -7.2476069736794351e+00, -7.0160909961088489e+00, -6.7865821832816833e+00, -6.5589502767074928e+00, -6.3330753329246656e+00, -6.1088464994807214e+00, -5.8861609677875624e+00, -5.6649230721526251e+00, -5.4450435103908958e+00, -5.2264386661630065e+00, -5.0090300168969302e+00, -4.7927436140809663e+00, -4.5775096250454670e+00, -4.3632619272160529e+00, -4.1499377473239889e+00, -3.9374773392776570e+00, -3.7258236953922830e+00, -3.5149222864888690e+00, -3.3047208270435604e+00, -3.0951690621230776e+00, -2.8862185733023908e+00, -2.6778226011448112e+00, -2.4699358821459070e+00, -2.2625144983121754e+00, -2.0555157377720055e+00, -1.8488979650073754e+00, -1.6426204994556326e+00, -1.4366435013663816e+00, -1.2309278639126584e+00, -1.0254351106514223e+00, -8.2012729750837221e-01, -6.1496691852828633e-01, -4.0991681468614050e-01, -2.0494008509748737e-01, -0.0000000000000000e+00, 2.0494008509748737e-01, 4.0991681468614050e-01, 6.1496691852828633e-01, 8.2012729750837221e-01, 1.0254351106514223e+00, 1.2309278639126584e+00, 1.4366435013663816e+00, 1.6426204994556326e+00, 1.8488979650073754e+00, 2.0555157377720055e+00, 2.2625144983121754e+00, 2.4699358821459070e+00, 2.6778226011448112e+00, 2.8862185733023908e+00, 3.0951690621230776e+00, 3.3047208270435604e+00, 3.5149222864888690e+00, 3.7258236953922830e+00, 3.9374773392776570e+00, 4.1499377473239889e+00, 4.3632619272160529e+00, 4.5775096250454670e+00, 4.7927436140809663e+00, 5.0090300168969302e+00, 5.2264386661630065e+00, 5.4450435103908958e+00, 5.6649230721526251e+00, 5.8861609677875624e+00, 6.1088464994807214e+00, 6.3330753329246656e+00, 6.5589502767074928e+00, 6.7865821832816833e+00, 7.0160909961088489e+00, 7.2476069736794351e+00, 7.4812721290378645e+00, 7.7172419338499774e+00, 7.9556873498473575e+00, 8.1967972689854154e+00, 8.4407814687705134e+00, 8.6878742237708870e+00, 8.9383387625761230e+00, 9.1924728279240568e+00, 9.4506156965670485e+00, 9.7131571610296650e+00, 9.9805491945452847e+00, 1.0253321358511124e+01, 1.0532101547973223e+01, 1.0817644548390337e+01, 1.1110872367128264e+01, 1.1412932942839976e+01, 1.1725288752112307e+01, 1.2049856556961975e+01, 1.2389240245284292e+01, 1.2747147119365039e+01, 1.3129205768185479e+01, 1.3544802666397535e+01, 1.4012158361728110e+01, 1.4578982825139288e+01}, + {-1.4645158053651027e+01, -1.4079178637349177e+01, -1.3612539492279215e+01, -1.3197595467366467e+01, -1.2816150525975972e+01, -1.2458830729659516e+01, -1.2120014970184142e+01, -1.1796000859913661e+01, -1.1484187962287965e+01, -1.1182662061890452e+01, -1.0889962635005938e+01, -1.0604943287993811e+01, -1.0326683268027864e+01, -1.0054428831215711e+01, -9.7875529641744929e+00, -9.5255268647413445e+00, -9.2678992236538775e+00, -9.0142808372415573e+00, -8.7643329577328277e+00, -8.5177583232401322e+00, -8.2742941470872093e+00, -8.0337065649878543e+00, -7.7957861839727647e+00, -7.5603444756835589e+00, -7.3272108250171302e+00, -7.0962300932900497e+00, -6.8672605896069676e+00, -6.6401723692025154e+00, -6.4148457960045002e+00, -6.1911703204459041e+00, -5.9690434339462293e+00, -5.7483697694039071e+00, -5.5290603231377613e+00, -5.3110317784497383e+00, -5.0942059146888043e+00, -4.8785090886224198e+00, -4.6638717772489988e+00, -4.4502281730478108e+00, -4.2375158241640083e+00, -4.0256753132434273e+00, -3.8146499696239737e+00, -3.6043856104035212e+00, -3.3948303065739314e+00, -3.1859341709648956e+00, -2.9776491652016608e+00, -2.7699289232646307e+00, -2.5627285895601974e+00, -2.3560046696818464e+00, -2.1497148922675668e+00, -1.9438180805509269e+00, -1.7382740323646890e+00, -1.5330434074921915e+00, -1.3280876213767709e+00, -1.1233687442963156e+00, -9.1884940519120828e-01, -7.1449269940145821e-01, -5.1026209962444491e-01, -3.0612136944972701e-01, -1.0203447886287802e-01, 1.0203447886287802e-01, 3.0612136944972701e-01, 5.1026209962444491e-01, 7.1449269940145821e-01, 9.1884940519120828e-01, 1.1233687442963156e+00, 1.3280876213767709e+00, 1.5330434074921915e+00, 1.7382740323646890e+00, 1.9438180805509269e+00, 2.1497148922675668e+00, 2.3560046696818464e+00, 2.5627285895601974e+00, 2.7699289232646307e+00, 2.9776491652016608e+00, 3.1859341709648956e+00, 3.3948303065739314e+00, 3.6043856104035212e+00, 3.8146499696239737e+00, 4.0256753132434273e+00, 4.2375158241640083e+00, 4.4502281730478108e+00, 4.6638717772489988e+00, 4.8785090886224198e+00, 5.0942059146888043e+00, 5.3110317784497383e+00, 5.5290603231377613e+00, 5.7483697694039071e+00, 5.9690434339462293e+00, 6.1911703204459041e+00, 6.4148457960045002e+00, 6.6401723692025154e+00, 6.8672605896069676e+00, 7.0962300932900497e+00, 7.3272108250171302e+00, 7.5603444756835589e+00, 7.7957861839727647e+00, 8.0337065649878543e+00, 8.2742941470872093e+00, 8.5177583232401322e+00, 8.7643329577328277e+00, 9.0142808372415573e+00, 9.2678992236538775e+00, 9.5255268647413445e+00, 9.7875529641744929e+00, 1.0054428831215711e+01, 1.0326683268027864e+01, 1.0604943287993811e+01, 1.0889962635005938e+01, 1.1182662061890452e+01, 1.1484187962287965e+01, 1.1796000859913661e+01, 1.2120014970184142e+01, 1.2458830729659516e+01, 1.2816150525975972e+01, 1.3197595467366467e+01, 1.3612539492279215e+01, 1.4079178637349177e+01, 1.4645158053651027e+01}, + {-1.4711048459763671e+01, -1.4145905481877998e+01, -1.3679975439346320e+01, -1.3265677382038762e+01, -1.2884839551290751e+01, -1.2528100425622796e+01, -1.2189846306095971e+01, -1.1866379672363987e+01, -1.1555103505482034e+01, -1.1254106111274996e+01, -1.0961928898971054e+01, -1.0677427003696076e+01, -1.0399680913497548e+01, -1.0127937914235881e+01, -9.8615718637313439e+00, -9.6000547095956161e+00, -9.3429357978203189e+00, -9.0898265054222858e+00, -8.8403886058470427e+00, -8.5943253105810840e+00, -8.3513742675803542e+00, -8.1113020156791773e+00, -7.8738995393403330e+00, -7.6389786667002593e+00, -7.4063691221380390e+00, -7.1759160927206223e+00, -6.9474782023460993e+00, -6.7209258124599129e+00, -6.4961395866732436e+00, -6.2730092703749003e+00, -6.0514326468076227e+00, -5.8313146389908859e+00, -5.6125665329607717e+00, -5.3951053025257689e+00, -5.1788530194404441e+00, -4.9637363358218023e+00, -4.7496860279573854e+00, -4.5366365925149861e+00, -4.3245258876633645e+00, -4.1132948128290048e+00, -3.9028870218050722e+00, -3.6932486647410911e+00, -3.4843281552109961e+00, -3.2760759591109072e+00, -3.0684444025981263e+00, -2.8613874966667088e+00, -2.6548607762763461e+00, -2.4488211522211656e+00, -2.2432267741522884e+00, -2.0380369033597177e+00, -1.8332117940811192e+00, -1.6287125822420414e+00, -1.4245011806478818e+00, -1.2205401797456257e+00, -1.0167927531555376e+00, -8.1322256724173581e-01, -6.0979369404756556e-01, -4.0647052696828645e-01, -2.0321769857092067e-01, -0.0000000000000000e+00, 2.0321769857092067e-01, 4.0647052696828645e-01, 6.0979369404756556e-01, 8.1322256724173581e-01, 1.0167927531555376e+00, 1.2205401797456257e+00, 1.4245011806478818e+00, 1.6287125822420414e+00, 1.8332117940811192e+00, 2.0380369033597177e+00, 2.2432267741522884e+00, 2.4488211522211656e+00, 2.6548607762763461e+00, 2.8613874966667088e+00, 3.0684444025981263e+00, 3.2760759591109072e+00, 3.4843281552109961e+00, 3.6932486647410911e+00, 3.9028870218050722e+00, 4.1132948128290048e+00, 4.3245258876633645e+00, 4.5366365925149861e+00, 4.7496860279573854e+00, 4.9637363358218023e+00, 5.1788530194404441e+00, 5.3951053025257689e+00, 5.6125665329607717e+00, 5.8313146389908859e+00, 6.0514326468076227e+00, 6.2730092703749003e+00, 6.4961395866732436e+00, 6.7209258124599129e+00, 6.9474782023460993e+00, 7.1759160927206223e+00, 7.4063691221380390e+00, 7.6389786667002593e+00, 7.8738995393403330e+00, 8.1113020156791773e+00, 8.3513742675803542e+00, 8.5943253105810840e+00, 8.8403886058470427e+00, 9.0898265054222858e+00, 9.3429357978203189e+00, 9.6000547095956161e+00, 9.8615718637313439e+00, 1.0127937914235881e+01, 1.0399680913497548e+01, 1.0677427003696076e+01, 1.0961928898971054e+01, 1.1254106111274996e+01, 1.1555103505482034e+01, 1.1866379672363987e+01, 1.2189846306095971e+01, 1.2528100425622796e+01, 1.2884839551290751e+01, 1.3265677382038762e+01, 1.3679975439346320e+01, 1.4145905481877998e+01, 1.4711048459763671e+01}, + {-1.4776657672798869e+01, -1.4212342685181815e+01, -1.3747114438757134e+01, -1.3333455576348189e+01, -1.2953218388266750e+01, -1.2597053652892484e+01, -1.2259355010417195e+01, -1.1936429761298314e+01, -1.1625684271126064e+01, -1.1325209342106415e+01, -1.1033548296890791e+01, -1.0749557783474378e+01, -1.0472319517421079e+01, -1.0201081802811933e+01, -9.9352193584733488e+00, -9.6742048725828571e+00, -9.4175883379130294e+00, -9.1649817042418142e+00, -8.9160472587078665e+00, -8.6704886789370494e+00, -8.4280440404817565e+00, -8.1884802783862387e+00, -7.9515887476984757e+00, -7.7171816262142663e+00, -7.4850889709254078e+00, -7.2551562877054536e+00, -7.0272425081913878e+00, -6.8012182928404501e+00, -6.5769645975720454e+00, -6.3543714551491233e+00, -6.1333369328198826e+00, -5.9137662356417078e+00, -5.6955709309901366e+00, -5.4786682744780215e+00, -5.2629806212085075e+00, -5.0484349092048060e+00, -4.8349622041811422e+00, -4.6224972966778903e+00, -4.4109783440817232e+00, -4.2003465512658975e+00, -3.9905458845758908e+00, -3.7815228146971922e+00, -3.5732260846105883e+00, -3.3656064993935964e+00, -3.1586167350865688e+00, -2.9522111642257620e+00, -2.7463456959669994e+00, -2.5409776289935784e+00, -2.3360655156294796e+00, -2.1315690357710211e+00, -1.9274488794124773e+00, -1.7236666366787170e+00, -1.5201846943942978e+00, -1.3169661383169375e+00, -1.1139746602463279e+00, -9.1117446928904511e-01, -7.0853020661847821e-01, -5.0600686311669596e-01, -3.0356969932406813e-01, -1.0118416715318335e-01, 1.0118416715318335e-01, 3.0356969932406813e-01, 5.0600686311669596e-01, 7.0853020661847821e-01, 9.1117446928904511e-01, 1.1139746602463279e+00, 1.3169661383169375e+00, 1.5201846943942978e+00, 1.7236666366787170e+00, 1.9274488794124773e+00, 2.1315690357710211e+00, 2.3360655156294796e+00, 2.5409776289935784e+00, 2.7463456959669994e+00, 2.9522111642257620e+00, 3.1586167350865688e+00, 3.3656064993935964e+00, 3.5732260846105883e+00, 3.7815228146971922e+00, 3.9905458845758908e+00, 4.2003465512658975e+00, 4.4109783440817232e+00, 4.6224972966778903e+00, 4.8349622041811422e+00, 5.0484349092048060e+00, 5.2629806212085075e+00, 5.4786682744780215e+00, 5.6955709309901366e+00, 5.9137662356417078e+00, 6.1333369328198826e+00, 6.3543714551491233e+00, 6.5769645975720454e+00, 6.8012182928404501e+00, 7.0272425081913878e+00, 7.2551562877054536e+00, 7.4850889709254078e+00, 7.7171816262142663e+00, 7.9515887476984757e+00, 8.1884802783862387e+00, 8.4280440404817565e+00, 8.6704886789370494e+00, 8.9160472587078665e+00, 9.1649817042418142e+00, 9.4175883379130294e+00, 9.6742048725828571e+00, 9.9352193584733488e+00, 1.0201081802811933e+01, 1.0472319517421079e+01, 1.0749557783474378e+01, 1.1033548296890791e+01, 1.1325209342106415e+01, 1.1625684271126064e+01, 1.1936429761298314e+01, 1.2259355010417195e+01, 1.2597053652892484e+01, 1.2953218388266750e+01, 1.3333455576348189e+01, 1.3747114438757134e+01, 1.4212342685181815e+01, 1.4776657672798869e+01}, + {-1.4841989245812462e+01, -1.4278493956537387e+01, -1.3813960337214354e+01, -1.3400934026297357e+01, -1.3021291138101008e+01, -1.2665694635824183e+01, -1.2328545429882384e+01, -1.2006155595899877e+01, -1.1695934851542777e+01, -1.1395976471020912e+01, -1.1104825671283981e+01, -1.0821340597636343e+01, -1.0544604180098764e+01, -1.0273865729711682e+01, -1.0008500816363464e+01, -9.7479828598297100e+00, -9.4918624914245004e+00, -9.2397522259904878e+00, -8.9913148570644346e+00, -8.7462545214071792e+00, -8.5043097153654035e+00, -8.2652477635213177e+00, -8.0288603849063733e+00, -7.7949601003933706e+00, -7.5633772929797445e+00, -7.3339577806748517e+00, -7.1065607960848611e+00, -6.8810572917778128e+00, -6.6573285089186554e+00, -6.4352647603911377e+00, -6.2147643899767431e+00, -5.9957328770520153e+00, -5.7780820623389184e+00, -5.5617294749593142e+00, -5.3465977447386317e+00, -5.1326140866195260e+00, -4.9197098463649933e+00, -4.7078200985868248e+00, -4.4968832896314073e+00, -4.2868409190677941e+00, -4.0776372545120747e+00, -3.8692190753327944e+00, -3.6615354414501788e+00, -3.4545374839947667e+00, -3.2481782150506633e+00, -3.0424123540922232e+00, -2.8371961690442937e+00, -2.6324873301662031e+00, -2.4282447751872818e+00, -2.2244285843140195e+00, -2.0209998638917077e+00, -1.8179206376413908e+00, -1.6151537445099000e+00, -1.4126627422698670e+00, -1.2104118160904516e+00, -1.0083656913702024e+00, -8.0648955018269064e-01, -6.0474895073475177e-01, -4.0310974927746679e-01, -2.0153802394231832e-01, -0.0000000000000000e+00, 2.0153802394231832e-01, 4.0310974927746679e-01, 6.0474895073475177e-01, 8.0648955018269064e-01, 1.0083656913702024e+00, 1.2104118160904516e+00, 1.4126627422698670e+00, 1.6151537445099000e+00, 1.8179206376413908e+00, 2.0209998638917077e+00, 2.2244285843140195e+00, 2.4282447751872818e+00, 2.6324873301662031e+00, 2.8371961690442937e+00, 3.0424123540922232e+00, 3.2481782150506633e+00, 3.4545374839947667e+00, 3.6615354414501788e+00, 3.8692190753327944e+00, 4.0776372545120747e+00, 4.2868409190677941e+00, 4.4968832896314073e+00, 4.7078200985868248e+00, 4.9197098463649933e+00, 5.1326140866195260e+00, 5.3465977447386317e+00, 5.5617294749593142e+00, 5.7780820623389184e+00, 5.9957328770520153e+00, 6.2147643899767431e+00, 6.4352647603911377e+00, 6.6573285089186554e+00, 6.8810572917778128e+00, 7.1065607960848611e+00, 7.3339577806748517e+00, 7.5633772929797445e+00, 7.7949601003933706e+00, 8.0288603849063733e+00, 8.2652477635213177e+00, 8.5043097153654035e+00, 8.7462545214071792e+00, 8.9913148570644346e+00, 9.2397522259904878e+00, 9.4918624914245004e+00, 9.7479828598297100e+00, 1.0008500816363464e+01, 1.0273865729711682e+01, 1.0544604180098764e+01, 1.0821340597636343e+01, 1.1104825671283981e+01, 1.1395976471020912e+01, 1.1695934851542777e+01, 1.2006155595899877e+01, 1.2328545429882384e+01, 1.2665694635824183e+01, 1.3021291138101008e+01, 1.3400934026297357e+01, 1.3813960337214354e+01, 1.4278493956537387e+01, 1.4841989245812462e+01}, + {-1.4907046657816622e+01, -1.4344362927004781e+01, -1.3880516899476401e+01, -1.3468116622389784e+01, -1.3089061813006204e+01, -1.2734027506319505e+01, -1.2397421815284703e+01, -1.2075561545881943e+01, -1.1765859735997486e+01, -1.1466412107936478e+01, -1.1175765754204676e+01, -1.0892780302181299e+01, -1.0616539883571752e+01, -1.0346294805375646e+01, -1.0081421478842227e+01, -9.8213940466086171e+00, -9.5657637705148062e+00, -9.3141437229916662e+00, -9.0661971968977273e+00, -8.8216287813440992e+00, -8.5801773868921547e+00, -8.3416107212171422e+00, -8.1057208609652847e+00, -7.8723206637443432e+00, -7.6412408321991903e+00, -7.4123274900628546e+00, -7.1854401644106494e+00, -6.9604500933022759e+00, -6.7372387963808658e+00, -6.5156968597076492e+00, -6.2957228964512764e+00, -6.0772226529322166e+00, -5.8601082355882221e+00, -5.6442974391377119e+00, -5.4297131599071493e+00, -5.2162828812008781e+00, -5.0039382199076590e+00, -4.7926145253924428e+00, -4.5822505232162971e+00, -4.3727879974390058e+00, -4.1641715062468725e+00, -3.9563481264582303e+00, -3.7492672231264832e+00, -3.5428802410129703e+00, -3.3371405151612126e+00, -3.1320030981875178e+00, -2.9274246022241841e+00, -2.7233630537216094e+00, -2.5197777595433375e+00, -2.3166291829805914e+00, -2.1138788284758951e+00, -1.9114891339837408e+00, -1.7094233700136701e+00, -1.5076455445008548e+00, -1.3061203127337706e+00, -1.1048128916400251e+00, -9.0368897779154544e-01, -7.0271466854059361e-01, -5.0185638573956481e-01, -3.0108080153124556e-01, -1.0035476572283220e-01, 1.0035476572283220e-01, 3.0108080153124556e-01, 5.0185638573956481e-01, 7.0271466854059361e-01, 9.0368897779154544e-01, 1.1048128916400251e+00, 1.3061203127337706e+00, 1.5076455445008548e+00, 1.7094233700136701e+00, 1.9114891339837408e+00, 2.1138788284758951e+00, 2.3166291829805914e+00, 2.5197777595433375e+00, 2.7233630537216094e+00, 2.9274246022241841e+00, 3.1320030981875178e+00, 3.3371405151612126e+00, 3.5428802410129703e+00, 3.7492672231264832e+00, 3.9563481264582303e+00, 4.1641715062468725e+00, 4.3727879974390058e+00, 4.5822505232162971e+00, 4.7926145253924428e+00, 5.0039382199076590e+00, 5.2162828812008781e+00, 5.4297131599071493e+00, 5.6442974391377119e+00, 5.8601082355882221e+00, 6.0772226529322166e+00, 6.2957228964512764e+00, 6.5156968597076492e+00, 6.7372387963808658e+00, 6.9604500933022759e+00, 7.1854401644106494e+00, 7.4123274900628546e+00, 7.6412408321991903e+00, 7.8723206637443432e+00, 8.1057208609652847e+00, 8.3416107212171422e+00, 8.5801773868921547e+00, 8.8216287813440992e+00, 9.0661971968977273e+00, 9.3141437229916662e+00, 9.5657637705148062e+00, 9.8213940466086171e+00, 1.0081421478842227e+01, 1.0346294805375646e+01, 1.0616539883571752e+01, 1.0892780302181299e+01, 1.1175765754204676e+01, 1.1466412107936478e+01, 1.1765859735997486e+01, 1.2075561545881943e+01, 1.2397421815284703e+01, 1.2734027506319505e+01, 1.3089061813006204e+01, 1.3468116622389784e+01, 1.3880516899476401e+01, 1.4344362927004781e+01, 1.4907046657816622e+01}, + {-1.4971833315919479e+01, -1.4409953151712163e+01, -1.3946787810773682e+01, -1.3535007172173161e+01, -1.3156534338879860e+01, -1.2802056306622088e+01, -1.2465988324400744e+01, -1.2144651884544359e+01, -1.1835463313889939e+01, -1.1536520759384242e+01, -1.1246373170717687e+01, -1.0963881642425228e+01, -1.0688131495402112e+01, -1.0418374021858449e+01, -1.0153986464937166e+01, -9.8944436816224322e+00, -9.6392975564791730e+00, -9.3881617122605014e+00, -9.1406999342794091e+00, -8.8966172574222746e+00, -8.6556530000977201e+00, -8.4175752468453187e+00, -8.1821764257789713e+00, -7.9492697251276718e+00, -7.7186861610617425e+00, -7.4902721568710229e+00, -7.2638875278553732e+00, -7.0394037912138101e+00, -6.8167027385795480e+00, -6.5956752225409012e+00, -6.3762201188154259e+00, -6.1582434336162883e+00, -5.9416575318080138e+00, -5.7263804661537199e+00, -5.5123353916408391e+00, -5.2994500517810534e+00, -5.0876563260932981e+00, -4.8768898298307777e+00, -4.6670895585055892e+00, -4.4581975709748294e+00, -4.2501587058390200e+00, -4.0429203267128022e+00, -3.8364320925946052e+00, -3.6306457501139446e+00, -3.4255149448939752e+00, -3.2209950496501372e+00, -3.0170430069668734e+00, -2.8136171849644747e+00, -2.6106772442959039e+00, -2.4081840151061349e+00, -2.2060993827498390e+00, -2.0043861812019168e+00, -1.8030080932132322e+00, -1.6019295563640745e+00, -1.4011156742530042e+00, -1.2005321321308888e+00, -1.0001451163508825e+00, -7.9992123705629015e-01, -5.9982745357081801e-01, -3.9983100199064880e-01, -1.9989932450580150e-01, -0.0000000000000000e+00, 1.9989932450580150e-01, 3.9983100199064880e-01, 5.9982745357081801e-01, 7.9992123705629015e-01, 1.0001451163508825e+00, 1.2005321321308888e+00, 1.4011156742530042e+00, 1.6019295563640745e+00, 1.8030080932132322e+00, 2.0043861812019168e+00, 2.2060993827498390e+00, 2.4081840151061349e+00, 2.6106772442959039e+00, 2.8136171849644747e+00, 3.0170430069668734e+00, 3.2209950496501372e+00, 3.4255149448939752e+00, 3.6306457501139446e+00, 3.8364320925946052e+00, 4.0429203267128022e+00, 4.2501587058390200e+00, 4.4581975709748294e+00, 4.6670895585055892e+00, 4.8768898298307777e+00, 5.0876563260932981e+00, 5.2994500517810534e+00, 5.5123353916408391e+00, 5.7263804661537199e+00, 5.9416575318080138e+00, 6.1582434336162883e+00, 6.3762201188154259e+00, 6.5956752225409012e+00, 6.8167027385795480e+00, 7.0394037912138101e+00, 7.2638875278553732e+00, 7.4902721568710229e+00, 7.7186861610617425e+00, 7.9492697251276718e+00, 8.1821764257789713e+00, 8.4175752468453187e+00, 8.6556530000977201e+00, 8.8966172574222746e+00, 9.1406999342794091e+00, 9.3881617122605014e+00, 9.6392975564791730e+00, 9.8944436816224322e+00, 1.0153986464937166e+01, 1.0418374021858449e+01, 1.0688131495402112e+01, 1.0963881642425228e+01, 1.1246373170717687e+01, 1.1536520759384242e+01, 1.1835463313889939e+01, 1.2144651884544359e+01, 1.2465988324400744e+01, 1.2802056306622088e+01, 1.3156534338879860e+01, 1.3535007172173161e+01, 1.3946787810773682e+01, 1.4409953151712163e+01, 1.4971833315919479e+01}, + {-1.5036352557386012e+01, -1.4475268112055591e+01, -1.4012776679134205e+01, -1.3601609402686369e+01, -1.3223712557871778e+01, -1.2869784992006130e+01, -1.2534249024802044e+01, -1.2213430791710801e+01, -1.1904749877820654e+01, -1.1606306831707778e+01, -1.1316652442235313e+01, -1.1034649256479808e+01, -1.0759383772299557e+01, -1.0490108256609062e+01, -1.0226200775202839e+01, -9.9671368911110161e+00, -9.7124691040283810e+00, -9.4618115799659321e+00, -9.2148285900237301e+00, -8.9712256084886892e+00, -8.7307423554516284e+00, -8.4931472862936879e+00, -8.2582331746602566e+00, -8.0258135335048770e+00, -7.7957196866256542e+00, -7.5677983509350675e+00, -7.3419096239550905e+00, -7.1179252959243602e+00, -6.8957274242423345e+00, -6.6752071216509830e+00, -6.4562635198693066e+00, -6.2388028782578386e+00, -6.0227378131410365e+00, -5.8079866281147483e+00, -5.5944727293462684e+00, -5.3821241127798674e+00, -5.1708729124709514e+00, -4.9606550011220074e+00, -4.7514096353844053e+00, -4.5430791396990857e+00, -4.3356086234350091e+00, -4.1289457268926073e+00, -3.9230403924055310e+00, -3.7178446573254824e+00, -3.5133124661335695e+00, -3.3093994993045657e+00, -3.1060630168714907e+00, -2.9032617149079720e+00, -2.7009555933736791e+00, -2.4991058339609178e+00, -2.2976746867440045e+00, -2.0966253645719419e+00, -1.8959219442631448e+00, -1.6955292737615766e+00, -1.4954128844992702e+00, -1.2955389082829973e+00, -1.0958739980844798e+00, -8.9638525216554721e-01, -6.9704014101314027e-01, -4.9780643659506446e-01, -2.9865214347665664e-01, -9.9545431361682174e-02, 9.9545431361682174e-02, 2.9865214347665664e-01, 4.9780643659506446e-01, 6.9704014101314027e-01, 8.9638525216554721e-01, 1.0958739980844798e+00, 1.2955389082829973e+00, 1.4954128844992702e+00, 1.6955292737615766e+00, 1.8959219442631448e+00, 2.0966253645719419e+00, 2.2976746867440045e+00, 2.4991058339609178e+00, 2.7009555933736791e+00, 2.9032617149079720e+00, 3.1060630168714907e+00, 3.3093994993045657e+00, 3.5133124661335695e+00, 3.7178446573254824e+00, 3.9230403924055310e+00, 4.1289457268926073e+00, 4.3356086234350091e+00, 4.5430791396990857e+00, 4.7514096353844053e+00, 4.9606550011220074e+00, 5.1708729124709514e+00, 5.3821241127798674e+00, 5.5944727293462684e+00, 5.8079866281147483e+00, 6.0227378131410365e+00, 6.2388028782578386e+00, 6.4562635198693066e+00, 6.6752071216509830e+00, 6.8957274242423345e+00, 7.1179252959243602e+00, 7.3419096239550905e+00, 7.5677983509350675e+00, 7.7957196866256542e+00, 8.0258135335048770e+00, 8.2582331746602566e+00, 8.4931472862936879e+00, 8.7307423554516284e+00, 8.9712256084886892e+00, 9.2148285900237301e+00, 9.4618115799659321e+00, 9.7124691040283810e+00, 9.9671368911110161e+00, 1.0226200775202839e+01, 1.0490108256609062e+01, 1.0759383772299557e+01, 1.1034649256479808e+01, 1.1316652442235313e+01, 1.1606306831707778e+01, 1.1904749877820654e+01, 1.2213430791710801e+01, 1.2534249024802044e+01, 1.2869784992006130e+01, 1.3223712557871778e+01, 1.3601609402686369e+01, 1.4012776679134205e+01, 1.4475268112055591e+01, 1.5036352557386012e+01}, + {-1.5100607651623633e+01, -1.4540311217817694e+01, -1.4078487037622645e+01, -1.3667926962814708e+01, -1.3290600230854309e+01, -1.2937217433362431e+01, -1.2602207896558657e+01, -1.2281902356552338e+01, -1.1973723626537621e+01, -1.1675774634136665e+01, -1.1386607989721913e+01, -1.1105087678592627e+01, -1.0830301363602338e+01, -1.0561502276097833e+01, -1.0298069295499928e+01, -1.0039478682788769e+01, -9.7852835453915379e+00, -9.5350985857059971e+00, -9.2885885541431801e+00, -9.0454593582072000e+00, -8.8054511136991565e+00, -8.5683326410153491e+00, -8.3338970535972763e+00, -8.1019581834327870e+00, -7.8723476562632699e+00, -7.6449124769105978e+00, -7.4195130193460823e+00, -7.1960213409877323e+00, -6.9743197590276207e+00, -6.7542996402499806e+00, -6.5358603661027201e+00, -6.3189084426373174e+00, -6.1033567309754471e+00, -5.8891237786542385e+00, -5.6761332358780425e+00, -5.4643133436064266e+00, -5.2535964827157065e+00, -5.0439187753191463e+00, -4.8352197308201870e+00, -4.6274419304806678e+00, -4.4205307452707974e+00, -4.2144340825751483e+00, -4.0091021579943744e+00, -3.8044872890333408e+00, -3.6005437079246576e+00, -3.3972273912192827e+00, -3.1944959040967831e+00, -2.9923082576177755e+00, -2.7906247773689459e+00, -2.5894069821439305e+00, -2.3886174714670143e+00, -2.1882198209057537e+00, -1.9881784842371524e+00, -1.7884587016329878e+00, -1.5890264131159799e+00, -1.3898481766117783e+00, -1.1908910899840175e+00, -9.9212271649240336e-01, -7.9351101315811157e-01, -5.9502426155773702e-01, -3.9663100059735329e-01, -1.9829996084264417e-01, -0.0000000000000000e+00, 1.9829996084264417e-01, 3.9663100059735329e-01, 5.9502426155773702e-01, 7.9351101315811157e-01, 9.9212271649240336e-01, 1.1908910899840175e+00, 1.3898481766117783e+00, 1.5890264131159799e+00, 1.7884587016329878e+00, 1.9881784842371524e+00, 2.1882198209057537e+00, 2.3886174714670143e+00, 2.5894069821439305e+00, 2.7906247773689459e+00, 2.9923082576177755e+00, 3.1944959040967831e+00, 3.3972273912192827e+00, 3.6005437079246576e+00, 3.8044872890333408e+00, 4.0091021579943744e+00, 4.2144340825751483e+00, 4.4205307452707974e+00, 4.6274419304806678e+00, 4.8352197308201870e+00, 5.0439187753191463e+00, 5.2535964827157065e+00, 5.4643133436064266e+00, 5.6761332358780425e+00, 5.8891237786542385e+00, 6.1033567309754471e+00, 6.3189084426373174e+00, 6.5358603661027201e+00, 6.7542996402499806e+00, 6.9743197590276207e+00, 7.1960213409877323e+00, 7.4195130193460823e+00, 7.6449124769105978e+00, 7.8723476562632699e+00, 8.1019581834327870e+00, 8.3338970535972763e+00, 8.5683326410153491e+00, 8.8054511136991565e+00, 9.0454593582072000e+00, 9.2885885541431801e+00, 9.5350985857059971e+00, 9.7852835453915379e+00, 1.0039478682788769e+01, 1.0298069295499928e+01, 1.0561502276097833e+01, 1.0830301363602338e+01, 1.1105087678592627e+01, 1.1386607989721913e+01, 1.1675774634136665e+01, 1.1973723626537621e+01, 1.2281902356552338e+01, 1.2602207896558657e+01, 1.2937217433362431e+01, 1.3290600230854309e+01, 1.3667926962814708e+01, 1.4078487037622645e+01, 1.4540311217817694e+01, 1.5100607651623633e+01}, + {-1.5164601802095889e+01, -1.4605085809208793e+01, -1.4143922346496764e+01, -1.3733963425557441e+01, -1.3357201039800040e+01, -1.3004357419686706e+01, -1.2669868834839699e+01, -1.2350070580302615e+01, -1.2042388667769094e+01, -1.1744928381740326e+01, -1.1456244136772701e+01, -1.1175201342355262e+01, -1.0900888814619361e+01, -1.0632560739297817e+01, -1.0369596800621338e+01, -1.0111473949621464e+01, -9.8577458942500833e+00, -9.6080278666058625e+00, -9.3619850901178872e+00, -9.1193238995071209e+00, -8.8797848004974700e+00, -8.6431369728612566e+00, -8.4091738642920379e+00, -8.1777096203182182e+00, -7.9485761631426497e+00, -7.7216207799931862e+00, -7.4967041157356897e+00, -7.2736984893343362e+00, -7.0524864720372555e+00, -6.8329596788076081e+00, -6.6150177348097277e+00, -6.3985673866027142e+00, -6.1835217337299566e+00, -5.9697995610809267e+00, -5.7573247560732410e+00, -5.5460257976013150e+00, -5.3358353060028794e+00, -5.1266896451402619e+00, -4.9185285691809160e+00, -4.7112949078678819e+00, -4.5049342850546665e+00, -4.2993948660856276e+00, -4.0946271302677770e+00, -3.8905836652304053e+00, -3.6872189804268034e+00, -3.4844893374148405e+00, -3.2823525948738599e+00, -3.0807680665852137e+00, -2.8796963908316315e+00, -2.6790994098635554e+00, -2.4789400582443553e+00, -2.2791822590257231e+00, -2.0797908268232597e+00, -1.8807313769636194e+00, -1.6819702399610155e+00, -1.4834743806546613e+00, -1.2852113214015310e+00, -1.0871490687721614e+00, -8.8925604324227414e-01, -6.9150101141075326e-01, -4.9385302030582290e-01, -2.9628133336672019e-01, -9.8755367708345074e-02, 9.8755367708345074e-02, 2.9628133336672019e-01, 4.9385302030582290e-01, 6.9150101141075326e-01, 8.8925604324227414e-01, 1.0871490687721614e+00, 1.2852113214015310e+00, 1.4834743806546613e+00, 1.6819702399610155e+00, 1.8807313769636194e+00, 2.0797908268232597e+00, 2.2791822590257231e+00, 2.4789400582443553e+00, 2.6790994098635554e+00, 2.8796963908316315e+00, 3.0807680665852137e+00, 3.2823525948738599e+00, 3.4844893374148405e+00, 3.6872189804268034e+00, 3.8905836652304053e+00, 4.0946271302677770e+00, 4.2993948660856276e+00, 4.5049342850546665e+00, 4.7112949078678819e+00, 4.9185285691809160e+00, 5.1266896451402619e+00, 5.3358353060028794e+00, 5.5460257976013150e+00, 5.7573247560732410e+00, 5.9697995610809267e+00, 6.1835217337299566e+00, 6.3985673866027142e+00, 6.6150177348097277e+00, 6.8329596788076081e+00, 7.0524864720372555e+00, 7.2736984893343362e+00, 7.4967041157356897e+00, 7.7216207799931862e+00, 7.9485761631426497e+00, 8.1777096203182182e+00, 8.4091738642920379e+00, 8.6431369728612566e+00, 8.8797848004974700e+00, 9.1193238995071209e+00, 9.3619850901178872e+00, 9.6080278666058625e+00, 9.8577458942500833e+00, 1.0111473949621464e+01, 1.0369596800621338e+01, 1.0632560739297817e+01, 1.0900888814619361e+01, 1.1175201342355262e+01, 1.1456244136772701e+01, 1.1744928381740326e+01, 1.2042388667769094e+01, 1.2350070580302615e+01, 1.2669868834839699e+01, 1.3004357419686706e+01, 1.3357201039800040e+01, 1.3733963425557441e+01, 1.4143922346496764e+01, 1.4605085809208793e+01, 1.5164601802095889e+01}, + {-1.5228338148167351e+01, -1.4669595158833971e+01, -1.4209085995284871e+01, -1.3799722290211674e+01, -1.3423518590070948e+01, -1.3071208660474600e+01, -1.2737235652415684e+01, -1.2417939378869717e+01, -1.2110749020947747e+01, -1.1813772198267726e+01, -1.1525565112572695e+01, -1.1244994583785543e+01, -1.0971150569840248e+01, -1.0703288201027481e+01, -1.0440787957772772e+01, -1.0183127473450343e+01, -9.9298610495114250e+00, -9.6806044412474730e+00, -9.4350233389881648e+00, -9.1928244988460293e+00, -8.9537488108565402e+00, -8.7175658087076293e+00, -8.4840692689832480e+00, -8.2530736454457152e+00, -8.0244111514703373e+00, -7.7979293513870109e+00, -7.5734891556083452e+00, -7.3509631392269048e+00, -7.1302341220350698e+00, -6.9111939615465703e+00, -6.6937425208758290e+00, -6.4777867811645358e+00, -6.2632400742737344e+00, -6.0500214161419841e+00, -5.8380549248774187e+00, -5.6272693105464811e+00, -5.4175974259243240e+00, -5.2089758693153980e+00, -5.0013446320386352e+00, -4.7946467843764919e+00, -4.5888281947698371e+00, -4.3838372778464736e+00, -4.1796247675352030e+00, -3.9761435120673356e+00, -3.7733482881250526e+00, -3.5711956317782176e+00, -3.3696436841717392e+00, -3.1686520501953628e+00, -2.9681816685955908e+00, -2.7681946921824054e+00, -2.5686543769473498e+00, -2.3695249790490402e+00, -2.1707716587411507e+00, -1.9723603904195017e+00, -1.7742578780516791e+00, -1.5764314753267801e+00, -1.3788491099261777e+00, -1.1814792113700685e+00, -9.8429064194027271e-01, -7.8725263021825032e-01, -5.9033470680942102e-01, -3.9350664185130130e-01, -1.9673838392423251e-01, -0.0000000000000000e+00, 1.9673838392423251e-01, 3.9350664185130130e-01, 5.9033470680942102e-01, 7.8725263021825032e-01, 9.8429064194027271e-01, 1.1814792113700685e+00, 1.3788491099261777e+00, 1.5764314753267801e+00, 1.7742578780516791e+00, 1.9723603904195017e+00, 2.1707716587411507e+00, 2.3695249790490402e+00, 2.5686543769473498e+00, 2.7681946921824054e+00, 2.9681816685955908e+00, 3.1686520501953628e+00, 3.3696436841717392e+00, 3.5711956317782176e+00, 3.7733482881250526e+00, 3.9761435120673356e+00, 4.1796247675352030e+00, 4.3838372778464736e+00, 4.5888281947698371e+00, 4.7946467843764919e+00, 5.0013446320386352e+00, 5.2089758693153980e+00, 5.4175974259243240e+00, 5.6272693105464811e+00, 5.8380549248774187e+00, 6.0500214161419841e+00, 6.2632400742737344e+00, 6.4777867811645358e+00, 6.6937425208758290e+00, 6.9111939615465703e+00, 7.1302341220350698e+00, 7.3509631392269048e+00, 7.5734891556083452e+00, 7.7979293513870109e+00, 8.0244111514703373e+00, 8.2530736454457152e+00, 8.4840692689832480e+00, 8.7175658087076293e+00, 8.9537488108565402e+00, 9.1928244988460293e+00, 9.4350233389881648e+00, 9.6806044412474730e+00, 9.9298610495114250e+00, 1.0183127473450343e+01, 1.0440787957772772e+01, 1.0703288201027481e+01, 1.0971150569840248e+01, 1.1244994583785543e+01, 1.1525565112572695e+01, 1.1813772198267726e+01, 1.2110749020947747e+01, 1.2417939378869717e+01, 1.2737235652415684e+01, 1.3071208660474600e+01, 1.3423518590070948e+01, 1.3799722290211674e+01, 1.4209085995284871e+01, 1.4669595158833971e+01, 1.5228338148167351e+01}, + {-1.5291819766882741e+01, -1.4733842473589300e+01, -1.4273981304787835e+01, -1.3865206984476242e+01, -1.3489556412623140e+01, -1.3137774788027649e+01, -1.2804312082067129e+01, -1.2485512585349447e+01, -1.2178808619831244e+01, -1.1882310118878310e+01, -1.1594575054741449e+01, -1.1314471644289977e+01, -1.1041090976019634e+01, -1.0773689115161440e+01, -1.0511647329914869e+01, -1.0254443928470931e+01, -1.0001633798930122e+01, -9.7528332134391675e+00, -9.5077083232790560e+00, -9.2659663002961761e+00, -9.0273484133947868e+00, -8.7916245448886858e+00, -8.5585887950645070e+00, -8.3280559207901454e+00, -8.0998584215078964e+00, -7.8738441335354343e+00, -7.6498742276810061e+00, -7.4278215299523005e+00, -7.2075691033873337e+00, -6.9890090426447742e+00, -6.7720414432559277e+00, -6.5565735152644828e+00, -6.3425188170017792e+00, -6.1297965894221624e+00, -5.9183311750858119e+00, -5.7080515087680856e+00, -5.4988906689739094e+00, -5.2907854814771786e+00, -5.0836761674893394e+00, -4.8775060302648141e+00, -4.6722211749326386e+00, -4.4677702571485822e+00, -4.2641042568255187e+00, -4.0611762737492727e+00, -3.8589413423442820e+00, -3.6573562632353078e+00, -3.4563794495717373e+00, -3.2559707863506588e+00, -3.0560915012026797e+00, -2.8567040452974051e+00, -2.6577719831894839e+00, -2.4592598905657392e+00, -2.2611332589730622e+00, -2.0633584067085660e+00, -1.8659023951405984e+00, -1.6687329498037236e+00, -1.4718183856744860e+00, -1.2751275360891583e+00, -1.0786296848109087e+00, -8.8229450079298133e-01, -6.8609197521733478e-01, -4.8999236041545891e-01, -2.9396611030029574e-01, -9.7983821955818992e-02, 9.7983821955818992e-02, 2.9396611030029574e-01, 4.8999236041545891e-01, 6.8609197521733478e-01, 8.8229450079298133e-01, 1.0786296848109087e+00, 1.2751275360891583e+00, 1.4718183856744860e+00, 1.6687329498037236e+00, 1.8659023951405984e+00, 2.0633584067085660e+00, 2.2611332589730622e+00, 2.4592598905657392e+00, 2.6577719831894839e+00, 2.8567040452974051e+00, 3.0560915012026797e+00, 3.2559707863506588e+00, 3.4563794495717373e+00, 3.6573562632353078e+00, 3.8589413423442820e+00, 4.0611762737492727e+00, 4.2641042568255187e+00, 4.4677702571485822e+00, 4.6722211749326386e+00, 4.8775060302648141e+00, 5.0836761674893394e+00, 5.2907854814771786e+00, 5.4988906689739094e+00, 5.7080515087680856e+00, 5.9183311750858119e+00, 6.1297965894221624e+00, 6.3425188170017792e+00, 6.5565735152644828e+00, 6.7720414432559277e+00, 6.9890090426447742e+00, 7.2075691033873337e+00, 7.4278215299523005e+00, 7.6498742276810061e+00, 7.8738441335354343e+00, 8.0998584215078964e+00, 8.3280559207901454e+00, 8.5585887950645070e+00, 8.7916245448886858e+00, 9.0273484133947868e+00, 9.2659663002961761e+00, 9.5077083232790560e+00, 9.7528332134391675e+00, 1.0001633798930122e+01, 1.0254443928470931e+01, 1.0511647329914869e+01, 1.0773689115161440e+01, 1.1041090976019634e+01, 1.1314471644289977e+01, 1.1594575054741449e+01, 1.1882310118878310e+01, 1.2178808619831244e+01, 1.2485512585349447e+01, 1.2804312082067129e+01, 1.3137774788027649e+01, 1.3489556412623140e+01, 1.3865206984476242e+01, 1.4273981304787835e+01, 1.4733842473589300e+01, 1.5291819766882741e+01}, + {-1.5355049674683126e+01, -1.4797830896490307e+01, -1.4338611529008967e+01, -1.3930420866479178e+01, -1.3555317966130856e+01, -1.3204059359674192e+01, -1.2871101778903627e+01, -1.2552793952444540e+01, -1.2246571315023999e+01, -1.1950546092769182e+01, -1.1663278012068952e+01, -1.1383636673511937e+01, -1.1110714285141645e+01, -1.0843767837715543e+01, -1.0582179378973514e+01, -1.0325427884573593e+01, -1.0073068822584037e+01, -9.8247189758331519e+00, -9.5800449507652310e+00, -9.3387543294632973e+00, -9.1005887544187765e+00, -8.8653184514446028e+00, -8.6327378395084349e+00, -8.4026619736253494e+00, -8.1749236343739895e+00, -7.9493709251260496e+00, -7.7258652721212853e+00, -7.5042797472635216e+00, -7.2844976517401534e+00, -7.0664113121603904e+00, -6.8499210511601492e+00, -6.6349343022359886e+00, -6.4213648445851028e+00, -6.2091321383995863e+00, -5.9981607447217984e+00, -5.7883798168558824e+00, -5.5797226526273649e+00, -5.3721262986220681e+00, -5.1655311990180879e+00, -4.9598808828268046e+00, -4.7551216843394561e+00, -4.5512024923799270e+00, -4.3480745246271999e+00, -4.1456911238198586e+00, -3.9440075731117403e+00, -3.7429809282294269e+00, -3.5425698644023571e+00, -3.3427345363058465e+00, -3.1434364494849998e+00, -2.9446383419204585e+00, -2.7463040745609382e+00, -2.5483985297872240e+00, -2.3508875168916132e+00, -2.1537376837587945e+00, -1.9569164340215148e+00, -1.7603918490392145e+00, -1.5641326141118630e+00, -1.3681079483960505e+00, -1.1722875380371232e+00, -9.7664147207086760e-01, -7.8114018068176028e-01, -5.8575437543280562e-01, -3.9045499110504589e-01, -1.9521312880340755e-01, -0.0000000000000000e+00, 1.9521312880340755e-01, 3.9045499110504589e-01, 5.8575437543280562e-01, 7.8114018068176028e-01, 9.7664147207086760e-01, 1.1722875380371232e+00, 1.3681079483960505e+00, 1.5641326141118630e+00, 1.7603918490392145e+00, 1.9569164340215148e+00, 2.1537376837587945e+00, 2.3508875168916132e+00, 2.5483985297872240e+00, 2.7463040745609382e+00, 2.9446383419204585e+00, 3.1434364494849998e+00, 3.3427345363058465e+00, 3.5425698644023571e+00, 3.7429809282294269e+00, 3.9440075731117403e+00, 4.1456911238198586e+00, 4.3480745246271999e+00, 4.5512024923799270e+00, 4.7551216843394561e+00, 4.9598808828268046e+00, 5.1655311990180879e+00, 5.3721262986220681e+00, 5.5797226526273649e+00, 5.7883798168558824e+00, 5.9981607447217984e+00, 6.2091321383995863e+00, 6.4213648445851028e+00, 6.6349343022359886e+00, 6.8499210511601492e+00, 7.0664113121603904e+00, 7.2844976517401534e+00, 7.5042797472635216e+00, 7.7258652721212853e+00, 7.9493709251260496e+00, 8.1749236343739895e+00, 8.4026619736253494e+00, 8.6327378395084349e+00, 8.8653184514446028e+00, 9.1005887544187765e+00, 9.3387543294632973e+00, 9.5800449507652310e+00, 9.8247189758331519e+00, 1.0073068822584037e+01, 1.0325427884573593e+01, 1.0582179378973514e+01, 1.0843767837715543e+01, 1.1110714285141645e+01, 1.1383636673511937e+01, 1.1663278012068952e+01, 1.1950546092769182e+01, 1.2246571315023999e+01, 1.2552793952444540e+01, 1.2871101778903627e+01, 1.3204059359674192e+01, 1.3555317966130856e+01, 1.3930420866479178e+01, 1.4338611529008967e+01, 1.4797830896490307e+01, 1.5355049674683126e+01}, + {-1.5418030829061875e+01, -1.4861563508435680e+01, -1.4402979857014893e+01, -1.3995367226732167e+01, -1.3620806639033354e+01, -1.3270065859909028e+01, -1.2937608322597471e+01, -1.2619787154794016e+01, -1.2314040876404606e+01, -1.2018483985703304e+01, -1.1731677947147649e+01, -1.1452493732070961e+01, -1.1180024657270208e+01, -1.0913528629812234e+01, -1.0652388468924656e+01, -1.0396083810552501e+01, -1.0144170696212489e+01, -9.8962664133982265e+00, -9.6520380180840490e+00, -9.4111934972461668e+00, -9.1734748618357518e+00, -8.9386526761940264e+00, -8.7065216731065060e+00, -8.4768972009392183e+00, -8.2496123166430966e+00, -8.0245153858819371e+00, -7.8014680855407574e+00, -7.5803437285851887e+00, -7.3610258494479153e+00, -7.1434070016947420e+00, -6.9273877299634155e+00, -6.7128756859735788e+00, -6.4997848644138259e+00, -6.2880349391774812e+00, -6.0775506840731746e+00, -5.8682614650210780e+00, -5.6601007930399492e+00, -5.4530059291673494e+00, -5.2469175339362204e+00, -5.0417793552319132e+00, -4.8375379493332744e+00, -4.6341424307446326e+00, -4.4315442470876985e+00, -4.2296969758707617e+00, -4.0285561404088908e+00, -3.8280790425501139e+00, -3.6282246101824178e+00, -3.4289532577657682e+00, -3.2302267583609394e+00, -3.0320081258198956e+00, -2.8342615059664689e+00, -2.6369520757359015e+00, -2.4400459493612159e+00, -2.2435100907965948e+00, -2.0473122316554950e+00, -1.8514207940163270e+00, -1.6558048175129170e+00, -1.4604338901821434e+00, -1.2652780825883267e+00, -1.0703078847841583e+00, -8.7549414570205153e-01, -6.8080801459844631e-01, -4.8622088419741660e-01, -2.9170433519935240e-01, -9.7230081835906187e-02, 9.7230081835906187e-02, 2.9170433519935240e-01, 4.8622088419741660e-01, 6.8080801459844631e-01, 8.7549414570205153e-01, 1.0703078847841583e+00, 1.2652780825883267e+00, 1.4604338901821434e+00, 1.6558048175129170e+00, 1.8514207940163270e+00, 2.0473122316554950e+00, 2.2435100907965948e+00, 2.4400459493612159e+00, 2.6369520757359015e+00, 2.8342615059664689e+00, 3.0320081258198956e+00, 3.2302267583609394e+00, 3.4289532577657682e+00, 3.6282246101824178e+00, 3.8280790425501139e+00, 4.0285561404088908e+00, 4.2296969758707617e+00, 4.4315442470876985e+00, 4.6341424307446326e+00, 4.8375379493332744e+00, 5.0417793552319132e+00, 5.2469175339362204e+00, 5.4530059291673494e+00, 5.6601007930399492e+00, 5.8682614650210780e+00, 6.0775506840731746e+00, 6.2880349391774812e+00, 6.4997848644138259e+00, 6.7128756859735788e+00, 6.9273877299634155e+00, 7.1434070016947420e+00, 7.3610258494479153e+00, 7.5803437285851887e+00, 7.8014680855407574e+00, 8.0245153858819371e+00, 8.2496123166430966e+00, 8.4768972009392183e+00, 8.7065216731065060e+00, 8.9386526761940264e+00, 9.1734748618357518e+00, 9.4111934972461668e+00, 9.6520380180840490e+00, 9.8962664133982265e+00, 1.0144170696212489e+01, 1.0396083810552501e+01, 1.0652388468924656e+01, 1.0913528629812234e+01, 1.1180024657270208e+01, 1.1452493732070961e+01, 1.1731677947147649e+01, 1.2018483985703304e+01, 1.2314040876404606e+01, 1.2619787154794016e+01, 1.2937608322597471e+01, 1.3270065859909028e+01, 1.3620806639033354e+01, 1.3995367226732167e+01, 1.4402979857014893e+01, 1.4861563508435680e+01, 1.5418030829061875e+01}, + {-1.5480766130162912e+01, -1.4925043329908892e+01, -1.4467089414730456e+01, -1.4060049290015051e+01, -1.3686025751508065e+01, -1.3335797702455430e+01, -1.3003835219535608e+01, -1.2686495791216792e+01, -1.2381220995463224e+01, -1.2086127582443233e+01, -1.1799778738905447e+01, -1.1521046794198202e+01, -1.1249026163290472e+01, -1.0982975660531801e+01, -1.0722278868759513e+01, -1.0466416077189237e+01, -1.0214943894423017e+01, -9.9674801067548007e+00, -9.7236922142042346e+00, -9.4832886034446808e+00, -9.2460116489073236e+00, -9.0116322486398488e+00, -8.7799454445339524e+00, -8.5507668736650881e+00, -8.3239298647512676e+00, -8.0992830411501870e+00, -7.8766883257751701e+00, -7.6560192679949264e+00, -7.4371596307659544e+00, -7.2200021898070377e+00, -7.0044477068537327e+00, -6.7904040468269269e+00, -6.5777854147500525e+00, -6.3665116929098069e+00, -6.1565078624054426e+00, -5.9477034961131627e+00, -5.7400323123838195e+00, -5.5334317806272333e+00, -5.3278427714156580e+00, -5.1232092449384545e+00, -4.9194779726184912e+00, -4.7165982875032402e+00, -4.5145218597049430e+00, -4.3132024937121241e+00, -4.1125959448506144e+00, -3.9126597525531843e+00, -3.7133530884165373e+00, -3.5146366172935721e+00, -3.3164723698963634e+00, -3.1188236255781381e+00, -2.9216548041266144e+00, -2.7249313655408702e+00, -2.5286197168834539e+00, -2.3326871254017765e+00, -2.1371016372005704e+00, -1.9418320008225314e+00, -1.7468475951589244e+00, -1.5521183611674445e+00, -1.3576147369221905e+00, -1.1633075955612597e+00, -9.6916818573207730e-01, -7.7516807416380029e-01, -5.8127909002062172e-01, -3.8747327070995596e-01, -1.9372280883577261e-01, -0.0000000000000000e+00, 1.9372280883577261e-01, 3.8747327070995596e-01, 5.8127909002062172e-01, 7.7516807416380029e-01, 9.6916818573207730e-01, 1.1633075955612597e+00, 1.3576147369221905e+00, 1.5521183611674445e+00, 1.7468475951589244e+00, 1.9418320008225314e+00, 2.1371016372005704e+00, 2.3326871254017765e+00, 2.5286197168834539e+00, 2.7249313655408702e+00, 2.9216548041266144e+00, 3.1188236255781381e+00, 3.3164723698963634e+00, 3.5146366172935721e+00, 3.7133530884165373e+00, 3.9126597525531843e+00, 4.1125959448506144e+00, 4.3132024937121241e+00, 4.5145218597049430e+00, 4.7165982875032402e+00, 4.9194779726184912e+00, 5.1232092449384545e+00, 5.3278427714156580e+00, 5.5334317806272333e+00, 5.7400323123838195e+00, 5.9477034961131627e+00, 6.1565078624054426e+00, 6.3665116929098069e+00, 6.5777854147500525e+00, 6.7904040468269269e+00, 7.0044477068537327e+00, 7.2200021898070377e+00, 7.4371596307659544e+00, 7.6560192679949264e+00, 7.8766883257751701e+00, 8.0992830411501870e+00, 8.3239298647512676e+00, 8.5507668736650881e+00, 8.7799454445339524e+00, 9.0116322486398488e+00, 9.2460116489073236e+00, 9.4832886034446808e+00, 9.7236922142042346e+00, 9.9674801067548007e+00, 1.0214943894423017e+01, 1.0466416077189237e+01, 1.0722278868759513e+01, 1.0982975660531801e+01, 1.1249026163290472e+01, 1.1521046794198202e+01, 1.1799778738905447e+01, 1.2086127582443233e+01, 1.2381220995463224e+01, 1.2686495791216792e+01, 1.3003835219535608e+01, 1.3335797702455430e+01, 1.3686025751508065e+01, 1.4060049290015051e+01, 1.4467089414730456e+01, 1.4925043329908892e+01, 1.5480766130162912e+01}, + {-1.5543258422323774e+01, -1.4988273322620483e+01, -1.4530943266670407e+01, -1.4124470217193569e+01, -1.3750978557373212e+01, -1.3401258232252896e+01, -1.3069785904893536e+01, -1.2752923386873304e+01, -1.2448115287552957e+01, -1.2153480589094658e+01, -1.1867584185044096e+01, -1.1589299750272769e+01, -1.1317722787546410e+01, -1.1052113009654860e+01, -1.0791854755335825e+01, -1.0536428960217005e+01, -1.0285392793773033e+01, -1.0038364535378761e+01, -9.7950121237570809e+00, -9.5550443402238834e+00, -9.3182039178520490e+00, -9.0842620837165757e+00, -8.8530141842483925e+00, -8.6242761407386386e+00, -8.3978815492187184e+00, -8.1736792862980483e+00, -7.9515315164625289e+00, -7.7313120209923101e+00, -7.5129047868198517e+00, -7.2962028071941081e+00, -7.0811070562331242e+00, -6.8675256072344579e+00, -6.6553728706063735e+00, -6.4445689319376820e+00, -6.2350389743700507e+00, -6.0267127723148342e+00, -5.8195242458455034e+00, -5.6134110669298432e+00, -5.4083143101435791e+00, -5.2041781417053947e+00, -5.0009495416506535e+00, -4.7985780547627241e+00, -4.5970155665415948e+00, -4.3962161010367922e+00, -4.1961356378270693e+00, -3.9967319458099735e+00, -3.7979644317837824e+00, -3.5997940020732910e+00, -3.4021829356783408e+00, -3.2050947676167678e+00, -3.0084941812975128e+00, -2.8123469088994537e+00, -2.6166196388511782e+00, -2.4212799296093106e+00, -2.2262961290209549e+00, -2.0316372986313107e+00, -1.8372731423624578e+00, -1.6431739390450815e+00, -1.4493104783328268e+00, -1.2556539995700138e+00, -1.0621761332184900e+00, -8.6884884447915023e-01, -6.7564437876870465e-01, -4.8253520873311562e-01, -2.8949398249614278e-01, -9.6493472854955881e-02, 9.6493472854955881e-02, 2.8949398249614278e-01, 4.8253520873311562e-01, 6.7564437876870465e-01, 8.6884884447915023e-01, 1.0621761332184900e+00, 1.2556539995700138e+00, 1.4493104783328268e+00, 1.6431739390450815e+00, 1.8372731423624578e+00, 2.0316372986313107e+00, 2.2262961290209549e+00, 2.4212799296093106e+00, 2.6166196388511782e+00, 2.8123469088994537e+00, 3.0084941812975128e+00, 3.2050947676167678e+00, 3.4021829356783408e+00, 3.5997940020732910e+00, 3.7979644317837824e+00, 3.9967319458099735e+00, 4.1961356378270693e+00, 4.3962161010367922e+00, 4.5970155665415948e+00, 4.7985780547627241e+00, 5.0009495416506535e+00, 5.2041781417053947e+00, 5.4083143101435791e+00, 5.6134110669298432e+00, 5.8195242458455034e+00, 6.0267127723148342e+00, 6.2350389743700507e+00, 6.4445689319376820e+00, 6.6553728706063735e+00, 6.8675256072344579e+00, 7.0811070562331242e+00, 7.2962028071941081e+00, 7.5129047868198517e+00, 7.7313120209923101e+00, 7.9515315164625289e+00, 8.1736792862980483e+00, 8.3978815492187184e+00, 8.6242761407386386e+00, 8.8530141842483925e+00, 9.0842620837165757e+00, 9.3182039178520490e+00, 9.5550443402238834e+00, 9.7950121237570809e+00, 1.0038364535378761e+01, 1.0285392793773033e+01, 1.0536428960217005e+01, 1.0791854755335825e+01, 1.1052113009654860e+01, 1.1317722787546410e+01, 1.1589299750272769e+01, 1.1867584185044096e+01, 1.2153480589094658e+01, 1.2448115287552957e+01, 1.2752923386873304e+01, 1.3069785904893536e+01, 1.3401258232252896e+01, 1.3750978557373212e+01, 1.4124470217193569e+01, 1.4530943266670407e+01, 1.4988273322620483e+01, 1.5543258422323774e+01}, + {-1.5605510495565703e+01, -1.5051256391093448e+01, -1.4594544417610667e+01, -1.4188633106973045e+01, -1.3815668245922964e+01, -1.3466450727373902e+01, -1.3135463744634585e+01, -1.2819073395348772e+01, -1.2514727294059055e+01, -1.2220546635363748e+01, -1.1935098004387349e+01, -1.1657256409263454e+01, -1.1386118430379335e+01, -1.1120944670301025e+01, -1.0861120216120376e+01, -1.0606126643170979e+01, -1.0355521675732227e+01, -1.0108924080680463e+01, -9.8660022302368411e+00, -9.6264652954408270e+00, -9.3900563633043106e+00, -9.1565469853869601e+00, -8.9257328082304568e+00, -8.6974300329890397e+00, -8.4714725186984587e+00, -8.2477093909264614e+00, -8.0260030514294165e+00, -7.8062275090663409e+00, -7.5882669703629624e+00, -7.3720146416474837e+00, -7.1573717048843459e+00, -6.9442464371104355e+00, -6.7325534493647661e+00, -6.5222130256523068e+00, -6.3131505461243611e+00, -6.1052959815328816e+00, -5.8985834483025466e+00, -5.6929508153954593e+00, -5.4883393556191784e+00, -5.2846934352257779e+00, -5.0819602366259380e+00, -4.8800895098428096e+00, -4.6790333489905045e+00, -4.4787459906088296e+00, -4.2791836311409464e+00, -4.0803042612209337e+00, -3.8820675147573152e+00, -3.6844345310674940e+00, -3.4873678285452550e+00, -3.2908311885362425e+00, -3.0947895482603323e+00, -2.8992089017596818e+00, -2.7040562079709125e+00, -2.5092993051224148e+00, -2.3149068307458065e+00, -2.1208481466662792e+00, -1.9270932684016822e+00, -1.7336127984562590e+00, -1.5403778630431328e+00, -1.3473600518110582e+00, -1.1545313601863669e+00, -9.6186413397127435e-01, -7.6933101586525243e-01, -5.7690489359762542e-01, -3.8455884937721463e-01, -1.9226611037913860e-01, -0.0000000000000000e+00, 1.9226611037913860e-01, 3.8455884937721463e-01, 5.7690489359762542e-01, 7.6933101586525243e-01, 9.6186413397127435e-01, 1.1545313601863669e+00, 1.3473600518110582e+00, 1.5403778630431328e+00, 1.7336127984562590e+00, 1.9270932684016822e+00, 2.1208481466662792e+00, 2.3149068307458065e+00, 2.5092993051224148e+00, 2.7040562079709125e+00, 2.8992089017596818e+00, 3.0947895482603323e+00, 3.2908311885362425e+00, 3.4873678285452550e+00, 3.6844345310674940e+00, 3.8820675147573152e+00, 4.0803042612209337e+00, 4.2791836311409464e+00, 4.4787459906088296e+00, 4.6790333489905045e+00, 4.8800895098428096e+00, 5.0819602366259380e+00, 5.2846934352257779e+00, 5.4883393556191784e+00, 5.6929508153954593e+00, 5.8985834483025466e+00, 6.1052959815328816e+00, 6.3131505461243611e+00, 6.5222130256523068e+00, 6.7325534493647661e+00, 6.9442464371104355e+00, 7.1573717048843459e+00, 7.3720146416474837e+00, 7.5882669703629624e+00, 7.8062275090663409e+00, 8.0260030514294165e+00, 8.2477093909264614e+00, 8.4714725186984587e+00, 8.6974300329890397e+00, 8.9257328082304568e+00, 9.1565469853869601e+00, 9.3900563633043106e+00, 9.6264652954408270e+00, 9.8660022302368411e+00, 1.0108924080680463e+01, 1.0355521675732227e+01, 1.0606126643170979e+01, 1.0861120216120376e+01, 1.1120944670301025e+01, 1.1386118430379335e+01, 1.1657256409263454e+01, 1.1935098004387349e+01, 1.2220546635363748e+01, 1.2514727294059055e+01, 1.2819073395348772e+01, 1.3135463744634585e+01, 1.3466450727373902e+01, 1.3815668245922964e+01, 1.4188633106973045e+01, 1.4594544417610667e+01, 1.5051256391093448e+01, 1.5605510495565703e+01}, + {-1.5667525087033042e+01, -1.5113995384194148e+01, -1.4657895814201638e+01, -1.4252540997590891e+01, -1.3880097943698006e+01, -1.3531378400872688e+01, -1.3200872037437804e+01, -1.2884949200661589e+01, -1.2581060484489544e+01, -1.2287329276732219e+01, -1.2002323839142806e+01, -1.1724920501080165e+01, -1.1454216910571811e+01, -1.1189474551468571e+01, -1.0930079251827893e+01, -1.0675513220130126e+01, -1.0425334729531320e+01, -1.0179163028964693e+01, -9.9366669190764370e+00, -9.6975559558409401e+00, -9.4615735756363968e+00, -9.2284916500953180e+00, -8.9981061215741249e+00, -8.7702334668725097e+00, -8.5447078038596302e+00, -8.3213785029101519e+00, -8.1001081988952368e+00, -7.8807711240717229e+00, -7.6632517003331104e+00, -7.4474433427993905e+00, -7.2332474369156490e+00, -7.0205724589985739e+00, -6.8093332161497848e+00, -6.5994501860991619e+00, -6.3908489411790317e+00, -6.1834596435017497e+00, -5.9772166006971021e+00, -5.7720578733949548e+00, -5.5679249271127809e+00, -5.3647623224033971e+00, -5.1625174380934791e+00, -4.9611402232433406e+00, -4.7605829741178525e+00, -4.5608001330046735e+00, -4.3617481061705252e+00, -4.1633850986262280e+00, -3.9656709636900676e+00, -3.7685670656076877e+00, -3.5720361537138379e+00, -3.3760422468139430e+00, -3.1805505266274205e+00, -2.9855272392745684e+00, -2.7909396039085173e+00, -2.5967557276963822e+00, -2.4029445264418832e+00, -2.2094756502175628e+00, -2.0163194134400269e+00, -1.8234467288779213e+00, -1.6308290451307998e+00, -1.4384382871587706e+00, -1.2462467994785644e+00, -1.0542272916723083e+00, -8.6235278588129705e-01, -6.7059656597901129e-01, -4.7893212813590247e-01, -2.8733313250340886e-01, -9.5773355756546857e-02, 9.5773355756546857e-02, 2.8733313250340886e-01, 4.7893212813590247e-01, 6.7059656597901129e-01, 8.6235278588129705e-01, 1.0542272916723083e+00, 1.2462467994785644e+00, 1.4384382871587706e+00, 1.6308290451307998e+00, 1.8234467288779213e+00, 2.0163194134400269e+00, 2.2094756502175628e+00, 2.4029445264418832e+00, 2.5967557276963822e+00, 2.7909396039085173e+00, 2.9855272392745684e+00, 3.1805505266274205e+00, 3.3760422468139430e+00, 3.5720361537138379e+00, 3.7685670656076877e+00, 3.9656709636900676e+00, 4.1633850986262280e+00, 4.3617481061705252e+00, 4.5608001330046735e+00, 4.7605829741178525e+00, 4.9611402232433406e+00, 5.1625174380934791e+00, 5.3647623224033971e+00, 5.5679249271127809e+00, 5.7720578733949548e+00, 5.9772166006971021e+00, 6.1834596435017497e+00, 6.3908489411790317e+00, 6.5994501860991619e+00, 6.8093332161497848e+00, 7.0205724589985739e+00, 7.2332474369156490e+00, 7.4474433427993905e+00, 7.6632517003331104e+00, 7.8807711240717229e+00, 8.1001081988952368e+00, 8.3213785029101519e+00, 8.5447078038596302e+00, 8.7702334668725097e+00, 8.9981061215741249e+00, 9.2284916500953180e+00, 9.4615735756363968e+00, 9.6975559558409401e+00, 9.9366669190764370e+00, 1.0179163028964693e+01, 1.0425334729531320e+01, 1.0675513220130126e+01, 1.0930079251827893e+01, 1.1189474551468571e+01, 1.1454216910571811e+01, 1.1724920501080165e+01, 1.2002323839142806e+01, 1.2287329276732219e+01, 1.2581060484489544e+01, 1.2884949200661589e+01, 1.3200872037437804e+01, 1.3531378400872688e+01, 1.3880097943698006e+01, 1.4252540997590891e+01, 1.4657895814201638e+01, 1.5113995384194148e+01, 1.5667525087033042e+01}, + {-1.5729304882383959e+01, -1.5176493096610994e+01, -1.4721000346526051e+01, -1.4316196868450396e+01, -1.3944270716194302e+01, -1.3596044402569063e+01, -1.3266014016557564e+01, -1.2950554119200040e+01, -1.2647118258490758e+01, -1.2353831996553668e+01, -1.2069265257081389e+01, -1.1792295678839055e+01, -1.1522021967701262e+01, -1.1257706480479557e+01, -1.0998735778960949e+01, -1.0744592698355470e+01, -1.0494836054902457e+01, -1.0249085574277188e+01, -1.0007010480604432e+01, -9.7683207101299594e+00, -9.5327600441503151e+00, -9.3001006700843707e+00, -9.0701388219340853e+00, -8.8426912480559938e+00, -8.6175923211137029e+00, -8.3946916522729023e+00, -8.1738521055035420e+00, -7.9549481324236444e+00, -7.7378643662186803e+00, -7.5224944266685263e+00, -7.3087398984951246e+00, -7.0965094530044173e+00, -6.8857180889690319e+00, -6.6762864733372753e+00, -6.4681403659874999e+00, -6.2612101156154036e+00, -6.0554302161231597e+00, -5.8507389147062092e+00, -5.6470778643062038e+00, -5.4443918142929100e+00, -5.2426283342121209e+00, -5.0417375662357022e+00, -4.8416720026085907e+00, -4.6423862849333188e+00, -4.4438370225867869e+00, -4.2459826279436079e+00, -4.0487831663989748e+00, -3.8522002194524045e+00, -3.6561967593406961e+00, -3.4607370339009882e+00, -3.2657864605087177e+00, -3.0713115280751384e+00, -2.8772797062087854e+00, -2.6836593607479262e+00, -2.4904196749593304e+00, -2.2975305757745934e+00, -2.1049626645007851e+00, -1.9126871514986146e+00, -1.7206757943700177e+00, -1.5289008392390442e+00, -1.3373349647460135e+00, -1.1459512284058875e+00, -9.5472301500823675e-01, -7.6362398675858623e-01, -5.7262803487972669e-01, -3.8170923240711668e-01, -1.9084178792504236e-01, -0.0000000000000000e+00, 1.9084178792504236e-01, 3.8170923240711668e-01, 5.7262803487972669e-01, 7.6362398675858623e-01, 9.5472301500823675e-01, 1.1459512284058875e+00, 1.3373349647460135e+00, 1.5289008392390442e+00, 1.7206757943700177e+00, 1.9126871514986146e+00, 2.1049626645007851e+00, 2.2975305757745934e+00, 2.4904196749593304e+00, 2.6836593607479262e+00, 2.8772797062087854e+00, 3.0713115280751384e+00, 3.2657864605087177e+00, 3.4607370339009882e+00, 3.6561967593406961e+00, 3.8522002194524045e+00, 4.0487831663989748e+00, 4.2459826279436079e+00, 4.4438370225867869e+00, 4.6423862849333188e+00, 4.8416720026085907e+00, 5.0417375662357022e+00, 5.2426283342121209e+00, 5.4443918142929100e+00, 5.6470778643062038e+00, 5.8507389147062092e+00, 6.0554302161231597e+00, 6.2612101156154036e+00, 6.4681403659874999e+00, 6.6762864733372753e+00, 6.8857180889690319e+00, 7.0965094530044173e+00, 7.3087398984951246e+00, 7.5224944266685263e+00, 7.7378643662186803e+00, 7.9549481324236444e+00, 8.1738521055035420e+00, 8.3946916522729023e+00, 8.6175923211137029e+00, 8.8426912480559938e+00, 9.0701388219340853e+00, 9.3001006700843707e+00, 9.5327600441503151e+00, 9.7683207101299594e+00, 1.0007010480604432e+01, 1.0249085574277188e+01, 1.0494836054902457e+01, 1.0744592698355470e+01, 1.0998735778960949e+01, 1.1257706480479557e+01, 1.1522021967701262e+01, 1.1792295678839055e+01, 1.2069265257081389e+01, 1.2353831996553668e+01, 1.2647118258490758e+01, 1.2950554119200040e+01, 1.3266014016557564e+01, 1.3596044402569063e+01, 1.3944270716194302e+01, 1.4316196868450396e+01, 1.4721000346526051e+01, 1.5176493096610994e+01, 1.5729304882383959e+01}, + {-1.5790852517134587e+01, -1.5238752270283085e+01, -1.4783860849603613e+01, -1.4379603641698345e+01, -1.4008189569512616e+01, -1.3660451820769911e+01, -1.3330892851617801e+01, -1.3015891401590464e+01, -1.2712903947791023e+01, -1.2420058208074661e+01, -1.2135925753638015e+01, -1.1859385521045176e+01, -1.1589537264407285e+01, -1.1325644205334678e+01, -1.1067093632255466e+01, -1.0813369000829548e+01, -1.0564029664716180e+01, -1.0318695821142974e+01, -1.0077037112888743e+01, -9.8387638519273803e+00, -9.6036201601455531e+00, -9.3713785365821725e+00, -9.1418355028369902e+00, -8.9148080748582679e+00, -8.6901308761912386e+00, -8.4676537549061486e+00, -8.2472398001890390e+00, -8.0287636791201553e+00, -7.8121102322437741e+00, -7.5971732800158449e+00, -7.3838546023854859e+00, -7.1720630615179752e+00, -6.9617138436331016e+00, -6.7527278005665341e+00, -6.5450308752913493e+00, -6.3385535985021413e+00, -6.1332306456429340e+00, -5.9290004455850367e+00, -5.7258048336320568e+00, -5.5235887427222501e+00, -5.3222999276716845e+00, -5.1218887180998118e+00, -4.9223077963371686e+00, -4.7235119971600676e+00, -4.5254581266508760e+00, -4.3281047978617426e+00, -4.1314122812779592e+00, -3.9353423683453870e+00, -3.7398582465531405e+00, -3.5449243847552383e+00, -3.3505064275787246e+00, -3.1565710979056170e+00, -2.9630861065357892e+00, -2.7700200682405702e+00, -2.5773424235052076e+00, -2.3850233653343853e+00, -2.1930337705606084e+00, -2.0013451351519014e+00, -1.8099295130641593e+00, -1.6187594582257014e+00, -1.4278079692779639e+00, -1.2370484367275345e+00, -1.0464545921915449e+00, -8.5600045944125114e-01, -6.6566030696788747e-01, -4.7540860181095812e-01, -2.8521996440226244e-01, -9.5069124189415724e-02, 9.5069124189415724e-02, 2.8521996440226244e-01, 4.7540860181095812e-01, 6.6566030696788747e-01, 8.5600045944125114e-01, 1.0464545921915449e+00, 1.2370484367275345e+00, 1.4278079692779639e+00, 1.6187594582257014e+00, 1.8099295130641593e+00, 2.0013451351519014e+00, 2.1930337705606084e+00, 2.3850233653343853e+00, 2.5773424235052076e+00, 2.7700200682405702e+00, 2.9630861065357892e+00, 3.1565710979056170e+00, 3.3505064275787246e+00, 3.5449243847552383e+00, 3.7398582465531405e+00, 3.9353423683453870e+00, 4.1314122812779592e+00, 4.3281047978617426e+00, 4.5254581266508760e+00, 4.7235119971600676e+00, 4.9223077963371686e+00, 5.1218887180998118e+00, 5.3222999276716845e+00, 5.5235887427222501e+00, 5.7258048336320568e+00, 5.9290004455850367e+00, 6.1332306456429340e+00, 6.3385535985021413e+00, 6.5450308752913493e+00, 6.7527278005665341e+00, 6.9617138436331016e+00, 7.1720630615179752e+00, 7.3838546023854859e+00, 7.5971732800158449e+00, 7.8121102322437741e+00, 8.0287636791201553e+00, 8.2472398001890390e+00, 8.4676537549061486e+00, 8.6901308761912386e+00, 8.9148080748582679e+00, 9.1418355028369902e+00, 9.3713785365821725e+00, 9.6036201601455531e+00, 9.8387638519273803e+00, 1.0077037112888743e+01, 1.0318695821142974e+01, 1.0564029664716180e+01, 1.0813369000829548e+01, 1.1067093632255466e+01, 1.1325644205334678e+01, 1.1589537264407285e+01, 1.1859385521045176e+01, 1.2135925753638015e+01, 1.2420058208074661e+01, 1.2712903947791023e+01, 1.3015891401590464e+01, 1.3330892851617801e+01, 1.3660451820769911e+01, 1.4008189569512616e+01, 1.4379603641698345e+01, 1.4783860849603613e+01, 1.5238752270283085e+01, 1.5790852517134587e+01}, + {-1.5852170577958367e+01, -1.5300775595780827e+01, -1.4846480104844703e+01, -1.4442764183748782e+01, -1.4071857451951351e+01, -1.3724603683931077e+01, -1.3395511650343654e+01, -1.3080964234499790e+01, -1.2778420818075578e+01, -1.2486011256383852e+01, -1.2202308753936913e+01, -1.1926193533696322e+01, -1.1656766388576511e+01, -1.1393291396981837e+01, -1.1135156567035956e+01, -1.0881845968701494e+01, -1.0632919487519736e+01, -1.0387997787201458e+01, -1.0146750924472403e+01, -9.9088895826069283e+00, -9.6741582198685645e+00, -9.4423296428652392e+00, -9.2132006568631315e+00, -8.9865885415552977e+00, -8.7623281675764328e+00, -8.5402696161385645e+00, -8.3202761978883633e+00, -8.1022227916007061e+00, -7.8859944413814738e+00, -7.6714851645199493e+00, -7.4585969322894226e+00, -7.2472387937374041e+00, -7.0373261184664502e+00, -6.8287799390351633e+00, -6.6215263772344395e+00, -6.4154961413560549e+00, -6.2106240838470441e+00, -6.0068488105662023e+00, -5.8041123343284946e+00, -5.6023597666149243e+00, -5.4015390422975438e+00, -5.2016006730266913e+00, -5.0024975255849276e+00, -4.8041846220567344e+00, -4.6066189591163766e+00, -4.4097593441152032e+00, -4.2135662459677485e+00, -4.0180016591039696e+00, -3.8230289789816339e+00, -3.6286128878452084e+00, -3.4347192495813528e+00, -3.2413150126609418e+00, -3.0483681202772592e+00, -2.8558474268927547e+00, -2.6637226204951387e+00, -2.4719641499397405e+00, -2.2805431568207979e+00, -2.0894314113711125e+00, -1.8986012519385917e+00, -1.7080255276306118e+00, -1.5176775437537562e+00, -1.3275310097080575e+00, -1.1375599890219745e+00, -9.4773885123753698e-01, -7.5804222537475319e-01, -5.6844495472091694e-01, -3.7892205270411800e-01, -1.8944865962132065e-01, -0.0000000000000000e+00, 1.8944865962132065e-01, 3.7892205270411800e-01, 5.6844495472091694e-01, 7.5804222537475319e-01, 9.4773885123753698e-01, 1.1375599890219745e+00, 1.3275310097080575e+00, 1.5176775437537562e+00, 1.7080255276306118e+00, 1.8986012519385917e+00, 2.0894314113711125e+00, 2.2805431568207979e+00, 2.4719641499397405e+00, 2.6637226204951387e+00, 2.8558474268927547e+00, 3.0483681202772592e+00, 3.2413150126609418e+00, 3.4347192495813528e+00, 3.6286128878452084e+00, 3.8230289789816339e+00, 4.0180016591039696e+00, 4.2135662459677485e+00, 4.4097593441152032e+00, 4.6066189591163766e+00, 4.8041846220567344e+00, 5.0024975255849276e+00, 5.2016006730266913e+00, 5.4015390422975438e+00, 5.6023597666149243e+00, 5.8041123343284946e+00, 6.0068488105662023e+00, 6.2106240838470441e+00, 6.4154961413560549e+00, 6.6215263772344395e+00, 6.8287799390351633e+00, 7.0373261184664502e+00, 7.2472387937374041e+00, 7.4585969322894226e+00, 7.6714851645199493e+00, 7.8859944413814738e+00, 8.1022227916007061e+00, 8.3202761978883633e+00, 8.5402696161385645e+00, 8.7623281675764328e+00, 8.9865885415552977e+00, 9.2132006568631315e+00, 9.4423296428652392e+00, 9.6741582198685645e+00, 9.9088895826069283e+00, 1.0146750924472403e+01, 1.0387997787201458e+01, 1.0632919487519736e+01, 1.0881845968701494e+01, 1.1135156567035956e+01, 1.1393291396981837e+01, 1.1656766388576511e+01, 1.1926193533696322e+01, 1.2202308753936913e+01, 1.2486011256383852e+01, 1.2778420818075578e+01, 1.3080964234499790e+01, 1.3395511650343654e+01, 1.3724603683931077e+01, 1.4071857451951351e+01, 1.4442764183748782e+01, 1.4846480104844703e+01, 1.5300775595780827e+01, 1.5852170577958367e+01}, + {-1.5913261603942480e+01, -1.5362565713640512e+01, -1.4908860841455180e+01, -1.4505681306755122e+01, -1.4135277255544954e+01, -1.3788502962262141e+01, -1.3459873460233181e+01, -1.3145775742375259e+01, -1.2843672070795714e+01, -1.2551694420292197e+01, -1.2268417614744900e+01, -1.1992723152311497e+01, -1.1723712855448614e+01, -1.1460651651502332e+01, -1.1202928261484638e+01, -1.0950027363642045e+01, -1.0701509369981165e+01, -1.0456995405743042e+01, -1.0216155937006269e+01, -9.9787020140292348e+00, -9.7443784273495506e+00, -9.5129582872037410e+00, -9.2842386787046287e+00, -9.0580371415563476e+00, -8.8341887898063280e+00, -8.6125439341638330e+00, -8.3929661031022729e+00, -8.1753303834489426e+00, -7.9595220192037859e+00, -7.7454352207811352e+00, -7.5329721470151476e+00, -7.3220420300038924e+00, -7.1125604188199452e+00, -6.9044485227388090e+00, -6.6976326382579296e+00, -6.4920436470380141e+00, -6.2876165741721222e+00, -6.0842901980089970e+00, -5.8820067042248958e+00, -5.6807113780286782e+00, -5.4803523293560428e+00, -5.2808802467053466e+00, -5.0822481759241382e+00, -4.8844113207996323e+00, -4.6873268627591953e+00, -4.4909537973654823e+00, -4.2952527856086178e+00, -4.1001860182656378e+00, -3.9057170918238593e+00, -3.7118108946570874e+00, -3.5184335023072513e+00, -3.3255520808638139e+00, -3.1331347975530193e+00, -2.9411507377518000e+00, -2.7495698277296028e+00, -2.5583627624976102e+00, -2.3675009382106698e+00, -2.1769563886241587e+00, -1.9867017251572272e+00, -1.7967100801564784e+00, -1.6069550529909824e+00, -1.4174106586413215e+00, -1.2280512784727862e+00, -1.0388516129063341e+00, -8.4978663572097946e-01, -6.6083154973822611e-01, -4.7196174365329491e-01, -2.8315274978949312e-01, -9.4380202561292328e-02, 9.4380202561292328e-02, 2.8315274978949312e-01, 4.7196174365329491e-01, 6.6083154973822611e-01, 8.4978663572097946e-01, 1.0388516129063341e+00, 1.2280512784727862e+00, 1.4174106586413215e+00, 1.6069550529909824e+00, 1.7967100801564784e+00, 1.9867017251572272e+00, 2.1769563886241587e+00, 2.3675009382106698e+00, 2.5583627624976102e+00, 2.7495698277296028e+00, 2.9411507377518000e+00, 3.1331347975530193e+00, 3.3255520808638139e+00, 3.5184335023072513e+00, 3.7118108946570874e+00, 3.9057170918238593e+00, 4.1001860182656378e+00, 4.2952527856086178e+00, 4.4909537973654823e+00, 4.6873268627591953e+00, 4.8844113207996323e+00, 5.0822481759241382e+00, 5.2808802467053466e+00, 5.4803523293560428e+00, 5.6807113780286782e+00, 5.8820067042248958e+00, 6.0842901980089970e+00, 6.2876165741721222e+00, 6.4920436470380141e+00, 6.6976326382579296e+00, 6.9044485227388090e+00, 7.1125604188199452e+00, 7.3220420300038924e+00, 7.5329721470151476e+00, 7.7454352207811352e+00, 7.9595220192037859e+00, 8.1753303834489426e+00, 8.3929661031022729e+00, 8.6125439341638330e+00, 8.8341887898063280e+00, 9.0580371415563476e+00, 9.2842386787046287e+00, 9.5129582872037410e+00, 9.7443784273495506e+00, 9.9787020140292348e+00, 1.0216155937006269e+01, 1.0456995405743042e+01, 1.0701509369981165e+01, 1.0950027363642045e+01, 1.1202928261484638e+01, 1.1460651651502332e+01, 1.1723712855448614e+01, 1.1992723152311497e+01, 1.2268417614744900e+01, 1.2551694420292197e+01, 1.2843672070795714e+01, 1.3145775742375259e+01, 1.3459873460233181e+01, 1.3788502962262141e+01, 1.4135277255544954e+01, 1.4505681306755122e+01, 1.4908860841455180e+01, 1.5362565713640512e+01, 1.5913261603942480e+01}, + {-1.5974128087803059e+01, -1.5424125215654696e+01, -1.4971005737794270e+01, -1.4568357770032772e+01, -1.4198451817550286e+01, -1.3852152569276431e+01, -1.3523981270171619e+01, -1.3210328989123949e+01, -1.2908660844914866e+01, -1.2617110914147242e+01, -1.2334255626355663e+01, -1.2058977743887230e+01, -1.1790380109646946e+01, -1.1527728492218195e+01, -1.1270412318828130e+01, -1.1017916870112439e+01, -1.0769803079243415e+01, -1.0525692528151630e+01, -1.0285256087783404e+01, -1.0048205171171734e+01, -9.8142848971316887e+00, -9.5832686756941996e+00, -9.3549538681059694e+00, -9.1291582704569425e+00, -8.9057172366410864e+00, -8.6844813033334454e+00, -8.4653142133164536e+00, -8.2480912579473227e+00, -8.0326978775762718e+00, -7.8190284721625867e+00, -7.6069853844711011e+00, -7.3964780259572480e+00, -7.1874221213951852e+00, -6.9797390529218948e+00, -6.7733552877875338e+00, -6.5682018769582182e+00, -6.3642140139886543e+00, -6.1613306454010424e+00, -5.9594941252729363e+00, -5.7586499079259337e+00, -5.5587462735771860e+00, -5.3597340826114390e+00, -5.1615665547873322e+00, -4.9641990702352388e+00, -4.7675889895563337e+00, -4.5716954907107725e+00, -4.3764794207003801e+00, -4.1819031603187895e+00, -3.9879305004682921e+00, -3.7945265287347798e+00, -3.6016575250757095e+00, -3.4092908656157688e+00, -3.2173949336645937e+00, -3.0259390371736554e+00, -2.8348933319378968e+00, -2.6442287499240060e+00, -2.4539169321730845e+00, -2.2639301657825421e+00, -2.0742413245213673e+00, -1.8848238126757204e+00, -1.6956515117588089e+00, -1.5066987297510446e+00, -1.3179401525641421e+00, -1.1293507974466097e+00, -9.4090596806846227e-01, -7.5258121104029896e-01, -5.6435227363645946e-01, -3.7619506250401802e-01, -1.8808560314914807e-01, -0.0000000000000000e+00, 1.8808560314914807e-01, 3.7619506250401802e-01, 5.6435227363645946e-01, 7.5258121104029896e-01, 9.4090596806846227e-01, 1.1293507974466097e+00, 1.3179401525641421e+00, 1.5066987297510446e+00, 1.6956515117588089e+00, 1.8848238126757204e+00, 2.0742413245213673e+00, 2.2639301657825421e+00, 2.4539169321730845e+00, 2.6442287499240060e+00, 2.8348933319378968e+00, 3.0259390371736554e+00, 3.2173949336645937e+00, 3.4092908656157688e+00, 3.6016575250757095e+00, 3.7945265287347798e+00, 3.9879305004682921e+00, 4.1819031603187895e+00, 4.3764794207003801e+00, 4.5716954907107725e+00, 4.7675889895563337e+00, 4.9641990702352388e+00, 5.1615665547873322e+00, 5.3597340826114390e+00, 5.5587462735771860e+00, 5.7586499079259337e+00, 5.9594941252729363e+00, 6.1613306454010424e+00, 6.3642140139886543e+00, 6.5682018769582182e+00, 6.7733552877875338e+00, 6.9797390529218948e+00, 7.1874221213951852e+00, 7.3964780259572480e+00, 7.6069853844711011e+00, 7.8190284721625867e+00, 8.0326978775762718e+00, 8.2480912579473227e+00, 8.4653142133164536e+00, 8.6844813033334454e+00, 8.9057172366410864e+00, 9.1291582704569425e+00, 9.3549538681059694e+00, 9.5832686756941996e+00, 9.8142848971316887e+00, 1.0048205171171734e+01, 1.0285256087783404e+01, 1.0525692528151630e+01, 1.0769803079243415e+01, 1.1017916870112439e+01, 1.1270412318828130e+01, 1.1527728492218195e+01, 1.1790380109646946e+01, 1.2058977743887230e+01, 1.2334255626355663e+01, 1.2617110914147242e+01, 1.2908660844914866e+01, 1.3210328989123949e+01, 1.3523981270171619e+01, 1.3852152569276431e+01, 1.4198451817550286e+01, 1.4568357770032772e+01, 1.4971005737794270e+01, 1.5424125215654696e+01, 1.5974128087803059e+01}, + {-1.6034772477060816e+01, -1.5485456646120181e+01, -1.5032917422687504e+01, -1.4630796281434252e+01, -1.4261383921882931e+01, -1.3915555363288536e+01, -1.3587838011990620e+01, -1.3274626979734647e+01, -1.2973390218594389e+01, -1.2682263889584272e+01, -1.2399826014408026e+01, -1.2124960608784908e+01, -1.1856771527137033e+01, -1.1594525371724179e+01, -1.1337612269445431e+01, -1.1085518097551031e+01, -1.0837804305192460e+01, -1.0594092926257336e+01, -1.0354055232179574e+01, -1.0117402994660386e+01, -9.8838816568977812e+00, -9.6532649249849332e+00, -9.4253504326923299e+00, -9.1999562289744645e+00, -8.9769179041114668e+00, -8.7560862173209468e+00, -8.5373251222877080e+00, -8.3205101114907762e+00, -8.1055268182049698e+00, -7.8922698284767430e+00, -7.6806416654983130e+00, -7.4705519165212015e+00, -7.2619164783901100e+00, -7.0546569023913719e+00, -6.8486998227236997e+00, -6.6439764557516492e+00, -6.4404221594710993e+00, -6.2379760444330401e+00, -6.0365806288366217e+00, -5.8361815316904240e+00, -5.6367271989099255e+00, -5.4381686580140975e+00, -5.2404592977393536e+00, -5.0435546694321367e+00, -4.8474123075333448e+00, -4.6519915668456937e+00, -4.4572534745922692e+00, -4.2631605955419172e+00, -4.0696769087032161e+00, -3.8767676942807565e+00, -3.6843994297509557e+00, -3.4925396940542712e+00, -3.3011570790203533e+00, -3.1102211072454056e+00, -2.9197021557295608e+00, -2.7295713846583514e+00, -2.5398006707783964e+00, -2.3503625448744949e+00, -2.1612301329048256e+00, -1.9723771003938499e+00, -1.7837775997197194e+00, -1.5954062199652144e+00, -1.4072379390291252e+00, -1.2192480777190431e+00, -1.0314122555671925e+00, -8.4370634812858625e-01, -6.5610644553571928e-01, -4.6858881209649367e-01, -2.8112984673230629e-01, -9.3706044061378571e-02, 9.3706044061378571e-02, 2.8112984673230629e-01, 4.6858881209649367e-01, 6.5610644553571928e-01, 8.4370634812858625e-01, 1.0314122555671925e+00, 1.2192480777190431e+00, 1.4072379390291252e+00, 1.5954062199652144e+00, 1.7837775997197194e+00, 1.9723771003938499e+00, 2.1612301329048256e+00, 2.3503625448744949e+00, 2.5398006707783964e+00, 2.7295713846583514e+00, 2.9197021557295608e+00, 3.1102211072454056e+00, 3.3011570790203533e+00, 3.4925396940542712e+00, 3.6843994297509557e+00, 3.8767676942807565e+00, 4.0696769087032161e+00, 4.2631605955419172e+00, 4.4572534745922692e+00, 4.6519915668456937e+00, 4.8474123075333448e+00, 5.0435546694321367e+00, 5.2404592977393536e+00, 5.4381686580140975e+00, 5.6367271989099255e+00, 5.8361815316904240e+00, 6.0365806288366217e+00, 6.2379760444330401e+00, 6.4404221594710993e+00, 6.6439764557516492e+00, 6.8486998227236997e+00, 7.0546569023913719e+00, 7.2619164783901100e+00, 7.4705519165212015e+00, 7.6806416654983130e+00, 7.8922698284767430e+00, 8.1055268182049698e+00, 8.3205101114907762e+00, 8.5373251222877080e+00, 8.7560862173209468e+00, 8.9769179041114668e+00, 9.1999562289744645e+00, 9.4253504326923299e+00, 9.6532649249849332e+00, 9.8838816568977812e+00, 1.0117402994660386e+01, 1.0354055232179574e+01, 1.0594092926257336e+01, 1.0837804305192460e+01, 1.1085518097551031e+01, 1.1337612269445431e+01, 1.1594525371724179e+01, 1.1856771527137033e+01, 1.2124960608784908e+01, 1.2399826014408026e+01, 1.2682263889584272e+01, 1.2973390218594389e+01, 1.3274626979734647e+01, 1.3587838011990620e+01, 1.3915555363288536e+01, 1.4261383921882931e+01, 1.4630796281434252e+01, 1.5032917422687504e+01, 1.5485456646120181e+01, 1.6034772477060816e+01}, + {-1.6095197175178654e+01, -1.5546562503045239e+01, -1.5094598476696428e+01, -1.4692999498678725e+01, -1.4324076300505626e+01, -1.3978714148861499e+01, -1.3651446561974707e+01, -1.3338672661844436e+01, -1.3037863210821454e+01, -1.2747156437216972e+01, -1.2465131941640982e+01, -1.2190674982552025e+01, -1.1922890417116040e+01, -1.1661045673847648e+01, -1.1404531572900545e+01, -1.1152834582481235e+01, -1.0905516662643253e+01, -1.0662200294603309e+01, -1.0422557146004042e+01, -1.0186299343207718e+01, -9.9531726499989794e+00, -9.7229510648991155e+00, -9.4954324906908987e+00, -9.2704352257718199e+00, -9.0477950934492313e+00, -8.8273630721636813e+00, -8.6090033232019607e+00, -8.3925915368661208e+00, -8.1780135360427444e+00, -7.9651640895243876e+00, -7.7539458975483946e+00, -7.5442687197268468e+00, -7.3360486214748111e+00, -7.1292073196522763e+00, -6.9236716117447346e+00, -6.7193728757570428e+00, -6.5162466302615387e+00, -6.3142321458564812e+00, -6.1132721007540169e+00, -5.9133122744035465e+00, -5.7143012740244483e+00, -5.5161902897161745e+00, -5.3189328744684259e+00, -5.1224847459365774e+00, -4.9268036072990391e+00, -4.7318489848907346e+00, -4.5375820806238156e+00, -4.3439656374738016e+00, -4.1509638165353397e+00, -3.9585420843435810e+00, -3.7666671093205584e+00, -3.5753066663455639e+00, -3.3844295485681095e+00, -3.1940054856848250e+00, -3.0040050679901400e+00, -2.8143996755869578e+00, -2.6251614122095890e+00, -2.4362630431683869e+00, -2.2476779369751214e+00, -2.0593800102511661e+00, -1.8713436755579074e+00, -1.6835437918212028e+00, -1.4959556170497912e+00, -1.3085547630718375e+00, -1.1213171520347327e+00, -9.3421897443120272e-01, -7.4723664843005233e-01, -5.6034678030272367e-01, -3.7352612574750421e-01, -1.8675155192184525e-01, -0.0000000000000000e+00, 1.8675155192184525e-01, 3.7352612574750421e-01, 5.6034678030272367e-01, 7.4723664843005233e-01, 9.3421897443120272e-01, 1.1213171520347327e+00, 1.3085547630718375e+00, 1.4959556170497912e+00, 1.6835437918212028e+00, 1.8713436755579074e+00, 2.0593800102511661e+00, 2.2476779369751214e+00, 2.4362630431683869e+00, 2.6251614122095890e+00, 2.8143996755869578e+00, 3.0040050679901400e+00, 3.1940054856848250e+00, 3.3844295485681095e+00, 3.5753066663455639e+00, 3.7666671093205584e+00, 3.9585420843435810e+00, 4.1509638165353397e+00, 4.3439656374738016e+00, 4.5375820806238156e+00, 4.7318489848907346e+00, 4.9268036072990391e+00, 5.1224847459365774e+00, 5.3189328744684259e+00, 5.5161902897161745e+00, 5.7143012740244483e+00, 5.9133122744035465e+00, 6.1132721007540169e+00, 6.3142321458564812e+00, 6.5162466302615387e+00, 6.7193728757570428e+00, 6.9236716117447346e+00, 7.1292073196522763e+00, 7.3360486214748111e+00, 7.5442687197268468e+00, 7.7539458975483946e+00, 7.9651640895243876e+00, 8.1780135360427444e+00, 8.3925915368661208e+00, 8.6090033232019607e+00, 8.8273630721636813e+00, 9.0477950934492313e+00, 9.2704352257718199e+00, 9.4954324906908987e+00, 9.7229510648991155e+00, 9.9531726499989794e+00, 1.0186299343207718e+01, 1.0422557146004042e+01, 1.0662200294603309e+01, 1.0905516662643253e+01, 1.1152834582481235e+01, 1.1404531572900545e+01, 1.1661045673847648e+01, 1.1922890417116040e+01, 1.2190674982552025e+01, 1.2465131941640982e+01, 1.2747156437216972e+01, 1.3037863210821454e+01, 1.3338672661844436e+01, 1.3651446561974707e+01, 1.3978714148861499e+01, 1.4324076300505626e+01, 1.4692999498678725e+01, 1.5094598476696428e+01, 1.5546562503045239e+01, 1.6095197175178654e+01}, + {-1.6155404542662776e+01, -1.5607445239317764e+01, -1.5156051433346871e+01, -1.4754970030637802e+01, -1.4386531634770627e+01, -1.4041631678205716e+01, -1.3714809742317117e+01, -1.3402468927252324e+01, -1.3102082782981558e+01, -1.2811791588270133e+01, -1.2530176509588186e+01, -1.2256124037680147e+01, -1.1988740023836153e+01, -1.1727292715539413e+01, -1.1471173619903071e+01, -1.1219869790544209e+01, -1.0972943693447091e+01, -1.0730018252630529e+01, -1.0490765527764685e+01, -1.0254897995961329e+01, -1.0022161737889968e+01, -9.7923310409601427e+00, -9.5652040735500723e+00, -9.3405993801743854e+00, -9.1183530139059350e+00, -8.8983161691878188e+00, -8.6803532117101110e+00, -8.4643400264036650e+00, -8.2501626225617972e+00, -8.0377159484935703e+00, -7.8269028782146863e+00, -7.6176333403821728e+00, -7.4098235656060059e+00, -7.2033954328740331e+00, -6.9982758994323033e+00, -6.7943965013094090e+00, -6.5916929139374751e+00, -6.3901045641355303e+00, -6.1895742861825749e+00, -5.9900480158931027e+00, -5.7914745175749145e+00, -5.5938051395422690e+00, -5.3969935945114758e+00, -5.2009957617479348e+00, -5.0057695082847111e+00, -4.8112745269098740e+00, -4.6174721889364516e+00, -4.4243254100357463e+00, -4.2317985276405068e+00, -4.0398571886161809e+00, -3.8484682460617101e+00, -3.6575996642408795e+00, -3.4672204307647947e+00, -3.2773004752487735e+00, -3.0878105937554641e+00, -2.8987223784123866e+00, -2.7100081516581653e+00, -2.5216409046290269e+00, -2.3335942392467470e+00, -2.1458423136124405e+00, -1.9583597903480086e+00, -1.7711217875596625e+00, -1.5841038321261636e+00, -1.3972818150389417e+00, -1.2106319485423875e+00, -1.0241307248408380e+00, -8.3775487615432709e-01, -6.5148133591837221e-01, -4.6528720093408932e-01, -2.7914969428399067e-01, -9.3046128836030015e-02, 9.3046128836030015e-02, 2.7914969428399067e-01, 4.6528720093408932e-01, 6.5148133591837221e-01, 8.3775487615432709e-01, 1.0241307248408380e+00, 1.2106319485423875e+00, 1.3972818150389417e+00, 1.5841038321261636e+00, 1.7711217875596625e+00, 1.9583597903480086e+00, 2.1458423136124405e+00, 2.3335942392467470e+00, 2.5216409046290269e+00, 2.7100081516581653e+00, 2.8987223784123866e+00, 3.0878105937554641e+00, 3.2773004752487735e+00, 3.4672204307647947e+00, 3.6575996642408795e+00, 3.8484682460617101e+00, 4.0398571886161809e+00, 4.2317985276405068e+00, 4.4243254100357463e+00, 4.6174721889364516e+00, 4.8112745269098740e+00, 5.0057695082847111e+00, 5.2009957617479348e+00, 5.3969935945114758e+00, 5.5938051395422690e+00, 5.7914745175749145e+00, 5.9900480158931027e+00, 6.1895742861825749e+00, 6.3901045641355303e+00, 6.5916929139374751e+00, 6.7943965013094090e+00, 6.9982758994323033e+00, 7.2033954328740331e+00, 7.4098235656060059e+00, 7.6176333403821728e+00, 7.8269028782146863e+00, 8.0377159484935703e+00, 8.2501626225617972e+00, 8.4643400264036650e+00, 8.6803532117101110e+00, 8.8983161691878188e+00, 9.1183530139059350e+00, 9.3405993801743854e+00, 9.5652040735500723e+00, 9.7923310409601427e+00, 1.0022161737889968e+01, 1.0254897995961329e+01, 1.0490765527764685e+01, 1.0730018252630529e+01, 1.0972943693447091e+01, 1.1219869790544209e+01, 1.1471173619903071e+01, 1.1727292715539413e+01, 1.1988740023836153e+01, 1.2256124037680147e+01, 1.2530176509588186e+01, 1.2811791588270133e+01, 1.3102082782981558e+01, 1.3402468927252324e+01, 1.3714809742317117e+01, 1.4041631678205716e+01, 1.4386531634770627e+01, 1.4754970030637802e+01, 1.5156051433346871e+01, 1.5607445239317764e+01, 1.6155404542662776e+01}, + {-1.6215396898128663e+01, -1.5668107263835802e+01, -1.5217278780317361e+01, -1.4816710438579342e+01, -1.4448752556717958e+01, -1.4104310652531494e+01, -1.3777930322527094e+01, -1.3466018613382040e+01, -1.3166051840377859e+01, -1.2876172316156813e+01, -1.2594962760214381e+01, -1.2321310885302282e+01, -1.2054323528364668e+01, -1.1793269748698537e+01, -1.1537541734199792e+01, -1.1286627118459547e+01, -1.1040088868523824e+01, -1.0797550346784112e+01, -1.0558684000851162e+01, -1.0323202654766870e+01, -1.0090852702474850e+01, -9.8614087168236804e+00, -9.6346691284611641e+00, -9.4104527247850562e+00, -9.1885957854652229e+00, -8.9689497178220225e+00, -8.7513790888474610e+00, -8.5357599750069966e+00, -8.3219785688987216e+00, -8.1099299952250909e+00, -7.8995172986236630e+00, -7.6906505735952022e+00, -7.4832462126880364e+00, -7.2772262536958907e+00, -7.0725178102281943e+00, -6.8690525728554430e+00, -6.6667663702937121e+00, -6.4655987819036467e+00, -6.2654927942392939e+00, -6.0663944955663265e+00, -5.8682528032352996e+00, -5.6710192195879507e+00, -5.4746476127280044e+00, -5.2790940190292117e+00, -5.0843164647041039e+00, -4.8902748041336244e+00, -4.6969305729742112e+00, -4.5042468543255083e+00, -4.3121881564674842e+00, -4.1207203008672968e+00, -3.9298103193193850e+00, -3.7394263592217327e+00, -3.5495375961107607e+00, -3.3601141526799938e+00, -3.1711270235961577e+00, -2.9825480055027773e+00, -2.7943496316674543e+00, -2.6065051107863355e+00, -2.4189882695090272e+00, -2.2317734982904458e+00, -2.0448357002136932e+00, -1.8581502424607397e+00, -1.6716929101361060e+00, -1.4854398621734262e+00, -1.2993675890761167e+00, -1.1134528722618340e+00, -9.2767274479622841e-01, -7.4200445331498865e-01, -5.5642542094454162e-01, -3.7091321104119962e-01, -1.8544549157619233e-01, -0.0000000000000000e+00, 1.8544549157619233e-01, 3.7091321104119962e-01, 5.5642542094454162e-01, 7.4200445331498865e-01, 9.2767274479622841e-01, 1.1134528722618340e+00, 1.2993675890761167e+00, 1.4854398621734262e+00, 1.6716929101361060e+00, 1.8581502424607397e+00, 2.0448357002136932e+00, 2.2317734982904458e+00, 2.4189882695090272e+00, 2.6065051107863355e+00, 2.7943496316674543e+00, 2.9825480055027773e+00, 3.1711270235961577e+00, 3.3601141526799938e+00, 3.5495375961107607e+00, 3.7394263592217327e+00, 3.9298103193193850e+00, 4.1207203008672968e+00, 4.3121881564674842e+00, 4.5042468543255083e+00, 4.6969305729742112e+00, 4.8902748041336244e+00, 5.0843164647041039e+00, 5.2790940190292117e+00, 5.4746476127280044e+00, 5.6710192195879507e+00, 5.8682528032352996e+00, 6.0663944955663265e+00, 6.2654927942392939e+00, 6.4655987819036467e+00, 6.6667663702937121e+00, 6.8690525728554430e+00, 7.0725178102281943e+00, 7.2772262536958907e+00, 7.4832462126880364e+00, 7.6906505735952022e+00, 7.8995172986236630e+00, 8.1099299952250909e+00, 8.3219785688987216e+00, 8.5357599750069966e+00, 8.7513790888474610e+00, 8.9689497178220225e+00, 9.1885957854652229e+00, 9.4104527247850562e+00, 9.6346691284611641e+00, 9.8614087168236804e+00, 1.0090852702474850e+01, 1.0323202654766870e+01, 1.0558684000851162e+01, 1.0797550346784112e+01, 1.1040088868523824e+01, 1.1286627118459547e+01, 1.1537541734199792e+01, 1.1793269748698537e+01, 1.2054323528364668e+01, 1.2321310885302282e+01, 1.2594962760214381e+01, 1.2876172316156813e+01, 1.3166051840377859e+01, 1.3466018613382040e+01, 1.3777930322527094e+01, 1.4104310652531494e+01, 1.4448752556717958e+01, 1.4816710438579342e+01, 1.5217278780317361e+01, 1.5668107263835802e+01, 1.6215396898128663e+01}, + {-1.6275176519333314e+01, -1.5728550942602004e+01, -1.5278282960589307e+01, -1.4878223237370916e+01, -1.4510741650331246e+01, -1.4166753723357122e+01, -1.3840811020790602e+01, -1.3529324504696065e+01, -1.3229773233699543e+01, -1.2940301538002238e+01, -1.2659493677496206e+01, -1.2386238576832154e+01, -1.2119644050283457e+01, -1.1858979961933818e+01, -1.1603639174400232e+01, -1.1353109895917042e+01, -1.1106955589822139e+01, -1.0864800052544570e+01, -1.0626316115639773e+01, -1.0391216946349248e+01, -1.0159249248367633e+01, -9.9301878766205718e+00, -9.7038315207870216e+00, -9.4799992080020576e+00, -9.2585274414535341e+00, -9.0392678383049354e+00, -8.8220851638421109e+00, -8.6068556830666605e+00, -8.3934657688780785e+00, -8.1818107193508762e+00, -7.9717937466932813e+00, -7.7633251081577797e+00, -7.5563213550879356e+00, -7.3507046808793666e+00, -7.1464023522306821e+00, -6.9433462109007360e+00, -6.7414722354477217e+00, -6.5407201542348838e+00, -6.3410331024462083e+00, -6.1423573170383490e+00, -5.9446418645201566e+00, -5.7478383972427567e+00, -5.5519009345358734e+00, -5.3567856655668686e+00, -5.1624507712492340e+00, -4.9688562629036443e+00, -4.7759638356907441e+00, -4.5837367351012581e+00, -4.3921396350144111e+00, -4.2011385260270222e+00, -4.0107006129187415e+00, -3.8207942202581950e+00, -3.6313887052743148e+00, -3.4424543772197556e+00, -3.2539624225418282e+00, -3.0658848352527657e+00, -2.8781943519573039e+00, -2.6908643910529264e+00, -2.5038689956679221e+00, -2.3171827799457509e+00, -2.1307808783218642e+00, -1.9446388974719979e+00, -1.7587328706394580e+00, -1.5730392140737939e+00, -1.3875346853347825e+00, -1.2021963432343084e+00, -1.0170015092047828e+00, -8.3192772989651476e-01, -6.4695274081809961e-01, -4.6205443084366904e-01, -2.7721080741886533e-01, -9.2399962303806829e-02, 9.2399962303806829e-02, 2.7721080741886533e-01, 4.6205443084366904e-01, 6.4695274081809961e-01, 8.3192772989651476e-01, 1.0170015092047828e+00, 1.2021963432343084e+00, 1.3875346853347825e+00, 1.5730392140737939e+00, 1.7587328706394580e+00, 1.9446388974719979e+00, 2.1307808783218642e+00, 2.3171827799457509e+00, 2.5038689956679221e+00, 2.6908643910529264e+00, 2.8781943519573039e+00, 3.0658848352527657e+00, 3.2539624225418282e+00, 3.4424543772197556e+00, 3.6313887052743148e+00, 3.8207942202581950e+00, 4.0107006129187415e+00, 4.2011385260270222e+00, 4.3921396350144111e+00, 4.5837367351012581e+00, 4.7759638356907441e+00, 4.9688562629036443e+00, 5.1624507712492340e+00, 5.3567856655668686e+00, 5.5519009345358734e+00, 5.7478383972427567e+00, 5.9446418645201566e+00, 6.1423573170383490e+00, 6.3410331024462083e+00, 6.5407201542348838e+00, 6.7414722354477217e+00, 6.9433462109007360e+00, 7.1464023522306821e+00, 7.3507046808793666e+00, 7.5563213550879356e+00, 7.7633251081577797e+00, 7.9717937466932813e+00, 8.1818107193508762e+00, 8.3934657688780785e+00, 8.6068556830666605e+00, 8.8220851638421109e+00, 9.0392678383049354e+00, 9.2585274414535341e+00, 9.4799992080020576e+00, 9.7038315207870216e+00, 9.9301878766205718e+00, 1.0159249248367633e+01, 1.0391216946349248e+01, 1.0626316115639773e+01, 1.0864800052544570e+01, 1.1106955589822139e+01, 1.1353109895917042e+01, 1.1603639174400232e+01, 1.1858979961933818e+01, 1.2119644050283457e+01, 1.2386238576832154e+01, 1.2659493677496206e+01, 1.2940301538002238e+01, 1.3229773233699543e+01, 1.3529324504696065e+01, 1.3840811020790602e+01, 1.4166753723357122e+01, 1.4510741650331246e+01, 1.4878223237370916e+01, 1.5278282960589307e+01, 1.5728550942602004e+01, 1.6275176519333314e+01}, + {-1.6334745644175054e+01, -1.5788778599783345e+01, -1.5339066373560392e+01, -1.4939510896644496e+01, -1.4572501452752805e+01, -1.4228963493774261e+01, -1.3903454505286284e+01, -1.3592389334062910e+01, -1.3293249760441302e+01, -1.3004182116116599e+01, -1.2723772188949674e+01, -1.2450910105547806e+01, -1.2184704649330305e+01, -1.1924426482264677e+01, -1.1669469135738963e+01, -1.1419321387402469e+01, -1.1173547192211004e+01, -1.0931770776387262e+01, -1.0693665351523348e+01, -1.0458944424415622e+01, -1.0227355005071125e+01, -9.9986722272145627e+00, -9.7726950364017036e+00, -9.5492426964438799e+00, -9.3281519310537870e+00, -9.1092745642913098e+00, -8.8924755568174323e+00, -8.6776313592631116e+00, -8.4646285219201989e+00, -8.2533625133112452e+00, -8.0437367102645929e+00, -7.8356615297967140e+00, -7.6290536790115411e+00, -7.4238355038151660e+00, -7.2199344208383769e+00, -7.0172824197970574e+00, -6.8158156257772653e+00, -6.6154739127391755e+00, -6.4162005609911104e+00, -6.2179419525665987e+00, -6.0206472994014675e+00, -5.8242683999987914e+00, -5.6287594209215639e+00, -5.4340766999932706e+00, -5.2401785685362707e+00, -5.0470251903539998e+00, -4.8545784154787137e+00, -4.6628016469727172e+00, -4.4716597192961824e+00, -4.2811187869459504e+00, -4.0911462222326103e+00, -3.9017105212024688e+00, -3.7127812168303533e+00, -3.5243287987118928e+00, -3.3363246385723251e+00, -3.1487409209853521e+00, -2.9615505787617051e+00, -2.7747272325244832e+00, -2.5882451340382215e+00, -2.4020791129020052e+00, -2.2162045262547485e+00, -2.0305972111736730e+00, -1.8452334394757037e+00, -1.6600898746564745e+00, -1.4751435307233549e+00, -1.2903717326977489e+00, -1.1057520785781945e+00, -9.2126240256979075e-01, -7.3688073939740739e-01, -5.5258528953022001e-01, -3.6835438515345242e-01, -1.8416645673001250e-01, -0.0000000000000000e+00, 1.8416645673001250e-01, 3.6835438515345242e-01, 5.5258528953022001e-01, 7.3688073939740739e-01, 9.2126240256979075e-01, 1.1057520785781945e+00, 1.2903717326977489e+00, 1.4751435307233549e+00, 1.6600898746564745e+00, 1.8452334394757037e+00, 2.0305972111736730e+00, 2.2162045262547485e+00, 2.4020791129020052e+00, 2.5882451340382215e+00, 2.7747272325244832e+00, 2.9615505787617051e+00, 3.1487409209853521e+00, 3.3363246385723251e+00, 3.5243287987118928e+00, 3.7127812168303533e+00, 3.9017105212024688e+00, 4.0911462222326103e+00, 4.2811187869459504e+00, 4.4716597192961824e+00, 4.6628016469727172e+00, 4.8545784154787137e+00, 5.0470251903539998e+00, 5.2401785685362707e+00, 5.4340766999932706e+00, 5.6287594209215639e+00, 5.8242683999987914e+00, 6.0206472994014675e+00, 6.2179419525665987e+00, 6.4162005609911104e+00, 6.6154739127391755e+00, 6.8158156257772653e+00, 7.0172824197970574e+00, 7.2199344208383769e+00, 7.4238355038151660e+00, 7.6290536790115411e+00, 7.8356615297967140e+00, 8.0437367102645929e+00, 8.2533625133112452e+00, 8.4646285219201989e+00, 8.6776313592631116e+00, 8.8924755568174323e+00, 9.1092745642913098e+00, 9.3281519310537870e+00, 9.5492426964438799e+00, 9.7726950364017036e+00, 9.9986722272145627e+00, 1.0227355005071125e+01, 1.0458944424415622e+01, 1.0693665351523348e+01, 1.0931770776387262e+01, 1.1173547192211004e+01, 1.1419321387402469e+01, 1.1669469135738963e+01, 1.1924426482264677e+01, 1.2184704649330305e+01, 1.2450910105547806e+01, 1.2723772188949674e+01, 1.3004182116116599e+01, 1.3293249760441302e+01, 1.3592389334062910e+01, 1.3903454505286284e+01, 1.4228963493774261e+01, 1.4572501452752805e+01, 1.4939510896644496e+01, 1.5339066373560392e+01, 1.5788778599783345e+01, 1.6334745644175054e+01}, + {-1.6394106471662131e+01, -1.5848792518737463e+01, -1.5399631376122628e+01, -1.5000575841923927e+01, -1.4634034455459645e+01, -1.4290942519672281e+01, -1.3965863395458523e+01, -1.3655215784079445e+01, -1.3356484166275854e+01, -1.3067816859418864e+01, -1.2787801167106462e+01, -1.2515328408121787e+01, -1.2249508326984577e+01, -1.1989612376763933e+01, -1.1735034751777302e+01, -1.1485264793960161e+01, -1.1239866945305195e+01, -1.0998465857673063e+01, -1.0760735118869476e+01, -1.0526388571683613e+01, -1.0295173529077774e+01, -1.0066865400378582e+01, -9.8412633839451633e+00, -9.6181869772854895e+00, -9.3974731217264083e+00, -9.1789738453613765e+00, -8.9625543013934692e+00, -8.7480911232640413e+00, -8.5354710358385653e+00, -8.3245896752567052e+00, -8.1153505801125796e+00, -7.9076643242985316e+00, -7.7014477677473518e+00, -7.4966234058915848e+00, -7.2931188022489746e+00, -7.0908660913775821e+00, -6.8898015416986063e+00, -6.6898651694904157e+00, -6.4910003968128018e+00, -6.2931537473009849e+00, -6.0962745747319902e+00, -5.9003148200559909e+00, -5.7052287932366612e+00, -5.5109729767842897e+00, -5.3175058483147666e+00, -5.1247877198432272e+00, -4.9327805918366323e+00, -4.7414480203154818e+00, -4.5507549955198634e+00, -4.3606678308461584e+00, -4.1711540609235342e+00, -3.9821823478385219e+00, -3.7937223946353149e+00, -3.6057448653220203e+00, -3.4182213107015205e+00, -3.2311240994220300e+00, -3.0444263537086158e+00, -2.8581018892943821e+00, -2.6721251591199171e+00, -2.4864712004130762e+00, -2.3011155847990197e+00, -2.1160343711234311e+00, -1.9312040607006651e+00, -1.7466015547236411e+00, -1.5622041135941906e+00, -1.3779893179515634e+00, -1.1939350311932622e+00, -1.0100193632965979e+00, -8.2622063576151961e-01, -6.4251734750563116e-01, -4.5888814155095509e-01, -2.7531177234913912e-01, -9.1767073597484664e-02, 9.1767073597484664e-02, 2.7531177234913912e-01, 4.5888814155095509e-01, 6.4251734750563116e-01, 8.2622063576151961e-01, 1.0100193632965979e+00, 1.1939350311932622e+00, 1.3779893179515634e+00, 1.5622041135941906e+00, 1.7466015547236411e+00, 1.9312040607006651e+00, 2.1160343711234311e+00, 2.3011155847990197e+00, 2.4864712004130762e+00, 2.6721251591199171e+00, 2.8581018892943821e+00, 3.0444263537086158e+00, 3.2311240994220300e+00, 3.4182213107015205e+00, 3.6057448653220203e+00, 3.7937223946353149e+00, 3.9821823478385219e+00, 4.1711540609235342e+00, 4.3606678308461584e+00, 4.5507549955198634e+00, 4.7414480203154818e+00, 4.9327805918366323e+00, 5.1247877198432272e+00, 5.3175058483147666e+00, 5.5109729767842897e+00, 5.7052287932366612e+00, 5.9003148200559909e+00, 6.0962745747319902e+00, 6.2931537473009849e+00, 6.4910003968128018e+00, 6.6898651694904157e+00, 6.8898015416986063e+00, 7.0908660913775821e+00, 7.2931188022489746e+00, 7.4966234058915848e+00, 7.7014477677473518e+00, 7.9076643242985316e+00, 8.1153505801125796e+00, 8.3245896752567052e+00, 8.5354710358385653e+00, 8.7480911232640413e+00, 8.9625543013934692e+00, 9.1789738453613765e+00, 9.3974731217264083e+00, 9.6181869772854895e+00, 9.8412633839451633e+00, 1.0066865400378582e+01, 1.0295173529077774e+01, 1.0526388571683613e+01, 1.0760735118869476e+01, 1.0998465857673063e+01, 1.1239866945305195e+01, 1.1485264793960161e+01, 1.1735034751777302e+01, 1.1989612376763933e+01, 1.2249508326984577e+01, 1.2515328408121787e+01, 1.2787801167106462e+01, 1.3067816859418864e+01, 1.3356484166275854e+01, 1.3655215784079445e+01, 1.3965863395458523e+01, 1.4290942519672281e+01, 1.4634034455459645e+01, 1.5000575841923927e+01, 1.5399631376122628e+01, 1.5848792518737463e+01, 1.6394106471662131e+01}, + {-1.6453261162851238e+01, -1.5908594943006905e+01, -1.5459980283706434e+01, -1.5061420455716602e+01, -1.4695343105401838e+01, -1.4352693310923225e+01, -1.4028040263249208e+01, -1.3717806488350135e+01, -1.3419479146381439e+01, -1.3131208524813520e+01, -1.2851583430941135e+01, -1.2579496366100177e+01, -1.2314058027999442e+01, -1.2054540654144855e+01, -1.1800339096046955e+01, -1.1550943254895040e+01, -1.1305918055227691e+01, -1.1064888570473238e+01, -1.0827528760910019e+01, -1.0593552801837916e+01, -1.0362708305895856e+01, -1.0134770954893138e+01, -9.9095401969966606e+00, -9.6868357605097319e+00, -9.4664948015418702e+00, -9.2483695494377951e+00, -9.0323253471918115e+00, -8.8182390083208837e+00, -8.6059974295318415e+00, -8.3954964118396482e+00, -8.1866396528418637e+00, -7.9793378805138149e+00, -7.7735081047843622e+00, -7.5690729677310218e+00, -7.3659601768199030e+00, -7.1641020084474496e+00, -6.9634348712930993e+00, -6.7638989207955804e+00, -6.5654377175196297e+00, -6.3679979233591490e+00, -6.1715290304849564e+00, -5.9759831187344989e+00, -5.7813146377916294e+00, -5.5874802110437694e+00, -5.3944384584526848e+00, -5.2021498361504346e+00, -5.0105764907872219e+00, -4.8196821269235706e+00, -4.6294318859840997e+00, -4.4397922354810584e+00, -4.2507308673785191e+00, -4.0622166046072063e+00, -3.8742193148591682e+00, -3.6867098308940789e+00, -3.4996598766773372e+00, -3.3130419987465562e+00, -3.1268295022692216e+00, -2.9409963913117498e+00, -2.7555173128901118e+00, -2.5703675044157226e+00, -2.3855227441881959e+00, -2.2009593046196674e+00, -2.0166539079042916e+00, -1.8325836838717240e+00, -1.6487261297853975e+00, -1.4650590718655645e+00, -1.2815606283337120e+00, -1.0982091737893589e+00, -9.1498330474263811e-01, -7.3186180613665275e-01, -5.4882361870252716e-01, -3.6584780699750397e-01, -1.8291352798246857e-01, -0.0000000000000000e+00, 1.8291352798246857e-01, 3.6584780699750397e-01, 5.4882361870252716e-01, 7.3186180613665275e-01, 9.1498330474263811e-01, 1.0982091737893589e+00, 1.2815606283337120e+00, 1.4650590718655645e+00, 1.6487261297853975e+00, 1.8325836838717240e+00, 2.0166539079042916e+00, 2.2009593046196674e+00, 2.3855227441881959e+00, 2.5703675044157226e+00, 2.7555173128901118e+00, 2.9409963913117498e+00, 3.1268295022692216e+00, 3.3130419987465562e+00, 3.4996598766773372e+00, 3.6867098308940789e+00, 3.8742193148591682e+00, 4.0622166046072063e+00, 4.2507308673785191e+00, 4.4397922354810584e+00, 4.6294318859840997e+00, 4.8196821269235706e+00, 5.0105764907872219e+00, 5.2021498361504346e+00, 5.3944384584526848e+00, 5.5874802110437694e+00, 5.7813146377916294e+00, 5.9759831187344989e+00, 6.1715290304849564e+00, 6.3679979233591490e+00, 6.5654377175196297e+00, 6.7638989207955804e+00, 6.9634348712930993e+00, 7.1641020084474496e+00, 7.3659601768199030e+00, 7.5690729677310218e+00, 7.7735081047843622e+00, 7.9793378805138149e+00, 8.1866396528418637e+00, 8.3954964118396482e+00, 8.6059974295318415e+00, 8.8182390083208837e+00, 9.0323253471918115e+00, 9.2483695494377951e+00, 9.4664948015418702e+00, 9.6868357605097319e+00, 9.9095401969966606e+00, 1.0134770954893138e+01, 1.0362708305895856e+01, 1.0593552801837916e+01, 1.0827528760910019e+01, 1.1064888570473238e+01, 1.1305918055227691e+01, 1.1550943254895040e+01, 1.1800339096046955e+01, 1.2054540654144855e+01, 1.2314058027999442e+01, 1.2579496366100177e+01, 1.2851583430941135e+01, 1.3131208524813520e+01, 1.3419479146381439e+01, 1.3717806488350135e+01, 1.4028040263249208e+01, 1.4352693310923225e+01, 1.4695343105401838e+01, 1.5061420455716602e+01, 1.5459980283706434e+01, 1.5908594943006905e+01, 1.6453261162851238e+01}, + {-1.6512211841757207e+01, -1.5968188077282482e+01, -1.5520115371292015e+01, -1.5122047078570679e+01, -1.4756429806104775e+01, -1.4414218332528858e+01, -1.4089987634289908e+01, -1.3780164032724846e+01, -1.3482237346726031e+01, -1.3194359818522189e+01, -1.2915121747251227e+01, -1.2643416807332409e+01, -1.2378356641882881e+01, -1.2119214266294843e+01, -1.1865385183637930e+01, -1.1616359849416588e+01, -1.1371703666311570e+01, -1.1131042125331231e+01, -1.0894049555564962e+01, -1.0660440461418377e+01, -1.0429962752004187e+01, -1.0202392378570206e+01, -9.9775290361704698e+00, -9.7551926810776539e+00, -9.5352206814286085e+00, -9.3174654651143189e+00, -9.1017925622483045e+00, -8.8880789637690558e+00, -8.6762117355753663e+00, -8.4660868409009815e+00, -8.2576081336726084e+00, -8.0506864932467330e+00, -7.8452390768098423e+00, -7.6411886703008571e+00, -7.4384631222974562e+00, -7.2369948481366277e+00, -7.0367203937895502e+00, -6.8375800508126918e+00, -6.6395175151495431e+00, -6.4424795837354694e+00, -6.2464158838193349e+00, -6.0512786307039113e+00, -5.8570224102572590e+00, -5.6636039830858733e+00, -5.4709821077089327e+00, -5.2791173804478735e+00, -5.0879720900604992e+00, -4.8975100854141935e+00, -4.7076966547174930e+00, -4.5184984150200371e+00, -4.3298832108534802e+00, -4.1418200210249481e+00, -3.9542788726937901e+00, -3.7672307619648824e+00, -3.5806475803201039e+00, -3.3945020462860152e+00, -3.2087676418019360e+00, -3.0234185528101056e+00, -2.8384296136395832e+00, -2.6537762547990797e+00, -2.4694344538319206e+00, -2.2853806889194859e+00, -2.1015918949484664e+00, -1.9180454217825835e+00, -1.7347189945015418e+00, -1.5515906753892701e+00, -1.3686388274702970e+00, -1.1858420794076876e+00, -1.0031792915885485e+00, -8.2062952323391314e-01, -6.3817200037899757e-01, -4.5578608457752007e-01, -2.7345124219010619e-01, -9.1147014121871414e-02, 9.1147014121871414e-02, 2.7345124219010619e-01, 4.5578608457752007e-01, 6.3817200037899757e-01, 8.2062952323391314e-01, 1.0031792915885485e+00, 1.1858420794076876e+00, 1.3686388274702970e+00, 1.5515906753892701e+00, 1.7347189945015418e+00, 1.9180454217825835e+00, 2.1015918949484664e+00, 2.2853806889194859e+00, 2.4694344538319206e+00, 2.6537762547990797e+00, 2.8384296136395832e+00, 3.0234185528101056e+00, 3.2087676418019360e+00, 3.3945020462860152e+00, 3.5806475803201039e+00, 3.7672307619648824e+00, 3.9542788726937901e+00, 4.1418200210249481e+00, 4.3298832108534802e+00, 4.5184984150200371e+00, 4.7076966547174930e+00, 4.8975100854141935e+00, 5.0879720900604992e+00, 5.2791173804478735e+00, 5.4709821077089327e+00, 5.6636039830858733e+00, 5.8570224102572590e+00, 6.0512786307039113e+00, 6.2464158838193349e+00, 6.4424795837354694e+00, 6.6395175151495431e+00, 6.8375800508126918e+00, 7.0367203937895502e+00, 7.2369948481366277e+00, 7.4384631222974562e+00, 7.6411886703008571e+00, 7.8452390768098423e+00, 8.0506864932467330e+00, 8.2576081336726084e+00, 8.4660868409009815e+00, 8.6762117355753663e+00, 8.8880789637690558e+00, 9.1017925622483045e+00, 9.3174654651143189e+00, 9.5352206814286085e+00, 9.7551926810776539e+00, 9.9775290361704698e+00, 1.0202392378570206e+01, 1.0429962752004187e+01, 1.0660440461418377e+01, 1.0894049555564962e+01, 1.1131042125331231e+01, 1.1371703666311570e+01, 1.1616359849416588e+01, 1.1865385183637930e+01, 1.2119214266294843e+01, 1.2378356641882881e+01, 1.2643416807332409e+01, 1.2915121747251227e+01, 1.3194359818522189e+01, 1.3482237346726031e+01, 1.3780164032724846e+01, 1.4089987634289908e+01, 1.4414218332528858e+01, 1.4756429806104775e+01, 1.5122047078570679e+01, 1.5520115371292015e+01, 1.5968188077282482e+01, 1.6512211841757207e+01}, + {-1.6570960596234816e+01, -1.6027574088336884e+01, -1.5580038874389315e+01, -1.5182458010099252e+01, -1.4817296918736639e+01, -1.4475520005731354e+01, -1.4151707989055947e+01, -1.3842290956496822e+01, -1.3544761365310002e+01, -1.3257273397371849e+01, -1.2978418831992128e+01, -1.2707092507353986e+01, -1.2442407004329516e+01, -1.2183636109757821e+01, -1.1930175972733117e+01, -1.1681517598227204e+01, -1.1437226862743914e+01, -1.1196929670964046e+01, -1.0960300717203255e+01, -1.0727054831642461e+01, -1.0496940216738453e+01, -1.0269733090205794e+01, -1.0045233391137220e+01, -9.8232613010212955e+00, -9.6036543973400637e+00, -9.3862653039000534e+00, -9.1709597353376804e+00, -8.9576148574362815e+00, -8.7461179027166409e+00, -8.5363649940564841e+00, -8.3282601391216602e+00, -8.1217143660350786e+00, -7.9166449765926146e+00, -7.7129748979045933e+00, -7.5106321169206671e+00, -7.3095491851216430e+00, -7.1096627829092727e+00, -6.9109133350249667e+00, -6.7132446697794288e+00, -6.5166037160520816e+00, -6.3209402329793747e+00, -6.1262065680386195e+00, -5.9323574398835213e+00, -5.7393497428256754e+00, -5.5471423703043676e+00, -5.3556960550616148e+00, -5.1649732240539885e+00, -4.9749378663979575e+00, -4.7855554128699298e+00, -4.5967926256728040e+00, -4.4086174973432648e+00, -4.2209991578129564e+00, -4.0339077887557737e+00, -3.8473145444559340e+00, -3.6611914785198536e+00, -3.4755114758312047e+00, -3.2902481892147279e+00, -3.1053759803318370e+00, -2.9208698643810656e+00, -2.7367054582199937e+00, -2.5528589315633066e+00, -2.3693069609448871e+00, -2.1860266861608908e+00, -2.0029956689361597e+00, -1.8201918535785517e+00, -1.6375935294051731e+00, -1.4551792947414237e+00, -1.2729280223085093e+00, -1.0908188258278129e+00, -9.0883102768153856e-01, -7.2694412747841530e-01, -5.4513777138121788e-01, -3.6339172205944553e-01, -1.8168582913588810e-01, -0.0000000000000000e+00, 1.8168582913588810e-01, 3.6339172205944553e-01, 5.4513777138121788e-01, 7.2694412747841530e-01, 9.0883102768153856e-01, 1.0908188258278129e+00, 1.2729280223085093e+00, 1.4551792947414237e+00, 1.6375935294051731e+00, 1.8201918535785517e+00, 2.0029956689361597e+00, 2.1860266861608908e+00, 2.3693069609448871e+00, 2.5528589315633066e+00, 2.7367054582199937e+00, 2.9208698643810656e+00, 3.1053759803318370e+00, 3.2902481892147279e+00, 3.4755114758312047e+00, 3.6611914785198536e+00, 3.8473145444559340e+00, 4.0339077887557737e+00, 4.2209991578129564e+00, 4.4086174973432648e+00, 4.5967926256728040e+00, 4.7855554128699298e+00, 4.9749378663979575e+00, 5.1649732240539885e+00, 5.3556960550616148e+00, 5.5471423703043676e+00, 5.7393497428256754e+00, 5.9323574398835213e+00, 6.1262065680386195e+00, 6.3209402329793747e+00, 6.5166037160520816e+00, 6.7132446697794288e+00, 6.9109133350249667e+00, 7.1096627829092727e+00, 7.3095491851216430e+00, 7.5106321169206671e+00, 7.7129748979045933e+00, 7.9166449765926146e+00, 8.1217143660350786e+00, 8.3282601391216602e+00, 8.5363649940564841e+00, 8.7461179027166409e+00, 8.9576148574362815e+00, 9.1709597353376804e+00, 9.3862653039000534e+00, 9.6036543973400637e+00, 9.8232613010212955e+00, 1.0045233391137220e+01, 1.0269733090205794e+01, 1.0496940216738453e+01, 1.0727054831642461e+01, 1.0960300717203255e+01, 1.1196929670964046e+01, 1.1437226862743914e+01, 1.1681517598227204e+01, 1.1930175972733117e+01, 1.2183636109757821e+01, 1.2442407004329516e+01, 1.2707092507353986e+01, 1.2978418831992128e+01, 1.3257273397371849e+01, 1.3544761365310002e+01, 1.3842290956496822e+01, 1.4151707989055947e+01, 1.4475520005731354e+01, 1.4817296918736639e+01, 1.5182458010099252e+01, 1.5580038874389315e+01, 1.6027574088336884e+01, 1.6570960596234816e+01}, + {-1.6629509478833860e+01, -1.6086755105929722e+01, -1.5639752989987683e+01, -1.5242655509972604e+01, -1.4877946763142496e+01, -1.4536600709088953e+01, -1.4213203763983850e+01, -1.3904189753562465e+01, -1.3607053753368865e+01, -1.3319951870041416e+01, -1.3041477351568494e+01, -1.2770526190723876e+01, -1.2506211898605262e+01, -1.2247809027167504e+01, -1.1994714366091593e+01, -1.1746419465057167e+01, -1.1502490670154140e+01, -1.1262554295905716e+01, -1.1026285398343321e+01, -1.0793399130164836e+01, -1.0563643984112028e+01, -1.0336796441464246e+01, -1.0112656682574075e+01, -9.8910451114622759e+00, -9.6717995123443519e+00, -9.4547727023830390e+00, -9.2398305782140078e+00, -9.0268504779630501e+00, -8.8157197982791242e+00, -8.6063348191874436e+00, -8.3985996995836860e+00, -8.1924256138258222e+00, -7.9877300057571530e+00, -7.7844359410588435e+00, -7.5824715424057798e+00, -7.3817694947224117e+00, -7.1822666100804051e+00, -6.9839034435780709e+00, -6.7866239529910715e+00, -6.5903751961596155e+00, -6.3951070610365948e+00, -6.2007720241079047e+00, -6.0073249335450427e+00, -5.8147228139876921e+00, -5.6229246903015975e+00, -5.4318914280313058e+00, -5.2415855885816516e+00, -5.0519712974268067e+00, -4.8630141238699967e+00, -4.6746809710674029e+00, -4.4869399751921195e+00, -4.2997604127527840e+00, -4.1131126152005661e+00, -3.9269678900605394e+00, -3.7412984479117779e+00, -3.5560773346168779e+00, -3.3712783682677476e+00, -3.1868760803720186e+00, -3.0028456608544345e+00, -2.8191629064911972e+00, -2.6358041724333074e+00, -2.4527463265082488e+00, -2.2699667060184630e+00, -2.0874430767805627e+00, -1.9051535941715365e+00, -1.7230767659677173e+00, -1.5411914167793415e+00, -1.3594766538983880e+00, -1.1779118343903046e+00, -9.9647653327140173e-01, -8.1515051262328730e-01, -6.3391369150388599e-01, -4.5274611652143021e-01, -2.7162793294346238e-01, -9.0539356217393022e-02, 9.0539356217393022e-02, 2.7162793294346238e-01, 4.5274611652143021e-01, 6.3391369150388599e-01, 8.1515051262328730e-01, 9.9647653327140173e-01, 1.1779118343903046e+00, 1.3594766538983880e+00, 1.5411914167793415e+00, 1.7230767659677173e+00, 1.9051535941715365e+00, 2.0874430767805627e+00, 2.2699667060184630e+00, 2.4527463265082488e+00, 2.6358041724333074e+00, 2.8191629064911972e+00, 3.0028456608544345e+00, 3.1868760803720186e+00, 3.3712783682677476e+00, 3.5560773346168779e+00, 3.7412984479117779e+00, 3.9269678900605394e+00, 4.1131126152005661e+00, 4.2997604127527840e+00, 4.4869399751921195e+00, 4.6746809710674029e+00, 4.8630141238699967e+00, 5.0519712974268067e+00, 5.2415855885816516e+00, 5.4318914280313058e+00, 5.6229246903015975e+00, 5.8147228139876921e+00, 6.0073249335450427e+00, 6.2007720241079047e+00, 6.3951070610365948e+00, 6.5903751961596155e+00, 6.7866239529910715e+00, 6.9839034435780709e+00, 7.1822666100804051e+00, 7.3817694947224117e+00, 7.5824715424057798e+00, 7.7844359410588435e+00, 7.9877300057571530e+00, 8.1924256138258222e+00, 8.3985996995836860e+00, 8.6063348191874436e+00, 8.8157197982791242e+00, 9.0268504779630501e+00, 9.2398305782140078e+00, 9.4547727023830390e+00, 9.6717995123443519e+00, 9.8910451114622759e+00, 1.0112656682574075e+01, 1.0336796441464246e+01, 1.0563643984112028e+01, 1.0793399130164836e+01, 1.1026285398343321e+01, 1.1262554295905716e+01, 1.1502490670154140e+01, 1.1746419465057167e+01, 1.1994714366091593e+01, 1.2247809027167504e+01, 1.2506211898605262e+01, 1.2770526190723876e+01, 1.3041477351568494e+01, 1.3319951870041416e+01, 1.3607053753368865e+01, 1.3904189753562465e+01, 1.4213203763983850e+01, 1.4536600709088953e+01, 1.4877946763142496e+01, 1.5242655509972604e+01, 1.5639752989987683e+01, 1.6086755105929722e+01, 1.6629509478833860e+01}, + {-1.6687860507628386e+01, -1.6145733223684985e+01, -1.5699259877476434e+01, -1.5302641798879872e+01, -1.4938381618846188e+01, -1.4597462779517947e+01, -1.4274477352553639e+01, -1.3965862873544308e+01, -1.3669117016537621e+01, -1.3382397798268309e+01, -1.3104299924083964e+01, -1.2833720532318454e+01, -1.2569774056886668e+01, -1.2311735808633442e+01, -1.2059003212482786e+01, -1.1811068358148432e+01, -1.1567498057148995e+01, -1.1327919030095220e+01, -1.1092006691295751e+01, -1.0859476512776732e+01, -1.0630077274574017e+01, -1.0403585718697158e+01, -1.0179802264046788e+01, -9.9585475345593846e+00, -9.7396595186399217e+00, -9.5229912243166375e+00, -9.3084087277706491e+00, -9.0957895370391153e+00, -8.8850212104784116e+00, -8.6760001828398110e+00, -8.4686307618168346e+00, -8.2628242655509627e+00, -8.0584982774535074e+00, -7.8555759992614407e+00, -7.6539856868168998e+00, -7.4536601558800220e+00, -7.2545363475276838e+00, -7.0565549444870097e+00, -6.8596600312005922e+00, -6.6637987915949521e+00, -6.4689212394819462e+00, -6.2749799773089512e+00, -6.0819299796217976e+00, -5.8897283981415303e+00, -5.6983343858032613e+00, -5.5077089374792596e+00, -5.3178147454224645e+00, -5.1286160677313077e+00, -4.9400786083607757e+00, -4.7521694073949581e+00, -4.5648567404584961e+00, -4.3781100262830321e+00, -4.1918997415637014e+00, -4.0061973423430199e+00, -3.8209751912478049e+00, -3.6362064899810247e+00, -3.4518652165367119e+00, -3.2679260666634748e+00, -3.0843643991522391e+00, -2.9011561845674412e+00, -2.7182779570790365e+00, -2.5357067690860005e+00, -2.3534201483511836e+00, -2.1713960573929474e+00, -1.9896128549013927e+00, -1.8080492589666075e+00, -1.6266843119235277e+00, -1.4454973466329897e+00, -1.2644679540316108e+00, -1.0835759517944645e+00, -9.0280135396429395e-01, -7.2212434140935688e-01, -5.4152523297908439e-01, -3.6098445723261258e-01, -1.8048252462003789e-01, -0.0000000000000000e+00, 1.8048252462003789e-01, 3.6098445723261258e-01, 5.4152523297908439e-01, 7.2212434140935688e-01, 9.0280135396429395e-01, 1.0835759517944645e+00, 1.2644679540316108e+00, 1.4454973466329897e+00, 1.6266843119235277e+00, 1.8080492589666075e+00, 1.9896128549013927e+00, 2.1713960573929474e+00, 2.3534201483511836e+00, 2.5357067690860005e+00, 2.7182779570790365e+00, 2.9011561845674412e+00, 3.0843643991522391e+00, 3.2679260666634748e+00, 3.4518652165367119e+00, 3.6362064899810247e+00, 3.8209751912478049e+00, 4.0061973423430199e+00, 4.1918997415637014e+00, 4.3781100262830321e+00, 4.5648567404584961e+00, 4.7521694073949581e+00, 4.9400786083607757e+00, 5.1286160677313077e+00, 5.3178147454224645e+00, 5.5077089374792596e+00, 5.6983343858032613e+00, 5.8897283981415303e+00, 6.0819299796217976e+00, 6.2749799773089512e+00, 6.4689212394819462e+00, 6.6637987915949521e+00, 6.8596600312005922e+00, 7.0565549444870097e+00, 7.2545363475276838e+00, 7.4536601558800220e+00, 7.6539856868168998e+00, 7.8555759992614407e+00, 8.0584982774535074e+00, 8.2628242655509627e+00, 8.4686307618168346e+00, 8.6760001828398110e+00, 8.8850212104784116e+00, 9.0957895370391153e+00, 9.3084087277706491e+00, 9.5229912243166375e+00, 9.7396595186399217e+00, 9.9585475345593846e+00, 1.0179802264046788e+01, 1.0403585718697158e+01, 1.0630077274574017e+01, 1.0859476512776732e+01, 1.1092006691295751e+01, 1.1327919030095220e+01, 1.1567498057148995e+01, 1.1811068358148432e+01, 1.2059003212482786e+01, 1.2311735808633442e+01, 1.2569774056886668e+01, 1.2833720532318454e+01, 1.3104299924083964e+01, 1.3382397798268309e+01, 1.3669117016537621e+01, 1.3965862873544308e+01, 1.4274477352553639e+01, 1.4597462779517947e+01, 1.4938381618846188e+01, 1.5302641798879872e+01, 1.5699259877476434e+01, 1.6145733223684985e+01, 1.6687860507628386e+01}, + {-1.6746015667021069e+01, -1.6204510499941978e+01, -1.5758561659537367e+01, -1.5362419059461168e+01, -1.4998603726021303e+01, -1.4658108513302281e+01, -1.4335531106337195e+01, -1.4027312722878635e+01, -1.3730953615978237e+01, -1.3444613698016527e+01, -1.3166889120550762e+01, -1.2896678158583638e+01, -1.2633096161556749e+01, -1.2375419193081754e+01, -1.2123045308073459e+01, -1.1875467131689264e+01, -1.1632251936796413e+01, -1.1393026846411182e+01, -1.1157467629750515e+01, -1.0925290075047540e+01, -1.0696243246707187e+01, -1.0470104144699656e+01, -1.0246673423826493e+01, -1.0025771925388167e+01, -9.8072378395003508e+00, -9.5909243626320890e+00, -9.3766977481232310e+00, -9.1644356715597066e+00, -8.9540258506546646e+00, -8.7453648725360029e+00, -8.5383571913371981e+00, -8.3329142666081459e+00, -8.1289538189277764e+00, -7.9263991836556649e+00, -7.7251787473280729e+00, -7.5252254540210100e+00, -7.3264763712435084e+00, -7.1288723067188302e+00, -6.9323574688579237e+00, -6.7368791649028887e+00, -6.5423875316754021e+00, -6.3488352946504518e+00, -6.1561775517231760e+00, -5.9643715785732399e+00, -5.7733766529779098e+00, -5.5831538957985396e+00, -5.3936661266788803e+00, -5.2048777327581446e+00, -5.0167545489255820e+00, -4.8292637483334380e+00, -4.6423737420472682e+00, -4.4560540868511129e+00, -4.2702754003439098e+00, -4.0850092825657862e+00, -3.9002282434810596e+00, -3.7159056357210827e+00, -3.5320155920561942e+00, -3.3485329671235227e+00, -3.1654332829874168e+00, -2.9826926781529521e+00, -2.8002878596910716e+00, -2.6181960581673263e+00, -2.4363949850953830e+00, -2.2548627926621019e+00, -2.0735780354934534e+00, -1.8925196342502328e+00, -1.7116668408598084e+00, -1.5309992052052144e+00, -1.3504965431061176e+00, -1.1701389054376192e+00, -9.8990654824282009e-01, -8.0977990370358899e-01, -6.2973955184126684e-01, -4.4976619282513375e-01, -2.6984061977151302e-01, -8.9943691920400901e-02, 8.9943691920400901e-02, 2.6984061977151302e-01, 4.4976619282513375e-01, 6.2973955184126684e-01, 8.0977990370358899e-01, 9.8990654824282009e-01, 1.1701389054376192e+00, 1.3504965431061176e+00, 1.5309992052052144e+00, 1.7116668408598084e+00, 1.8925196342502328e+00, 2.0735780354934534e+00, 2.2548627926621019e+00, 2.4363949850953830e+00, 2.6181960581673263e+00, 2.8002878596910716e+00, 2.9826926781529521e+00, 3.1654332829874168e+00, 3.3485329671235227e+00, 3.5320155920561942e+00, 3.7159056357210827e+00, 3.9002282434810596e+00, 4.0850092825657862e+00, 4.2702754003439098e+00, 4.4560540868511129e+00, 4.6423737420472682e+00, 4.8292637483334380e+00, 5.0167545489255820e+00, 5.2048777327581446e+00, 5.3936661266788803e+00, 5.5831538957985396e+00, 5.7733766529779098e+00, 5.9643715785732399e+00, 6.1561775517231760e+00, 6.3488352946504518e+00, 6.5423875316754021e+00, 6.7368791649028887e+00, 6.9323574688579237e+00, 7.1288723067188302e+00, 7.3264763712435084e+00, 7.5252254540210100e+00, 7.7251787473280729e+00, 7.9263991836556649e+00, 8.1289538189277764e+00, 8.3329142666081459e+00, 8.5383571913371981e+00, 8.7453648725360029e+00, 8.9540258506546646e+00, 9.1644356715597066e+00, 9.3766977481232310e+00, 9.5909243626320890e+00, 9.8072378395003508e+00, 1.0025771925388167e+01, 1.0246673423826493e+01, 1.0470104144699656e+01, 1.0696243246707187e+01, 1.0925290075047540e+01, 1.1157467629750515e+01, 1.1393026846411182e+01, 1.1632251936796413e+01, 1.1875467131689264e+01, 1.2123045308073459e+01, 1.2375419193081754e+01, 1.2633096161556749e+01, 1.2896678158583638e+01, 1.3166889120550762e+01, 1.3444613698016527e+01, 1.3730953615978237e+01, 1.4027312722878635e+01, 1.4335531106337195e+01, 1.4658108513302281e+01, 1.4998603726021303e+01, 1.5362419059461168e+01, 1.5758561659537367e+01, 1.6204510499941978e+01, 1.6746015667021069e+01}, + {-1.6803976908523694e+01, -1.6263088958580713e+01, -1.5817660423010251e+01, -1.5421989437211316e+01, -1.5058615286432362e+01, -1.4718540167071973e+01, -1.4396367336014109e+01, -1.4088541665869107e+01, -1.3792565969471646e+01, -1.3506602040607744e+01, -1.3229247466060766e+01, -1.2959401648746917e+01, -1.2696180846459008e+01, -1.2438861869552357e+01, -1.2186843397769389e+01, -1.1939618587201746e+01, -1.1696755168060276e+01, -1.1457880662155430e+01, -1.1222671190311015e+01, -1.0990842853911044e+01, -1.0762144998868230e+01, -1.0536354880406639e+01, -1.0313273386643994e+01, -1.0092721573755421e+01, -9.8745378311513203e+00, -9.6585755413803565e+00, -9.4447011326189330e+00, -9.2327924457049324e+00, -9.0227373554249493e+00, -8.8144325990031405e+00, -8.6077827747261111e+00, -8.4026994812503251e+00, -8.1991005739976206e+00, -7.9969095195952864e+00, -7.7960548328817607e+00, -7.5964695838133709e+00, -7.3980909638458217e+00, -7.2008599031569602e+00, -7.0047207315224398e+00, -6.8096208768281805e+00, -6.6155105961598455e+00, -6.4223427351940696e+00, -6.2300725122630887e+00, -6.0386573240004857e+00, -5.8480565699220763e+00, -5.6582314936691613e+00, -5.4691450389548066e+00, -5.2807617185180318e+00, -5.0930474946144608e+00, -4.9059696697619373e+00, -4.7194967866215638e+00, -4.5335985360330326e+00, -4.3482456723419469e+00, -4.1634099352589846e+00, -3.9790639775789276e+00, -3.7951812981638180e+00, -3.6117361796606513e+00, -3.4287036304814422e+00, -3.2460593306235781e+00, -3.0637795809520179e+00, -2.8818412556030690e+00, -2.7002217572028795e+00, -2.5188989746230557e+00, -2.3378512430214919e+00, -2.1570573059390363e+00, -1.9764962792423748e+00, -1.7961476167208907e+00, -1.6159910771604287e+00, -1.4360066927302104e+00, -1.2561747385307371e+00, -1.0764757031605943e+00, -8.9689026016876394e-01, -7.1739924026651414e-01, -5.3798360417923241e-01, -3.5862441602383283e-01, -1.7930281710163956e-01, -0.0000000000000000e+00, 1.7930281710163956e-01, 3.5862441602383283e-01, 5.3798360417923241e-01, 7.1739924026651414e-01, 8.9689026016876394e-01, 1.0764757031605943e+00, 1.2561747385307371e+00, 1.4360066927302104e+00, 1.6159910771604287e+00, 1.7961476167208907e+00, 1.9764962792423748e+00, 2.1570573059390363e+00, 2.3378512430214919e+00, 2.5188989746230557e+00, 2.7002217572028795e+00, 2.8818412556030690e+00, 3.0637795809520179e+00, 3.2460593306235781e+00, 3.4287036304814422e+00, 3.6117361796606513e+00, 3.7951812981638180e+00, 3.9790639775789276e+00, 4.1634099352589846e+00, 4.3482456723419469e+00, 4.5335985360330326e+00, 4.7194967866215638e+00, 4.9059696697619373e+00, 5.0930474946144608e+00, 5.2807617185180318e+00, 5.4691450389548066e+00, 5.6582314936691613e+00, 5.8480565699220763e+00, 6.0386573240004857e+00, 6.2300725122630887e+00, 6.4223427351940696e+00, 6.6155105961598455e+00, 6.8096208768281805e+00, 7.0047207315224398e+00, 7.2008599031569602e+00, 7.3980909638458217e+00, 7.5964695838133709e+00, 7.7960548328817607e+00, 7.9969095195952864e+00, 8.1991005739976206e+00, 8.4026994812503251e+00, 8.6077827747261111e+00, 8.8144325990031405e+00, 9.0227373554249493e+00, 9.2327924457049324e+00, 9.4447011326189330e+00, 9.6585755413803565e+00, 9.8745378311513203e+00, 1.0092721573755421e+01, 1.0313273386643994e+01, 1.0536354880406639e+01, 1.0762144998868230e+01, 1.0990842853911044e+01, 1.1222671190311015e+01, 1.1457880662155430e+01, 1.1696755168060276e+01, 1.1939618587201746e+01, 1.2186843397769389e+01, 1.2438861869552357e+01, 1.2696180846459008e+01, 1.2959401648746917e+01, 1.3229247466060766e+01, 1.3506602040607744e+01, 1.3792565969471646e+01, 1.4088541665869107e+01, 1.4396367336014109e+01, 1.4718540167071973e+01, 1.5058615286432362e+01, 1.5421989437211316e+01, 1.5817660423010251e+01, 1.6263088958580713e+01, 1.6803976908523694e+01}, + {-1.6861746151514453e+01, -1.6321470589822656e+01, -1.5876558219732326e+01, -1.5481355041356229e+01, -1.5118418464347313e+01, -1.4778759958751550e+01, -1.4456988312356128e+01, -1.4149552025707647e+01, -1.3853956452475600e+01, -1.3568365253816872e+01, -1.3291377440919536e+01, -1.3021893535990777e+01, -1.2759030698111300e+01, -1.2502066478454370e+01, -1.2250400176513523e+01, -1.2003525474883981e+01, -1.1761010557188053e+01, -1.1522483340487554e+01, -1.1287620293977072e+01, -1.1056137829198551e+01, -1.0827785570772761e+01, -1.0602341026531503e+01, -1.0379605315384135e+01, -1.0159399705951289e+01, -9.9415627845826098e+00, -9.7259481176063289e+00, -9.5124223057752690e+00, -9.3008633529456954e+00, -9.0911592887589681e+00, -8.8832069983214303e+00, -8.6769112218541409e+00, -8.4721836948885070e+00, -8.2689424054370715e+00, -8.0671109491149302e+00, -7.8666179667484384e+00, -7.6673966518192671e+00, -7.4693843173280303e+00, -7.2725220134526776e+00, -7.0767541888205505e+00, -6.8820283893841117e+00, -6.6882949898457129e+00, -6.4955069533605654e+00, -6.3036196158933109e+00, -6.1125904921391818e+00, -5.9223791003665953e+00, -5.7329468039109130e+00, -5.5442566673621716e+00, -5.3562733257536657e+00, -5.1689628652816504e+00, -4.9822927142762881e+00, -4.7962315433057050e+00, -4.6107491734334216e+00, -4.4258164917680798e+00, -4.2414053735465238e+00, -4.0574886100793801e+00, -3.8740398419645214e+00, -3.6910334970398750e+00, -3.5084447326044930e+00, -3.3262493814868481e+00, -3.1444239015829951e+00, -2.9629453285254086e+00, -2.7817912311767614e+00, -2.6009396696722078e+00, -2.4203691557594618e+00, -2.2400586152085502e+00, -2.0599873520829730e+00, -1.8801350146814075e+00, -1.7004815629744074e+00, -1.5210072373739318e+00, -1.3416925286852595e+00, -1.1625181491010375e+00, -9.8346500410607329e-01, -8.0451416516907071e-01, -6.2564684310401653e-01, -4.4684436198936728e-01, -2.6808813353769451e-01, -8.9359631812036308e-02, 8.9359631812036308e-02, 2.6808813353769451e-01, 4.4684436198936728e-01, 6.2564684310401653e-01, 8.0451416516907071e-01, 9.8346500410607329e-01, 1.1625181491010375e+00, 1.3416925286852595e+00, 1.5210072373739318e+00, 1.7004815629744074e+00, 1.8801350146814075e+00, 2.0599873520829730e+00, 2.2400586152085502e+00, 2.4203691557594618e+00, 2.6009396696722078e+00, 2.7817912311767614e+00, 2.9629453285254086e+00, 3.1444239015829951e+00, 3.3262493814868481e+00, 3.5084447326044930e+00, 3.6910334970398750e+00, 3.8740398419645214e+00, 4.0574886100793801e+00, 4.2414053735465238e+00, 4.4258164917680798e+00, 4.6107491734334216e+00, 4.7962315433057050e+00, 4.9822927142762881e+00, 5.1689628652816504e+00, 5.3562733257536657e+00, 5.5442566673621716e+00, 5.7329468039109130e+00, 5.9223791003665953e+00, 6.1125904921391818e+00, 6.3036196158933109e+00, 6.4955069533605654e+00, 6.6882949898457129e+00, 6.8820283893841117e+00, 7.0767541888205505e+00, 7.2725220134526776e+00, 7.4693843173280303e+00, 7.6673966518192671e+00, 7.8666179667484384e+00, 8.0671109491149302e+00, 8.2689424054370715e+00, 8.4721836948885070e+00, 8.6769112218541409e+00, 8.8832069983214303e+00, 9.0911592887589681e+00, 9.3008633529456954e+00, 9.5124223057752690e+00, 9.7259481176063289e+00, 9.9415627845826098e+00, 1.0159399705951289e+01, 1.0379605315384135e+01, 1.0602341026531503e+01, 1.0827785570772761e+01, 1.1056137829198551e+01, 1.1287620293977072e+01, 1.1522483340487554e+01, 1.1761010557188053e+01, 1.2003525474883981e+01, 1.2250400176513523e+01, 1.2502066478454370e+01, 1.2759030698111300e+01, 1.3021893535990777e+01, 1.3291377440919536e+01, 1.3568365253816872e+01, 1.3853956452475600e+01, 1.4149552025707647e+01, 1.4456988312356128e+01, 1.4778759958751550e+01, 1.5118418464347313e+01, 1.5481355041356229e+01, 1.5876558219732326e+01, 1.6321470589822656e+01, 1.6861746151514453e+01}, + {-1.6919325283973091e+01, -1.6379657351007765e+01, -1.5935257067352701e+01, -1.5540517945702927e+01, -1.5178015387422422e+01, -1.4838770068479555e+01, -1.4517396267181470e+01, -1.4210346085463854e+01, -1.3915127399149720e+01, -1.3629905722933353e+01, -1.3353281481744700e+01, -1.3084156308589026e+01, -1.2821648256881092e+01, -1.2565035612781342e+01, -1.2313718290542331e+01, -1.2067190494908804e+01, -1.1825020859053186e+01, -1.1586837691812352e+01, -1.1352317807578974e+01, -1.1121177925121051e+01, -1.0893167945027271e+01, -1.0668065625149652e+01, -1.0445672312722746e+01, -1.0225809486441577e+01, -1.0008315927297842e+01, -9.7930453831581623e+00, -9.5798646251513500e+00, -9.3686518179792717e+00, -9.1592951439814989e+00, -8.9516916339961323e+00, -8.7457461680254056e+00, -8.5413706163114078e+00, -8.3384830972746489e+00, -8.1370073333099651e+00, -7.9368720889917341e+00, -7.7380106790491130e+00, -7.5403605357059194e+00, -7.3438628267689321e+00, -7.1484621172907721e+00, -6.9541060688033616e+00, -6.7607451710725037e+00, -6.5683325021070607e+00, -6.3768235128018915e+00, -6.1861758331287540e+00, -5.9963490972348117e+00, -5.8073047851809010e+00, -5.6190060793645857e+00, -5.4314177339367200e+00, -5.2445059557435734e+00, -5.0582382955161487e+00, -4.8725835481900202e+00, -4.6875116613772301e+00, -4.5029936511304234e+00, -4.3190015242413970e+00, -4.1355082064043351e+00, -3.9524874756501580e+00, -3.7699139005244779e+00, -3.5877627825391012e+00, -3.4060101024770435e+00, -3.2246324701747149e+00, -3.0436070774431303e+00, -2.8629116538234336e+00, -2.6825244249014188e+00, -2.5024240729314422e+00, -2.3225896995428044e+00, -2.1430007903215516e+00, -1.9636371810781683e+00, -1.7844790256269836e+00, -1.6055067649166126e+00, -1.4267010973625776e+00, -1.2480429502435568e+00, -1.0695134520316971e+00, -8.9109390553517087e-01, -7.1276576173782080e-01, -5.3451059422635872e-01, -3.5631007410029453e-01, -1.7814594526358507e-01, -0.0000000000000000e+00, 1.7814594526358507e-01, 3.5631007410029453e-01, 5.3451059422635872e-01, 7.1276576173782080e-01, 8.9109390553517087e-01, 1.0695134520316971e+00, 1.2480429502435568e+00, 1.4267010973625776e+00, 1.6055067649166126e+00, 1.7844790256269836e+00, 1.9636371810781683e+00, 2.1430007903215516e+00, 2.3225896995428044e+00, 2.5024240729314422e+00, 2.6825244249014188e+00, 2.8629116538234336e+00, 3.0436070774431303e+00, 3.2246324701747149e+00, 3.4060101024770435e+00, 3.5877627825391012e+00, 3.7699139005244779e+00, 3.9524874756501580e+00, 4.1355082064043351e+00, 4.3190015242413970e+00, 4.5029936511304234e+00, 4.6875116613772301e+00, 4.8725835481900202e+00, 5.0582382955161487e+00, 5.2445059557435734e+00, 5.4314177339367200e+00, 5.6190060793645857e+00, 5.8073047851809010e+00, 5.9963490972348117e+00, 6.1861758331287540e+00, 6.3768235128018915e+00, 6.5683325021070607e+00, 6.7607451710725037e+00, 6.9541060688033616e+00, 7.1484621172907721e+00, 7.3438628267689321e+00, 7.5403605357059194e+00, 7.7380106790491130e+00, 7.9368720889917341e+00, 8.1370073333099651e+00, 8.3384830972746489e+00, 8.5413706163114078e+00, 8.7457461680254056e+00, 8.9516916339961323e+00, 9.1592951439814989e+00, 9.3686518179792717e+00, 9.5798646251513500e+00, 9.7930453831581623e+00, 1.0008315927297842e+01, 1.0225809486441577e+01, 1.0445672312722746e+01, 1.0668065625149652e+01, 1.0893167945027271e+01, 1.1121177925121051e+01, 1.1352317807578974e+01, 1.1586837691812352e+01, 1.1825020859053186e+01, 1.2067190494908804e+01, 1.2313718290542331e+01, 1.2565035612781342e+01, 1.2821648256881092e+01, 1.3084156308589026e+01, 1.3353281481744700e+01, 1.3629905722933353e+01, 1.3915127399149720e+01, 1.4210346085463854e+01, 1.4517396267181470e+01, 1.4838770068479555e+01, 1.5178015387422422e+01, 1.5540517945702927e+01, 1.5935257067352701e+01, 1.6379657351007765e+01, 1.6919325283973091e+01}, + {-1.6976716163194499e+01, -1.6437651167348605e+01, -1.5993758950122626e+01, -1.5599480189464179e+01, -1.5237408147560531e+01, -1.4898572639500255e+01, -1.4577593394280033e+01, -1.4270926089044083e+01, -1.3976081103348914e+01, -1.3691225791789593e+01, -1.3414961982530070e+01, -1.3146192411007465e+01, -1.2884036018123565e+01, -1.2627771819287853e+01, -1.2376800338602001e+01, -1.2130616298680719e+01, -1.1888788778454018e+01, -1.1650946475122105e+01, -1.1416766545164455e+01, -1.1185966011702471e+01, -1.0958295048610227e+01, -1.0733531661229089e+01, -1.0511477422708499e+01, -1.0291954019502739e+01, -1.0074800425004574e+01, -9.8598705664345285e+00, -9.6470313831544541e+00, -9.4361611985975138e+00, -9.2271483457046273e+00, -9.0198899989563817e+00, -8.8142911760456872e+00, -8.6102638798256326e+00, -8.4077263570086043e+00, -8.2066024546299392e+00, -8.0068210588433661e+00, -7.8083156034214856e+00, -7.6110236375661993e+00, -7.4148864444214286e+00, -7.2198487031214214e+00, -7.0258581883766524e+00, -6.8328655025529308e+00, -6.6408238359815064e+00, -6.4496887518830528e+00, -6.2594179928228799e+00, -6.0699713060598244e+00, -5.8813102855233703e+00, -5.6933982284661457e+00, -5.5062000051024196e+00, -5.3196819397663528e+00, -5.1338117023131167e+00, -4.9485582086476523e+00, -4.7638915294038444e+00, -4.5797828059155004e+00, -4.3962041727224284e+00, -4.2131286859429329e+00, -4.0305302569201968e+00, -3.8483835906160127e+00, -3.6666641282827874e+00, -3.4853479939947509e+00, -3.3044119446629794e+00, -3.1238333231970716e+00, -2.9435900145097715e+00, -2.7636604040902180e+00, -2.5840233388973028e+00, -2.4046580903472949e+00, -2.2255443191898578e+00, -2.0466620420841379e+00, -1.8679915997020398e+00, -1.6895136261993984e+00, -1.5112090199076367e+00, -1.3330589151089478e+00, -1.1550446547671134e+00, -9.7714776409397042e-01, -7.9934992483832146e-01, -6.2163295018989517e-01, -4.4397876019583243e-01, -2.6636935759120106e-01, -8.8786803948269877e-02, 8.8786803948269877e-02, 2.6636935759120106e-01, 4.4397876019583243e-01, 6.2163295018989517e-01, 7.9934992483832146e-01, 9.7714776409397042e-01, 1.1550446547671134e+00, 1.3330589151089478e+00, 1.5112090199076367e+00, 1.6895136261993984e+00, 1.8679915997020398e+00, 2.0466620420841379e+00, 2.2255443191898578e+00, 2.4046580903472949e+00, 2.5840233388973028e+00, 2.7636604040902180e+00, 2.9435900145097715e+00, 3.1238333231970716e+00, 3.3044119446629794e+00, 3.4853479939947509e+00, 3.6666641282827874e+00, 3.8483835906160127e+00, 4.0305302569201968e+00, 4.2131286859429329e+00, 4.3962041727224284e+00, 4.5797828059155004e+00, 4.7638915294038444e+00, 4.9485582086476523e+00, 5.1338117023131167e+00, 5.3196819397663528e+00, 5.5062000051024196e+00, 5.6933982284661457e+00, 5.8813102855233703e+00, 6.0699713060598244e+00, 6.2594179928228799e+00, 6.4496887518830528e+00, 6.6408238359815064e+00, 6.8328655025529308e+00, 7.0258581883766524e+00, 7.2198487031214214e+00, 7.4148864444214286e+00, 7.6110236375661993e+00, 7.8083156034214856e+00, 8.0068210588433661e+00, 8.2066024546299392e+00, 8.4077263570086043e+00, 8.6102638798256326e+00, 8.8142911760456872e+00, 9.0198899989563817e+00, 9.2271483457046273e+00, 9.4361611985975138e+00, 9.6470313831544541e+00, 9.8598705664345285e+00, 1.0074800425004574e+01, 1.0291954019502739e+01, 1.0511477422708499e+01, 1.0733531661229089e+01, 1.0958295048610227e+01, 1.1185966011702471e+01, 1.1416766545164455e+01, 1.1650946475122105e+01, 1.1888788778454018e+01, 1.2130616298680719e+01, 1.2376800338602001e+01, 1.2627771819287853e+01, 1.2884036018123565e+01, 1.3146192411007465e+01, 1.3414961982530070e+01, 1.3691225791789593e+01, 1.3976081103348914e+01, 1.4270926089044083e+01, 1.4577593394280033e+01, 1.4898572639500255e+01, 1.5237408147560531e+01, 1.5599480189464179e+01, 1.5993758950122626e+01, 1.6437651167348605e+01, 1.6976716163194499e+01}, + {-1.7033920616481659e+01, -1.6495453932662432e+01, -1.6052065819662449e+01, -1.5658243778058655e+01, -1.5296598801743723e+01, -1.4958169779028550e+01, -1.4637581850310665e+01, -1.4331294242121345e+01, -1.4036819819586414e+01, -1.3752327763757672e+01, -1.3476421295676769e+01, -1.3208004244970210e+01, -1.2946196433284063e+01, -1.2690277599628986e+01, -1.2439648873125966e+01, -1.2193805490052643e+01, -1.1952316971370964e+01, -1.1714812399295406e+01, -1.1480969269340585e+01, -1.1250504906165974e+01, -1.1023169754304320e+01, -1.0798742064110225e+01, -1.0577023632291938e+01, -1.0357836350801911e+01, -1.0141019383247183e+01, -9.9264268340723447e+00, -9.7139258087846567e+00, -9.5033947874905458e+00, -9.2947222516928303e+00, -9.0878055174840568e+00, -8.8825497382175893e+00, -8.6788670473198550e+00, -8.4766758177429260e+00, -8.2759000190893772e+00, -8.0764686569918620e+00, -7.8783152821330633e+00, -7.6813775585211594e+00, -7.4855968824216461e+00, -7.2909180447858821e+00, -7.0972889311843357e+00, -6.9046602542051492e+00, -6.7129853140601305e+00, -6.5222197837846556e+00, -6.3323215159520476e+00, -6.1432503682675650e+00, -5.9549680457789771e+00, -5.7674379577529349e+00, -5.5806250875296657e+00, -5.3944958738913487e+00, -5.2090181026688498e+00, -5.0241608074728896e+00, -4.8398941785737106e+00, -4.6561894790717648e+00, -4.4730189676038190e+00, -4.2903558269168203e+00, -4.1081740977179662e+00, -3.9264486172753981e+00, -3.7451549623013909e+00, -3.5642693956998519e+00, -3.3837688168037010e+00, -3.2036307147658607e+00, -3.0238331248011101e+00, -2.8443545870054412e+00, -2.6651741075053921e+00, -2.4862711217125546e+00, -2.3076254594784578e+00, -2.1292173119626474e+00, -1.9510272000422848e+00, -1.7730359441052344e+00, -1.5952246350806079e+00, -1.4175746065712449e+00, -1.2400674079618077e+00, -1.0626847783841744e+00, -8.8540862142874210e-01, -7.0822098049619520e-01, -5.3110401468933777e-01, -3.5403997514879265e-01, -1.7701118173979521e-01, -0.0000000000000000e+00, 1.7701118173979521e-01, 3.5403997514879265e-01, 5.3110401468933777e-01, 7.0822098049619520e-01, 8.8540862142874210e-01, 1.0626847783841744e+00, 1.2400674079618077e+00, 1.4175746065712449e+00, 1.5952246350806079e+00, 1.7730359441052344e+00, 1.9510272000422848e+00, 2.1292173119626474e+00, 2.3076254594784578e+00, 2.4862711217125546e+00, 2.6651741075053921e+00, 2.8443545870054412e+00, 3.0238331248011101e+00, 3.2036307147658607e+00, 3.3837688168037010e+00, 3.5642693956998519e+00, 3.7451549623013909e+00, 3.9264486172753981e+00, 4.1081740977179662e+00, 4.2903558269168203e+00, 4.4730189676038190e+00, 4.6561894790717648e+00, 4.8398941785737106e+00, 5.0241608074728896e+00, 5.2090181026688498e+00, 5.3944958738913487e+00, 5.5806250875296657e+00, 5.7674379577529349e+00, 5.9549680457789771e+00, 6.1432503682675650e+00, 6.3323215159520476e+00, 6.5222197837846556e+00, 6.7129853140601305e+00, 6.9046602542051492e+00, 7.0972889311843357e+00, 7.2909180447858821e+00, 7.4855968824216461e+00, 7.6813775585211594e+00, 7.8783152821330633e+00, 8.0764686569918620e+00, 8.2759000190893772e+00, 8.4766758177429260e+00, 8.6788670473198550e+00, 8.8825497382175893e+00, 9.0878055174840568e+00, 9.2947222516928303e+00, 9.5033947874905458e+00, 9.7139258087846567e+00, 9.9264268340723447e+00, 1.0141019383247183e+01, 1.0357836350801911e+01, 1.0577023632291938e+01, 1.0798742064110225e+01, 1.1023169754304320e+01, 1.1250504906165974e+01, 1.1480969269340585e+01, 1.1714812399295406e+01, 1.1952316971370964e+01, 1.2193805490052643e+01, 1.2439648873125966e+01, 1.2690277599628986e+01, 1.2946196433284063e+01, 1.3208004244970210e+01, 1.3476421295676769e+01, 1.3752327763757672e+01, 1.4036819819586414e+01, 1.4331294242121345e+01, 1.4637581850310665e+01, 1.4958169779028550e+01, 1.5296598801743723e+01, 1.5658243778058655e+01, 1.6052065819662449e+01, 1.6495453932662432e+01, 1.7033920616481659e+01}, + {-1.7090940441818589e+01, -1.6553067510081998e+01, -1.6110179595706111e+01, -1.5716810683887498e+01, -1.5355589372841228e+01, -1.5017563559089020e+01, -1.4697363755671436e+01, -1.4391452713037102e+01, -1.4097345763967498e+01, -1.3813213902715583e+01, -1.3537661732992635e+01, -1.3269594170493015e+01, -1.3008131910966144e+01, -1.2752555411464087e+01, -1.2502266401375357e+01, -1.2256760626504082e+01, -1.2015608046183521e+01, -1.1778438124354272e+01, -1.1544928692572215e+01, -1.1314797374275166e+01, -1.1087794882081830e+01, -1.0863699708936927e+01, -1.0642313872803815e+01, -1.0423459468924202e+01, -1.0206975848984905e+01, -9.9927172925773995e+00, -9.7805510693200404e+00, -9.5703558139886304e+00, -9.3620201546636572e+00, -9.1554415470755703e+00, -8.9505252782658893e+00, -8.7471836102562435e+00, -8.5453350402475099e+00, -8.3449036583995202e+00, -8.1458185877888383e+00, -7.9480134939425788e+00, -7.7514261535735791e+00, -7.5559980739261903e+00, -7.3616741555800598e+00, -7.1684023927258176e+00, -6.9761336058782426e+00, -6.7848212027732666e+00, -6.5944209638389415e+00, -6.4048908491640280e+00, -6.2161908243320640e+00, -6.0282827028602410e+00, -5.8411300032943645e+00, -5.6546978192742712e+00, -5.4689527011066783e+00, -5.2838625475716334e+00, -5.0993965068499545e+00, -4.9155248855969580e+00, -4.7322190653061282e+00, -4.5494514252081650e+00, -4.3671952710387769e+00, -4.1854247690845812e+00, -4.0041148849824761e+00, -3.8232413268052290e+00, -3.6427804920159894e+00, -3.4627094179181652e+00, -3.2830057352652728e+00, -3.1036476247289064e+00, -2.9246137759523689e+00, -2.7458833489433849e+00, -2.5674359375820566e+00, -2.3892515350402799e+00, -2.2113105009265008e+00, -2.0335935299852599e+00, -1.8560816221946776e+00, -1.6787560541171089e+00, -1.5015983513687976e+00, -1.3245902620836472e+00, -1.1477137312543411e+00, -9.7095087584109574e-01, -7.9428396054439432e-01, -6.1769537414325426e-01, -4.4116760630493546e-01, -2.6468322477561551e-01, -8.8224852864438347e-02, 8.8224852864438347e-02, 2.6468322477561551e-01, 4.4116760630493546e-01, 6.1769537414325426e-01, 7.9428396054439432e-01, 9.7095087584109574e-01, 1.1477137312543411e+00, 1.3245902620836472e+00, 1.5015983513687976e+00, 1.6787560541171089e+00, 1.8560816221946776e+00, 2.0335935299852599e+00, 2.2113105009265008e+00, 2.3892515350402799e+00, 2.5674359375820566e+00, 2.7458833489433849e+00, 2.9246137759523689e+00, 3.1036476247289064e+00, 3.2830057352652728e+00, 3.4627094179181652e+00, 3.6427804920159894e+00, 3.8232413268052290e+00, 4.0041148849824761e+00, 4.1854247690845812e+00, 4.3671952710387769e+00, 4.5494514252081650e+00, 4.7322190653061282e+00, 4.9155248855969580e+00, 5.0993965068499545e+00, 5.2838625475716334e+00, 5.4689527011066783e+00, 5.6546978192742712e+00, 5.8411300032943645e+00, 6.0282827028602410e+00, 6.2161908243320640e+00, 6.4048908491640280e+00, 6.5944209638389415e+00, 6.7848212027732666e+00, 6.9761336058782426e+00, 7.1684023927258176e+00, 7.3616741555800598e+00, 7.5559980739261903e+00, 7.7514261535735791e+00, 7.9480134939425788e+00, 8.1458185877888383e+00, 8.3449036583995202e+00, 8.5453350402475099e+00, 8.7471836102562435e+00, 8.9505252782658893e+00, 9.1554415470755703e+00, 9.3620201546636572e+00, 9.5703558139886304e+00, 9.7805510693200404e+00, 9.9927172925773995e+00, 1.0206975848984905e+01, 1.0423459468924202e+01, 1.0642313872803815e+01, 1.0863699708936927e+01, 1.1087794882081830e+01, 1.1314797374275166e+01, 1.1544928692572215e+01, 1.1778438124354272e+01, 1.2015608046183521e+01, 1.2256760626504082e+01, 1.2502266401375357e+01, 1.2752555411464087e+01, 1.3008131910966144e+01, 1.3269594170493015e+01, 1.3537661732992635e+01, 1.3813213902715583e+01, 1.4097345763967498e+01, 1.4391452713037102e+01, 1.4697363755671436e+01, 1.5017563559089020e+01, 1.5355589372841228e+01, 1.5716810683887498e+01, 1.6110179595706111e+01, 1.6553067510081998e+01, 1.7090940441818589e+01}, + {-1.7147777408524032e+01, -1.6610493732745791e+01, -1.6168102166823996e+01, -1.5775182847088153e+01, -1.5414381850393539e+01, -1.5076756017330117e+01, -1.4756941195343936e+01, -1.4451403633675961e+01, -1.4157661115094985e+01, -1.3873886433984071e+01, -1.3598685566661047e+01, -1.3330964506884797e+01, -1.3069844817966612e+01, -1.2814607669526135e+01, -1.2564655386543684e+01, -1.2319484220282153e+01, -1.2078664564848737e+01, -1.1841826262681151e+01, -1.1608647478438799e+01, -1.1378846131631990e+01, -1.1152173200444981e+01, -1.0928407418040756e+01, -1.0707351021384738e+01, -1.0488826306849386e+01, -1.0272672812117237e+01, -1.0058744989900266e+01, -9.8469102719449655e+00, -9.6370474457447699e+00, -9.4290452840267438e+00, -9.2228013802394901e+00, -9.0182211531960341e+00, -8.8152169915922389e+00, -8.6137075149457782e+00, -8.4136169320244640e+00, -8.2148744813764658e+00, -8.0174139413725705e+00, -7.8211731993958935e+00, -7.6260938715966651e+00, -7.4321209660664360e+00, -7.2392025834514619e+00, -7.0472896499758120e+00, -6.8563356786247329e+00, -6.6662965548819884e+00, -6.4771303439479562e+00, -6.2887971168089667e+00, -6.1012587928995696e+00, -5.9144789974110621e+00, -5.7284229315624149e+00, -5.5430572543722416e+00, -5.3583499746593573e+00, -5.1742703521606801e+00, -4.9907888067929420e+00, -4.8078768352029666e+00, -4.6255069338529911e+00, -4.4436525279753418e+00, -4.2622879058067751e+00, -4.0813881575787159e+00, -3.9009291187969852e+00, -3.7208873173946002e+00, -3.5412399243848873e+00, -3.3619647076803778e+00, -3.1830399887764611e+00, -3.0044446020282125e+00, -2.8261578562746821e+00, -2.6481594985877317e+00, -2.4704296799425793e+00, -2.2929489226249280e+00, -2.1156980892051682e+00, -1.9386583529239170e+00, -1.7618111693452876e+00, -1.5851382491449768e+00, -1.4086215319096145e+00, -1.2322431608320461e+00, -1.0559854581943640e+00, -8.7983090153669952e-01, -7.0376210041511855e-01, -5.2776177365646371e-01, -3.5181272702177707e-01, -1.7589783119299077e-01, -0.0000000000000000e+00, 1.7589783119299077e-01, 3.5181272702177707e-01, 5.2776177365646371e-01, 7.0376210041511855e-01, 8.7983090153669952e-01, 1.0559854581943640e+00, 1.2322431608320461e+00, 1.4086215319096145e+00, 1.5851382491449768e+00, 1.7618111693452876e+00, 1.9386583529239170e+00, 2.1156980892051682e+00, 2.2929489226249280e+00, 2.4704296799425793e+00, 2.6481594985877317e+00, 2.8261578562746821e+00, 3.0044446020282125e+00, 3.1830399887764611e+00, 3.3619647076803778e+00, 3.5412399243848873e+00, 3.7208873173946002e+00, 3.9009291187969852e+00, 4.0813881575787159e+00, 4.2622879058067751e+00, 4.4436525279753418e+00, 4.6255069338529911e+00, 4.8078768352029666e+00, 4.9907888067929420e+00, 5.1742703521606801e+00, 5.3583499746593573e+00, 5.5430572543722416e+00, 5.7284229315624149e+00, 5.9144789974110621e+00, 6.1012587928995696e+00, 6.2887971168089667e+00, 6.4771303439479562e+00, 6.6662965548819884e+00, 6.8563356786247329e+00, 7.0472896499758120e+00, 7.2392025834514619e+00, 7.4321209660664360e+00, 7.6260938715966651e+00, 7.8211731993958935e+00, 8.0174139413725705e+00, 8.2148744813764658e+00, 8.4136169320244640e+00, 8.6137075149457782e+00, 8.8152169915922389e+00, 9.0182211531960341e+00, 9.2228013802394901e+00, 9.4290452840267438e+00, 9.6370474457447699e+00, 9.8469102719449655e+00, 1.0058744989900266e+01, 1.0272672812117237e+01, 1.0488826306849386e+01, 1.0707351021384738e+01, 1.0928407418040756e+01, 1.1152173200444981e+01, 1.1378846131631990e+01, 1.1608647478438799e+01, 1.1841826262681151e+01, 1.2078664564848737e+01, 1.2319484220282153e+01, 1.2564655386543684e+01, 1.2814607669526135e+01, 1.3069844817966612e+01, 1.3330964506884797e+01, 1.3598685566661047e+01, 1.3873886433984071e+01, 1.4157661115094985e+01, 1.4451403633675961e+01, 1.4756941195343936e+01, 1.5076756017330117e+01, 1.5414381850393539e+01, 1.5775182847088153e+01, 1.6168102166823996e+01, 1.6610493732745791e+01, 1.7147777408524032e+01}, + {-1.7204433257886514e+01, -1.6667734404468501e+01, -1.6225835391124875e+01, -1.5833362176266244e+01, -1.5472978191373558e+01, -1.5135749157814335e+01, -1.4816316219712570e+01, -1.4511149100314286e+01, -1.4217768014947598e+01, -1.3934347545235219e+01, -1.3659495030180320e+01, -1.3392117533718560e+01, -1.3131337480278725e+01, -1.2876436746658081e+01, -1.2626818248827179e+01, -1.2381978739506893e+01, -1.2141489044042531e+01, -1.1904979380197393e+01, -1.1672128242851137e+01, -1.1442653844932979e+01, -1.1216307427723020e+01, -1.0992867962280265e+01, -1.0772137902368133e+01, -1.0553939743380022e+01, -1.0338113206958853e+01, -1.0124512916959700e+01, -9.9130064653237309e+00, -9.7034727903605109e+00, -9.4958008075637199e+00, -9.2898882462326107e+00, -9.0856406550885644e+00, -8.8829705476356562e+00, -8.6817966638328432e+00, -8.4820433291649113e+00, -8.2836398957394959e+00, -8.0865202528325053e+00, -7.8906223965273750e+00, -7.6958880498740347e+00, -7.5022623264288848e+00, -7.3096934312013273e+00, -7.1181323939823153e+00, -6.9275328308096045e+00, -6.7378507299670023e+00, -6.5490442594474336e+00, -6.3610735932529767e+00, -6.1739007542758424e+00, -5.9874894718156684e+00, -5.8018050520510185e+00, -5.6168142600053486e+00, -5.4324852117363971e+00, -5.2487872756390139e+00, -5.0656909818891060e+00, -4.8831679391745020e+00, -4.7011907579602283e+00, -4.5197329796234431e+00, -4.3387690108692292e+00, -4.1582740629043391e+00, -3.9782240949032923e+00, -3.7985957613512462e+00, -3.6193663628916424e+00, -3.4405138003449269e+00, -3.2620165315981051e+00, -3.0838535310943649e+00, -2.9060042516778903e+00, -2.7284485885718048e+00, -2.5511668452873062e+00, -2.3741397012797925e+00, -2.1973481811834414e+00, -2.0207736254695439e+00, -1.8443976623860776e+00, -1.6682021810467551e+00, -1.4921693055472409e+00, -1.3162813699945290e+00, -1.1405208943427161e+00, -9.6487056093471757e-01, -7.8931319165491054e-01, -6.1383172560234123e-01, -4.3840919719805421e-01, -2.6302871464332994e-01, -8.7673438648223800e-02, 8.7673438648223800e-02, 2.6302871464332994e-01, 4.3840919719805421e-01, 6.1383172560234123e-01, 7.8931319165491054e-01, 9.6487056093471757e-01, 1.1405208943427161e+00, 1.3162813699945290e+00, 1.4921693055472409e+00, 1.6682021810467551e+00, 1.8443976623860776e+00, 2.0207736254695439e+00, 2.1973481811834414e+00, 2.3741397012797925e+00, 2.5511668452873062e+00, 2.7284485885718048e+00, 2.9060042516778903e+00, 3.0838535310943649e+00, 3.2620165315981051e+00, 3.4405138003449269e+00, 3.6193663628916424e+00, 3.7985957613512462e+00, 3.9782240949032923e+00, 4.1582740629043391e+00, 4.3387690108692292e+00, 4.5197329796234431e+00, 4.7011907579602283e+00, 4.8831679391745020e+00, 5.0656909818891060e+00, 5.2487872756390139e+00, 5.4324852117363971e+00, 5.6168142600053486e+00, 5.8018050520510185e+00, 5.9874894718156684e+00, 6.1739007542758424e+00, 6.3610735932529767e+00, 6.5490442594474336e+00, 6.7378507299670023e+00, 6.9275328308096045e+00, 7.1181323939823153e+00, 7.3096934312013273e+00, 7.5022623264288848e+00, 7.6958880498740347e+00, 7.8906223965273750e+00, 8.0865202528325053e+00, 8.2836398957394959e+00, 8.4820433291649113e+00, 8.6817966638328432e+00, 8.8829705476356562e+00, 9.0856406550885644e+00, 9.2898882462326107e+00, 9.4958008075637199e+00, 9.7034727903605109e+00, 9.9130064653237309e+00, 1.0124512916959700e+01, 1.0338113206958853e+01, 1.0553939743380022e+01, 1.0772137902368133e+01, 1.0992867962280265e+01, 1.1216307427723020e+01, 1.1442653844932979e+01, 1.1672128242851137e+01, 1.1904979380197393e+01, 1.2141489044042531e+01, 1.2381978739506893e+01, 1.2626818248827179e+01, 1.2876436746658081e+01, 1.3131337480278725e+01, 1.3392117533718560e+01, 1.3659495030180320e+01, 1.3934347545235219e+01, 1.4217768014947598e+01, 1.4511149100314286e+01, 1.4816316219712570e+01, 1.5135749157814335e+01, 1.5472978191373558e+01, 1.5833362176266244e+01, 1.6225835391124875e+01, 1.6667734404468501e+01, 1.7204433257886514e+01}, + {-1.7260909703781458e+01, -1.6724791300392337e+01, -1.6283381096937688e+01, -1.5891350549206285e+01, -1.5531380320925585e+01, -1.5194544951785256e+01, -1.4875490845359661e+01, -1.4570691174443654e+01, -1.4277668569732091e+01, -1.3994599387373768e+01, -1.3720092319274791e+01, -1.3453055491772846e+01, -1.3192612184064762e+01, -1.2938044974817329e+01, -1.2688757366462070e+01, -1.2444246609242258e+01, -1.2204083956265350e+01, -1.1967899997504619e+01, -1.1735373555229600e+01, -1.1506223133185523e+01, -1.1280200233327742e+01, -1.1057084062337088e+01, -1.0836677288618299e+01, -1.0618802604522946e+01, -1.0403299913666036e+01, -1.0190024009115621e+01, -9.9788426411218261e+00, -9.7696348969572284e+00, -9.5622898330514161e+00, -9.3567053127370503e+00, -9.1527870128321815e+00, -8.9504475698358625e+00, -8.7496058423271297e+00, -8.5501862706726577e+00, -8.3521183186851253e+00, -8.1553359846666886e+00, -7.9597773714928959e+00, -7.7653843071712023e+00, -7.5721020087422000e+00, -7.3798787835549238e+00, -7.1886657628964983e+00, -6.9984166637349920e+00, -6.8090875749762771e+00, -6.6206367651677347e+00, -6.4330245090246105e+00, -6.2462129305252470e+00, -6.0601658606325453e+00, -5.8748487079613687e+00, -5.6902283409336283e+00, -5.5062729801514685e+00, -5.3229520998798137e+00, -5.1402363376670781e+00, -4.9580974112509208e+00, -4.7765080419975057e+00, -4.5954418842104330e+00, -4.4148734597213917e+00, -4.2347780972404623e+00, -4.0551318760012771e+00, -3.8759115732862068e+00, -3.6970946154603719e+00, -3.5186590321815130e+00, -3.3405834134862555e+00, -3.1628468694827729e+00, -2.9854289924057533e+00, -2.8083098208124282e+00, -2.6314698057185479e+00, -2.4548897784909895e+00, -2.2785509203293697e+00, -2.1024347331829158e+00, -1.9265230119611116e+00, -1.7507978179074160e+00, -1.5752414530149108e+00, -1.3998364353710842e+00, -1.2245654753263127e+00, -1.0494114523869875e+00, -8.7435739273980528e-01, -6.9938644731849353e-01, -5.2448187032830795e-01, -3.4962699814701426e-01, -1.7480522852383426e-01, -0.0000000000000000e+00, 1.7480522852383426e-01, 3.4962699814701426e-01, 5.2448187032830795e-01, 6.9938644731849353e-01, 8.7435739273980528e-01, 1.0494114523869875e+00, 1.2245654753263127e+00, 1.3998364353710842e+00, 1.5752414530149108e+00, 1.7507978179074160e+00, 1.9265230119611116e+00, 2.1024347331829158e+00, 2.2785509203293697e+00, 2.4548897784909895e+00, 2.6314698057185479e+00, 2.8083098208124282e+00, 2.9854289924057533e+00, 3.1628468694827729e+00, 3.3405834134862555e+00, 3.5186590321815130e+00, 3.6970946154603719e+00, 3.8759115732862068e+00, 4.0551318760012771e+00, 4.2347780972404623e+00, 4.4148734597213917e+00, 4.5954418842104330e+00, 4.7765080419975057e+00, 4.9580974112509208e+00, 5.1402363376670781e+00, 5.3229520998798137e+00, 5.5062729801514685e+00, 5.6902283409336283e+00, 5.8748487079613687e+00, 6.0601658606325453e+00, 6.2462129305252470e+00, 6.4330245090246105e+00, 6.6206367651677347e+00, 6.8090875749762771e+00, 6.9984166637349920e+00, 7.1886657628964983e+00, 7.3798787835549238e+00, 7.5721020087422000e+00, 7.7653843071712023e+00, 7.9597773714928959e+00, 8.1553359846666886e+00, 8.3521183186851253e+00, 8.5501862706726577e+00, 8.7496058423271297e+00, 8.9504475698358625e+00, 9.1527870128321815e+00, 9.3567053127370503e+00, 9.5622898330514161e+00, 9.7696348969572284e+00, 9.9788426411218261e+00, 1.0190024009115621e+01, 1.0403299913666036e+01, 1.0618802604522946e+01, 1.0836677288618299e+01, 1.1057084062337088e+01, 1.1280200233327742e+01, 1.1506223133185523e+01, 1.1735373555229600e+01, 1.1967899997504619e+01, 1.2204083956265350e+01, 1.2444246609242258e+01, 1.2688757366462070e+01, 1.2938044974817329e+01, 1.3192612184064762e+01, 1.3453055491772846e+01, 1.3720092319274791e+01, 1.3994599387373768e+01, 1.4277668569732091e+01, 1.4570691174443654e+01, 1.4875490845359661e+01, 1.5194544951785256e+01, 1.5531380320925585e+01, 1.5891350549206285e+01, 1.6283381096937688e+01, 1.6724791300392337e+01, 1.7260909703781458e+01}, + {-1.7317208433270949e+01, -1.6781666167619914e+01, -1.6340741083473855e+01, -1.5949149813561979e+01, -1.5589590133082927e+01, -1.5253145338412237e+01, -1.4934467055837311e+01, -1.4630031883570041e+01, -1.4337364850710150e+01, -1.4054644075392147e+01, -1.3780479592778537e+01, -1.3513780583944808e+01, -1.3253671176599115e+01, -1.2999434646049597e+01, -1.2750475076730016e+01, -1.2506290212533999e+01, -1.2266451730913499e+01, -1.2030590590990464e+01, -1.1798385939645330e+01, -1.1569556568885659e+01, -1.1343854238969067e+01, -1.1121058389970566e+01, -1.0900971902825360e+01, -1.0683417664825948e+01, -1.0468235759616565e+01, -1.0255281147593752e+01, -1.0044421735476904e+01, -9.8355367576951434e+00, -9.6285154098307064e+00, -9.4232556874808058e+00, -9.2196633937979797e+00, -9.0176512865137788e+00, -8.8171383410582820e+00, -8.6180491108986974e+00, -8.4203131697537437e+00, -8.2238646231301775e+00, -8.0286416788466841e+00, -7.8345862679873983e+00, -7.6416437091600784e+00, -7.4497624100959028e+00, -7.2588936015760819e+00, -7.0689910994481711e+00, -6.8800110911364190e+00, -6.6919119435819789e+00, -6.5046540299913760e+00, -6.3181995731417278e+00, -6.1325125033020340e+00, -5.9475583290919758e+00, -5.7633040198215193e+00, -5.5797178980431177e+00, -5.3967695412089913e+00, -5.2144296914634500e+00, -5.0326701727181335e+00, -4.8514638142596134e+00, -4.6707843802263858e+00, -4.4906065043681664e+00, -4.3109056295662098e+00, -4.1316579516506131e+00, -3.9528403671005403e+00, -3.7744304242568925e+00, -3.5964062777151744e+00, -3.4187466455998319e+00, -3.2414307694507918e+00, -3.0644383764788512e+00, -2.8877496439694483e+00, -2.7113451656344782e+00, -2.5352059197296661e+00, -2.3593132387707172e+00, -2.1836487806954117e+00, -2.0081945013310838e+00, -1.8329326280378133e+00, -1.6578456344072345e+00, -1.4829162159053173e+00, -1.3081272663548922e+00, -1.1334618551601847e+00, -9.5890320518127026e-01, -7.8443467117124477e-01, -6.1003971869307638e-01, -4.3570190343662574e-01, -2.6140485085923082e-01, -8.7132236075583736e-02, 8.7132236075583736e-02, 2.6140485085923082e-01, 4.3570190343662574e-01, 6.1003971869307638e-01, 7.8443467117124477e-01, 9.5890320518127026e-01, 1.1334618551601847e+00, 1.3081272663548922e+00, 1.4829162159053173e+00, 1.6578456344072345e+00, 1.8329326280378133e+00, 2.0081945013310838e+00, 2.1836487806954117e+00, 2.3593132387707172e+00, 2.5352059197296661e+00, 2.7113451656344782e+00, 2.8877496439694483e+00, 3.0644383764788512e+00, 3.2414307694507918e+00, 3.4187466455998319e+00, 3.5964062777151744e+00, 3.7744304242568925e+00, 3.9528403671005403e+00, 4.1316579516506131e+00, 4.3109056295662098e+00, 4.4906065043681664e+00, 4.6707843802263858e+00, 4.8514638142596134e+00, 5.0326701727181335e+00, 5.2144296914634500e+00, 5.3967695412089913e+00, 5.5797178980431177e+00, 5.7633040198215193e+00, 5.9475583290919758e+00, 6.1325125033020340e+00, 6.3181995731417278e+00, 6.5046540299913760e+00, 6.6919119435819789e+00, 6.8800110911364190e+00, 7.0689910994481711e+00, 7.2588936015760819e+00, 7.4497624100959028e+00, 7.6416437091600784e+00, 7.8345862679873983e+00, 8.0286416788466841e+00, 8.2238646231301775e+00, 8.4203131697537437e+00, 8.6180491108986974e+00, 8.8171383410582820e+00, 9.0176512865137788e+00, 9.2196633937979797e+00, 9.4232556874808058e+00, 9.6285154098307064e+00, 9.8355367576951434e+00, 1.0044421735476904e+01, 1.0255281147593752e+01, 1.0468235759616565e+01, 1.0683417664825948e+01, 1.0900971902825360e+01, 1.1121058389970566e+01, 1.1343854238969067e+01, 1.1569556568885659e+01, 1.1798385939645330e+01, 1.2030590590990464e+01, 1.2266451730913499e+01, 1.2506290212533999e+01, 1.2750475076730016e+01, 1.2999434646049597e+01, 1.3253671176599115e+01, 1.3513780583944808e+01, 1.3780479592778537e+01, 1.4054644075392147e+01, 1.4337364850710150e+01, 1.4630031883570041e+01, 1.4934467055837311e+01, 1.5253145338412237e+01, 1.5589590133082927e+01, 1.5949149813561979e+01, 1.6340741083473855e+01, 1.6781666167619914e+01, 1.7317208433270949e+01}, + {-1.7373331107186754e+01, -1.6838360725829279e+01, -1.6397917121470808e+01, -1.6006761787526802e+01, -1.5647609491464893e+01, -1.5311552225513632e+01, -1.4993246802416799e+01, -1.4689173221989655e+01, -1.4396858895000966e+01, -1.4114483689200235e+01, -1.3840658973492838e+01, -1.3574294976135944e+01, -1.3314516667182943e+01, -1.3060608013433232e+01, -1.2811973676932878e+01, -1.2568111891415747e+01, -1.2328594755317379e+01, -1.2093053593899976e+01, -1.1861167875925814e+01, -1.1632656679158853e+01, -1.1407272019832192e+01, -1.1184793569232429e+01, -1.0965024418758787e+01, -1.0747787648671435e+01, -1.0532923520744902e+01, -1.0320287160863774e+01, -1.0109746630421466e+01, -9.9011813092421690e+00, -9.6944805303231938e+00, -9.4895424198040619e+00, -9.2862729054572402e+00, -9.0845848645331397e+00, -8.8843973875939959e+00, -8.6856351394777924e+00, -8.4882278020634931e+00, -8.2921095862957674e+00, -8.0972188031442496e+00, -7.9034974849477484e+00, -7.7108910500251024e+00, -7.5193480045954200e+00, -7.3288196769976075e+00, -7.1392599799761927e+00, -6.9506251974411839e+00, -6.7628737926408222e+00, -6.5759662351281483e+00, -6.3898648442721324e+00, -6.2045336473746264e+00, -6.0199382507162937e+00, -5.8360457220763333e+00, -5.6528244834591428e+00, -5.4702442129216378e+00, -5.2882757545322603e+00, -5.1068910356106052e+00, -4.9260629904980000e+00, -4.7457654901969706e+00, -4.5659732772932937e+00, -4.3866619056401390e+00, -4.2078076843410157e+00, -4.0293876256181580e+00, -3.8513793961965916e+00, -3.6737612718723360e+00, -3.4965120949666812e+00, -3.3196112343979944e+00, -3.1430385481283984e+00, -2.9667743477655746e+00, -2.7907993651201082e+00, -2.6150947205366424e+00, -2.4396418928328796e+00, -2.2644226906944231e+00, -2.0894192253858019e+00, -1.9146138846489213e+00, -1.7399893076698572e+00, -1.5655283610033905e+00, -1.3912141153521926e+00, -1.2170298231041317e+00, -1.0429588965369114e+00, -8.6898488660423323e-01, -6.9509146222196017e-01, -5.2126238997639096e-01, -3.4748151417981160e-01, -1.7373273720096005e-01, -0.0000000000000000e+00, 1.7373273720096005e-01, 3.4748151417981160e-01, 5.2126238997639096e-01, 6.9509146222196017e-01, 8.6898488660423323e-01, 1.0429588965369114e+00, 1.2170298231041317e+00, 1.3912141153521926e+00, 1.5655283610033905e+00, 1.7399893076698572e+00, 1.9146138846489213e+00, 2.0894192253858019e+00, 2.2644226906944231e+00, 2.4396418928328796e+00, 2.6150947205366424e+00, 2.7907993651201082e+00, 2.9667743477655746e+00, 3.1430385481283984e+00, 3.3196112343979944e+00, 3.4965120949666812e+00, 3.6737612718723360e+00, 3.8513793961965916e+00, 4.0293876256181580e+00, 4.2078076843410157e+00, 4.3866619056401390e+00, 4.5659732772932937e+00, 4.7457654901969706e+00, 4.9260629904980000e+00, 5.1068910356106052e+00, 5.2882757545322603e+00, 5.4702442129216378e+00, 5.6528244834591428e+00, 5.8360457220763333e+00, 6.0199382507162937e+00, 6.2045336473746264e+00, 6.3898648442721324e+00, 6.5759662351281483e+00, 6.7628737926408222e+00, 6.9506251974411839e+00, 7.1392599799761927e+00, 7.3288196769976075e+00, 7.5193480045954200e+00, 7.7108910500251024e+00, 7.9034974849477484e+00, 8.0972188031442496e+00, 8.2921095862957674e+00, 8.4882278020634931e+00, 8.6856351394777924e+00, 8.8843973875939959e+00, 9.0845848645331397e+00, 9.2862729054572402e+00, 9.4895424198040619e+00, 9.6944805303231938e+00, 9.9011813092421690e+00, 1.0109746630421466e+01, 1.0320287160863774e+01, 1.0532923520744902e+01, 1.0747787648671435e+01, 1.0965024418758787e+01, 1.1184793569232429e+01, 1.1407272019832192e+01, 1.1632656679158853e+01, 1.1861167875925814e+01, 1.2093053593899976e+01, 1.2328594755317379e+01, 1.2568111891415747e+01, 1.2811973676932878e+01, 1.3060608013433232e+01, 1.3314516667182943e+01, 1.3574294976135944e+01, 1.3840658973492838e+01, 1.4114483689200235e+01, 1.4396858895000966e+01, 1.4689173221989655e+01, 1.4993246802416799e+01, 1.5311552225513632e+01, 1.5647609491464893e+01, 1.6006761787526802e+01, 1.6397917121470808e+01, 1.6838360725829279e+01, 1.7373331107186754e+01}, + {-1.7429279360697116e+01, -1.6894876667871738e+01, -1.6454910953817389e+01, -1.6064188260485547e+01, -1.5705440229953897e+01, -1.5369767490259161e+01, -1.5051832004816319e+01, -1.4748117151542182e+01, -1.4456152706360307e+01, -1.4174120274430678e+01, -1.3900632549018214e+01, -1.3634600798111430e+01, -1.3375150828031479e+01, -1.3121567291995134e+01, -1.2873255425338009e+01, -1.2629713947884454e+01, -1.2390515375747968e+01, -1.2155291397374004e+01, -1.1923721800726158e+01, -1.1695525946865237e+01, -1.1470456105717808e+01, -1.1248292177643179e+01, -1.1028837462481100e+01, -1.0811915231528733e+01, -1.0597365922834403e+01, -1.0385044825972880e+01, -1.0174820155259216e+01, -9.9665714341945719e+00, -9.7601881314978272e+00, -9.5555685021734451e+00, -9.3526185969451436e+00, -9.1512514109155187e+00, -8.9513861481082948e+00, -8.7529475830520980e+00, -8.5558655040914431e+00, -8.3600742258949641e+00, -8.1655121608455978e+00, -7.9721214407712111e+00, -7.7798475819041020e+00, -7.5886391871177059e+00, -7.3984476804351802e+00, -7.2092270695808969e+00, -7.0209337329860251e+00, -6.8335262281900011e+00, -6.6469651190213561e+00, -6.4612128193108518e+00, -6.2762334512001194e+00, -6.0919927163706555e+00, -5.9084577787394661e+00, -5.7255971573558835e+00, -5.5433806283944191e+00, -5.3617791352758264e+00, -5.1807647060662454e+00, -5.0003103774057065e+00, -4.8203901243047591e+00, -4.6409787952237167e+00, -4.4620520519147870e+00, -4.2835863135645020e+00, -4.1055587048237943e+00, -3.9279470073566172e+00, -3.7507296145762479e+00, -3.5738854892718694e+00, -3.3973941238575383e+00, -3.2212355030015671e+00, -3.0453900684172543e+00, -2.8698386856160685e+00, -2.6945626124422972e+00, -2.5195434692239367e+00, -2.3447632103886216e+00, -2.1702040974057377e+00, -1.9958486729268685e+00, -1.8216797360063830e+00, -1.6476803182925728e+00, -1.4738336610872771e+00, -1.3001231931786021e+00, -1.1265325093571319e+00, -9.5304534953113307e-01, -7.7964557836059989e-01, -6.0631716533377134e-01, -4.3304416521289407e-01, -2.5981069877863450e-01, -8.6600933804640304e-02, 8.6600933804640304e-02, 2.5981069877863450e-01, 4.3304416521289407e-01, 6.0631716533377134e-01, 7.7964557836059989e-01, 9.5304534953113307e-01, 1.1265325093571319e+00, 1.3001231931786021e+00, 1.4738336610872771e+00, 1.6476803182925728e+00, 1.8216797360063830e+00, 1.9958486729268685e+00, 2.1702040974057377e+00, 2.3447632103886216e+00, 2.5195434692239367e+00, 2.6945626124422972e+00, 2.8698386856160685e+00, 3.0453900684172543e+00, 3.2212355030015671e+00, 3.3973941238575383e+00, 3.5738854892718694e+00, 3.7507296145762479e+00, 3.9279470073566172e+00, 4.1055587048237943e+00, 4.2835863135645020e+00, 4.4620520519147870e+00, 4.6409787952237167e+00, 4.8203901243047591e+00, 5.0003103774057065e+00, 5.1807647060662454e+00, 5.3617791352758264e+00, 5.5433806283944191e+00, 5.7255971573558835e+00, 5.9084577787394661e+00, 6.0919927163706555e+00, 6.2762334512001194e+00, 6.4612128193108518e+00, 6.6469651190213561e+00, 6.8335262281900011e+00, 7.0209337329860251e+00, 7.2092270695808969e+00, 7.3984476804351802e+00, 7.5886391871177059e+00, 7.7798475819041020e+00, 7.9721214407712111e+00, 8.1655121608455978e+00, 8.3600742258949641e+00, 8.5558655040914431e+00, 8.7529475830520980e+00, 8.9513861481082948e+00, 9.1512514109155187e+00, 9.3526185969451436e+00, 9.5555685021734451e+00, 9.7601881314978272e+00, 9.9665714341945719e+00, 1.0174820155259216e+01, 1.0385044825972880e+01, 1.0597365922834403e+01, 1.0811915231528733e+01, 1.1028837462481100e+01, 1.1248292177643179e+01, 1.1470456105717808e+01, 1.1695525946865237e+01, 1.1923721800726158e+01, 1.2155291397374004e+01, 1.2390515375747968e+01, 1.2629713947884454e+01, 1.2873255425338009e+01, 1.3121567291995134e+01, 1.3375150828031479e+01, 1.3634600798111430e+01, 1.3900632549018214e+01, 1.4174120274430678e+01, 1.4456152706360307e+01, 1.4748117151542182e+01, 1.5051832004816319e+01, 1.5369767490259161e+01, 1.5705440229953897e+01, 1.6064188260485547e+01, 1.6454910953817389e+01, 1.6894876667871738e+01, 1.7429279360697116e+01}, + {-1.7485054803857970e+01, -1.6951215660353082e+01, -1.6511724296161706e+01, -1.6121430993647511e+01, -1.5763084153353320e+01, -1.5427792979852288e+01, -1.5110224551907818e+01, -1.4806865602342286e+01, -1.4515248255936989e+01, -1.4233555843220696e+01, -1.3960402372562056e+01, -1.3694700144334103e+01, -1.3435575795134914e+01, -1.3182314659599264e+01, -1.2934322542095073e+01, -1.2691098644846306e+01, -1.2452215898392630e+01, -1.2217306351455802e+01, -1.1986050108567399e+01, -1.1758166811670554e+01, -1.1533408982146776e+01, -1.1311556747331544e+01, -1.1092413613523263e+01, -1.0875803041166620e+01, -1.0661565642768281e+01, -1.0449556869836458e+01, -1.0239645087896863e+01, -1.0031709962451384e+01, -9.8256410962894503e+00, -9.6213368716463528e+00, -9.4187034605725390e+00, -9.2176539744013386e+00, -9.0181077289936873e+00, -8.8199896069364012e+00, -8.6232295013939773e+00, -8.4277618290957275e+00, -8.2335251021525675e+00, -8.0404615501699581e+00, -7.8485167855520830e+00, -7.6576395060512166e+00, -7.4677812295616199e+00, -7.2788960569330223e+00, -7.0909404592182668e+00, -6.9038730862998348e+00, -6.7176545942812487e+00, -6.5322474893984905e+00, -6.3476159865165220e+00, -6.1637258805374548e+00, -5.9805444292681393e+00, -5.7980402464829925e+00, -5.6161832040781530e+00, -5.4349443423501533e+00, -5.2542957875499878e+00, -5.0742106759647410e+00, -4.8946630838663463e+00, -4.7156279627427748e+00, -4.5370810792926148e+00, -4.3589989597211884e+00, -4.1813588379261919e+00, -4.0041386072044292e+00, -3.8273167751493955e+00, -3.6508724214429682e+00, -3.4747851582739164e+00, -3.2990350931419172e+00, -3.1236027938286419e+00, -2.9484692553376957e+00, -2.7736158686231027e+00, -2.5990243909418167e+00, -2.4246769176797933e+00, -2.2505558555135576e+00, -2.0766438967802112e+00, -1.9029239949385686e+00, -1.7293793410127316e+00, -1.5559933409170248e+00, -1.3827495935679281e+00, -1.2096318696945301e+00, -1.0366240912641824e+00, -8.6371031144450516e-01, -6.9087469502674481e-01, -5.1810149923876170e-01, -3.4537505487866837e-01, -1.7267974770236652e-01, -0.0000000000000000e+00, 1.7267974770236652e-01, 3.4537505487866837e-01, 5.1810149923876170e-01, 6.9087469502674481e-01, 8.6371031144450516e-01, 1.0366240912641824e+00, 1.2096318696945301e+00, 1.3827495935679281e+00, 1.5559933409170248e+00, 1.7293793410127316e+00, 1.9029239949385686e+00, 2.0766438967802112e+00, 2.2505558555135576e+00, 2.4246769176797933e+00, 2.5990243909418167e+00, 2.7736158686231027e+00, 2.9484692553376957e+00, 3.1236027938286419e+00, 3.2990350931419172e+00, 3.4747851582739164e+00, 3.6508724214429682e+00, 3.8273167751493955e+00, 4.0041386072044292e+00, 4.1813588379261919e+00, 4.3589989597211884e+00, 4.5370810792926148e+00, 4.7156279627427748e+00, 4.8946630838663463e+00, 5.0742106759647410e+00, 5.2542957875499878e+00, 5.4349443423501533e+00, 5.6161832040781530e+00, 5.7980402464829925e+00, 5.9805444292681393e+00, 6.1637258805374548e+00, 6.3476159865165220e+00, 6.5322474893984905e+00, 6.7176545942812487e+00, 6.9038730862998348e+00, 7.0909404592182668e+00, 7.2788960569330223e+00, 7.4677812295616199e+00, 7.6576395060512166e+00, 7.8485167855520830e+00, 8.0404615501699581e+00, 8.2335251021525675e+00, 8.4277618290957275e+00, 8.6232295013939773e+00, 8.8199896069364012e+00, 9.0181077289936873e+00, 9.2176539744013386e+00, 9.4187034605725390e+00, 9.6213368716463528e+00, 9.8256410962894503e+00, 1.0031709962451384e+01, 1.0239645087896863e+01, 1.0449556869836458e+01, 1.0661565642768281e+01, 1.0875803041166620e+01, 1.1092413613523263e+01, 1.1311556747331544e+01, 1.1533408982146776e+01, 1.1758166811670554e+01, 1.1986050108567399e+01, 1.2217306351455802e+01, 1.2452215898392630e+01, 1.2691098644846306e+01, 1.2934322542095073e+01, 1.3182314659599264e+01, 1.3435575795134914e+01, 1.3694700144334103e+01, 1.3960402372562056e+01, 1.4233555843220696e+01, 1.4515248255936989e+01, 1.4806865602342286e+01, 1.5110224551907818e+01, 1.5427792979852288e+01, 1.5763084153353320e+01, 1.6121430993647511e+01, 1.6511724296161706e+01, 1.6951215660353082e+01, 1.7485054803857970e+01}, + {-1.7540659022148994e+01, -1.7007379344198675e+01, -1.6568358837502078e+01, -1.6178491720661924e+01, -1.5820543038026845e+01, -1.5485630512193200e+01, -1.5168426302403656e+01, -1.4865420473490115e+01, -1.4574147483007465e+01, -1.4292792374971157e+01, -1.4019970463722631e+01, -1.3754595074773901e+01, -1.3495793669093878e+01, -1.3242852257808744e+01, -1.2995177210125478e+01, -1.2752268207034200e+01, -1.2513698590301434e+01, -1.2279100766067012e+01, -1.2048155152843032e+01, -1.1820581671084192e+01, -1.1596133091430600e+01, -1.1374589766138451e+01, -1.1155755406023257e+01, -1.0939453658827642e+01, -1.0725525309740862e+01, -1.0513825970487574e+01, -1.0304224156133158e+01, -1.0096599672544393e+01, -9.8908422549712061e+00, -9.6868504112873062e+00, -9.4845304332878886e+00, -9.2837955469590963e+00, -9.0845651784194441e+00, -8.8867643167273460e+00, -8.6903229582689274e+00, -8.4951756202195732e+00, -8.3012609127831123e+00, -8.1085211616830808e+00, -7.9169020738077709e+00, -7.7263524400685295e+00, -7.5368238704753843e+00, -7.3482705572089442e+00, -7.1606490621065957e+00, -6.9739181255105622e+00, -6.7880384938663552e+00, -6.6029727638288866e+00, -6.4186852409432520e+00, -6.2351418112283552e+00, -6.0523098242126343e+00, -5.8701579861589899e+00, -5.6886562623761669e+00, -5.5077757876508500e+00, -5.3274887839522851e+00, -5.1477684846624596e+00, -4.9685890646722539e+00, -4.7899255757595700e+00, -4.6117538867311527e+00, -4.4340506278668892e+00, -4.2567931392552376e+00, -4.0799594226519913e+00, -3.9035280965327215e+00, -3.7274783540427840e+00, -3.5517899235782049e+00, -3.3764430317567267e+00, -3.2014183685612045e+00, -3.0266970544577654e+00, -2.8522606093090528e+00, -2.6780909229187282e+00, -2.5041702270574335e+00, -2.3304810688329010e+00, -2.1570062852778933e+00, -1.9837289790394881e+00, -1.8106324950618549e+00, -1.6377003981623639e+00, -1.4649164514076216e+00, -1.2922645952019900e+00, -1.1197289270063837e+00, -9.4729368160967065e-01, -7.7494321187896786e-01, -6.0266196991848653e-01, -4.3043448856942984e-01, -2.5824536318581770e-01, -8.6079233622990678e-02, 8.6079233622990678e-02, 2.5824536318581770e-01, 4.3043448856942984e-01, 6.0266196991848653e-01, 7.7494321187896786e-01, 9.4729368160967065e-01, 1.1197289270063837e+00, 1.2922645952019900e+00, 1.4649164514076216e+00, 1.6377003981623639e+00, 1.8106324950618549e+00, 1.9837289790394881e+00, 2.1570062852778933e+00, 2.3304810688329010e+00, 2.5041702270574335e+00, 2.6780909229187282e+00, 2.8522606093090528e+00, 3.0266970544577654e+00, 3.2014183685612045e+00, 3.3764430317567267e+00, 3.5517899235782049e+00, 3.7274783540427840e+00, 3.9035280965327215e+00, 4.0799594226519913e+00, 4.2567931392552376e+00, 4.4340506278668892e+00, 4.6117538867311527e+00, 4.7899255757595700e+00, 4.9685890646722539e+00, 5.1477684846624596e+00, 5.3274887839522851e+00, 5.5077757876508500e+00, 5.6886562623761669e+00, 5.8701579861589899e+00, 6.0523098242126343e+00, 6.2351418112283552e+00, 6.4186852409432520e+00, 6.6029727638288866e+00, 6.7880384938663552e+00, 6.9739181255105622e+00, 7.1606490621065957e+00, 7.3482705572089442e+00, 7.5368238704753843e+00, 7.7263524400685295e+00, 7.9169020738077709e+00, 8.1085211616830808e+00, 8.3012609127831123e+00, 8.4951756202195732e+00, 8.6903229582689274e+00, 8.8867643167273460e+00, 9.0845651784194441e+00, 9.2837955469590963e+00, 9.4845304332878886e+00, 9.6868504112873062e+00, 9.8908422549712061e+00, 1.0096599672544393e+01, 1.0304224156133158e+01, 1.0513825970487574e+01, 1.0725525309740862e+01, 1.0939453658827642e+01, 1.1155755406023257e+01, 1.1374589766138451e+01, 1.1596133091430600e+01, 1.1820581671084192e+01, 1.2048155152843032e+01, 1.2279100766067012e+01, 1.2513698590301434e+01, 1.2752268207034200e+01, 1.2995177210125478e+01, 1.3242852257808744e+01, 1.3495793669093878e+01, 1.3754595074773901e+01, 1.4019970463722631e+01, 1.4292792374971157e+01, 1.4574147483007465e+01, 1.4865420473490115e+01, 1.5168426302403656e+01, 1.5485630512193200e+01, 1.5820543038026845e+01, 1.6178491720661924e+01, 1.6568358837502078e+01, 1.7007379344198675e+01, 1.7540659022148994e+01}, + {-1.7596093576995067e+01, -1.7063369335203092e+01, -1.6624816240761632e+01, -1.6235372148216229e+01, -1.5877818632519856e+01, -1.5543281876523103e+01, -1.5226439085523806e+01, -1.4923783633761518e+01, -1.4632852295689380e+01, -1.4351831817083784e+01, -1.4079338809250348e+01, -1.3814287615693701e+01, -1.3555806515930390e+01, -1.3303182192722531e+01, -1.3055821575985398e+01, -1.2813224821897842e+01, -1.2574965680305057e+01, -1.2340676911954159e+01, -1.2110039246794949e+01, -1.1882772881465453e+01, -1.1658630833708994e+01, -1.1437393678686862e+01, -1.1218865329829219e+01, -1.1002869620365653e+01, -1.0789247506430682e+01, -1.0577854758286833e+01, -1.0368560038906804e+01, -1.0161243292925425e+01, -9.9557943864826086e+00, -9.7521119515382608e+00, -9.5501023980913669e+00, -9.3496790652448780e+00, -9.1507614878382224e+00, -8.9532747598589513e+00, -8.7571489793618653e+00, -8.5623187624005972e+00, -8.3687228156851035e+00, -8.1763035594473781e+00, -7.9850067934236462e+00, -7.7947814000180404e+00, -7.6055790796564340e+00, -7.4173541141133637e+00, -7.2300631542333695e+00, -7.0436650289972214e+00, -6.8581205733240118e+00, -6.6733924723685520e+00, -6.4894451203829293e+00, -6.3062444924720467e+00, -6.1237580277938539e+00, -5.9419545229426243e+00, -5.7608040344137255e+00, -5.5802777891851223e+00, -5.4003481025684028e+00, -5.2209883025831942e+00, -5.0421726601961838e+00, -4.8638763248414749e+00, -4.6860752647046970e+00, -4.5087462113102941e+00, -4.3318666080012935e+00, -4.1554145619443341e+00, -3.9793687993309228e+00, -3.8037086234793556e+00, -3.6284138755712148e+00, -3.4534648977822986e+00, -3.2788424985907505e+00, -3.1045279200654083e+00, -2.9305028069552952e+00, -2.7567491774170563e+00, -2.5832493952312059e+00, -2.4099861433705372e+00, -2.2369423987951111e+00, -2.0641014083580762e+00, -1.8914466657152740e+00, -1.7189618891393004e+00, -1.5466310001455315e+00, -1.3744381028436181e+00, -1.2023674639332740e+00, -1.0304034932677821e+00, -8.5853072491269411e-01, -6.8673379863064854e-01, -5.1499744172618944e-01, -3.4330645118694048e-01, -1.7164567605949776e-01, -0.0000000000000000e+00, 1.7164567605949776e-01, 3.4330645118694048e-01, 5.1499744172618944e-01, 6.8673379863064854e-01, 8.5853072491269411e-01, 1.0304034932677821e+00, 1.2023674639332740e+00, 1.3744381028436181e+00, 1.5466310001455315e+00, 1.7189618891393004e+00, 1.8914466657152740e+00, 2.0641014083580762e+00, 2.2369423987951111e+00, 2.4099861433705372e+00, 2.5832493952312059e+00, 2.7567491774170563e+00, 2.9305028069552952e+00, 3.1045279200654083e+00, 3.2788424985907505e+00, 3.4534648977822986e+00, 3.6284138755712148e+00, 3.8037086234793556e+00, 3.9793687993309228e+00, 4.1554145619443341e+00, 4.3318666080012935e+00, 4.5087462113102941e+00, 4.6860752647046970e+00, 4.8638763248414749e+00, 5.0421726601961838e+00, 5.2209883025831942e+00, 5.4003481025684028e+00, 5.5802777891851223e+00, 5.7608040344137255e+00, 5.9419545229426243e+00, 6.1237580277938539e+00, 6.3062444924720467e+00, 6.4894451203829293e+00, 6.6733924723685520e+00, 6.8581205733240118e+00, 7.0436650289972214e+00, 7.2300631542333695e+00, 7.4173541141133637e+00, 7.6055790796564340e+00, 7.7947814000180404e+00, 7.9850067934236462e+00, 8.1763035594473781e+00, 8.3687228156851035e+00, 8.5623187624005972e+00, 8.7571489793618653e+00, 8.9532747598589513e+00, 9.1507614878382224e+00, 9.3496790652448780e+00, 9.5501023980913669e+00, 9.7521119515382608e+00, 9.9557943864826086e+00, 1.0161243292925425e+01, 1.0368560038906804e+01, 1.0577854758286833e+01, 1.0789247506430682e+01, 1.1002869620365653e+01, 1.1218865329829219e+01, 1.1437393678686862e+01, 1.1658630833708994e+01, 1.1882772881465453e+01, 1.2110039246794949e+01, 1.2340676911954159e+01, 1.2574965680305057e+01, 1.2813224821897842e+01, 1.3055821575985398e+01, 1.3303182192722531e+01, 1.3555806515930390e+01, 1.3814287615693701e+01, 1.4079338809250348e+01, 1.4351831817083784e+01, 1.4632852295689380e+01, 1.4923783633761518e+01, 1.5226439085523806e+01, 1.5543281876523103e+01, 1.5877818632519856e+01, 1.6235372148216229e+01, 1.6624816240761632e+01, 1.7063369335203092e+01, 1.7596093576995067e+01}, + {-1.7651360006273592e+01, -1.7119187224564673e+01, -1.6681098143347068e+01, -1.6292073956617820e+01, -1.5934912658163535e+01, -1.5600748834050473e+01, -1.5284264701644213e+01, -1.4981956922278711e+01, -1.4691364571634727e+01, -1.4410676085677181e+01, -1.4138509363787067e+01, -1.3873779760412367e+01, -1.3615616367875141e+01, -1.3363306535787522e+01, -1.3116257750703349e+01, -1.2873970640467419e+01, -1.2636019359905287e+01, -1.2402037021606754e+01, -1.2171704664459938e+01, -1.1944742758999288e+01, -1.1720904567955738e+01, -1.1499970887418726e+01, -1.1281745831568482e+01, -1.1066053417347991e+01, -1.0852734770136896e+01, -1.0641645817094179e+01, -1.0432655367504838e+01, -1.0225643503212597e+01, -1.0020500219714993e+01, -9.8171242715446922e+00, -9.6154221854030180e+00, -9.4153074120141333e+00, -9.2166995934430851e+00, -9.0195239271065724e+00, -8.8237106112187824e+00, -8.6291943591887517e+00, -8.4359139726921839e+00, -8.2438119649078239e+00, -8.0528342268332285e+00, -7.8629297307503139e+00, -7.6740502658540599e+00, -7.4861502018311290e+00, -7.2991862768130868e+00, -7.1131174066575413e+00, -6.9279045129506267e+00, -6.7435103674923891e+00, -6.5598994513357987e+00, -6.3770378267108159e+00, -6.1948930203856341e+00, -6.0134339172047717e+00, -5.8326306627035311e+00, -5.6524545738351115e+00, -5.4728780569640936e+00, -5.2938745323809906e+00, -5.1154183646798366e+00, -4.9374847984163193e+00, -4.7600498985294708e+00, -4.5830904950670517e+00, -4.4065841318044781e+00, -4.2305090183906966e+00, -4.0548439856925214e+00, -3.8795684440424409e+00, -3.7046623441243547e+00, -3.5301061402576419e+00, -3.3558807558629016e+00, -3.1819675509129310e+00, -3.0083482911904582e+00, -2.8350051191900167e+00, -2.6619205265154431e+00, -2.4890773276369966e+00, -2.3164586348831824e+00, -2.1440478345522327e+00, -1.9718285640369488e+00, -1.7997846898643619e+00, -1.6279002865585475e+00, -1.4561596162410049e+00, -1.2845471088883613e+00, -1.1130473431718593e+00, -9.4164502780718806e-01, -7.7032498334676469e-01, -5.9907212434961710e-01, -4.2787144186658727e-01, -2.5670798618070745e-01, -8.5566849744303619e-02, 8.5566849744303619e-02, 2.5670798618070745e-01, 4.2787144186658727e-01, 5.9907212434961710e-01, 7.7032498334676469e-01, 9.4164502780718806e-01, 1.1130473431718593e+00, 1.2845471088883613e+00, 1.4561596162410049e+00, 1.6279002865585475e+00, 1.7997846898643619e+00, 1.9718285640369488e+00, 2.1440478345522327e+00, 2.3164586348831824e+00, 2.4890773276369966e+00, 2.6619205265154431e+00, 2.8350051191900167e+00, 3.0083482911904582e+00, 3.1819675509129310e+00, 3.3558807558629016e+00, 3.5301061402576419e+00, 3.7046623441243547e+00, 3.8795684440424409e+00, 4.0548439856925214e+00, 4.2305090183906966e+00, 4.4065841318044781e+00, 4.5830904950670517e+00, 4.7600498985294708e+00, 4.9374847984163193e+00, 5.1154183646798366e+00, 5.2938745323809906e+00, 5.4728780569640936e+00, 5.6524545738351115e+00, 5.8326306627035311e+00, 6.0134339172047717e+00, 6.1948930203856341e+00, 6.3770378267108159e+00, 6.5598994513357987e+00, 6.7435103674923891e+00, 6.9279045129506267e+00, 7.1131174066575413e+00, 7.2991862768130868e+00, 7.4861502018311290e+00, 7.6740502658540599e+00, 7.8629297307503139e+00, 8.0528342268332285e+00, 8.2438119649078239e+00, 8.4359139726921839e+00, 8.6291943591887517e+00, 8.8237106112187824e+00, 9.0195239271065724e+00, 9.2166995934430851e+00, 9.4153074120141333e+00, 9.6154221854030180e+00, 9.8171242715446922e+00, 1.0020500219714993e+01, 1.0225643503212597e+01, 1.0432655367504838e+01, 1.0641645817094179e+01, 1.0852734770136896e+01, 1.1066053417347991e+01, 1.1281745831568482e+01, 1.1499970887418726e+01, 1.1720904567955738e+01, 1.1944742758999288e+01, 1.2171704664459938e+01, 1.2402037021606754e+01, 1.2636019359905287e+01, 1.2873970640467419e+01, 1.3116257750703349e+01, 1.3363306535787522e+01, 1.3615616367875141e+01, 1.3873779760412367e+01, 1.4138509363787067e+01, 1.4410676085677181e+01, 1.4691364571634727e+01, 1.4981956922278711e+01, 1.5284264701644213e+01, 1.5600748834050473e+01, 1.5934912658163535e+01, 1.6292073956617820e+01, 1.6681098143347068e+01, 1.7119187224564673e+01, 1.7651360006273592e+01}, + {-1.7706459824808160e+01, -1.7174834579405605e+01, -1.6737206157692185e+01, -1.6348598800359760e+01, -1.5991826809662236e+01, -1.5658033118559841e+01, -1.5341904922927041e+01, -1.5039942149162044e+01, -1.4749686158703426e+01, -1.4469327066282485e+01, -1.4197484050584235e+01, -1.3933073470045795e+01, -1.3675225224131985e+01, -1.3423227324587016e+01, -1.3176487810593191e+01, -1.2934507778191829e+01, -1.2696861784139129e+01, -1.2463183290148008e+01, -1.2233153641587771e+01, -1.2006493580642585e+01, -1.1782956612954054e+01, -1.1562323753600294e+01, -1.1344399315683788e+01, -1.1129007498123606e+01, -1.0915989593880358e+01, -1.0705201685404040e+01, -1.0496512726733012e+01, -1.0289802935397134e+01, -1.0084962434756044e+01, -9.8818901004391417e+00, -9.6804925743867667e+00, -9.4806834174876062e+00, -9.2823823775768961e+00, -9.0855147540413785e+00, -8.8900108437873531e+00, -8.6958054560996842e+00, -8.5028374861240277e+00, -8.3110495384702450e+00, -8.1203875938581902e+00, -7.9308007128818385e+00, -7.7422407719095485e+00, -7.5546622269112049e+00, -7.3680219016401658e+00, -7.1822787971261874e+00, -6.9973939198751642e+00, -6.8133301265393582e+00, -6.6300519831306728e+00, -6.4475256371099929e+00, -6.2657187009061461e+00, -6.0846001456053820e+00, -5.9041402037120223e+00, -5.7243102800175727e+00, -5.5450828697328980e+00, -5.3664314831390003e+00, -5.1883305760991361e+00, -5.0107554858504457e+00, -4.8336823715588126e+00, -4.6570881591776718e+00, -4.4809504902012192e+00, -4.3052476739459955e+00, -4.1299586430328983e+00, -3.9550629117751774e+00, -3.7805405372073957e+00, -3.6063720825162893e+00, -3.4325385826573980e+00, -3.2590215119615689e+00, -3.0858027535533901e+00, -2.9128645704195151e+00, -2.7401895779789363e+00, -2.5677607180197990e+00, -2.3955612338784800e+00, -2.2235746467465418e+00, -2.0517847329999523e+00, -1.8801755024527722e+00, -1.7087311774444227e+00, -1.5374361726757684e+00, -1.3662750757146653e+00, -1.1952326280963763e+00, -1.0242937069484293e+00, -8.5344330707311145e-01, -6.8266652342392853e-01, -5.1194853391500583e-01, -3.4127458250465148e-01, -1.7062996249611376e-01, -0.0000000000000000e+00, 1.7062996249611376e-01, 3.4127458250465148e-01, 5.1194853391500583e-01, 6.8266652342392853e-01, 8.5344330707311145e-01, 1.0242937069484293e+00, 1.1952326280963763e+00, 1.3662750757146653e+00, 1.5374361726757684e+00, 1.7087311774444227e+00, 1.8801755024527722e+00, 2.0517847329999523e+00, 2.2235746467465418e+00, 2.3955612338784800e+00, 2.5677607180197990e+00, 2.7401895779789363e+00, 2.9128645704195151e+00, 3.0858027535533901e+00, 3.2590215119615689e+00, 3.4325385826573980e+00, 3.6063720825162893e+00, 3.7805405372073957e+00, 3.9550629117751774e+00, 4.1299586430328983e+00, 4.3052476739459955e+00, 4.4809504902012192e+00, 4.6570881591776718e+00, 4.8336823715588126e+00, 5.0107554858504457e+00, 5.1883305760991361e+00, 5.3664314831390003e+00, 5.5450828697328980e+00, 5.7243102800175727e+00, 5.9041402037120223e+00, 6.0846001456053820e+00, 6.2657187009061461e+00, 6.4475256371099929e+00, 6.6300519831306728e+00, 6.8133301265393582e+00, 6.9973939198751642e+00, 7.1822787971261874e+00, 7.3680219016401658e+00, 7.5546622269112049e+00, 7.7422407719095485e+00, 7.9308007128818385e+00, 8.1203875938581902e+00, 8.3110495384702450e+00, 8.5028374861240277e+00, 8.6958054560996842e+00, 8.8900108437873531e+00, 9.0855147540413785e+00, 9.2823823775768961e+00, 9.4806834174876062e+00, 9.6804925743867667e+00, 9.8818901004391417e+00, 1.0084962434756044e+01, 1.0289802935397134e+01, 1.0496512726733012e+01, 1.0705201685404040e+01, 1.0915989593880358e+01, 1.1129007498123606e+01, 1.1344399315683788e+01, 1.1562323753600294e+01, 1.1782956612954054e+01, 1.2006493580642585e+01, 1.2233153641587771e+01, 1.2463183290148008e+01, 1.2696861784139129e+01, 1.2934507778191829e+01, 1.3176487810593191e+01, 1.3423227324587016e+01, 1.3675225224131985e+01, 1.3933073470045795e+01, 1.4197484050584235e+01, 1.4469327066282485e+01, 1.4749686158703426e+01, 1.5039942149162044e+01, 1.5341904922927041e+01, 1.5658033118559841e+01, 1.5991826809662236e+01, 1.6348598800359760e+01, 1.6737206157692185e+01, 1.7174834579405605e+01, 1.7706459824808160e+01}, + {-1.7761394524848996e+01, -1.7230312943277969e+01, -1.6793141871786613e+01, -1.6404948308671031e+01, -1.6048562755664683e+01, -1.5715136437003761e+01, -1.5399361493933315e+01, -1.5097741096163510e+01, -1.4807818875617881e+01, -1.4527786614519313e+01, -1.4256264762200541e+01, -1.3992170674226745e+01, -1.3734635051620387e+01, -1.3482946563606328e+01, -1.3236513798043475e+01, -1.2994838315752334e+01, -1.2757495072417459e+01, -1.2524117876199165e+01, -1.2294388376531968e+01, -1.2068027585042133e+01, -1.1844789248242524e+01, -1.1624454598296943e+01, -1.1406828145437910e+01, -1.1191734268858408e+01, -1.0979014427470727e+01, -1.0768524857445218e+01, -1.0560134656049588e+01, -1.0353724175012228e+01, -1.0149183664094940e+01, -9.9464121185839414e+00, -9.7453162942320208e+00, -9.5458098606732449e+00, -9.3478126700959958e+00, -9.1512501224373288e+00, -8.9560526118688415e+00, -8.7621550421132515e+00, -8.5694964003332892e+00, -8.3780193810985182e+00, -8.1876700533578219e+00, -7.9983975644987861e+00, -7.8101538765164022e+00, -7.6228935300856273e+00, -7.4365734329690358e+00, -7.2511526697184987e+00, -7.0665923300691791e+00, -6.8828553537915784e+00, -6.6999063900760145e+00, -6.5177116697841271e+00, -6.3362388891223835e+00, -6.1554571034797059e+00, -5.9753366303309603e+00, -5.7958489602446139e+00, -5.6169666751500360e+00, -5.4386633731207876e+00, -5.2609135990173996e+00, -5.0836927804084810e+00, -4.9069771682545298e+00, -4.7307437818957530e+00, -4.5549703579349439e+00, -4.3796353026499011e+00, -4.2047176476080219e+00, -4.0301970081890968e+00, -3.8560535447518163e+00, -3.6822679262054381e+00, -3.5088212957709741e+00, -3.3356952387365157e+00, -3.1628717520292895e+00, -2.9903332154429094e+00, -2.8180623643724516e+00, -2.6460422639225052e+00, -2.4742562842645146e+00, -2.3026880771296399e+00, -2.1313215533321839e+00, -1.9601408612264668e+00, -1.7891303660069930e+00, -1.6182746297679145e+00, -1.4475583922432660e+00, -1.2769665521542517e+00, -1.1064841490940971e+00, -9.3609634588467550e-01, -7.6578841134230902e-01, -5.9554570339290602e-01, -4.2535365247890039e-01, -2.5519774520239308e-01, -8.5063508150433453e-02, 8.5063508150433453e-02, 2.5519774520239308e-01, 4.2535365247890039e-01, 5.9554570339290602e-01, 7.6578841134230902e-01, 9.3609634588467550e-01, 1.1064841490940971e+00, 1.2769665521542517e+00, 1.4475583922432660e+00, 1.6182746297679145e+00, 1.7891303660069930e+00, 1.9601408612264668e+00, 2.1313215533321839e+00, 2.3026880771296399e+00, 2.4742562842645146e+00, 2.6460422639225052e+00, 2.8180623643724516e+00, 2.9903332154429094e+00, 3.1628717520292895e+00, 3.3356952387365157e+00, 3.5088212957709741e+00, 3.6822679262054381e+00, 3.8560535447518163e+00, 4.0301970081890968e+00, 4.2047176476080219e+00, 4.3796353026499011e+00, 4.5549703579349439e+00, 4.7307437818957530e+00, 4.9069771682545298e+00, 5.0836927804084810e+00, 5.2609135990173996e+00, 5.4386633731207876e+00, 5.6169666751500360e+00, 5.7958489602446139e+00, 5.9753366303309603e+00, 6.1554571034797059e+00, 6.3362388891223835e+00, 6.5177116697841271e+00, 6.6999063900760145e+00, 6.8828553537915784e+00, 7.0665923300691791e+00, 7.2511526697184987e+00, 7.4365734329690358e+00, 7.6228935300856273e+00, 7.8101538765164022e+00, 7.9983975644987861e+00, 8.1876700533578219e+00, 8.3780193810985182e+00, 8.5694964003332892e+00, 8.7621550421132515e+00, 8.9560526118688415e+00, 9.1512501224373288e+00, 9.3478126700959958e+00, 9.5458098606732449e+00, 9.7453162942320208e+00, 9.9464121185839414e+00, 1.0149183664094940e+01, 1.0353724175012228e+01, 1.0560134656049588e+01, 1.0768524857445218e+01, 1.0979014427470727e+01, 1.1191734268858408e+01, 1.1406828145437910e+01, 1.1624454598296943e+01, 1.1844789248242524e+01, 1.2068027585042133e+01, 1.2294388376531968e+01, 1.2524117876199165e+01, 1.2757495072417459e+01, 1.2994838315752334e+01, 1.3236513798043475e+01, 1.3482946563606328e+01, 1.3734635051620387e+01, 1.3992170674226745e+01, 1.4256264762200541e+01, 1.4527786614519313e+01, 1.4807818875617881e+01, 1.5097741096163510e+01, 1.5399361493933315e+01, 1.5715136437003761e+01, 1.6048562755664683e+01, 1.6404948308671031e+01, 1.6793141871786613e+01, 1.7230312943277969e+01, 1.7761394524848996e+01}, + {-1.7816165576540595e+01, -1.7285623836656182e+01, -1.6848906849690259e+01, -1.6461124086051807e+01, -1.6105122139319558e+01, -1.5772060470078458e+01, -1.5456636132218662e+01, -1.5155355517282629e+01, -1.4865764512599243e+01, -1.4586056556752672e+01, -1.4314853361179868e+01, -1.4051073271804183e+01, -1.3793847785696649e+01, -1.3542466224976369e+01, -1.3296337722283933e+01, -1.3054964299852571e+01, -1.2817921309339152e+01, -1.2584842902718409e+01, -1.2355411031114167e+01, -1.2129346973425209e+01, -1.1906404715032753e+01, -1.1686365703318645e+01, -1.1469034643887829e+01, -1.1254236094539081e+01, -1.1041811678540856e+01, -1.0831617784246889e+01, -1.0623523650663971e+01, -1.0417409762265434e+01, -1.0213166493789654e+01, -1.0010692958774635e+01, -9.8098960253945080e+00, -9.6106894706457702e+00, -9.4129932496899222e+00, -9.2167328616325275e+00, -9.0218387965226103e+00, -8.8282460511228340e+00, -8.6358937032013543e+00, -8.4447245358586134e+00, -8.2546847048231751e+00, -8.0657234428032414e+00, -7.8777927959207110e+00, -7.6908473880261887e+00, -7.5048442093293950e+00, -7.3197424263067070e+00, -7.1355032102865055e+00, -6.9520895824801361e+00, -6.7694662735346460e+00, -6.5875995959434990e+00, -6.4064573278715784e+00, -6.2260086071378540e+00, -6.0462238342585293e+00, -5.8670745835899512e+00, -5.6885335217276216e+00, -5.5105743324184848e+00, -5.3331716473306852e+00, -5.1563009821003343e+00, -4.9799386771402681e+00, -4.8040618427527138e+00, -4.6286483081374303e+00, -4.4536765739303981e+00, -4.2791257679461268e+00, -4.1049756038301792e+00, -3.9312063423578660e+00, -3.7577987551410561e+00, -3.5847340905279546e+00, -3.4119940415009409e+00, -3.2395607153955579e+00, -3.0674166052796257e+00, -2.8955445628456173e+00, -2.7239277726819950e+00, -2.5525497278003657e+00, -2.3813942063052753e+00, -2.2104452491022966e+00, -2.0396871385479329e+00, -1.8691043779518630e+00, -1.6986816718482496e+00, -1.5284039069583553e+00, -1.3582561337715613e+00, -1.1882235486761765e+00, -1.0182914765751778e+00, -8.4844535392529652e-01, -6.7867071214067709e-01, -5.0895316130475177e-01, -3.3927837413597878e-01, -1.6963207015474091e-01, -0.0000000000000000e+00, 1.6963207015474091e-01, 3.3927837413597878e-01, 5.0895316130475177e-01, 6.7867071214067709e-01, 8.4844535392529652e-01, 1.0182914765751778e+00, 1.1882235486761765e+00, 1.3582561337715613e+00, 1.5284039069583553e+00, 1.6986816718482496e+00, 1.8691043779518630e+00, 2.0396871385479329e+00, 2.2104452491022966e+00, 2.3813942063052753e+00, 2.5525497278003657e+00, 2.7239277726819950e+00, 2.8955445628456173e+00, 3.0674166052796257e+00, 3.2395607153955579e+00, 3.4119940415009409e+00, 3.5847340905279546e+00, 3.7577987551410561e+00, 3.9312063423578660e+00, 4.1049756038301792e+00, 4.2791257679461268e+00, 4.4536765739303981e+00, 4.6286483081374303e+00, 4.8040618427527138e+00, 4.9799386771402681e+00, 5.1563009821003343e+00, 5.3331716473306852e+00, 5.5105743324184848e+00, 5.6885335217276216e+00, 5.8670745835899512e+00, 6.0462238342585293e+00, 6.2260086071378540e+00, 6.4064573278715784e+00, 6.5875995959434990e+00, 6.7694662735346460e+00, 6.9520895824801361e+00, 7.1355032102865055e+00, 7.3197424263067070e+00, 7.5048442093293950e+00, 7.6908473880261887e+00, 7.8777927959207110e+00, 8.0657234428032414e+00, 8.2546847048231751e+00, 8.4447245358586134e+00, 8.6358937032013543e+00, 8.8282460511228340e+00, 9.0218387965226103e+00, 9.2167328616325275e+00, 9.4129932496899222e+00, 9.6106894706457702e+00, 9.8098960253945080e+00, 1.0010692958774635e+01, 1.0213166493789654e+01, 1.0417409762265434e+01, 1.0623523650663971e+01, 1.0831617784246889e+01, 1.1041811678540856e+01, 1.1254236094539081e+01, 1.1469034643887829e+01, 1.1686365703318645e+01, 1.1906404715032753e+01, 1.2129346973425209e+01, 1.2355411031114167e+01, 1.2584842902718409e+01, 1.2817921309339152e+01, 1.3054964299852571e+01, 1.3296337722283933e+01, 1.3542466224976369e+01, 1.3793847785696649e+01, 1.4051073271804183e+01, 1.4314853361179868e+01, 1.4586056556752672e+01, 1.4865764512599243e+01, 1.5155355517282629e+01, 1.5456636132218662e+01, 1.5772060470078458e+01, 1.6105122139319558e+01, 1.6461124086051807e+01, 1.6848906849690259e+01, 1.7285623836656182e+01, 1.7816165576540595e+01}, + {-1.7870774428377043e+01, -1.7340768757416335e+01, -1.6904502632033939e+01, -1.6517127712794291e+01, -1.6161506578815988e+01, -1.5828806872783744e+01, -1.5513730528912630e+01, -1.5212787139365300e+01, -1.4923524831985965e+01, -1.4644138690731507e+01, -1.4373251680710139e+01, -1.4109783131522859e+01, -1.3852865330854605e+01, -1.3601788249195971e+01, -1.3355961560129954e+01, -1.3114887743985697e+01, -1.2878142545481497e+01, -1.2645360457815213e+01, -1.2416223731463095e+01, -1.2190453910463864e+01, -1.1967805217099682e+01, -1.1748059312137153e+01, -1.1531021094829603e+01, -1.1316515299946504e+01, -1.1104383713549687e+01, -1.0894482874671912e+01, -1.0686682162601475e+01, -1.0480862193135913e+01, -1.0276913464597831e+01, -1.0074735207405618e+01, -9.8742344007979135e+00, -9.6753249277855886e+00, -9.4779268451589243e+00, -9.2819657498467407e+00, -9.0873722264251189e+00, -8.8940813633373228e+00, -8.7020323275849982e+00, -8.5111679894115486e+00, -8.3214345899181446e+00, -8.1327814457042589e+00, -7.9451606855641499e+00, -7.7585270150414196e+00, -7.5728375052793471e+00, -7.3880514031314979e+00, -7.2041299599356252e+00, -7.0210362767207544e+00, -6.8387351639253717e+00, -6.6571930139644744e+00, -6.4763776852031878e+00, -6.2962583960814955e+00, -6.1168056282939949e+00, -5.9379910380649177e+00, -5.7597873746756241e+00, -5.5821684055025109e+00, -5.4051088469102604e+00, -5.2285843004206338e+00, -5.0525711936423852e+00, -4.8770467255047967e+00, -4.7019888153869536e+00, -4.5273760557783174e+00, -4.3531876681442050e+00, -4.1794034617032088e+00, -4.0060037948530276e+00, -3.8329695390070744e+00, -3.6602820446272100e+00, -3.4879231092581433e+00, -3.3158749473870577e+00, -3.1441201619679244e+00, -2.9726417174641275e+00, -2.8014229142755962e+00, -2.6304473644278392e+00, -2.4596989684102435e+00, -2.2891618930598643e+00, -2.1188205503948270e+00, -1.9486595773085056e+00, -1.7786638160418760e+00, -1.6088182953569903e+00, -1.4391082123394401e+00, -1.2695189147619996e+00, -1.1000358839454638e+00, -9.3064471805601867e-01, -7.6133111578138291e-01, -5.9208086033042751e-01, -4.2287980370308703e-01, -2.5371385117911249e-01, -8.4568945975610571e-02, 8.4568945975610571e-02, 2.5371385117911249e-01, 4.2287980370308703e-01, 5.9208086033042751e-01, 7.6133111578138291e-01, 9.3064471805601867e-01, 1.1000358839454638e+00, 1.2695189147619996e+00, 1.4391082123394401e+00, 1.6088182953569903e+00, 1.7786638160418760e+00, 1.9486595773085056e+00, 2.1188205503948270e+00, 2.2891618930598643e+00, 2.4596989684102435e+00, 2.6304473644278392e+00, 2.8014229142755962e+00, 2.9726417174641275e+00, 3.1441201619679244e+00, 3.3158749473870577e+00, 3.4879231092581433e+00, 3.6602820446272100e+00, 3.8329695390070744e+00, 4.0060037948530276e+00, 4.1794034617032088e+00, 4.3531876681442050e+00, 4.5273760557783174e+00, 4.7019888153869536e+00, 4.8770467255047967e+00, 5.0525711936423852e+00, 5.2285843004206338e+00, 5.4051088469102604e+00, 5.5821684055025109e+00, 5.7597873746756241e+00, 5.9379910380649177e+00, 6.1168056282939949e+00, 6.2962583960814955e+00, 6.4763776852031878e+00, 6.6571930139644744e+00, 6.8387351639253717e+00, 7.0210362767207544e+00, 7.2041299599356252e+00, 7.3880514031314979e+00, 7.5728375052793471e+00, 7.7585270150414196e+00, 7.9451606855641499e+00, 8.1327814457042589e+00, 8.3214345899181446e+00, 8.5111679894115486e+00, 8.7020323275849982e+00, 8.8940813633373228e+00, 9.0873722264251189e+00, 9.2819657498467407e+00, 9.4779268451589243e+00, 9.6753249277855886e+00, 9.8742344007979135e+00, 1.0074735207405618e+01, 1.0276913464597831e+01, 1.0480862193135913e+01, 1.0686682162601475e+01, 1.0894482874671912e+01, 1.1104383713549687e+01, 1.1316515299946504e+01, 1.1531021094829603e+01, 1.1748059312137153e+01, 1.1967805217099682e+01, 1.2190453910463864e+01, 1.2416223731463095e+01, 1.2645360457815213e+01, 1.2878142545481497e+01, 1.3114887743985697e+01, 1.3355961560129954e+01, 1.3601788249195971e+01, 1.3852865330854605e+01, 1.4109783131522859e+01, 1.4373251680710139e+01, 1.4644138690731507e+01, 1.4923524831985965e+01, 1.5212787139365300e+01, 1.5513730528912630e+01, 1.5828806872783744e+01, 1.6161506578815988e+01, 1.6517127712794291e+01, 1.6904502632033939e+01, 1.7340768757416335e+01, 1.7870774428377043e+01}, + {-1.7925222507645273e+01, -1.7395749181302794e+01, -1.6959930736506667e+01, -1.6572960745489535e+01, -1.6217717667909398e+01, -1.5885377274967727e+01, -1.5570646349282180e+01, -1.5270037662686175e+01, -1.4981101568835271e+01, -1.4702034786209495e+01, -1.4431461525263758e+01, -1.4168302092683751e+01, -1.3911689561406538e+01, -1.3660914545833675e+01, -1.3415387256705733e+01, -1.3174610629179487e+01, -1.2938160798167818e+01, -1.2705672595541055e+01, -1.2476828568829013e+01, -1.2251350525113802e+01, -1.2028992921645616e+01, -1.1809537630775932e+01, -1.1592789743714977e+01, -1.1378574170599888e+01, -1.1166732858754798e+01, -1.0957122496418719e+01, -1.0749612601735487e+01, -1.0544083920437931e+01, -1.0340427073072608e+01, -1.0138541405599460e+01, -9.9383340069978168e+00, -9.7397188649785829e+00, -9.5426161366508815e+00, -9.3469515154567748e+00, -9.1526556791851785e+00, -8.9596638066377352e+00, -8.7679151527158581e+00, -8.5773526734573888e+00, -8.3879226939696405e+00, -8.1995746133560008e+00, -8.0122606416719417e+00, -7.8259355647163380e+00, -7.6405565330989909e+00, -7.4560828725515957e+00, -7.2724759128875176e+00, -7.0896988333823048e+00, -6.9077165226546269e+00, -6.7264954513869304e+00, -6.5460035564448802e+00, -6.3662101351413103e+00, -6.1870857485496860e+00, -6.0086021329082362e+00, -5.8307321182728238e+00, -5.6534495536772900e+00, -5.4767292381468682e+00, -5.3005468569855445e+00, -5.1248789228235241e+00, -4.9497027209678768e+00, -4.7749962586489980e+00, -4.6007382177989511e+00, -4.4269079110357756e+00, -4.2534852405612638e+00, -4.0804506597091201e+00, -3.9077851369063397e+00, -3.7354701218335649e+00, -3.5634875135904314e+00, -3.3918196306899016e+00, -3.2204491827214987e+00, -3.0493592435375283e+00, -2.8785332258289715e+00, -2.7079548569689353e+00, -2.5376081560115265e+00, -2.3674774117429300e+00, -2.1975471616893691e+00, -2.0278021719937014e+00, -1.8582274180786869e+00, -1.6888080660205369e+00, -1.5195294545613143e+00, -1.3503770776931412e+00, -1.1813365677510279e+00, -1.0123936789545276e+00, -8.4353427134138192e-01, -6.7474429503886002e-01, -5.0600977482067722e-01, -3.3731679489919819e-01, -1.6865148390411927e-01, -0.0000000000000000e+00, 1.6865148390411927e-01, 3.3731679489919819e-01, 5.0600977482067722e-01, 6.7474429503886002e-01, 8.4353427134138192e-01, 1.0123936789545276e+00, 1.1813365677510279e+00, 1.3503770776931412e+00, 1.5195294545613143e+00, 1.6888080660205369e+00, 1.8582274180786869e+00, 2.0278021719937014e+00, 2.1975471616893691e+00, 2.3674774117429300e+00, 2.5376081560115265e+00, 2.7079548569689353e+00, 2.8785332258289715e+00, 3.0493592435375283e+00, 3.2204491827214987e+00, 3.3918196306899016e+00, 3.5634875135904314e+00, 3.7354701218335649e+00, 3.9077851369063397e+00, 4.0804506597091201e+00, 4.2534852405612638e+00, 4.4269079110357756e+00, 4.6007382177989511e+00, 4.7749962586489980e+00, 4.9497027209678768e+00, 5.1248789228235241e+00, 5.3005468569855445e+00, 5.4767292381468682e+00, 5.6534495536772900e+00, 5.8307321182728238e+00, 6.0086021329082362e+00, 6.1870857485496860e+00, 6.3662101351413103e+00, 6.5460035564448802e+00, 6.7264954513869304e+00, 6.9077165226546269e+00, 7.0896988333823048e+00, 7.2724759128875176e+00, 7.4560828725515957e+00, 7.6405565330989909e+00, 7.8259355647163380e+00, 8.0122606416719417e+00, 8.1995746133560008e+00, 8.3879226939696405e+00, 8.5773526734573888e+00, 8.7679151527158581e+00, 8.9596638066377352e+00, 9.1526556791851785e+00, 9.3469515154567748e+00, 9.5426161366508815e+00, 9.7397188649785829e+00, 9.9383340069978168e+00, 1.0138541405599460e+01, 1.0340427073072608e+01, 1.0544083920437931e+01, 1.0749612601735487e+01, 1.0957122496418719e+01, 1.1166732858754798e+01, 1.1378574170599888e+01, 1.1592789743714977e+01, 1.1809537630775932e+01, 1.2028992921645616e+01, 1.2251350525113802e+01, 1.2476828568829013e+01, 1.2705672595541055e+01, 1.2938160798167818e+01, 1.3174610629179487e+01, 1.3415387256705733e+01, 1.3660914545833675e+01, 1.3911689561406538e+01, 1.4168302092683751e+01, 1.4431461525263758e+01, 1.4702034786209495e+01, 1.4981101568835271e+01, 1.5270037662686175e+01, 1.5570646349282180e+01, 1.5885377274967727e+01, 1.6217717667909398e+01, 1.6572960745489535e+01, 1.6959930736506667e+01, 1.7395749181302794e+01, 1.7925222507645273e+01}, + {-1.7979511220856821e+01, -1.7450566562382527e+01, -1.7015192658329994e+01, -1.6628624717520726e+01, -1.6273756976433262e+01, -1.5941773281856777e+01, -1.5627385233279865e+01, -1.5327108761515133e+01, -1.5038496431508072e+01, -1.4759746585548676e+01, -1.4489484671220278e+01, -1.4226631965786098e+01, -1.3970322322144929e+01, -1.3719846994209712e+01, -1.3474616726146943e+01, -1.3234134904720168e+01, -1.2997978052213019e+01, -1.2765781336657277e+01, -1.2537227600374516e+01, -1.2312038911428751e+01, -1.2089969960138866e+01, -1.1870802828673778e+01, -1.1654342798540783e+01, -1.1440414953672729e+01, -1.1228861401155735e+01, -1.1019538976992907e+01, -1.0812317336788272e+01, -1.0607077354851786e+01, -1.0403709772624749e+01, -1.0202114050301228e+01, -1.0002197385309380e+01, -9.8038738687782931e+00, -9.6070637568592137e+00, -9.4116928382313976e+00, -9.2176918826171956e+00, -9.0249961578901878e+00, -8.8335450055546225e+00, -8.6432814661321498e+00, -8.4541519474088638e+00, -8.2661059296450645e+00, -8.0790957027880133e+00, -7.8930761314972990e+00, -7.7080044444269156e+00, -7.5238400447339577e+00, -7.3405443392217018e+00, -7.1580805838909543e+00, -6.9764137439811300e+00, -6.7955103668419072e+00, -6.6153384661958059e+00, -6.4358674165386551e+00, -6.2570678565839728e+00, -6.0789116007933410e+00, -5.9013715581517205e+00, -5.7244216574471602e+00, -5.5480367784012250e+00, -5.3721926880716282e+00, -5.1968659820138337e+00, -5.0220340297452291e+00, -4.8476749241050427e+00, -4.6737674341465381e+00, -4.5002909612360460e+00, -4.3272254980667917e+00, -4.1545515903248518e+00, -3.9822503007705263e+00, -3.8103031755212977e+00, -3.6386922123428187e+00, -3.4673998307723486e+00, -3.2964088439149859e+00, -3.1257024317672348e+00, -2.9552641159350221e+00, -2.7850777356245309e+00, -2.6151274247942147e+00, -2.4453975903652418e+00, -2.2758728913956188e+00, -2.1065382191302762e+00, -1.9373786778457494e+00, -1.7683795664136901e+00, -1.5995263605124337e+00, -1.4308046954202789e+00, -1.2622003493280531e+00, -1.0936992271119663e+00, -9.2528734451076988e-01, -7.5695081265386188e-01, -5.8867582288920217e-01, -4.2044863186181980e-01, -2.5225554679525719e-01, -8.4082910929564950e-02, 8.4082910929564950e-02, 2.5225554679525719e-01, 4.2044863186181980e-01, 5.8867582288920217e-01, 7.5695081265386188e-01, 9.2528734451076988e-01, 1.0936992271119663e+00, 1.2622003493280531e+00, 1.4308046954202789e+00, 1.5995263605124337e+00, 1.7683795664136901e+00, 1.9373786778457494e+00, 2.1065382191302762e+00, 2.2758728913956188e+00, 2.4453975903652418e+00, 2.6151274247942147e+00, 2.7850777356245309e+00, 2.9552641159350221e+00, 3.1257024317672348e+00, 3.2964088439149859e+00, 3.4673998307723486e+00, 3.6386922123428187e+00, 3.8103031755212977e+00, 3.9822503007705263e+00, 4.1545515903248518e+00, 4.3272254980667917e+00, 4.5002909612360460e+00, 4.6737674341465381e+00, 4.8476749241050427e+00, 5.0220340297452291e+00, 5.1968659820138337e+00, 5.3721926880716282e+00, 5.5480367784012250e+00, 5.7244216574471602e+00, 5.9013715581517205e+00, 6.0789116007933410e+00, 6.2570678565839728e+00, 6.4358674165386551e+00, 6.6153384661958059e+00, 6.7955103668419072e+00, 6.9764137439811300e+00, 7.1580805838909543e+00, 7.3405443392217018e+00, 7.5238400447339577e+00, 7.7080044444269156e+00, 7.8930761314972990e+00, 8.0790957027880133e+00, 8.2661059296450645e+00, 8.4541519474088638e+00, 8.6432814661321498e+00, 8.8335450055546225e+00, 9.0249961578901878e+00, 9.2176918826171956e+00, 9.4116928382313976e+00, 9.6070637568592137e+00, 9.8038738687782931e+00, 1.0002197385309380e+01, 1.0202114050301228e+01, 1.0403709772624749e+01, 1.0607077354851786e+01, 1.0812317336788272e+01, 1.1019538976992907e+01, 1.1228861401155735e+01, 1.1440414953672729e+01, 1.1654342798540783e+01, 1.1870802828673778e+01, 1.2089969960138866e+01, 1.2312038911428751e+01, 1.2537227600374516e+01, 1.2765781336657277e+01, 1.2997978052213019e+01, 1.3234134904720168e+01, 1.3474616726146943e+01, 1.3719846994209712e+01, 1.3970322322144929e+01, 1.4226631965786098e+01, 1.4489484671220278e+01, 1.4759746585548676e+01, 1.5038496431508072e+01, 1.5327108761515133e+01, 1.5627385233279865e+01, 1.5941773281856777e+01, 1.6273756976433262e+01, 1.6628624717520726e+01, 1.7015192658329994e+01, 1.7450566562382527e+01, 1.7979511220856821e+01}, + {-1.8033641954168267e+01, -1.7505222333487513e+01, -1.7070289870719815e+01, -1.6684121139543407e+01, -1.6329626050797177e+01, -1.5997996474571265e+01, -1.5683948796077209e+01, -1.5384002084668344e+01, -1.5095711102237930e+01, -1.4817275804306519e+01, -1.4547322867471838e+01, -1.4284774533151579e+01, -1.4028765428985777e+01, -1.3778587444058825e+01, -1.3533651852283532e+01, -1.3293462488855706e+01, -1.3057596260647884e+01, -1.2825688669380938e+01, -1.2597422849942523e+01, -1.2372521129351217e+01, -1.2150738429127935e+01, -1.1931857039523125e+01, -1.1715682430712077e+01, -1.1502039858881551e+01, -1.1290771589409180e+01, -1.1081734604649661e+01, -1.0874798696301507e+01, -1.0669844865923427e+01, -1.0466763974552268e+01, -1.0265455595339178e+01, -1.0065827032900119e+01, -9.8677924805319144e+00, -9.6712722921832484e+00, -9.4761923505272865e+00, -9.2824835159740040e+00, -9.0900811442169349e+00, -8.8989246621016740e+00, -8.7089571933595398e+00, -8.5201252271656553e+00, -8.3323783236290581e+00, -8.1456688512594901e+00, -7.9599517522241854e+00, -7.7751843318419356e+00, -7.5913260692870139e+00, -7.4083384469130396e+00, -7.2261847959726726e+00, -7.0448301568163600e+00, -6.8642411519124229e+00, -6.6843858702502548e+00, -6.5052337618746865e+00, -6.3267555414586063e+00, -6.1489230999568738e+00, -5.9717094235012285e+00, -5.7950885187964847e+00, -5.6190353443649403e+00, -5.4435257470611598e+00, -5.2685364033444513e+00, -5.0940447648531757e+00, -4.9200290078745663e+00, -4.7464679863470698e+00, -4.5733411880702048e+00, -4.4006286938303605e+00, -4.2283111391802617e+00, -4.0563696786358214e+00, -3.8847859520769483e+00, -3.7135420531591667e+00, -3.5426204995608663e+00, -3.3720042049069567e+00, -3.2016764522238601e+00, -3.0316208687934161e+00, -2.8618214022844848e+00, -2.6922622980510740e+00, -2.5229280774947309e+00, -2.3538035173969201e+00, -2.1848736301342204e+00, -2.0161236446955049e+00, -1.8475389884259239e+00, -1.6791052694275435e+00, -1.5108082595509420e+00, -1.3426338779160372e+00, -1.1745681749038943e+00, -1.0065973165643360e+00, -8.3870756938683533e-01, -6.7088528538449332e-01, -5.0311688744285843e-01, -3.3538885488700437e-01, -1.6768770922162865e-01, -0.0000000000000000e+00, 1.6768770922162865e-01, 3.3538885488700437e-01, 5.0311688744285843e-01, 6.7088528538449332e-01, 8.3870756938683533e-01, 1.0065973165643360e+00, 1.1745681749038943e+00, 1.3426338779160372e+00, 1.5108082595509420e+00, 1.6791052694275435e+00, 1.8475389884259239e+00, 2.0161236446955049e+00, 2.1848736301342204e+00, 2.3538035173969201e+00, 2.5229280774947309e+00, 2.6922622980510740e+00, 2.8618214022844848e+00, 3.0316208687934161e+00, 3.2016764522238601e+00, 3.3720042049069567e+00, 3.5426204995608663e+00, 3.7135420531591667e+00, 3.8847859520769483e+00, 4.0563696786358214e+00, 4.2283111391802617e+00, 4.4006286938303605e+00, 4.5733411880702048e+00, 4.7464679863470698e+00, 4.9200290078745663e+00, 5.0940447648531757e+00, 5.2685364033444513e+00, 5.4435257470611598e+00, 5.6190353443649403e+00, 5.7950885187964847e+00, 5.9717094235012285e+00, 6.1489230999568738e+00, 6.3267555414586063e+00, 6.5052337618746865e+00, 6.6843858702502548e+00, 6.8642411519124229e+00, 7.0448301568163600e+00, 7.2261847959726726e+00, 7.4083384469130396e+00, 7.5913260692870139e+00, 7.7751843318419356e+00, 7.9599517522241854e+00, 8.1456688512594901e+00, 8.3323783236290581e+00, 8.5201252271656553e+00, 8.7089571933595398e+00, 8.8989246621016740e+00, 9.0900811442169349e+00, 9.2824835159740040e+00, 9.4761923505272865e+00, 9.6712722921832484e+00, 9.8677924805319144e+00, 1.0065827032900119e+01, 1.0265455595339178e+01, 1.0466763974552268e+01, 1.0669844865923427e+01, 1.0874798696301507e+01, 1.1081734604649661e+01, 1.1290771589409180e+01, 1.1502039858881551e+01, 1.1715682430712077e+01, 1.1931857039523125e+01, 1.2150738429127935e+01, 1.2372521129351217e+01, 1.2597422849942523e+01, 1.2825688669380938e+01, 1.3057596260647884e+01, 1.3293462488855706e+01, 1.3533651852283532e+01, 1.3778587444058825e+01, 1.4028765428985777e+01, 1.4284774533151579e+01, 1.4547322867471838e+01, 1.4817275804306519e+01, 1.5095711102237930e+01, 1.5384002084668344e+01, 1.5683948796077209e+01, 1.5997996474571265e+01, 1.6329626050797177e+01, 1.6684121139543407e+01, 1.7070289870719815e+01, 1.7505222333487513e+01, 1.8033641954168267e+01}, + {-1.8087616073790890e+01, -1.7559717906645613e+01, -1.7125223825336107e+01, -1.6739451499952981e+01, -1.6385326414471709e+01, -1.6054048410627541e+01, -1.5740338628583727e+01, -1.5440719256044483e+01, -1.5152747237684542e+01, -1.4874624131806939e+01, -1.4604977836012001e+01, -1.4342731549531273e+01, -1.4087020669594040e+01, -1.3837137716174603e+01, -1.3592494489303405e+01, -1.3352595269479263e+01, -1.3117017345422802e+01, -1.2885396550109379e+01, -1.2657416308802228e+01, -1.2432799205480446e+01, -1.2211300391032086e+01, -1.1992702362083911e+01, -1.1776810775879971e+01, -1.1563451059348457e+01, -1.1352465634716971e+01, -1.1143711629308052e+01, -1.0937058969577729e+01, -1.0732388783033896e+01, -1.0529592049038808e+01, -1.0328568452453034e+01, -1.0129225403849107e+01, -9.9314771974714695e+00, -9.7352442838524844e+00, -9.5404526384475599e+00, -9.3470332111408592e+00, -9.1549214442271172e+00, -8.9640568486659262e+00, -8.7743826301592698e+00, -8.5858453580177638e+00, -8.3983946709283614e+00, -8.2119830146725530e+00, -8.0265654076120381e+00, -7.8420992303922956e+00, -7.6585440368392881e+00, -7.4758613834617105e+00, -7.2940146753366397e+00, -7.1129690264635128e+00, -6.9326911329302607e+00, -6.7531491574546436e+00, -6.5743126240500311e+00, -6.3961523217237177e+00, -6.2186402162517354e+00, -6.0417493691907094e+00, -5.8654538633877182e+00, -5.6897287343358398e+00, -5.5145499067980914e+00, -5.3398941361876862e+00, -5.1657389542492513e+00, -4.9920626186351811e+00, -4.8188440660145870e+00, -4.6460628683903158e+00, -4.4736991923328295e+00, -4.3017337608691273e+00, -4.1301478177908013e+00, -3.9589230941681977e+00, -3.7880417768779360e+00, -3.6174864789689782e+00, -3.4472402117084235e+00, -3.2772863581623723e+00, -3.1076086481798137e+00, -2.9381911346587741e+00, -2.7690181709839532e+00, -2.6000743895340599e+00, -2.4313446811650303e+00, -2.2628141755824469e+00, -2.0944682225228455e+00, -1.9262923736692732e+00, -1.7582723652315242e+00, -1.5903941011259675e+00, -1.4226436366938928e+00, -1.2550071629008195e+00, -1.0874709909623226e+00, -9.2002153734466763e-01, -7.5264530909089167e-01, -5.8532888942501560e-01, -4.1805892358878166e-01, -2.5082210486674750e-01, -8.3605160756706529e-02, 8.3605160756706529e-02, 2.5082210486674750e-01, 4.1805892358878166e-01, 5.8532888942501560e-01, 7.5264530909089167e-01, 9.2002153734466763e-01, 1.0874709909623226e+00, 1.2550071629008195e+00, 1.4226436366938928e+00, 1.5903941011259675e+00, 1.7582723652315242e+00, 1.9262923736692732e+00, 2.0944682225228455e+00, 2.2628141755824469e+00, 2.4313446811650303e+00, 2.6000743895340599e+00, 2.7690181709839532e+00, 2.9381911346587741e+00, 3.1076086481798137e+00, 3.2772863581623723e+00, 3.4472402117084235e+00, 3.6174864789689782e+00, 3.7880417768779360e+00, 3.9589230941681977e+00, 4.1301478177908013e+00, 4.3017337608691273e+00, 4.4736991923328295e+00, 4.6460628683903158e+00, 4.8188440660145870e+00, 4.9920626186351811e+00, 5.1657389542492513e+00, 5.3398941361876862e+00, 5.5145499067980914e+00, 5.6897287343358398e+00, 5.8654538633877182e+00, 6.0417493691907094e+00, 6.2186402162517354e+00, 6.3961523217237177e+00, 6.5743126240500311e+00, 6.7531491574546436e+00, 6.9326911329302607e+00, 7.1129690264635128e+00, 7.2940146753366397e+00, 7.4758613834617105e+00, 7.6585440368392881e+00, 7.8420992303922956e+00, 8.0265654076120381e+00, 8.2119830146725530e+00, 8.3983946709283614e+00, 8.5858453580177638e+00, 8.7743826301592698e+00, 8.9640568486659262e+00, 9.1549214442271172e+00, 9.3470332111408592e+00, 9.5404526384475599e+00, 9.7352442838524844e+00, 9.9314771974714695e+00, 1.0129225403849107e+01, 1.0328568452453034e+01, 1.0529592049038808e+01, 1.0732388783033896e+01, 1.0937058969577729e+01, 1.1143711629308052e+01, 1.1352465634716971e+01, 1.1563451059348457e+01, 1.1776810775879971e+01, 1.1992702362083911e+01, 1.2211300391032086e+01, 1.2432799205480446e+01, 1.2657416308802228e+01, 1.2885396550109379e+01, 1.3117017345422802e+01, 1.3352595269479263e+01, 1.3592494489303405e+01, 1.3837137716174603e+01, 1.4087020669594040e+01, 1.4342731549531273e+01, 1.4604977836012001e+01, 1.4874624131806939e+01, 1.5152747237684542e+01, 1.5440719256044483e+01, 1.5740338628583727e+01, 1.6054048410627541e+01, 1.6385326414471709e+01, 1.6739451499952981e+01, 1.7125223825336107e+01, 1.7559717906645613e+01, 1.8087616073790890e+01}, + {-1.8141434926389717e+01, -1.7614054673500309e+01, -1.7179995952720883e+01, -1.6794617265339959e+01, -1.6440859568460443e+01, -1.6109930624426557e+01, -1.5796556297952138e+01, -1.5497261875146510e+01, -1.5209606469472327e+01, -1.4931793231695860e+01, -1.4662451272508532e+01, -1.4400504742695974e+01, -1.4145089803991842e+01, -1.3895499603035967e+01, -1.3651146462397561e+01, -1.3411535104793492e+01, -1.3176243198091708e+01, -1.2944906904124267e+01, -1.2717209936373832e+01, -1.2492875133818373e+01, -1.2271657874909140e+01, -1.2053340860973840e+01, -1.1837729934755059e+01, -1.1624650692438404e+01, -1.1413945711687965e+01, -1.1205472263438262e+01, -1.0999100407593694e+01, -1.0794711396339702e+01, -1.0592196326121911e+01, -1.0391454992291058e+01, -1.0192394910173833e+01, -9.9949304737714737e+00, -9.7989822290161133e+00, -9.6044762429642674e+00, -9.4113435537920687e+00, -9.2195196892087417e+00, -9.0289442430934326e+00, -8.8395605019136383e+00, -8.6513151138967856e+00, -8.4641577950728877e+00, -8.2780410672415687e+00, -8.0929200236841812e+00, -7.9087521190744416e+00, -7.7254969805656009e+00, -7.5431162374687224e+00, -7.3615733673019719e+00, -7.1808335562975261e+00, -7.0008635727114159e+00, -6.8216316515006419e+00, -6.6431073891179739e+00, -6.4652616473335298e+00, -6.2880664651279838e+00, -6.1114949778187784e+00, -5.9355213426810298e+00, -5.7601206704114505e+00, -5.5852689618586204e+00, -5.4109430495080577e+00, -5.2371205432672880e+00, -5.0637797801455120e+00, -4.8908997774658411e+00, -4.7184601892859508e+00, -4.5464412657363820e+00, -4.3748238150150680e+00, -4.2035891678025479e+00, -4.0327191438852346e+00, -3.8621960207943373e+00, -3.6920025042860427e+00, -3.5221217005044698e+00, -3.3525370896831359e+00, -3.1832325012532876e+00, -3.0141920902387014e+00, -2.8454003148266174e+00, -2.6768419150134308e+00, -2.5085018922317608e+00, -2.3403654898726809e+00, -2.1724181746232882e+00, -2.0046456185454748e+00, -1.8370336818268698e+00, -1.6695683961394456e+00, -1.5022359485453094e+00, -1.3350226658927800e+00, -1.1679149996489939e+00, -1.0008995111180643e+00, -8.3396285699622974e-01, -6.6709177521751994e-01, -5.0027307104524965e-01, -3.3349360336615247e-01, -1.6674027114518436e-01, -0.0000000000000000e+00, 1.6674027114518436e-01, 3.3349360336615247e-01, 5.0027307104524965e-01, 6.6709177521751994e-01, 8.3396285699622974e-01, 1.0008995111180643e+00, 1.1679149996489939e+00, 1.3350226658927800e+00, 1.5022359485453094e+00, 1.6695683961394456e+00, 1.8370336818268698e+00, 2.0046456185454748e+00, 2.1724181746232882e+00, 2.3403654898726809e+00, 2.5085018922317608e+00, 2.6768419150134308e+00, 2.8454003148266174e+00, 3.0141920902387014e+00, 3.1832325012532876e+00, 3.3525370896831359e+00, 3.5221217005044698e+00, 3.6920025042860427e+00, 3.8621960207943373e+00, 4.0327191438852346e+00, 4.2035891678025479e+00, 4.3748238150150680e+00, 4.5464412657363820e+00, 4.7184601892859508e+00, 4.8908997774658411e+00, 5.0637797801455120e+00, 5.2371205432672880e+00, 5.4109430495080577e+00, 5.5852689618586204e+00, 5.7601206704114505e+00, 5.9355213426810298e+00, 6.1114949778187784e+00, 6.2880664651279838e+00, 6.4652616473335298e+00, 6.6431073891179739e+00, 6.8216316515006419e+00, 7.0008635727114159e+00, 7.1808335562975261e+00, 7.3615733673019719e+00, 7.5431162374687224e+00, 7.7254969805656009e+00, 7.9087521190744416e+00, 8.0929200236841812e+00, 8.2780410672415687e+00, 8.4641577950728877e+00, 8.6513151138967856e+00, 8.8395605019136383e+00, 9.0289442430934326e+00, 9.2195196892087417e+00, 9.4113435537920687e+00, 9.6044762429642674e+00, 9.7989822290161133e+00, 9.9949304737714737e+00, 1.0192394910173833e+01, 1.0391454992291058e+01, 1.0592196326121911e+01, 1.0794711396339702e+01, 1.0999100407593694e+01, 1.1205472263438262e+01, 1.1413945711687965e+01, 1.1624650692438404e+01, 1.1837729934755059e+01, 1.2053340860973840e+01, 1.2271657874909140e+01, 1.2492875133818373e+01, 1.2717209936373832e+01, 1.2944906904124267e+01, 1.3176243198091708e+01, 1.3411535104793492e+01, 1.3651146462397561e+01, 1.3895499603035967e+01, 1.4145089803991842e+01, 1.4400504742695974e+01, 1.4662451272508532e+01, 1.4931793231695860e+01, 1.5209606469472327e+01, 1.5497261875146510e+01, 1.5796556297952138e+01, 1.6109930624426557e+01, 1.6440859568460443e+01, 1.6794617265339959e+01, 1.7179995952720883e+01, 1.7614054673500309e+01, 1.8141434926389717e+01}, + {-1.8195099839472430e+01, -1.7668234005719587e+01, -1.7234607662724841e+01, -1.6849619880933339e+01, -1.6496226991759631e+01, -1.6165644627729627e+01, -1.5852603348070128e+01, -1.5553631517589562e+01, -1.5266290404714507e+01, -1.4988784742481727e+01, -1.4719744846860621e+01, -1.4458095814010402e+01, -1.4202974565149994e+01, -1.3953674869416368e+01, -1.3709609568387386e+01, -1.3470283823956324e+01, -1.3235275680476827e+01, -1.3004221626275813e+01, -1.2776805660932723e+01, -1.2552750876494338e+01, -1.2331812877201305e+01, -1.2113774567435913e+01, -1.1898441973897304e+01, -1.1685640860572095e+01, -1.1475213959174649e+01, -1.1267018682922650e+01, -1.1060925223886697e+01, -1.0856814957685176e+01, -1.0654579096632252e+01, -1.0454117545377073e+01, -1.0255337922825921e+01, -1.0058154721574315e+01, -9.8624885817991093e+00, -9.6682656610062114e+00, -9.4754170845116796e+00, -9.2838784642833954e+00, -9.0935894759573372e+00, -8.9044934855939797e+00, -8.7165372191524781e+00, -8.5296704688056462e+00, -8.3438458311533719e+00, -8.1590184731587261e+00, -7.9751459222633976e+00, -7.7921878776629914e+00, -7.6101060401591205e+00, -7.4288639583701048e+00, -7.2484268893885622e+00, -7.0687616722327293e+00, -6.8898366126570973e+00, -6.7116213780739269e+00, -6.5340869014957565e+00, -6.3572052935446060e+00, -6.1809497616900950e+00, -6.0052945359788579e+00, -5.8302148006042280e+00, -5.6556866307401252e+00, -5.4816869341281516e+00, -5.3081933969635617e+00, -5.1351844336752253e+00, -4.9626391402379442e+00, -4.7905372506934265e+00, -4.6188590965895351e+00, -4.4475855690767556e+00, -4.2766980834267416e+00, -4.1061785457606526e+00, -3.9360093217952534e+00, -3.7661732074327352e+00, -3.5966534010361229e+00, -3.4274334772463870e+00, -3.2584973622099573e+00, -3.0898293100966461e+00, -2.9214138807980121e+00, -2.7532359187051947e+00, -2.5852805324732593e+00, -2.4175330756862730e+00, -2.2499791283437252e+00, -2.0826044790946652e+00, -1.9153951081510019e+00, -1.7483371708160103e+00, -1.5814169815681258e+00, -1.4146209986437335e+00, -1.2479358090658317e+00, -1.0813481140682928e+00, -9.1484471486787966e-01, -7.4841249873834059e-01, -5.8203842534274008e-01, -4.1570951328174155e-01, -2.4941282681685847e-01, -8.3135462728728945e-02, 8.3135462728728945e-02, 2.4941282681685847e-01, 4.1570951328174155e-01, 5.8203842534274008e-01, 7.4841249873834059e-01, 9.1484471486787966e-01, 1.0813481140682928e+00, 1.2479358090658317e+00, 1.4146209986437335e+00, 1.5814169815681258e+00, 1.7483371708160103e+00, 1.9153951081510019e+00, 2.0826044790946652e+00, 2.2499791283437252e+00, 2.4175330756862730e+00, 2.5852805324732593e+00, 2.7532359187051947e+00, 2.9214138807980121e+00, 3.0898293100966461e+00, 3.2584973622099573e+00, 3.4274334772463870e+00, 3.5966534010361229e+00, 3.7661732074327352e+00, 3.9360093217952534e+00, 4.1061785457606526e+00, 4.2766980834267416e+00, 4.4475855690767556e+00, 4.6188590965895351e+00, 4.7905372506934265e+00, 4.9626391402379442e+00, 5.1351844336752253e+00, 5.3081933969635617e+00, 5.4816869341281516e+00, 5.6556866307401252e+00, 5.8302148006042280e+00, 6.0052945359788579e+00, 6.1809497616900950e+00, 6.3572052935446060e+00, 6.5340869014957565e+00, 6.7116213780739269e+00, 6.8898366126570973e+00, 7.0687616722327293e+00, 7.2484268893885622e+00, 7.4288639583701048e+00, 7.6101060401591205e+00, 7.7921878776629914e+00, 7.9751459222633976e+00, 8.1590184731587261e+00, 8.3438458311533719e+00, 8.5296704688056462e+00, 8.7165372191524781e+00, 8.9044934855939797e+00, 9.0935894759573372e+00, 9.2838784642833954e+00, 9.4754170845116796e+00, 9.6682656610062114e+00, 9.8624885817991093e+00, 1.0058154721574315e+01, 1.0255337922825921e+01, 1.0454117545377073e+01, 1.0654579096632252e+01, 1.0856814957685176e+01, 1.1060925223886697e+01, 1.1267018682922650e+01, 1.1475213959174649e+01, 1.1685640860572095e+01, 1.1898441973897304e+01, 1.2113774567435913e+01, 1.2331812877201305e+01, 1.2552750876494338e+01, 1.2776805660932723e+01, 1.3004221626275813e+01, 1.3235275680476827e+01, 1.3470283823956324e+01, 1.3709609568387386e+01, 1.3953674869416368e+01, 1.4202974565149994e+01, 1.4458095814010402e+01, 1.4719744846860621e+01, 1.4988784742481727e+01, 1.5266290404714507e+01, 1.5553631517589562e+01, 1.5852603348070128e+01, 1.6165644627729627e+01, 1.6496226991759631e+01, 1.6849619880933339e+01, 1.7234607662724841e+01, 1.7668234005719587e+01, 1.8195099839472430e+01}, + {-1.8248612121768343e+01, -1.7722257255394386e+01, -1.7289060344922966e+01, -1.6904460771032490e+01, -1.6551430141805881e+01, -1.6221191910121661e+01, -1.5908481300039147e+01, -1.5609829735595335e+01, -1.5322800626523263e+01, -1.5045600278061576e+01, -1.4776860203741105e+01, -1.4515506438991860e+01, -1.4260676659563400e+01, -1.4011665252976300e+01, -1.3767885576334674e+01, -1.3528843227708883e+01, -1.3294116625314924e+01, -1.3063342581647838e+01, -1.2836205380293851e+01, -1.2612428364469304e+01, -1.2391767362459763e+01, -1.2174005480084015e+01, -1.1958948926483190e+01, -1.1746423632015365e+01, -1.1536272481085435e+01, -1.1328353027891652e+01, -1.1122535595414808e+01, -1.0918701681487823e+01, -1.0716742613104932e+01, -1.0516558403048526e+01, -1.0318056772656865e+01, -1.0121152311984588e+01, -9.9257657543260880e+00, -9.7318233465134139e+00, -9.5392562998795718e+00, -9.3480003095250854e+00, -9.1579951317106332e+00, -8.9691842109485744e+00, -8.7815143497770496e+00, -8.5949354153447821e+00, -8.4094000778684173e+00, -8.2248635767903480e+00, -8.0412835110966494e+00, -7.8586196507783281e+00, -7.6768337668550366e+00, -7.4958894777450231e+00, -7.3157521100712737e+00, -7.1363885722521356e+00, -6.9577672394433048e+00, -6.7798578485838581e+00, -6.6026314024574280e+00, -6.4260600818151339e+00, -6.2501171647232399e+00, -6.0747769523986586e+00, -5.9000147008819077e+00, -5.7258065579720290e+00, -5.5521295049130304e+00, -5.3789613023779728e+00, -5.2062804403463288e+00, -5.0340660915133606e+00, -4.8622980679082559e+00, -4.6909567804310086e+00, -4.5200232010473753e+00, -4.3494788274071139e+00, -4.1793056496735739e+00, -4.0094861193729656e+00, -3.8400031200895830e+00, -3.6708399398492308e+00, -3.5019802450472732e+00, -3.3334080557903905e+00, -3.1651077225323845e+00, -2.9970639038944427e+00, -2.8292615455692673e+00, -2.6616858602164983e+00, -2.4943223082640649e+00, -2.3271565795365086e+00, -2.1601745756370865e+00, -1.9933623930155944e+00, -1.8267063066584319e+00, -1.6601927543415429e+00, -1.4938083213904756e+00, -1.3275397258950710e+00, -1.1613738043291120e+00, -9.9529749752779750e-01, -8.2929783697808435e-01, -6.6336193137884258e-01, -4.9747695342938458e-01, -3.3163012680628950e-01, -1.6580871328955671e-01, -0.0000000000000000e+00, 1.6580871328955671e-01, 3.3163012680628950e-01, 4.9747695342938458e-01, 6.6336193137884258e-01, 8.2929783697808435e-01, 9.9529749752779750e-01, 1.1613738043291120e+00, 1.3275397258950710e+00, 1.4938083213904756e+00, 1.6601927543415429e+00, 1.8267063066584319e+00, 1.9933623930155944e+00, 2.1601745756370865e+00, 2.3271565795365086e+00, 2.4943223082640649e+00, 2.6616858602164983e+00, 2.8292615455692673e+00, 2.9970639038944427e+00, 3.1651077225323845e+00, 3.3334080557903905e+00, 3.5019802450472732e+00, 3.6708399398492308e+00, 3.8400031200895830e+00, 4.0094861193729656e+00, 4.1793056496735739e+00, 4.3494788274071139e+00, 4.5200232010473753e+00, 4.6909567804310086e+00, 4.8622980679082559e+00, 5.0340660915133606e+00, 5.2062804403463288e+00, 5.3789613023779728e+00, 5.5521295049130304e+00, 5.7258065579720290e+00, 5.9000147008819077e+00, 6.0747769523986586e+00, 6.2501171647232399e+00, 6.4260600818151339e+00, 6.6026314024574280e+00, 6.7798578485838581e+00, 6.9577672394433048e+00, 7.1363885722521356e+00, 7.3157521100712737e+00, 7.4958894777450231e+00, 7.6768337668550366e+00, 7.8586196507783281e+00, 8.0412835110966494e+00, 8.2248635767903480e+00, 8.4094000778684173e+00, 8.5949354153447821e+00, 8.7815143497770496e+00, 8.9691842109485744e+00, 9.1579951317106332e+00, 9.3480003095250854e+00, 9.5392562998795718e+00, 9.7318233465134139e+00, 9.9257657543260880e+00, 1.0121152311984588e+01, 1.0318056772656865e+01, 1.0516558403048526e+01, 1.0716742613104932e+01, 1.0918701681487823e+01, 1.1122535595414808e+01, 1.1328353027891652e+01, 1.1536272481085435e+01, 1.1746423632015365e+01, 1.1958948926483190e+01, 1.2174005480084015e+01, 1.2391767362459763e+01, 1.2612428364469304e+01, 1.2836205380293851e+01, 1.3063342581647838e+01, 1.3294116625314924e+01, 1.3528843227708883e+01, 1.3767885576334674e+01, 1.4011665252976300e+01, 1.4260676659563400e+01, 1.4515506438991860e+01, 1.4776860203741105e+01, 1.5045600278061576e+01, 1.5322800626523263e+01, 1.5609829735595335e+01, 1.5908481300039147e+01, 1.6221191910121661e+01, 1.6551430141805881e+01, 1.6904460771032490e+01, 1.7289060344922966e+01, 1.7722257255394386e+01, 1.8248612121768343e+01}, + {-1.8301973063597831e+01, -1.7776125755426882e+01, -1.7343355369019513e+01, -1.6959141339427859e+01, -1.6606470454912181e+01, -1.6276573939462359e+01, -1.5964191652640661e+01, -1.5665858058473457e+01, -1.5379138694506308e+01, -1.5102241428233055e+01, -1.4833798963124122e+01, -1.4572738267853815e+01, -1.4318197767810874e+01, -1.4069472464839684e+01, -1.3825976228134913e+01, -1.3587215088986124e+01, -1.3352767836885693e+01, -1.3122271606204340e+01, -1.2895410962476978e+01, -1.2671909498220252e+01, -1.2451523264048797e+01, -1.2234035565627281e+01, -1.2019252793050947e+01, -1.1807001041645883e+01, -1.1597123347173454e+01, -1.1389477403535365e+01, -1.1183933663391947e+01, -1.0980373745597644e+01, -1.0778689090663802e+01, -1.0578779818366641e+01, -1.0380553751354837e+01, -1.0183925576033463e+01, -9.9888161177141903e+00, -9.7951517114594342e+00, -9.6028636535242580e+00, -9.4118877210445753e+00, -9.2221637498031388e+00, -9.0336352616534104e+00, -8.8462491345909715e+00, -8.6599553096056603e+00, -8.4747065293805139e+00, -8.2904581046690247e+00, -8.1071677048133868e+00, -7.9247951693895704e+00, -7.7433023384005537e+00, -7.5626528988034316e+00, -7.3828122454620404e+00, -7.2037473548748121e+00, -7.0254266702460146e+00, -6.8478199966541871e+00, -6.6708984052298304e+00, -6.4946341453898597e+00, -6.3190005642925637e+00, -6.1439720327768708e+00, -5.9695238771362042e+00, -5.7956323161519689e+00, -5.6222744028767648e+00, -5.4494279707139679e+00, -5.2770715833897031e+00, -5.1051844884564179e+00, -4.9337465740051734e+00, -4.7627383282970204e+00, -4.5921408020531498e+00, -4.4219355731693852e+00, -4.2521047136434067e+00, -4.0826307585233783e+00, -3.9134966767045909e+00, -3.7446858434166801e+00, -3.5761820142581890e+00, -3.4079693006478804e+00, -3.2400321465734825e+00, -3.0723553065286380e+00, -2.9049238245378035e+00, -2.7377230141769160e+00, -2.5707384395048281e+00, -2.4039558968269845e+00, -2.2373613972185420e+00, -2.0709411497393346e+00, -1.9046815452776742e+00, -1.7385691409641026e+00, -1.5725906450998823e+00, -1.4067329025482804e+00, -1.2409828805395797e+00, -1.0753276548433179e+00, -9.0975439626347543e-01, -7.4425035741428780e-01, -5.7880285973602430e-01, -4.1339928071149723e-01, -2.4802704124523722e-01, -8.2673593168222662e-02, 8.2673593168222662e-02, 2.4802704124523722e-01, 4.1339928071149723e-01, 5.7880285973602430e-01, 7.4425035741428780e-01, 9.0975439626347543e-01, 1.0753276548433179e+00, 1.2409828805395797e+00, 1.4067329025482804e+00, 1.5725906450998823e+00, 1.7385691409641026e+00, 1.9046815452776742e+00, 2.0709411497393346e+00, 2.2373613972185420e+00, 2.4039558968269845e+00, 2.5707384395048281e+00, 2.7377230141769160e+00, 2.9049238245378035e+00, 3.0723553065286380e+00, 3.2400321465734825e+00, 3.4079693006478804e+00, 3.5761820142581890e+00, 3.7446858434166801e+00, 3.9134966767045909e+00, 4.0826307585233783e+00, 4.2521047136434067e+00, 4.4219355731693852e+00, 4.5921408020531498e+00, 4.7627383282970204e+00, 4.9337465740051734e+00, 5.1051844884564179e+00, 5.2770715833897031e+00, 5.4494279707139679e+00, 5.6222744028767648e+00, 5.7956323161519689e+00, 5.9695238771362042e+00, 6.1439720327768708e+00, 6.3190005642925637e+00, 6.4946341453898597e+00, 6.6708984052298304e+00, 6.8478199966541871e+00, 7.0254266702460146e+00, 7.2037473548748121e+00, 7.3828122454620404e+00, 7.5626528988034316e+00, 7.7433023384005537e+00, 7.9247951693895704e+00, 8.1071677048133868e+00, 8.2904581046690247e+00, 8.4747065293805139e+00, 8.6599553096056603e+00, 8.8462491345909715e+00, 9.0336352616534104e+00, 9.2221637498031388e+00, 9.4118877210445753e+00, 9.6028636535242580e+00, 9.7951517114594342e+00, 9.9888161177141903e+00, 1.0183925576033463e+01, 1.0380553751354837e+01, 1.0578779818366641e+01, 1.0778689090663802e+01, 1.0980373745597644e+01, 1.1183933663391947e+01, 1.1389477403535365e+01, 1.1597123347173454e+01, 1.1807001041645883e+01, 1.2019252793050947e+01, 1.2234035565627281e+01, 1.2451523264048797e+01, 1.2671909498220252e+01, 1.2895410962476978e+01, 1.3122271606204340e+01, 1.3352767836885693e+01, 1.3587215088986124e+01, 1.3825976228134913e+01, 1.4069472464839684e+01, 1.4318197767810874e+01, 1.4572738267853815e+01, 1.4833798963124122e+01, 1.5102241428233055e+01, 1.5379138694506308e+01, 1.5665858058473457e+01, 1.5964191652640661e+01, 1.6276573939462359e+01, 1.6606470454912181e+01, 1.6959141339427859e+01, 1.7343355369019513e+01, 1.7776125755426882e+01, 1.8301973063597831e+01}, + {-1.8355183937232482e+01, -1.7829840819908938e+01, -1.7397494085242659e+01, -1.7013662969810934e+01, -1.6661349346692710e+01, -1.6331792162325648e+01, -1.6019735882790211e+01, -1.5721717993090206e+01, -1.5435306145250426e+01, -1.5158709759192869e+01, -1.4890562720798751e+01, -1.4629792926034948e+01, -1.4375539545099908e+01, -1.4127098190154650e+01, -1.3883883239094454e+01, -1.3645401153510734e+01, -1.3411231091622829e+01, -1.3181010507418183e+01, -1.2954424246353401e+01, -1.2731196148405482e+01, -1.2511082484830109e+01, -1.2293866759574003e+01, -1.2079355542224606e+01, -1.1867375091697919e+01, -1.1657768593802700e+01, -1.1450393880891689e+01, -1.1245121534098722e+01, -1.1041833292131351e+01, -1.0840420707879813e+01, -1.0640784006999668e+01, -1.0442831112353673e+01, -1.0246476805614231e+01, -1.0051642003036079e+01, -9.8582531268427509e+00, -9.6662415571436178e+00, -9.4755431520404851e+00, -9.2860978257640348e+00, -9.0978491764272782e+00, -8.9107441563917540e+00, -8.7247327793845830e+00, -8.5397678594367203e+00, -8.3558047774774487e+00, -8.1728012720508225e+00, -7.9907172511424713e+00, -7.8095146225403225e+00, -7.6291571405168730e+00, -7.4496102669262783e+00, -7.2708410450674368e+00, -7.0928179848824850e+00, -6.9155109582455818e+00, -6.7388911032550611e+00, -6.5629307365772949e+00, -6.3876032730067926e+00, -6.2128831515070333e+00, -6.0387457670829185e+00, -5.8651674079104827e+00, -5.6921251972144509e+00, -5.5195970394407690e+00, -5.3475615703205710e+00, -5.1759981104652155e+00, -5.0048866221698640e+00, -4.8342076691363776e+00, -4.6639423788555394e+00, -4.4940724074145217e+00, -4.3245799065183155e+00, -4.1554474925341225e+00, -3.9866582173856151e+00, -3.8181955411399695e+00, -3.6500433061447404e+00, -3.4821857125843008e+00, -3.3146072953368710e+00, -3.1472929020232101e+00, -2.9802276721470844e+00, -2.8133970172356633e+00, -2.6467866018952186e+00, -2.4803823257039688e+00, -2.3141703058696805e+00, -2.1481368605848363e+00, -1.9822684930168015e+00, -1.8165518758745727e+00, -1.6509738364973834e+00, -1.4855213424137426e+00, -1.3201814873224036e+00, -1.1549414774493456e+00, -9.8978861823713149e-01, -8.2471030132498657e-01, -6.5969399177967603e-01, -4.9472721553871407e-01, -3.2979754702868869e-01, -1.6489259692248556e-01, -0.0000000000000000e+00, 1.6489259692248556e-01, 3.2979754702868869e-01, 4.9472721553871407e-01, 6.5969399177967603e-01, 8.2471030132498657e-01, 9.8978861823713149e-01, 1.1549414774493456e+00, 1.3201814873224036e+00, 1.4855213424137426e+00, 1.6509738364973834e+00, 1.8165518758745727e+00, 1.9822684930168015e+00, 2.1481368605848363e+00, 2.3141703058696805e+00, 2.4803823257039688e+00, 2.6467866018952186e+00, 2.8133970172356633e+00, 2.9802276721470844e+00, 3.1472929020232101e+00, 3.3146072953368710e+00, 3.4821857125843008e+00, 3.6500433061447404e+00, 3.8181955411399695e+00, 3.9866582173856151e+00, 4.1554474925341225e+00, 4.3245799065183155e+00, 4.4940724074145217e+00, 4.6639423788555394e+00, 4.8342076691363776e+00, 5.0048866221698640e+00, 5.1759981104652155e+00, 5.3475615703205710e+00, 5.5195970394407690e+00, 5.6921251972144509e+00, 5.8651674079104827e+00, 6.0387457670829185e+00, 6.2128831515070333e+00, 6.3876032730067926e+00, 6.5629307365772949e+00, 6.7388911032550611e+00, 6.9155109582455818e+00, 7.0928179848824850e+00, 7.2708410450674368e+00, 7.4496102669262783e+00, 7.6291571405168730e+00, 7.8095146225403225e+00, 7.9907172511424713e+00, 8.1728012720508225e+00, 8.3558047774774487e+00, 8.5397678594367203e+00, 8.7247327793845830e+00, 8.9107441563917540e+00, 9.0978491764272782e+00, 9.2860978257640348e+00, 9.4755431520404851e+00, 9.6662415571436178e+00, 9.8582531268427509e+00, 1.0051642003036079e+01, 1.0246476805614231e+01, 1.0442831112353673e+01, 1.0640784006999668e+01, 1.0840420707879813e+01, 1.1041833292131351e+01, 1.1245121534098722e+01, 1.1450393880891689e+01, 1.1657768593802700e+01, 1.1867375091697919e+01, 1.2079355542224606e+01, 1.2293866759574003e+01, 1.2511082484830109e+01, 1.2731196148405482e+01, 1.2954424246353401e+01, 1.3181010507418183e+01, 1.3411231091622829e+01, 1.3645401153510734e+01, 1.3883883239094454e+01, 1.4127098190154650e+01, 1.4375539545099908e+01, 1.4629792926034948e+01, 1.4890562720798751e+01, 1.5158709759192869e+01, 1.5435306145250426e+01, 1.5721717993090206e+01, 1.6019735882790211e+01, 1.6331792162325648e+01, 1.6661349346692710e+01, 1.7013662969810934e+01, 1.7397494085242659e+01, 1.7829840819908938e+01, 1.8355183937232482e+01}, + {-1.8408245997246180e+01, -1.7883403744491030e+01, -1.7451477824729114e+01, -1.7068027026173699e+01, -1.6716068212476749e+01, -1.6386848004427836e+01, -1.6075115445979726e+01, -1.5777411024325023e+01, -1.5491304492792262e+01, -1.5215006814022102e+01, -1.4947153048869007e+01, -1.4686672014714095e+01, -1.4432703621796808e+01, -1.4184544088639219e+01, -1.3941608298492062e+01, -1.3703403140370927e+01, -1.3469508138708429e+01, -1.3239561064882505e+01, -1.3013247042274847e+01, -1.2790290156511402e+01, -1.2570446897828043e+01, -1.2353500966915787e+01, -1.2139259111417608e+01, -1.1927547752486015e+01, -1.1718210224692305e+01, -1.1511104497611852e+01, -1.1306101279669830e+01, -1.1103082428282363e+01, -1.0901939607604296e+01, -1.0702573148080202e+01, -1.0504891071714988e+01, -1.0308808254390055e+01, -1.0114245702254145e+01, -9.9211299236483459e+00, -9.7293923814947600e+00, -9.5389690138184235e+00, -9.3497998122512573e+00, -9.1618284501124911e+00, -8.9750019530671192e+00, -8.7892704065055494e+00, -8.6045866947189253e+00, -8.4209062677087161e+00, -8.2381869320992998e+00, -8.0563886631444781e+00, -7.8754734352537348e+00, -7.6954050688277018e+00, -7.5161490914978035e+00, -7.3376726121226348e+00, -7.1599442061117617e+00, -6.9829338108329129e+00, -6.8066126300166054e+00, -6.6309530462073942e+00, -6.4559285404270428e+00, -6.2815136183148121e+00, -6.1076837420963281e+00, -5.9344152678072613e+00, -5.7616853872629088e+00, -5.5894720743212600e+00, -5.4177540350364595e+00, -5.2465106613426817e+00, -5.0757219879463076e+00, -4.9053686521374775e+00, -4.7354318562614344e+00, -4.5658933326158548e+00, -4.3967353105632334e+00, -4.2279404856676086e+00, -4.0594919906828633e+00, -3.8913733682357932e+00, -3.7235685450613194e+00, -3.5560618076598769e+00, -3.3888377792582984e+00, -3.2218813979656056e+00, -3.0551778960241212e+00, -2.8887127800643957e+00, -2.7224718122796761e+00, -2.5564409924420968e+00, -2.3906065406885992e+00, -2.2249548810097695e+00, -2.0594726253794451e+00, -1.8941465584671033e+00, -1.7289636228787715e+00, -1.5639109048755229e+00, -1.3989756205215691e+00, -1.2341451022165917e+00, -1.0694067855692595e+00, -9.0474819657091143e-01, -7.4015693903015356e-01, -5.7562068223063112e-01, -4.1112714877553319e-01, -2.4666410258345153e-01, -8.2219337001082138e-02, 8.2219337001082138e-02, 2.4666410258345153e-01, 4.1112714877553319e-01, 5.7562068223063112e-01, 7.4015693903015356e-01, 9.0474819657091143e-01, 1.0694067855692595e+00, 1.2341451022165917e+00, 1.3989756205215691e+00, 1.5639109048755229e+00, 1.7289636228787715e+00, 1.8941465584671033e+00, 2.0594726253794451e+00, 2.2249548810097695e+00, 2.3906065406885992e+00, 2.5564409924420968e+00, 2.7224718122796761e+00, 2.8887127800643957e+00, 3.0551778960241212e+00, 3.2218813979656056e+00, 3.3888377792582984e+00, 3.5560618076598769e+00, 3.7235685450613194e+00, 3.8913733682357932e+00, 4.0594919906828633e+00, 4.2279404856676086e+00, 4.3967353105632334e+00, 4.5658933326158548e+00, 4.7354318562614344e+00, 4.9053686521374775e+00, 5.0757219879463076e+00, 5.2465106613426817e+00, 5.4177540350364595e+00, 5.5894720743212600e+00, 5.7616853872629088e+00, 5.9344152678072613e+00, 6.1076837420963281e+00, 6.2815136183148121e+00, 6.4559285404270428e+00, 6.6309530462073942e+00, 6.8066126300166054e+00, 6.9829338108329129e+00, 7.1599442061117617e+00, 7.3376726121226348e+00, 7.5161490914978035e+00, 7.6954050688277018e+00, 7.8754734352537348e+00, 8.0563886631444781e+00, 8.2381869320992998e+00, 8.4209062677087161e+00, 8.6045866947189253e+00, 8.7892704065055494e+00, 8.9750019530671192e+00, 9.1618284501124911e+00, 9.3497998122512573e+00, 9.5389690138184235e+00, 9.7293923814947600e+00, 9.9211299236483459e+00, 1.0114245702254145e+01, 1.0308808254390055e+01, 1.0504891071714988e+01, 1.0702573148080202e+01, 1.0901939607604296e+01, 1.1103082428282363e+01, 1.1306101279669830e+01, 1.1511104497611852e+01, 1.1718210224692305e+01, 1.1927547752486015e+01, 1.2139259111417608e+01, 1.2353500966915787e+01, 1.2570446897828043e+01, 1.2790290156511402e+01, 1.3013247042274847e+01, 1.3239561064882505e+01, 1.3469508138708429e+01, 1.3703403140370927e+01, 1.3941608298492062e+01, 1.4184544088639219e+01, 1.4432703621796808e+01, 1.4686672014714095e+01, 1.4947153048869007e+01, 1.5215006814022102e+01, 1.5491304492792262e+01, 1.5777411024325023e+01, 1.6075115445979726e+01, 1.6386848004427836e+01, 1.6716068212476749e+01, 1.7068027026173699e+01, 1.7451477824729114e+01, 1.7883403744491030e+01, 1.8408245997246180e+01}, + {-1.8461160480857558e+01, -1.7936815806741905e+01, -1.7505307899899091e+01, -1.7122234853198016e+01, -1.6770628427712005e+01, -1.6441742871044735e+01, -1.6130331776708392e+01, -1.5832938615515195e+01, -1.5547135229076916e+01, -1.5271134113158810e+01, -1.5003571496240674e+01, -1.4743377111311560e+01, -1.4489691603942756e+01, -1.4241811795112390e+01, -1.3999153070125370e+01, -1.3761222742582584e+01, -1.3527600700651213e+01, -1.3297925030905425e+01, -1.3071881132685062e+01, -1.2849193335481473e+01, -1.2629618346876333e+01, -1.2412940062792593e+01, -1.2198965407516690e+01, -1.1987520963108198e+01, -1.1778450211639703e+01, -1.1571611258704099e+01, -1.1366874938858906e+01, -1.1164123227107424e+01, -1.0963247897778071e+01, -1.0764149385037474e+01, -1.0566735808984420e+01, -1.0370922138674908e+01, -1.0176629469126997e+01, -9.9837843937805424e+00, -9.7923184573541491e+00, -9.6021676767792830e+00, -9.4132721200689708e+00, -9.2255755347225286e+00, -9.0390250186738808e+00, -8.8535707279314924e+00, -8.6691656159885877e+00, -8.4857652008457727e+00, -8.3033273561177268e+00, -8.1218121232175022e+00, -7.9411815420463903e+00, -7.7613994979807179e+00, -7.5824315832521663e+00, -7.4042449710755918e+00, -7.2268083010962609e+00, -7.0500915749135666e+00, -6.8740660605962152e+00, -6.6987042052389292e+00, -6.5239795547267194e+00, -6.3498666799725676e+00, -6.1763411089806590e+00, -6.0033792641618602e+00, -5.8309584043931153e+00, -5.6590565713687386e+00, -5.4876525398409859e+00, -5.3167257713902920e+00, -5.1462563714034442e+00, -4.9762250489711075e+00, -4.8066130794454613e+00, -4.6374022694244390e+00, -4.4685749239519819e+00, -4.3001138157438552e+00, -4.1320021562665863e+00, -3.9642235685129914e+00, -3.7967620613319606e+00, -3.6296020051828295e+00, -3.4627281091959579e+00, -3.2961253994312023e+00, -3.1297791982350316e+00, -2.9636751046050795e+00, -2.7977989754781833e+00, -2.6321369078644477e+00, -2.4666752217556631e+00, -2.3014004437416671e+00, -2.1362992912728620e+00, -1.9713586575113293e+00, -1.8065655967166996e+00, -1.6419073101163049e+00, -1.4773711322121057e+00, -1.3129445174795540e+00, -1.1486150274158851e+00, -9.8437031789740859e-01, -8.2019812680717263e-01, -6.5608626189593511e-01, -4.9202258884072003e-01, -3.2799501946636006e-01, -1.6399150009634114e-01, -0.0000000000000000e+00, 1.6399150009634114e-01, 3.2799501946636006e-01, 4.9202258884072003e-01, 6.5608626189593511e-01, 8.2019812680717263e-01, 9.8437031789740859e-01, 1.1486150274158851e+00, 1.3129445174795540e+00, 1.4773711322121057e+00, 1.6419073101163049e+00, 1.8065655967166996e+00, 1.9713586575113293e+00, 2.1362992912728620e+00, 2.3014004437416671e+00, 2.4666752217556631e+00, 2.6321369078644477e+00, 2.7977989754781833e+00, 2.9636751046050795e+00, 3.1297791982350316e+00, 3.2961253994312023e+00, 3.4627281091959579e+00, 3.6296020051828295e+00, 3.7967620613319606e+00, 3.9642235685129914e+00, 4.1320021562665863e+00, 4.3001138157438552e+00, 4.4685749239519819e+00, 4.6374022694244390e+00, 4.8066130794454613e+00, 4.9762250489711075e+00, 5.1462563714034442e+00, 5.3167257713902920e+00, 5.4876525398409859e+00, 5.6590565713687386e+00, 5.8309584043931153e+00, 6.0033792641618602e+00, 6.1763411089806590e+00, 6.3498666799725676e+00, 6.5239795547267194e+00, 6.6987042052389292e+00, 6.8740660605962152e+00, 7.0500915749135666e+00, 7.2268083010962609e+00, 7.4042449710755918e+00, 7.5824315832521663e+00, 7.7613994979807179e+00, 7.9411815420463903e+00, 8.1218121232175022e+00, 8.3033273561177268e+00, 8.4857652008457727e+00, 8.6691656159885877e+00, 8.8535707279314924e+00, 9.0390250186738808e+00, 9.2255755347225286e+00, 9.4132721200689708e+00, 9.6021676767792830e+00, 9.7923184573541491e+00, 9.9837843937805424e+00, 1.0176629469126997e+01, 1.0370922138674908e+01, 1.0566735808984420e+01, 1.0764149385037474e+01, 1.0963247897778071e+01, 1.1164123227107424e+01, 1.1366874938858906e+01, 1.1571611258704099e+01, 1.1778450211639703e+01, 1.1987520963108198e+01, 1.2198965407516690e+01, 1.2412940062792593e+01, 1.2629618346876333e+01, 1.2849193335481473e+01, 1.3071881132685062e+01, 1.3297925030905425e+01, 1.3527600700651213e+01, 1.3761222742582584e+01, 1.3999153070125370e+01, 1.4241811795112390e+01, 1.4489691603942756e+01, 1.4743377111311560e+01, 1.5003571496240674e+01, 1.5271134113158810e+01, 1.5547135229076916e+01, 1.5832938615515195e+01, 1.6130331776708392e+01, 1.6441742871044735e+01, 1.6770628427712005e+01, 1.7122234853198016e+01, 1.7505307899899091e+01, 1.7936815806741905e+01, 1.8461160480857558e+01}, + {-1.8513928608263910e+01, -1.7990078266499342e+01, -1.7558985604821832e+01, -1.7176287776635139e+01, -1.6825031348357740e+01, -1.6496478147418177e+01, -1.6185386288902521e+01, -1.5888302208889046e+01, -1.5602799824404595e+01, -1.5327093154858311e+01, -1.5059819589095412e+01, -1.4799909769977225e+01, -1.4546505073756210e+01, -1.4298902920011114e+01, -1.4056519192842705e+01, -1.3818861627636300e+01, -1.3585510473849133e+01, -1.3356104131088610e+01, -1.3130328272714728e+01, -1.2907907470327904e+01, -1.2688598647247023e+01, -1.2472185893139361e+01, -1.2258476307546671e+01, -1.2047296632129509e+01, -1.1838490495223393e+01, -1.1631916137256281e+01, -1.1427444517781534e+01, -1.1224957728290695e+01, -1.1024347652217228e+01, -1.0825514826405534e+01, -1.0628367468022887e+01, -1.0432820638288694e+01, -1.0238795520089184e+01, -1.0046218790968188e+01, -9.8550220764490426e+00, -9.6651414713778827e+00, -9.4765171191542965e+00, -9.2890928404578474e+00, -9.1028158044838392e+00, -8.9176362368413074e+00, -8.7335071591960247e+00, -8.5503841565041103e+00, -8.3682251683108984e+00, -8.1869903011111198e+00, -8.0066416592005272e+00, -7.8271431918122021e+00, -7.6484605546357463e+00, -7.4705609840747460e+00, -7.2934131828156445e+00, -7.1169872154661693e+00, -6.9412544131792480e+00, -6.7661872863133015e+00, -6.5917594442957039e+00, -6.4179455219559527e+00, -6.2447211116812200e+00, -6.0720627008216166e+00, -5.8999476138372433e+00, -5.7283539587355410e+00, -5.5572605773966774e+00, -5.3866469994277919e+00, -5.2164933992246887e+00, -5.0467805559527736e+00, -4.8774898161882945e+00, -4.7086030589866992e+00, -4.5401026631678034e+00, -4.3719714766276327e+00, -4.2041927875047698e+00, -4.0367502970449332e+00, -3.8696280940217886e+00, -3.7028106305845436e+00, -3.5362826994142633e+00, -3.3700294120808700e+00, -3.2040361785018661e+00, -3.0382886874118746e+00, -2.8727728877593544e+00, -2.7074749709533479e+00, -2.5423813538889330e+00, -2.3774786626852964e+00, -2.2127537170750284e+00, -2.0481935153874455e+00, -1.8837852200725123e+00, -1.7195161437153161e+00, -1.5553737354940405e+00, -1.3913455680370777e+00, -1.2274193246372884e+00, -1.0635827867835286e+00, -8.9982382197139399e-01, -7.3613037175675000e-01, -5.7249044001699179e-01, -4.0889208138615224e-01, -2.4532338983095259e-01, -8.1772487335672980e-02, 8.1772487335672980e-02, 2.4532338983095259e-01, 4.0889208138615224e-01, 5.7249044001699179e-01, 7.3613037175675000e-01, 8.9982382197139399e-01, 1.0635827867835286e+00, 1.2274193246372884e+00, 1.3913455680370777e+00, 1.5553737354940405e+00, 1.7195161437153161e+00, 1.8837852200725123e+00, 2.0481935153874455e+00, 2.2127537170750284e+00, 2.3774786626852964e+00, 2.5423813538889330e+00, 2.7074749709533479e+00, 2.8727728877593544e+00, 3.0382886874118746e+00, 3.2040361785018661e+00, 3.3700294120808700e+00, 3.5362826994142633e+00, 3.7028106305845436e+00, 3.8696280940217886e+00, 4.0367502970449332e+00, 4.2041927875047698e+00, 4.3719714766276327e+00, 4.5401026631678034e+00, 4.7086030589866992e+00, 4.8774898161882945e+00, 5.0467805559527736e+00, 5.2164933992246887e+00, 5.3866469994277919e+00, 5.5572605773966774e+00, 5.7283539587355410e+00, 5.8999476138372433e+00, 6.0720627008216166e+00, 6.2447211116812200e+00, 6.4179455219559527e+00, 6.5917594442957039e+00, 6.7661872863133015e+00, 6.9412544131792480e+00, 7.1169872154661693e+00, 7.2934131828156445e+00, 7.4705609840747460e+00, 7.6484605546357463e+00, 7.8271431918122021e+00, 8.0066416592005272e+00, 8.1869903011111198e+00, 8.3682251683108984e+00, 8.5503841565041103e+00, 8.7335071591960247e+00, 8.9176362368413074e+00, 9.1028158044838392e+00, 9.2890928404578474e+00, 9.4765171191542965e+00, 9.6651414713778827e+00, 9.8550220764490426e+00, 1.0046218790968188e+01, 1.0238795520089184e+01, 1.0432820638288694e+01, 1.0628367468022887e+01, 1.0825514826405534e+01, 1.1024347652217228e+01, 1.1224957728290695e+01, 1.1427444517781534e+01, 1.1631916137256281e+01, 1.1838490495223393e+01, 1.2047296632129509e+01, 1.2258476307546671e+01, 1.2472185893139361e+01, 1.2688598647247023e+01, 1.2907907470327904e+01, 1.3130328272714728e+01, 1.3356104131088610e+01, 1.3585510473849133e+01, 1.3818861627636300e+01, 1.4056519192842705e+01, 1.4298902920011114e+01, 1.4546505073756210e+01, 1.4799909769977225e+01, 1.5059819589095412e+01, 1.5327093154858311e+01, 1.5602799824404595e+01, 1.5888302208889046e+01, 1.6185386288902521e+01, 1.6496478147418177e+01, 1.6825031348357740e+01, 1.7176287776635139e+01, 1.7558985604821832e+01, 1.7990078266499342e+01, 1.8513928608263910e+01}, + {-1.8566551582966934e+01, -1.8043192366212146e+01, -1.7612512215572043e+01, -1.7230187103675732e+01, -1.6879278311267964e+01, -1.6551055199152213e+01, -1.6240280376324659e+01, -1.5943503225988053e+01, -1.5658299727865778e+01, -1.5382885415641553e+01, -1.5115898831352473e+01, -1.4856271522065896e+01, -1.4603145590122086e+01, -1.4355819049893570e+01, -1.4113708281060786e+01, -1.3876321438029819e+01, -1.3643239129136898e+01, -1.3414100064890203e+01, -1.3188590190760220e+01, -1.2966434318726625e+01, -1.2747389586262109e+01, -1.2531240275314762e+01, -1.2317793659316827e+01, -1.2106876638246456e+01, -1.1898332985486029e+01, -1.1692021075138110e+01, -1.1487811990637235e+01, -1.1285587938886058e+01, -1.1085240911376399e+01, -1.0886671546608126e+01, -1.0689788157813780e+01, -1.0494505897387436e+01, -1.0300746035105149e+01, -1.0108435331643134e+01, -9.9175054923613413e+00, -9.7278926890529842e+00, -9.5395371395344313e+00, -9.3523827366910055e+00, -9.1663767199978832e+00, -8.9814693836739572e+00, -8.7976138165555611e+00, -8.6147656695390857e+00, -8.4328829470701354e+00, -8.2519258196777496e+00, -8.0718564549859924e+00, -7.8926388649980117e+00, -7.7142387677523603e+00, -7.5366234617083592e+00, -7.3597617114348806e+00, -7.1836236433617389e+00, -7.0081806505105702e+00, -6.8334053052569255e+00, -6.6592712792911071e+00, -6.4857532700449330e+00, -6.3128269329377309e+00, -6.1404688188693868e+00, -5.9686563164530524e+00, -5.7973675985364332e+00, -5.6265815726098278e+00, -5.4562778347421155e+00, -5.2864366267236216e+00, -5.1170387961280301e+00, -4.9480657590346588e+00, -4.7794994651782767e+00, -4.6113223653163988e+00, -4.4435173806242290e+00, -4.2760678739453368e+00, -4.1089576227421016e+00, -3.9421707936041384e+00, -3.7756919181855801e+00, -3.6095058704533836e+00, -3.4435978451389198e+00, -3.2779533372941430e+00, -3.1125581228617367e+00, -2.9473982401758851e+00, -2.7824599723168095e+00, -2.6177298302480856e+00, -2.4531945366709622e+00, -2.2888410105346408e+00, -2.1246563521456703e+00, -1.9606278288234207e+00, -1.7967428610519807e+00, -1.6329890090818511e+00, -1.4693539599375276e+00, -1.3058255147894620e+00, -1.1423915766510224e+00, -9.7904013836295944e-01, -8.1575927082952060e-01, -6.5253711147178228e-01, -4.8936185286498823e-01, -3.2622173152770212e-01, -1.6310501683142664e-01, -0.0000000000000000e+00, 1.6310501683142664e-01, 3.2622173152770212e-01, 4.8936185286498823e-01, 6.5253711147178228e-01, 8.1575927082952060e-01, 9.7904013836295944e-01, 1.1423915766510224e+00, 1.3058255147894620e+00, 1.4693539599375276e+00, 1.6329890090818511e+00, 1.7967428610519807e+00, 1.9606278288234207e+00, 2.1246563521456703e+00, 2.2888410105346408e+00, 2.4531945366709622e+00, 2.6177298302480856e+00, 2.7824599723168095e+00, 2.9473982401758851e+00, 3.1125581228617367e+00, 3.2779533372941430e+00, 3.4435978451389198e+00, 3.6095058704533836e+00, 3.7756919181855801e+00, 3.9421707936041384e+00, 4.1089576227421016e+00, 4.2760678739453368e+00, 4.4435173806242290e+00, 4.6113223653163988e+00, 4.7794994651782767e+00, 4.9480657590346588e+00, 5.1170387961280301e+00, 5.2864366267236216e+00, 5.4562778347421155e+00, 5.6265815726098278e+00, 5.7973675985364332e+00, 5.9686563164530524e+00, 6.1404688188693868e+00, 6.3128269329377309e+00, 6.4857532700449330e+00, 6.6592712792911071e+00, 6.8334053052569255e+00, 7.0081806505105702e+00, 7.1836236433617389e+00, 7.3597617114348806e+00, 7.5366234617083592e+00, 7.7142387677523603e+00, 7.8926388649980117e+00, 8.0718564549859924e+00, 8.2519258196777496e+00, 8.4328829470701354e+00, 8.6147656695390857e+00, 8.7976138165555611e+00, 8.9814693836739572e+00, 9.1663767199978832e+00, 9.3523827366910055e+00, 9.5395371395344313e+00, 9.7278926890529842e+00, 9.9175054923613413e+00, 1.0108435331643134e+01, 1.0300746035105149e+01, 1.0494505897387436e+01, 1.0689788157813780e+01, 1.0886671546608126e+01, 1.1085240911376399e+01, 1.1285587938886058e+01, 1.1487811990637235e+01, 1.1692021075138110e+01, 1.1898332985486029e+01, 1.2106876638246456e+01, 1.2317793659316827e+01, 1.2531240275314762e+01, 1.2747389586262109e+01, 1.2966434318726625e+01, 1.3188590190760220e+01, 1.3414100064890203e+01, 1.3643239129136898e+01, 1.3876321438029819e+01, 1.4113708281060786e+01, 1.4355819049893570e+01, 1.4603145590122086e+01, 1.4856271522065896e+01, 1.5115898831352473e+01, 1.5382885415641553e+01, 1.5658299727865778e+01, 1.5943503225988053e+01, 1.6240280376324659e+01, 1.6551055199152213e+01, 1.6879278311267964e+01, 1.7230187103675732e+01, 1.7612512215572043e+01, 1.8043192366212146e+01, 1.8566551582966934e+01}, + {-1.8619030592090468e+01, -1.8096159331273782e+01, -1.7665888990577489e+01, -1.7283934123310647e+01, -1.6933370634565016e+01, -1.6605475372599290e+01, -1.6295015412972358e+01, -1.5998543068078176e+01, -1.5713636367765231e+01, -1.5438512350731910e+01, -1.5171810705118517e+01, -1.4912463876600265e+01, -1.4659614689068135e+01, -1.4412561747929246e+01, -1.4170721925268760e+01, -1.3933603791786325e+01, -1.3700788312318828e+01, -1.3471914506172659e+01, -1.3246668589046763e+01, -1.3024775611596180e+01, -1.2805992923888546e+01, -1.2590104998712771e+01, -1.2376919282049462e+01, -1.2166262830933078e+01, -1.1957979562598471e+01, -1.1751927983683725e+01, -1.1547979300411118e+01, -1.1346015834038415e+01, -1.1145929683090303e+01, -1.0947621586721102e+01, -1.0750999953246895e+01, -1.0555980025269434e+01, -1.0362483158498314e+01, -1.0170436195792986e+01, -9.9797709214047838e+00, -9.7904235831297708e+00, -9.6023344722552224e+00, -9.4154475529222363e+00, -9.2297101339294976e+00, -9.0450725771408784e+00, -8.8614880375878489e+00, -8.6789122311192006e+00, -8.4973032260786319e+00, -8.3166212560112189e+00, -8.1368285508332487e+00, -7.9578891842622976e+00, -7.7797689356090070e+00, -7.6024351642886749e+00, -7.4258566956282692e+00, -7.2500037167290969e+00, -7.0748476813029546e+00, -6.9003612225343067e+00, -6.7265180731367256e+00, -6.5532929918714933e+00, -6.3806616958821749e+00, -6.2086007982735998e+00, -6.0370877504282516e+00, -5.8661007886095131e+00, -5.6956188844502709e+00, -5.5256216989684903e+00, -5.3560895397890276e+00, -5.1870033212841671e+00, -5.0183445273745217e+00, -4.8500951767577565e+00, -4.6822377903553614e+00, -4.5147553607879187e+00, -4.3476313237072048e+00, -4.1808495308294304e+00, -4.0143942245280941e+00, -3.8482500138575717e+00, -3.6824018518898707e+00, -3.5168350142570763e+00, -3.3515350788010423e+00, -3.1864879062399973e+00, -3.0216796217689894e+00, -2.8570965975176055e+00, -2.6927254357942609e+00, -2.5285529530516158e+00, -2.3645661645123681e+00, -2.2007522693989476e+00, -2.0370986367144122e+00, -1.8735927915252717e+00, -1.7102224017000158e+00, -1.5469752650598505e+00, -1.3838392969005895e+00, -1.2208025178467894e+00, -1.0578530420011503e+00, -8.9497906535386207e-01, -7.3216885441804769e-01, -5.6941073505871143e-01, -4.0669308148366978e-01, -2.4400430536582823e-01, -8.1332845066888051e-02, 8.1332845066888051e-02, 2.4400430536582823e-01, 4.0669308148366978e-01, 5.6941073505871143e-01, 7.3216885441804769e-01, 8.9497906535386207e-01, 1.0578530420011503e+00, 1.2208025178467894e+00, 1.3838392969005895e+00, 1.5469752650598505e+00, 1.7102224017000158e+00, 1.8735927915252717e+00, 2.0370986367144122e+00, 2.2007522693989476e+00, 2.3645661645123681e+00, 2.5285529530516158e+00, 2.6927254357942609e+00, 2.8570965975176055e+00, 3.0216796217689894e+00, 3.1864879062399973e+00, 3.3515350788010423e+00, 3.5168350142570763e+00, 3.6824018518898707e+00, 3.8482500138575717e+00, 4.0143942245280941e+00, 4.1808495308294304e+00, 4.3476313237072048e+00, 4.5147553607879187e+00, 4.6822377903553614e+00, 4.8500951767577565e+00, 5.0183445273745217e+00, 5.1870033212841671e+00, 5.3560895397890276e+00, 5.5256216989684903e+00, 5.6956188844502709e+00, 5.8661007886095131e+00, 6.0370877504282516e+00, 6.2086007982735998e+00, 6.3806616958821749e+00, 6.5532929918714933e+00, 6.7265180731367256e+00, 6.9003612225343067e+00, 7.0748476813029546e+00, 7.2500037167290969e+00, 7.4258566956282692e+00, 7.6024351642886749e+00, 7.7797689356090070e+00, 7.9578891842622976e+00, 8.1368285508332487e+00, 8.3166212560112189e+00, 8.4973032260786319e+00, 8.6789122311192006e+00, 8.8614880375878489e+00, 9.0450725771408784e+00, 9.2297101339294976e+00, 9.4154475529222363e+00, 9.6023344722552224e+00, 9.7904235831297708e+00, 9.9797709214047838e+00, 1.0170436195792986e+01, 1.0362483158498314e+01, 1.0555980025269434e+01, 1.0750999953246895e+01, 1.0947621586721102e+01, 1.1145929683090303e+01, 1.1346015834038415e+01, 1.1547979300411118e+01, 1.1751927983683725e+01, 1.1957979562598471e+01, 1.2166262830933078e+01, 1.2376919282049462e+01, 1.2590104998712771e+01, 1.2805992923888546e+01, 1.3024775611596180e+01, 1.3246668589046763e+01, 1.3471914506172659e+01, 1.3700788312318828e+01, 1.3933603791786325e+01, 1.4170721925268760e+01, 1.4412561747929246e+01, 1.4659614689068135e+01, 1.4912463876600265e+01, 1.5171810705118517e+01, 1.5438512350731910e+01, 1.5713636367765231e+01, 1.5998543068078176e+01, 1.6295015412972358e+01, 1.6605475372599290e+01, 1.6933370634565016e+01, 1.7283934123310647e+01, 1.7665888990577489e+01, 1.8096159331273782e+01, 1.8619030592090468e+01}, + {-1.8671366806690571e+01, -1.8148980370347783e+01, -1.7719117170958008e+01, -1.7337530106682756e+01, -1.6987309618003824e+01, -1.6659739995236801e+01, -1.6349592753466883e+01, -1.6053423116550778e+01, -1.5768811152035209e+01, -1.5493975394480826e+01, -1.5227556671125813e+01, -1.4968488320721917e+01, -1.4715913884228952e+01, -1.4469132554376165e+01, -1.4227561692518973e+01, -1.3990710282959036e+01, -1.3758159644687614e+01, -1.3529549103735965e+01, -1.3304565144176481e+01, -1.3082933053660961e+01, -1.2864410393317099e+01, -1.2648781825357542e+01, -1.2435854966991251e+01, -1.2225457031069224e+01, -1.2017432077505465e+01, -1.1811638744355296e+01, -1.1607948359555895e+01, -1.1406243357684700e+01, -1.1206415943294315e+01, -1.1008366955213159e+01, -1.0812004895879960e+01, -1.0617245097158223e+01, -1.0424008999756163e+01, -1.0232223527789033e+01, -1.0041820543476462e+01, -9.8527363696957284e+00, -9.6649113702822387e+00, -9.4782895797065567e+00, -9.2928183751587881e+00, -9.1084481852078358e+00, -8.9251322301305365e+00, -8.7428262897666009e+00, -8.5614884953828341e+00, -8.3810791425501474e+00, -8.2015605224698938e+00, -8.0228967695483639e+00, -7.8450537233223443e+00, -7.6679988030953385e+00, -7.4917008938611840e+00, -7.3161302422763823e+00, -7.1412583615998901e+00, -6.9670579446537078e+00, -6.7935027839732776e+00, -6.6205676984161617e+00, -6.4482284655834805e+00, -6.2764617594829843e+00, -6.1052450929273041e+00, -5.9345567642172057e+00, -5.7643758077087970e+00, -5.5946819479066203e+00, -5.4254555567622882e+00, -5.2566776138914113e+00, -5.0883296694508156e+00, -4.9203938094437563e+00, -4.7528526232436477e+00, -4.5856891731470037e+00, -4.4188869657842096e+00, -4.2524299252326587e+00, -4.0863023676909851e+00, -3.9204889775857690e+00, -3.7549747849933839e+00, -3.5897451442697546e+00, -3.4247857137898574e+00, -3.2600824367068570e+00, -3.0956215226480941e+00, -2.9313894302716164e+00, -2.7673728506128410e+00, -2.6035586911561817e+00, -2.4399340605712174e+00, -2.2764862540572279e+00, -2.1132027392437367e+00, -1.9500711425981514e+00, -1.7870792362946351e+00, -1.6242149255011178e+00, -1.4614662360438109e+00, -1.2988213024107587e+00, -1.1362683560579210e+00, -9.7379571398297626e-01, -8.1139176753353270e-01, -6.4904497141773709e-01, -4.8674383288637452e-01, -3.2447690105649102e-01, -1.6223275634733261e-01, -0.0000000000000000e+00, 1.6223275634733261e-01, 3.2447690105649102e-01, 4.8674383288637452e-01, 6.4904497141773709e-01, 8.1139176753353270e-01, 9.7379571398297626e-01, 1.1362683560579210e+00, 1.2988213024107587e+00, 1.4614662360438109e+00, 1.6242149255011178e+00, 1.7870792362946351e+00, 1.9500711425981514e+00, 2.1132027392437367e+00, 2.2764862540572279e+00, 2.4399340605712174e+00, 2.6035586911561817e+00, 2.7673728506128410e+00, 2.9313894302716164e+00, 3.0956215226480941e+00, 3.2600824367068570e+00, 3.4247857137898574e+00, 3.5897451442697546e+00, 3.7549747849933839e+00, 3.9204889775857690e+00, 4.0863023676909851e+00, 4.2524299252326587e+00, 4.4188869657842096e+00, 4.5856891731470037e+00, 4.7528526232436477e+00, 4.9203938094437563e+00, 5.0883296694508156e+00, 5.2566776138914113e+00, 5.4254555567622882e+00, 5.5946819479066203e+00, 5.7643758077087970e+00, 5.9345567642172057e+00, 6.1052450929273041e+00, 6.2764617594829843e+00, 6.4482284655834805e+00, 6.6205676984161617e+00, 6.7935027839732776e+00, 6.9670579446537078e+00, 7.1412583615998901e+00, 7.3161302422763823e+00, 7.4917008938611840e+00, 7.6679988030953385e+00, 7.8450537233223443e+00, 8.0228967695483639e+00, 8.2015605224698938e+00, 8.3810791425501474e+00, 8.5614884953828341e+00, 8.7428262897666009e+00, 8.9251322301305365e+00, 9.1084481852078358e+00, 9.2928183751587881e+00, 9.4782895797065567e+00, 9.6649113702822387e+00, 9.8527363696957284e+00, 1.0041820543476462e+01, 1.0232223527789033e+01, 1.0424008999756163e+01, 1.0617245097158223e+01, 1.0812004895879960e+01, 1.1008366955213159e+01, 1.1206415943294315e+01, 1.1406243357684700e+01, 1.1607948359555895e+01, 1.1811638744355296e+01, 1.2017432077505465e+01, 1.2225457031069224e+01, 1.2435854966991251e+01, 1.2648781825357542e+01, 1.2864410393317099e+01, 1.3082933053660961e+01, 1.3304565144176481e+01, 1.3529549103735965e+01, 1.3758159644687614e+01, 1.3990710282959036e+01, 1.4227561692518973e+01, 1.4469132554376165e+01, 1.4715913884228952e+01, 1.4968488320721917e+01, 1.5227556671125813e+01, 1.5493975394480826e+01, 1.5768811152035209e+01, 1.6053423116550778e+01, 1.6349592753466883e+01, 1.6659739995236801e+01, 1.6987309618003824e+01, 1.7337530106682756e+01, 1.7719117170958008e+01, 1.8148980370347783e+01, 1.8671366806690571e+01}, + {-1.8723561382058008e+01, -1.8201656675685278e+01, -1.7772197980856198e+01, -1.7390976307430105e+01, -1.7041096543327139e+01, -1.6713850376034177e+01, -1.6404013733432148e+01, -1.6108144733313441e+01, -1.5823825468638194e+01, -1.5549275960782586e+01, -1.5283138169159214e+01, -1.5024346320130698e+01, -1.4772044667297957e+01, -1.4525532987045759e+01, -1.4284229126904924e+01, -1.4047642482122557e+01, -1.3815354723529373e+01, -1.3587005481836711e+01, -1.3362281507661821e+01, -1.3140908323999378e+01, -1.2922643701525621e+01, -1.2707272490482195e+01, -1.2494602478007950e+01, -1.2284461031551617e+01, -1.2076692352553557e+01, -1.1871155209388238e+01, -1.1667721050654935e+01, -1.1466272423235269e+01, -1.1266701636724759e+01, -1.1068909628665612e+01, -1.0872804994678496e+01, -1.0678303154963148e+01, -1.0485325634312177e+01, -1.0293799437190248e+01, -1.0103656502883585e+01, -9.9148332284509078e+00, -9.7272700493753241e+00, -9.5409110695534167e+00, -9.3557037336580802e+00, -9.1715985360473766e+00, -8.9885487613184782e+00, -8.8065102523660030e+00, -8.6254412024311282e+00, -8.4453019681474064e+00, -8.2660549010220361e+00, -8.0876641951531028e+00, -7.9100957492873887e+00, -7.7333170415796193e+00, -7.5572970156311445e+00, -7.3820059765703627e+00, -7.2074154960945611e+00, -7.0334983255273515e+00, -6.8602283160613764e+00, -6.6875803454554488e+00, -6.5155302505411381e+00, -6.3440547649682282e+00, -6.1731314616830320e+00, -6.0027386996898384e+00, -5.8328555746948121e+00, -5.6634618732746507e+00, -5.4945380302499895e+00, -5.3260650889766197e+00, -5.1580246642968088e+00, -4.9903989079186992e+00, -4.8231704760145977e+00, -4.6563224988490806e+00, -4.4898385522658026e+00, -4.3237026308777766e+00, -4.1578991228200994e+00, -3.9924127859367369e+00, -3.8272287252842805e+00, -3.6623323718456740e+00, -3.4977094623559837e+00, -3.3333460201503651e+00, -3.1692283369516736e+00, -3.0053429555216815e+00, -2.8416766531057553e+00, -2.6782164256060947e+00, -2.5149494724234098e+00, -2.3518631819111540e+00, -2.1889451173902774e+00, -2.0261830036759103e+00, -1.8635647140704730e+00, -1.7010782577804868e+00, -1.5387117677168360e+00, -1.3764534886404416e+00, -1.2142917656172734e+00, -1.0522150327483684e+00, -8.9021180214204398e-01, -7.2827065309683536e-01, -5.6638022146482336e-01, -4.0452918916600705e-01, -2.4270627382517243e-01, -8.0900218503372048e-02, 8.0900218503372048e-02, 2.4270627382517243e-01, 4.0452918916600705e-01, 5.6638022146482336e-01, 7.2827065309683536e-01, 8.9021180214204398e-01, 1.0522150327483684e+00, 1.2142917656172734e+00, 1.3764534886404416e+00, 1.5387117677168360e+00, 1.7010782577804868e+00, 1.8635647140704730e+00, 2.0261830036759103e+00, 2.1889451173902774e+00, 2.3518631819111540e+00, 2.5149494724234098e+00, 2.6782164256060947e+00, 2.8416766531057553e+00, 3.0053429555216815e+00, 3.1692283369516736e+00, 3.3333460201503651e+00, 3.4977094623559837e+00, 3.6623323718456740e+00, 3.8272287252842805e+00, 3.9924127859367369e+00, 4.1578991228200994e+00, 4.3237026308777766e+00, 4.4898385522658026e+00, 4.6563224988490806e+00, 4.8231704760145977e+00, 4.9903989079186992e+00, 5.1580246642968088e+00, 5.3260650889766197e+00, 5.4945380302499895e+00, 5.6634618732746507e+00, 5.8328555746948121e+00, 6.0027386996898384e+00, 6.1731314616830320e+00, 6.3440547649682282e+00, 6.5155302505411381e+00, 6.6875803454554488e+00, 6.8602283160613764e+00, 7.0334983255273515e+00, 7.2074154960945611e+00, 7.3820059765703627e+00, 7.5572970156311445e+00, 7.7333170415796193e+00, 7.9100957492873887e+00, 8.0876641951531028e+00, 8.2660549010220361e+00, 8.4453019681474064e+00, 8.6254412024311282e+00, 8.8065102523660030e+00, 8.9885487613184782e+00, 9.1715985360473766e+00, 9.3557037336580802e+00, 9.5409110695534167e+00, 9.7272700493753241e+00, 9.9148332284509078e+00, 1.0103656502883585e+01, 1.0293799437190248e+01, 1.0485325634312177e+01, 1.0678303154963148e+01, 1.0872804994678496e+01, 1.1068909628665612e+01, 1.1266701636724759e+01, 1.1466272423235269e+01, 1.1667721050654935e+01, 1.1871155209388238e+01, 1.2076692352553557e+01, 1.2284461031551617e+01, 1.2494602478007950e+01, 1.2707272490482195e+01, 1.2922643701525621e+01, 1.3140908323999378e+01, 1.3362281507661821e+01, 1.3587005481836711e+01, 1.3815354723529373e+01, 1.4047642482122557e+01, 1.4284229126904924e+01, 1.4525532987045759e+01, 1.4772044667297957e+01, 1.5024346320130698e+01, 1.5283138169159214e+01, 1.5549275960782586e+01, 1.5823825468638194e+01, 1.6108144733313441e+01, 1.6404013733432148e+01, 1.6713850376034177e+01, 1.7041096543327139e+01, 1.7390976307430105e+01, 1.7772197980856198e+01, 1.8201656675685278e+01, 1.8723561382058008e+01}, + {-1.8775615458013544e+01, -1.8254189423434781e+01, -1.7825132627760091e+01, -1.7444273962020645e+01, -1.7094732674611997e+01, -1.6767807805810907e+01, -1.6458279669864240e+01, -1.6162709261170946e+01, -1.5878680685959477e+01, -1.5604415443478599e+01, -1.5338556618472303e+01, -1.5080039319512867e+01, -1.4828008508467775e+01, -1.4581764541755678e+01, -1.4340725750026818e+01, -1.4104401936851414e+01, -1.3872375122615423e+01, -1.3644285240693469e+01, -1.3419819306444866e+01, -1.3198703076577427e+01, -1.2980694529827234e+01, -1.2765578703092004e+01, -1.2553163552163017e+01, -1.2343276597888334e+01, -1.2135762182101830e+01, -1.1930479202418702e+01, -1.1727299227066995e+01, -1.1526104914236369e+01, -1.1326788677599657e+01, -1.1129251552471963e+01, -1.0933402226734774e+01, -1.0739156208018326e+01, -1.0546435104305445e+01, -1.0355165999524157e+01, -1.0165280909146327e+01, -9.9767163035334772e+00, -9.7894126889375794e+00, -9.6033142377998999e+00, -9.4183684613901413e+00, -9.2345259189629125e+00, -9.0517399585345863e+00, -8.8699664851432551e+00, -8.6891637530810133e+00, -8.5092921791069820e+00, -8.3303141740818543e+00, -8.1521939908263850e+00, -7.9748975863098721e+00, -7.7983924965309503e+00, -7.6226477226697984e+00, -7.4476336272751640e+00, -7.2733218394067363e+00, -7.0996851677878805e+00, -6.9266975211391140e+00, -6.7543338349621100e+00, -6.5825700041298303e+00, -6.4113828207126948e+00, -6.2407499165352709e+00, -6.0706497100141474e+00, -5.9010613568767107e+00, -5.7319647044035085e+00, -5.5633402488744599e+00, -5.3951690959323528e+00, -5.2274329236061510e+00, -5.0601139477624058e+00, -4.8931948897757946e+00, -4.7266589462300219e+00, -4.5604897604781494e+00, -4.3946713959074097e+00, -4.2291883107676789e+00, -4.0640253344354704e+00, -3.8991676449965649e+00, -3.7346007480405388e+00, -3.5703104565694619e+00, -3.4062828719311762e+00, -3.2425043656948236e+00, -3.0789615623928461e+00, -2.9156413230595541e+00, -2.7525307295016344e+00, -2.5896170692407368e+00, -2.4268878210725524e+00, -2.2643306411906372e+00, -2.1019333498267070e+00, -1.9396839183622288e+00, -1.7775704568689277e+00, -1.6155812020383324e+00, -1.4537045054627018e+00, -1.2919288222316836e+00, -1.1302426998108011e+00, -9.6863476716944097e-01, -8.0709372412735814e-01, -6.4560833088991310e-01, -4.8416739774326256e-01, -3.2275977488157320e-01, -1.6137434233903589e-01, -0.0000000000000000e+00, 1.6137434233903589e-01, 3.2275977488157320e-01, 4.8416739774326256e-01, 6.4560833088991310e-01, 8.0709372412735814e-01, 9.6863476716944097e-01, 1.1302426998108011e+00, 1.2919288222316836e+00, 1.4537045054627018e+00, 1.6155812020383324e+00, 1.7775704568689277e+00, 1.9396839183622288e+00, 2.1019333498267070e+00, 2.2643306411906372e+00, 2.4268878210725524e+00, 2.5896170692407368e+00, 2.7525307295016344e+00, 2.9156413230595541e+00, 3.0789615623928461e+00, 3.2425043656948236e+00, 3.4062828719311762e+00, 3.5703104565694619e+00, 3.7346007480405388e+00, 3.8991676449965649e+00, 4.0640253344354704e+00, 4.2291883107676789e+00, 4.3946713959074097e+00, 4.5604897604781494e+00, 4.7266589462300219e+00, 4.8931948897757946e+00, 5.0601139477624058e+00, 5.2274329236061510e+00, 5.3951690959323528e+00, 5.5633402488744599e+00, 5.7319647044035085e+00, 5.9010613568767107e+00, 6.0706497100141474e+00, 6.2407499165352709e+00, 6.4113828207126948e+00, 6.5825700041298303e+00, 6.7543338349621100e+00, 6.9266975211391140e+00, 7.0996851677878805e+00, 7.2733218394067363e+00, 7.4476336272751640e+00, 7.6226477226697984e+00, 7.7983924965309503e+00, 7.9748975863098721e+00, 8.1521939908263850e+00, 8.3303141740818543e+00, 8.5092921791069820e+00, 8.6891637530810133e+00, 8.8699664851432551e+00, 9.0517399585345863e+00, 9.2345259189629125e+00, 9.4183684613901413e+00, 9.6033142377998999e+00, 9.7894126889375794e+00, 9.9767163035334772e+00, 1.0165280909146327e+01, 1.0355165999524157e+01, 1.0546435104305445e+01, 1.0739156208018326e+01, 1.0933402226734774e+01, 1.1129251552471963e+01, 1.1326788677599657e+01, 1.1526104914236369e+01, 1.1727299227066995e+01, 1.1930479202418702e+01, 1.2135762182101830e+01, 1.2343276597888334e+01, 1.2553163552163017e+01, 1.2765578703092004e+01, 1.2980694529827234e+01, 1.3198703076577427e+01, 1.3419819306444866e+01, 1.3644285240693469e+01, 1.3872375122615423e+01, 1.4104401936851414e+01, 1.4340725750026818e+01, 1.4581764541755678e+01, 1.4828008508467775e+01, 1.5080039319512867e+01, 1.5338556618472303e+01, 1.5604415443478599e+01, 1.5878680685959477e+01, 1.6162709261170946e+01, 1.6458279669864240e+01, 1.6767807805810907e+01, 1.7094732674611997e+01, 1.7444273962020645e+01, 1.7825132627760091e+01, 1.8254189423434781e+01, 1.8775615458013544e+01}, + {-1.8827530159196098e+01, -1.8306579773944520e+01, -1.7877922302817918e+01, -1.7497424290078804e+01, -1.7148219258607661e+01, -1.6821613557585714e+01, -1.6512391861491736e+01, -1.6217118024196811e+01, -1.5933378153189908e+01, -1.5659395216751500e+01, -1.5393813418192966e+01, -1.5135568742958350e+01, -1.4883806856859362e+01, -1.4637828692771006e+01, -1.4397053061445078e+01, -1.4160990172186152e+01, -1.3929222392681286e+01, -1.3701389956978932e+01, -1.3477180143402940e+01, -1.3256318940768097e+01, -1.3038564534403923e+01, -1.2823702146512529e+01, -1.2611539900280661e+01, -1.2401905468777167e+01, -1.2194643333116042e+01, -1.1989612519093924e+01, -1.1786684713553210e+01, -1.1585742685014308e+01, -1.1386678950280542e+01, -1.1189394641517911e+01, -1.0993798537966583e+01, -1.0799806233800744e+01, -1.0607339419318674e+01, -1.0416325257045436e+01, -1.0226695837777637e+01, -1.0038387704321417e+01, -9.8513414328396713e+00, -9.6655012634583866e+00, -9.4808147731799934e+00, -9.2972325852854905e+00, -9.1147081103323924e+00, -8.9331973146145547e+00, -8.7526585125759730e+00, -8.5730521801893929e+00, -8.3943407867426210e+00, -8.2164886428367048e+00, -8.0394617627036364e+00, -7.8632277392072103e+00, -7.6877556301072998e+00, -7.5130158543520213e+00, -7.3389800973191823e+00, -7.1656212240628339e+00, -6.9929131997360230e+00, -6.8208310164601347e+00, -6.6493506259970188e+00, -6.4784488776542828e+00, -6.3081034609187254e+00, -6.1382928523689460e+00, -5.9689962664672880e+00, -5.8001936098740767e+00, -5.6318654389648133e+00, -5.4639929202639941e+00, -5.2965577935384172e+00, -5.1295423373184992e+00, -4.9629293366389069e+00, -4.7967020528099553e+00, -4.6308441950490966e+00, -4.4653398938177720e+00, -4.3001736757230296e+00, -4.1353304398559789e+00, -3.9707954354504480e+00, -3.8065542407552790e+00, -3.6425927430227989e+00, -3.4788971195240692e+00, -3.3154538195088263e+00, -3.1522495470345691e+00, -2.9892712445951148e+00, -2.8265060774842699e+00, -2.6639414188349808e+00, -2.5015648352786735e+00, -2.3393640731732996e+00, -2.1773270453521110e+00, -2.0154418183483078e+00, -1.8536966000534938e+00, -1.6920797277704067e+00, -1.5305796566226446e+00, -1.3691849482861076e+00, -1.2078842600086817e+00, -1.0466663338862598e+00, -8.8551998636459661e-01, -7.2443409793770541e-01, -5.6339760301455488e-01, -4.0239947992671032e-01, -2.4142874105030510e-01, -8.0474423016328678e-02, 8.0474423016328678e-02, 2.4142874105030510e-01, 4.0239947992671032e-01, 5.6339760301455488e-01, 7.2443409793770541e-01, 8.8551998636459661e-01, 1.0466663338862598e+00, 1.2078842600086817e+00, 1.3691849482861076e+00, 1.5305796566226446e+00, 1.6920797277704067e+00, 1.8536966000534938e+00, 2.0154418183483078e+00, 2.1773270453521110e+00, 2.3393640731732996e+00, 2.5015648352786735e+00, 2.6639414188349808e+00, 2.8265060774842699e+00, 2.9892712445951148e+00, 3.1522495470345691e+00, 3.3154538195088263e+00, 3.4788971195240692e+00, 3.6425927430227989e+00, 3.8065542407552790e+00, 3.9707954354504480e+00, 4.1353304398559789e+00, 4.3001736757230296e+00, 4.4653398938177720e+00, 4.6308441950490966e+00, 4.7967020528099553e+00, 4.9629293366389069e+00, 5.1295423373184992e+00, 5.2965577935384172e+00, 5.4639929202639941e+00, 5.6318654389648133e+00, 5.8001936098740767e+00, 5.9689962664672880e+00, 6.1382928523689460e+00, 6.3081034609187254e+00, 6.4784488776542828e+00, 6.6493506259970188e+00, 6.8208310164601347e+00, 6.9929131997360230e+00, 7.1656212240628339e+00, 7.3389800973191823e+00, 7.5130158543520213e+00, 7.6877556301072998e+00, 7.8632277392072103e+00, 8.0394617627036364e+00, 8.2164886428367048e+00, 8.3943407867426210e+00, 8.5730521801893929e+00, 8.7526585125759730e+00, 8.9331973146145547e+00, 9.1147081103323924e+00, 9.2972325852854905e+00, 9.4808147731799934e+00, 9.6655012634583866e+00, 9.8513414328396713e+00, 1.0038387704321417e+01, 1.0226695837777637e+01, 1.0416325257045436e+01, 1.0607339419318674e+01, 1.0799806233800744e+01, 1.0993798537966583e+01, 1.1189394641517911e+01, 1.1386678950280542e+01, 1.1585742685014308e+01, 1.1786684713553210e+01, 1.1989612519093924e+01, 1.2194643333116042e+01, 1.2401905468777167e+01, 1.2611539900280661e+01, 1.2823702146512529e+01, 1.3038564534403923e+01, 1.3256318940768097e+01, 1.3477180143402940e+01, 1.3701389956978932e+01, 1.3929222392681286e+01, 1.4160990172186152e+01, 1.4397053061445078e+01, 1.4637828692771006e+01, 1.4883806856859362e+01, 1.5135568742958350e+01, 1.5393813418192966e+01, 1.5659395216751500e+01, 1.5933378153189908e+01, 1.6217118024196811e+01, 1.6512391861491736e+01, 1.6821613557585714e+01, 1.7148219258607661e+01, 1.7497424290078804e+01, 1.7877922302817918e+01, 1.8306579773944520e+01, 1.8827530159196098e+01}, + {-1.8879306595344101e+01, -1.8358828872057543e+01, -1.7930568181145354e+01, -1.7550428494704086e+01, -1.7201557525065336e+01, -1.6875268886917173e+01, -1.6566351589127169e+01, -1.6271372328095570e+01, -1.5987919200699100e+01, -1.5714216635509363e+01, -1.5448909947718773e+01, -1.5190935994367434e+01, -1.4939441140940190e+01, -1.4693726893234164e+01, -1.4453212539122219e+01, -1.4217408691087410e+01, -1.3985898061893202e+01, -1.3758321184299211e+01, -1.3534365597840969e+01, -1.3313757521857125e+01, -1.3096255346825995e+01, -1.2881644478923162e+01, -1.2669733207493820e+01, -1.2460349356668459e+01, -1.2253337545746717e+01, -1.2048556927665979e+01, -1.1845879306886999e+01, -1.1645187561301928e+01, -1.1446374309916036e+01, -1.1249340780842516e+01, -1.1053995843796514e+01, -1.0860255178628208e+01, -1.0668040557095399e+01, -1.0477279219472964e+01, -1.0287903331040779e+01, -1.0099849506211216e+01, -9.9130583902203586e+00, -9.7274742900396252e+00, -9.5430448475612568e+00, -9.3597207492442038e+00, -9.1774554673313418e+00, -8.9962050285074913e+00, -8.8159278064930948e+00, -8.6365843355868694e+00, -8.4581371426023590e+00, -8.2805505950043532e+00, -8.1037907633543647e+00, -7.9278252964301190e+00, -7.7526233076005129e+00, -7.5781552712214886e+00, -7.4043929279751541e+00, -7.2313091982087343e+00, -7.0588781024451404e+00, -6.8870746883362148e+00, -6.7158749634153345e+00, -6.5452558330803203e+00, -6.3751950433020319e+00, -6.2056711276101213e+00, -6.0366633579564608e+00, -5.8681516990995659e+00, -5.7001167661909662e+00, -5.5325397852775344e+00, -5.3654025564628540e+00, -5.1986874194964612e+00, -5.0323772215824860e+00, -4.8664552872193818e+00, -4.7009053899003126e+00, -4.5357117255196737e+00, -4.3708588873453733e+00, -4.2063318424291563e+00, -4.0421159093385528e+00, -3.8781967371040955e+00, -3.7145602852845432e+00, -3.5511928050609516e+00, -3.3880808212776983e+00, -3.2252111153551550e+00, -3.0625707090045471e+00, -2.9001468486808863e+00, -2.7379269907145933e+00, -2.5758987870667562e+00, -2.4140500716568205e+00, -2.2523688472150090e+00, -2.0908432726148978e+00, -1.9294616506444018e+00, -1.7682124161759520e+00, -1.6070841246989318e+00, -1.4460654411794531e+00, -1.2851451292143858e+00, -1.1243120404481430e+00, -9.6355510422216051e-01, -8.0286331742823902e-01, -6.4222573453801035e-01, -4.8163145778170013e-01, -3.2106962745015089e-01, -1.6052941229469772e-01, -0.0000000000000000e+00, 1.6052941229469772e-01, 3.2106962745015089e-01, 4.8163145778170013e-01, 6.4222573453801035e-01, 8.0286331742823902e-01, 9.6355510422216051e-01, 1.1243120404481430e+00, 1.2851451292143858e+00, 1.4460654411794531e+00, 1.6070841246989318e+00, 1.7682124161759520e+00, 1.9294616506444018e+00, 2.0908432726148978e+00, 2.2523688472150090e+00, 2.4140500716568205e+00, 2.5758987870667562e+00, 2.7379269907145933e+00, 2.9001468486808863e+00, 3.0625707090045471e+00, 3.2252111153551550e+00, 3.3880808212776983e+00, 3.5511928050609516e+00, 3.7145602852845432e+00, 3.8781967371040955e+00, 4.0421159093385528e+00, 4.2063318424291563e+00, 4.3708588873453733e+00, 4.5357117255196737e+00, 4.7009053899003126e+00, 4.8664552872193818e+00, 5.0323772215824860e+00, 5.1986874194964612e+00, 5.3654025564628540e+00, 5.5325397852775344e+00, 5.7001167661909662e+00, 5.8681516990995659e+00, 6.0366633579564608e+00, 6.2056711276101213e+00, 6.3751950433020319e+00, 6.5452558330803203e+00, 6.7158749634153345e+00, 6.8870746883362148e+00, 7.0588781024451404e+00, 7.2313091982087343e+00, 7.4043929279751541e+00, 7.5781552712214886e+00, 7.7526233076005129e+00, 7.9278252964301190e+00, 8.1037907633543647e+00, 8.2805505950043532e+00, 8.4581371426023590e+00, 8.6365843355868694e+00, 8.8159278064930948e+00, 8.9962050285074913e+00, 9.1774554673313418e+00, 9.3597207492442038e+00, 9.5430448475612568e+00, 9.7274742900396252e+00, 9.9130583902203586e+00, 1.0099849506211216e+01, 1.0287903331040779e+01, 1.0477279219472964e+01, 1.0668040557095399e+01, 1.0860255178628208e+01, 1.1053995843796514e+01, 1.1249340780842516e+01, 1.1446374309916036e+01, 1.1645187561301928e+01, 1.1845879306886999e+01, 1.2048556927665979e+01, 1.2253337545746717e+01, 1.2460349356668459e+01, 1.2669733207493820e+01, 1.2881644478923162e+01, 1.3096255346825995e+01, 1.3313757521857125e+01, 1.3534365597840969e+01, 1.3758321184299211e+01, 1.3985898061893202e+01, 1.4217408691087410e+01, 1.4453212539122219e+01, 1.4693726893234164e+01, 1.4939441140940190e+01, 1.5190935994367434e+01, 1.5448909947718773e+01, 1.5714216635509363e+01, 1.5987919200699100e+01, 1.6271372328095570e+01, 1.6566351589127169e+01, 1.6875268886917173e+01, 1.7201557525065336e+01, 1.7550428494704086e+01, 1.7930568181145354e+01, 1.8358828872057543e+01, 1.8879306595344101e+01}, + {-1.8930945861570141e+01, -1.8410937847399730e+01, -1.7983071422125320e+01, -1.7603287762782053e+01, -1.7254748687059873e+01, -1.6928775032235986e+01, -1.6620160116009828e+01, -1.6325473460556140e+01, -1.6042305140399389e+01, -1.5768881035760351e+01, -1.5503847567102451e+01, -1.5246142457847222e+01, -1.4994912768931876e+01, -1.4749460575583919e+01, -1.4509205639853443e+01, -1.4273658974878348e+01, -1.4042403636302666e+01, -1.3815080453660714e+01, -1.3591377225971019e+01, -1.3371020401535507e+01, -1.3153768574557885e+01, -1.2939407333876543e+01, -1.2727745133777605e+01, -1.2518609948312903e+01, -1.2311846533891678e+01, -1.2107314169569506e+01, -1.1904884776447382e+01, -1.1704441340847984e+01, -1.1505876583067728e+01, -1.1309091826281094e+01, -1.1113996029812375e+01, -1.0920504958337819e+01, -1.0728540464237067e+01, -1.0538029864706095e+01, -1.0348905398685391e+01, -1.0161103751374336e+01, -9.9745656362640407e+00, -9.7892354263520396e+00, -9.6050608275979510e+00, -9.4219925888112019e+00, -9.2399842430857984e+00, -9.0589918766548454e+00, -8.8789739216625421e+00, -8.6998909698693474e+00, -8.5217056047373152e+00, -8.3443822497033171e+00, -8.1678870307509044e+00, -7.9921876516470487e+00, -7.8172532804264092e+00, -7.6430544458895735e+00, -7.4695629430384693e+00, -7.2967517465063425e+00, -7.1245949311547765e+00, -6.9530675991094046e+00, -6.7821458125915717e+00, -6.6118065319773942e+00, -6.4420275585800111e+00, -6.2727874817069420e+00, -6.1040656295934008e+00, -5.9358420238552689e+00, -5.7680973371429536e+00, -5.6008128537104387e+00, -5.4339704326429148e+00, -5.2675524735120289e+00, -5.1015418842505529e+00, -4.9359220510583919e+00, -4.7706768101697055e+00, -4.6057904213268381e+00, -4.4412475428209168e+00, -4.2770332079715754e+00, -4.1131328029295950e+00, -3.9495320456963339e+00, -3.7862169662628560e+00, -3.6231738877798154e+00, -3.4603894086764226e+00, -3.2978503856533741e+00, -3.1355439174805326e+00, -2.9734573295354325e+00, -2.8115781590234925e+00, -2.6498941408250944e+00, -2.4883931939185926e+00, -2.3270634083318020e+00, -2.1658930325776748e+00, -2.0048704615326960e+00, -1.8439842247190983e+00, -1.6832229749542722e+00, -1.5225754773327997e+00, -1.3620305985083838e+00, -1.2015772962445594e+00, -1.0412046092045326e+00, -8.8090164695175288e-01, -7.2065758013394154e-01, -5.6046163082425071e-01, -4.0030306299404111e-01, -2.4017117309244904e-01, -8.0055280708449292e-02, 8.0055280708449292e-02, 2.4017117309244904e-01, 4.0030306299404111e-01, 5.6046163082425071e-01, 7.2065758013394154e-01, 8.8090164695175288e-01, 1.0412046092045326e+00, 1.2015772962445594e+00, 1.3620305985083838e+00, 1.5225754773327997e+00, 1.6832229749542722e+00, 1.8439842247190983e+00, 2.0048704615326960e+00, 2.1658930325776748e+00, 2.3270634083318020e+00, 2.4883931939185926e+00, 2.6498941408250944e+00, 2.8115781590234925e+00, 2.9734573295354325e+00, 3.1355439174805326e+00, 3.2978503856533741e+00, 3.4603894086764226e+00, 3.6231738877798154e+00, 3.7862169662628560e+00, 3.9495320456963339e+00, 4.1131328029295950e+00, 4.2770332079715754e+00, 4.4412475428209168e+00, 4.6057904213268381e+00, 4.7706768101697055e+00, 4.9359220510583919e+00, 5.1015418842505529e+00, 5.2675524735120289e+00, 5.4339704326429148e+00, 5.6008128537104387e+00, 5.7680973371429536e+00, 5.9358420238552689e+00, 6.1040656295934008e+00, 6.2727874817069420e+00, 6.4420275585800111e+00, 6.6118065319773942e+00, 6.7821458125915717e+00, 6.9530675991094046e+00, 7.1245949311547765e+00, 7.2967517465063425e+00, 7.4695629430384693e+00, 7.6430544458895735e+00, 7.8172532804264092e+00, 7.9921876516470487e+00, 8.1678870307509044e+00, 8.3443822497033171e+00, 8.5217056047373152e+00, 8.6998909698693474e+00, 8.8789739216625421e+00, 9.0589918766548454e+00, 9.2399842430857984e+00, 9.4219925888112019e+00, 9.6050608275979510e+00, 9.7892354263520396e+00, 9.9745656362640407e+00, 1.0161103751374336e+01, 1.0348905398685391e+01, 1.0538029864706095e+01, 1.0728540464237067e+01, 1.0920504958337819e+01, 1.1113996029812375e+01, 1.1309091826281094e+01, 1.1505876583067728e+01, 1.1704441340847984e+01, 1.1904884776447382e+01, 1.2107314169569506e+01, 1.2311846533891678e+01, 1.2518609948312903e+01, 1.2727745133777605e+01, 1.2939407333876543e+01, 1.3153768574557885e+01, 1.3371020401535507e+01, 1.3591377225971019e+01, 1.3815080453660714e+01, 1.4042403636302666e+01, 1.4273658974878348e+01, 1.4509205639853443e+01, 1.4749460575583919e+01, 1.4994912768931876e+01, 1.5246142457847222e+01, 1.5503847567102451e+01, 1.5768881035760351e+01, 1.6042305140399389e+01, 1.6325473460556140e+01, 1.6620160116009828e+01, 1.6928775032235986e+01, 1.7254748687059873e+01, 1.7603287762782053e+01, 1.7983071422125320e+01, 1.8410937847399730e+01, 1.8930945861570141e+01}, + {-1.8982449038629166e+01, -1.8462907814661030e+01, -1.8035433169700678e+01, -1.7656003265287762e+01, -1.7307793941303686e+01, -1.6982133215169227e+01, -1.6673818688140226e+01, -1.6379422691596499e+01, -1.6096537266100814e+01, -1.5823389734978102e+01, -1.5558627617427760e+01, -1.5301189498098173e+01, -1.5050223129207568e+01, -1.4805031151963790e+01, -1.4565033799686276e+01, -1.4329742483675762e+01, -1.4098740600289259e+01, -1.3871669273924994e+01, -1.3648216561379414e+01, -1.3428109138379162e+01, -1.3211105801450707e+01, -1.2996992320804354e+01, -1.2785577314468604e+01, -1.2576688905294764e+01, -1.2370171985743601e+01, -1.2165885959983921e+01, -1.1963702864796298e+01, -1.1763505794009992e+01, -1.1565187568319024e+01, -1.1368649605090505e+01, -1.1173800952409410e+01, -1.0980557458945643e+01, -1.0788841056880692e+01, -1.0598579139520853e+01, -1.0409704018662802e+01, -1.0222152449492267e+01, -1.0035865212956141e+01, -9.8507867472781321e+00, -9.6668648216825712e+00, -9.4840502465221892e+00, -9.3022966149286930e+00, -9.1215600718621754e+00, -8.9417991070598717e+00, -8.7629743689023787e+00, -8.5850484966463263e+00, -8.4079859688330369e+00, -8.2317529659853896e+00, -8.0563172459604981e+00, -7.8816480305419629e+00, -7.7077159020391406e+00, -7.5344927088175595e+00, -7.3619514788185860e+00, -7.1900663402415486e+00, -7.0188124486605776e+00, -6.8481659199339457e+00, -6.6781037683378583e+00, -6.5086038494209282e+00, -6.3396448071316529e+00, -6.1712060248201084e+00, -6.0032675797578730e+00, -5.8358102008577646e+00, -5.6688152293079357e+00, -5.5022645818639999e+00, -5.3361407165684911e+00, -5.1704266006896686e+00, -5.0051056806918259e+00, -4.8401618540670963e+00, -4.6755794428746595e+00, -4.5113431688473895e+00, -4.3474381299386442e+00, -4.1838497781931396e+00, -4.0205638988360004e+00, -3.8575665904830925e+00, -3.6948442463838789e+00, -3.5323835366153280e+00, -3.3701713911519686e+00, -3.2081949837430650e+00, -3.0464417165332232e+00, -2.8848992053675047e+00, -2.7235552657264601e+00, -2.5623978992403580e+00, -2.4014152807354292e+00, -2.2405957457680694e+00, -2.0799277786058252e+00, -1.9194000006165373e+00, -1.7590011590293138e+00, -1.5987201160331019e+00, -1.4385458381804410e+00, -1.2784673860656646e+00, -1.1184739042482656e+00, -9.5855461139344544e-01, -7.9869879060299465e-01, -6.3889577991065161e-01, -4.7913496291691687e-01, -3.1940575953902500e-01, -1.5969761685235179e-01, -0.0000000000000000e+00, 1.5969761685235179e-01, 3.1940575953902500e-01, 4.7913496291691687e-01, 6.3889577991065161e-01, 7.9869879060299465e-01, 9.5855461139344544e-01, 1.1184739042482656e+00, 1.2784673860656646e+00, 1.4385458381804410e+00, 1.5987201160331019e+00, 1.7590011590293138e+00, 1.9194000006165373e+00, 2.0799277786058252e+00, 2.2405957457680694e+00, 2.4014152807354292e+00, 2.5623978992403580e+00, 2.7235552657264601e+00, 2.8848992053675047e+00, 3.0464417165332232e+00, 3.2081949837430650e+00, 3.3701713911519686e+00, 3.5323835366153280e+00, 3.6948442463838789e+00, 3.8575665904830925e+00, 4.0205638988360004e+00, 4.1838497781931396e+00, 4.3474381299386442e+00, 4.5113431688473895e+00, 4.6755794428746595e+00, 4.8401618540670963e+00, 5.0051056806918259e+00, 5.1704266006896686e+00, 5.3361407165684911e+00, 5.5022645818639999e+00, 5.6688152293079357e+00, 5.8358102008577646e+00, 6.0032675797578730e+00, 6.1712060248201084e+00, 6.3396448071316529e+00, 6.5086038494209282e+00, 6.6781037683378583e+00, 6.8481659199339457e+00, 7.0188124486605776e+00, 7.1900663402415486e+00, 7.3619514788185860e+00, 7.5344927088175595e+00, 7.7077159020391406e+00, 7.8816480305419629e+00, 8.0563172459604981e+00, 8.2317529659853896e+00, 8.4079859688330369e+00, 8.5850484966463263e+00, 8.7629743689023787e+00, 8.9417991070598717e+00, 9.1215600718621754e+00, 9.3022966149286930e+00, 9.4840502465221892e+00, 9.6668648216825712e+00, 9.8507867472781321e+00, 1.0035865212956141e+01, 1.0222152449492267e+01, 1.0409704018662802e+01, 1.0598579139520853e+01, 1.0788841056880692e+01, 1.0980557458945643e+01, 1.1173800952409410e+01, 1.1368649605090505e+01, 1.1565187568319024e+01, 1.1763505794009992e+01, 1.1963702864796298e+01, 1.2165885959983921e+01, 1.2370171985743601e+01, 1.2576688905294764e+01, 1.2785577314468604e+01, 1.2996992320804354e+01, 1.3211105801450707e+01, 1.3428109138379162e+01, 1.3648216561379414e+01, 1.3871669273924994e+01, 1.4098740600289259e+01, 1.4329742483675762e+01, 1.4565033799686276e+01, 1.4805031151963790e+01, 1.5050223129207568e+01, 1.5301189498098173e+01, 1.5558627617427760e+01, 1.5823389734978102e+01, 1.6096537266100814e+01, 1.6379422691596499e+01, 1.6673818688140226e+01, 1.6982133215169227e+01, 1.7307793941303686e+01, 1.7656003265287762e+01, 1.8035433169700678e+01, 1.8462907814661030e+01, 1.8982449038629166e+01}, + {-1.9033817193180372e+01, -1.8514739873870020e+01, -1.8087654552659949e+01, -1.7708576157582009e+01, -1.7360694468453165e+01, -1.7035344640856714e+01, -1.6727328534606457e+01, -1.6433221273899989e+01, -1.6150616853857390e+01, -1.5877744032458063e+01, -1.5613251421176075e+01, -1.5356078460791041e+01, -1.5105373590679383e+01, -1.4860440014620181e+01, -1.4620698434329638e+01, -1.4385660656810286e+01, -1.4154910416992225e+01, -1.3928089132251925e+01, -1.3704885115481808e+01, -1.3485025268316207e+01, -1.3268268588222005e+01, -1.3054401025509831e+01, -1.2843231360770561e+01, -1.2634587864551046e+01, -1.2428315564322974e+01, -1.2224273988380631e+01, -1.2022335288240422e+01, -1.1822382664331087e+01, -1.1624309036867450e+01, -1.1428015916557383e+01, -1.1233412439414929e+01, -1.1040414537288214e+01, -1.0848944221357737e+01, -1.0658928960246737e+01, -1.0470301137821307e+01, -1.0282997578470843e+01, -1.0096959129817110e+01, -9.9121302945287511e+00, -9.7284589043113154e+00, -9.5458958302732722e+00, -9.3643947247907189e+00, -9.1839117907500878e+00, -9.0044055746721732e+00, -8.8258367807379408e+00, -8.6481681031671602e+00, -8.4713640747611425e+00, -8.2953909297232951e+00, -8.1202164791264426e+00, -7.9458099976117715e+00, -7.7721421200878789e+00, -7.5991847473548857e+00, -7.4269109597125382e+00, -7.2552949377261493e+00, -7.0843118894232422e+00, -6.9139379832792587e+00, -6.7441502864247154e+00, -6.5749267075705307e+00, -6.4062459442041968e+00, -6.2380874336583796e+00, -6.0704313076963157e+00, -5.9032583502958440e+00, -5.7365499583469575e+00, -5.5702881050067488e+00, -5.4044553054813402e+00, -5.2390345850270315e+00, -5.0740094489830243e+00, -4.9093638546659628e+00, -4.7450821849723575e+00, -4.5811492235491675e+00, -4.4175501314054006e+00, -4.2542704248488947e+00, -4.0912959546425300e+00, -3.9286128862831946e+00, -3.7662076813149068e+00, -3.6040670795948389e+00, -3.4421780824374997e+00, -3.2805279365682800e+00, -3.1191041188228450e+00, -2.9578943215336770e+00, -2.7968864385493881e+00, -2.6360685518363063e+00, -2.4754289186153811e+00, -2.3149559589906059e+00, -2.1546382440280341e+00, -1.9944644842470249e+00, -1.8344235184876900e+00, -1.6745043031205911e+00, -1.5146959015666042e+00, -1.3549874740965486e+00, -1.1953682678816466e+00, -1.0358276072672234e+00, -8.7635488424319652e-01, -7.1693954908593016e-01, -5.5757110114689967e-01, -3.9823907976435802e-01, -2.3893305527481104e-01, -7.9642620101614783e-02, 7.9642620101614783e-02, 2.3893305527481104e-01, 3.9823907976435802e-01, 5.5757110114689967e-01, 7.1693954908593016e-01, 8.7635488424319652e-01, 1.0358276072672234e+00, 1.1953682678816466e+00, 1.3549874740965486e+00, 1.5146959015666042e+00, 1.6745043031205911e+00, 1.8344235184876900e+00, 1.9944644842470249e+00, 2.1546382440280341e+00, 2.3149559589906059e+00, 2.4754289186153811e+00, 2.6360685518363063e+00, 2.7968864385493881e+00, 2.9578943215336770e+00, 3.1191041188228450e+00, 3.2805279365682800e+00, 3.4421780824374997e+00, 3.6040670795948389e+00, 3.7662076813149068e+00, 3.9286128862831946e+00, 4.0912959546425300e+00, 4.2542704248488947e+00, 4.4175501314054006e+00, 4.5811492235491675e+00, 4.7450821849723575e+00, 4.9093638546659628e+00, 5.0740094489830243e+00, 5.2390345850270315e+00, 5.4044553054813402e+00, 5.5702881050067488e+00, 5.7365499583469575e+00, 5.9032583502958440e+00, 6.0704313076963157e+00, 6.2380874336583796e+00, 6.4062459442041968e+00, 6.5749267075705307e+00, 6.7441502864247154e+00, 6.9139379832792587e+00, 7.0843118894232422e+00, 7.2552949377261493e+00, 7.4269109597125382e+00, 7.5991847473548857e+00, 7.7721421200878789e+00, 7.9458099976117715e+00, 8.1202164791264426e+00, 8.2953909297232951e+00, 8.4713640747611425e+00, 8.6481681031671602e+00, 8.8258367807379408e+00, 9.0044055746721732e+00, 9.1839117907500878e+00, 9.3643947247907189e+00, 9.5458958302732722e+00, 9.7284589043113154e+00, 9.9121302945287511e+00, 1.0096959129817110e+01, 1.0282997578470843e+01, 1.0470301137821307e+01, 1.0658928960246737e+01, 1.0848944221357737e+01, 1.1040414537288214e+01, 1.1233412439414929e+01, 1.1428015916557383e+01, 1.1624309036867450e+01, 1.1822382664331087e+01, 1.2022335288240422e+01, 1.2224273988380631e+01, 1.2428315564322974e+01, 1.2634587864551046e+01, 1.2843231360770561e+01, 1.3054401025509831e+01, 1.3268268588222005e+01, 1.3485025268316207e+01, 1.3704885115481808e+01, 1.3928089132251925e+01, 1.4154910416992225e+01, 1.4385660656810286e+01, 1.4620698434329638e+01, 1.4860440014620181e+01, 1.5105373590679383e+01, 1.5356078460791041e+01, 1.5613251421176075e+01, 1.5877744032458063e+01, 1.6150616853857390e+01, 1.6433221273899989e+01, 1.6727328534606457e+01, 1.7035344640856714e+01, 1.7360694468453165e+01, 1.7708576157582009e+01, 1.8087654552659949e+01, 1.8514739873870020e+01, 1.9033817193180372e+01}, + {-1.9085051378043033e+01, -1.8566435110662020e+01, -1.8139736684916269e+01, -1.7761007579700482e+01, -1.7413451433407719e+01, -1.7088410498259837e+01, -1.6780690867902603e+01, -1.6486870443143417e+01, -1.6204545162304957e+01, -1.5931945209665145e+01, -1.5667720282583909e+01, -1.5410810672934431e+01, -1.5160365503176191e+01, -1.4915688536290588e+01, -1.4676200939552615e+01, -1.4441414913235960e+01, -1.4210914528731067e+01, -1.3984341494531598e+01, -1.3761384377966619e+01, -1.3541770305082187e+01, -1.3325258472923085e+01, -1.3111635010647520e+01, -1.2900708860246835e+01, -1.2692308438876983e+01, -1.2486278907997042e+01, -1.2282479919055724e+01, -1.2080783737378024e+01, -1.1881073669101410e+01, -1.1683242733101009e+01, -1.1487192532589896e+01, -1.1292832290695909e+01, -1.1100078021646450e+01, -1.0908851814834854e+01, -1.0719081213424776e+01, -1.0530698672582092e+01, -1.0343641085134585e+01, -1.0157849364615741e+01, -9.9732680773760247e+00, -9.7898451168372347e+00, -9.6075314140949892e+00, -9.4262806799959176e+00, -9.2460491745721143e+00, -9.0667955003389675e+00, -8.8884804164791387e+00, -8.7110666713658151e+00, -8.5345188512382073e+00, -8.3588032431445285e+00, -8.1838877105226704e+00, -8.0097415800046274e+00, -7.8363355382140769e+00, -7.6636415374829738e+00, -7.4916327095468409e+00, -7.3202832863932787e+00, -7.1495685275371788e+00, -6.9794646530814948e+00, -6.8099487819964919e+00, -6.6409988751145752e+00, -6.4725936823937991e+00, -6.3047126940519806e+00, -6.1373360952161162e+00, -5.9704447237692317e+00, -5.8040200311098342e+00, -5.6380440455680922e+00, -5.4724993382485847e+00, -5.3073689910920496e+00, -5.1426365669687621e+00, -4.9782860816339154e+00, -4.8143019773913309e+00, -4.6506690983259311e+00, -4.4873726669780289e+00, -4.3243982623437809e+00, -4.1617317990962412e+00, -3.9993595079305000e+00, -3.8372679169445236e+00, -3.6754438339745814e+00, -3.5138743298107440e+00, -3.3525467222238068e+00, -3.1914485607403469e+00, -3.0305676121073946e+00, -2.8698918463925485e+00, -2.7094094236692574e+00, -2.5491086812405244e+00, -2.3889781213574715e+00, -2.2290063993920741e+00, -2.0691823124259607e+00, -1.9094947882195137e+00, -1.7499328745276050e+00, -1.5904857287301759e+00, -1.4311426077475764e+00, -1.2718928582120677e+00, -1.1127259068682478e+00, -9.5363125117633152e-01, -7.9459845009326358e-01, -6.3561711500753826e-01, -4.7667690080438158e-01, -3.1776749703859319e-01, -1.5887861919288843e-01, -0.0000000000000000e+00, 1.5887861919288843e-01, 3.1776749703859319e-01, 4.7667690080438158e-01, 6.3561711500753826e-01, 7.9459845009326358e-01, 9.5363125117633152e-01, 1.1127259068682478e+00, 1.2718928582120677e+00, 1.4311426077475764e+00, 1.5904857287301759e+00, 1.7499328745276050e+00, 1.9094947882195137e+00, 2.0691823124259607e+00, 2.2290063993920741e+00, 2.3889781213574715e+00, 2.5491086812405244e+00, 2.7094094236692574e+00, 2.8698918463925485e+00, 3.0305676121073946e+00, 3.1914485607403469e+00, 3.3525467222238068e+00, 3.5138743298107440e+00, 3.6754438339745814e+00, 3.8372679169445236e+00, 3.9993595079305000e+00, 4.1617317990962412e+00, 4.3243982623437809e+00, 4.4873726669780289e+00, 4.6506690983259311e+00, 4.8143019773913309e+00, 4.9782860816339154e+00, 5.1426365669687621e+00, 5.3073689910920496e+00, 5.4724993382485847e+00, 5.6380440455680922e+00, 5.8040200311098342e+00, 5.9704447237692317e+00, 6.1373360952161162e+00, 6.3047126940519806e+00, 6.4725936823937991e+00, 6.6409988751145752e+00, 6.8099487819964919e+00, 6.9794646530814948e+00, 7.1495685275371788e+00, 7.3202832863932787e+00, 7.4916327095468409e+00, 7.6636415374829738e+00, 7.8363355382140769e+00, 8.0097415800046274e+00, 8.1838877105226704e+00, 8.3588032431445285e+00, 8.5345188512382073e+00, 8.7110666713658151e+00, 8.8884804164791387e+00, 9.0667955003389675e+00, 9.2460491745721143e+00, 9.4262806799959176e+00, 9.6075314140949892e+00, 9.7898451168372347e+00, 9.9732680773760247e+00, 1.0157849364615741e+01, 1.0343641085134585e+01, 1.0530698672582092e+01, 1.0719081213424776e+01, 1.0908851814834854e+01, 1.1100078021646450e+01, 1.1292832290695909e+01, 1.1487192532589896e+01, 1.1683242733101009e+01, 1.1881073669101410e+01, 1.2080783737378024e+01, 1.2282479919055724e+01, 1.2486278907997042e+01, 1.2692308438876983e+01, 1.2900708860246835e+01, 1.3111635010647520e+01, 1.3325258472923085e+01, 1.3541770305082187e+01, 1.3761384377966619e+01, 1.3984341494531598e+01, 1.4210914528731067e+01, 1.4441414913235960e+01, 1.4676200939552615e+01, 1.4915688536290588e+01, 1.5160365503176191e+01, 1.5410810672934431e+01, 1.5667720282583909e+01, 1.5931945209665145e+01, 1.6204545162304957e+01, 1.6486870443143417e+01, 1.6780690867902603e+01, 1.7088410498259837e+01, 1.7413451433407719e+01, 1.7761007579700482e+01, 1.8139736684916269e+01, 1.8566435110662020e+01, 1.9085051378043033e+01}, + {-1.9136152632446343e+01, -1.8617994596540964e+01, -1.8191680665779813e+01, -1.7813298656636132e+01, -1.7466065985601755e+01, -1.7141331960462935e+01, -1.6833906884239585e+01, -1.6540371418317267e+01, -1.6258323432990789e+01, -1.5985994530572864e+01, -1.5722035487991715e+01, -1.5465387443233377e+01, -1.5215200197812091e+01, -1.4970778070582133e+01, -1.4731542691573273e+01, -1.4497006651929539e+01, -1.4266754357415572e+01, -1.4040427805805265e+01, -1.3817715817227148e+01, -1.3598345740663659e+01, -1.3382076971394328e+01, -1.3168695816190608e+01, -1.2958011377300066e+01, -1.2749852217418379e+01, -1.2544063630985093e+01, -1.2340505391648597e+01, -1.2139049877631299e+01, -1.1939580499904540e+01, -1.1741990375159112e+01, -1.1546181198293549e+01, -1.1352062278750141e+01, -1.1159549712352600e+01, -1.0968565665937081e+01, -1.0779037756447492e+01, -1.0590898509596441e+01, -1.0404084885901707e+01, -1.0218537864062538e+01, -1.0034202073365652e+01, -9.8510254682020655e+00, -9.6689590389043136e+00, -9.4879565540345112e+00, -9.3079743300090456e+00, -9.1289710245687488e+00, -8.9509074511196953e+00, -8.7737464113997543e+00, -8.5974525442855416e+00, -8.4219921888566009e+00, -8.2473332600882276e+00, -8.0734451357601422e+00, -7.9002985533514174e+00, -7.7278655158483680e+00, -7.5561192055258362e+00, -7.3850339048770719e+00, -7.2145849239662976e+00, -7.0447485335633226e+00, -6.8755019034936238e+00, -6.7068230457014044e+00, -6.5386907615791259e+00, -6.3710845931658042e+00, -6.2039847778590458e+00, -6.0373722063233055e+00, -5.8712283833097523e+00, -5.7055353911321696e+00, -5.5402758555689235e+00, -5.3754329139836932e+00, -5.2109901854777609e+00, -5.0469317429044782e+00, -4.8832420865923929e+00, -4.7199061196376721e+00, -4.5569091246390609e+00, -4.3942367417598831e+00, -4.2318749480117184e+00, -4.0698100376633946e+00, -3.9080286036870948e+00, -3.7465175201606447e+00, -3.5852639255516232e+00, -3.4242552068148551e+00, -3.2634789842401504e+00, -3.1029230969919848e+00, -2.9425755892871246e+00, -2.7824246971601365e+00, -2.6224588357702330e+00, -2.4626665872061215e+00, -2.3030366887483824e+00, -2.1435580215515251e+00, -1.9842195997101939e+00, -1.8250105596761317e+00, -1.6659201499943919e+00, -1.5069377213289974e+00, -1.3480527167497827e+00, -1.1892546622534923e+00, -1.0305331574934382e+00, -8.7187786669305845e-01, -7.1327850971966389e-01, -5.5472485329544763e-01, -3.9620670232352440e-01, -2.3771389130732343e-01, -7.9236275842124657e-02, 7.9236275842124657e-02, 2.3771389130732343e-01, 3.9620670232352440e-01, 5.5472485329544763e-01, 7.1327850971966389e-01, 8.7187786669305845e-01, 1.0305331574934382e+00, 1.1892546622534923e+00, 1.3480527167497827e+00, 1.5069377213289974e+00, 1.6659201499943919e+00, 1.8250105596761317e+00, 1.9842195997101939e+00, 2.1435580215515251e+00, 2.3030366887483824e+00, 2.4626665872061215e+00, 2.6224588357702330e+00, 2.7824246971601365e+00, 2.9425755892871246e+00, 3.1029230969919848e+00, 3.2634789842401504e+00, 3.4242552068148551e+00, 3.5852639255516232e+00, 3.7465175201606447e+00, 3.9080286036870948e+00, 4.0698100376633946e+00, 4.2318749480117184e+00, 4.3942367417598831e+00, 4.5569091246390609e+00, 4.7199061196376721e+00, 4.8832420865923929e+00, 5.0469317429044782e+00, 5.2109901854777609e+00, 5.3754329139836932e+00, 5.5402758555689235e+00, 5.7055353911321696e+00, 5.8712283833097523e+00, 6.0373722063233055e+00, 6.2039847778590458e+00, 6.3710845931658042e+00, 6.5386907615791259e+00, 6.7068230457014044e+00, 6.8755019034936238e+00, 7.0447485335633226e+00, 7.2145849239662976e+00, 7.3850339048770719e+00, 7.5561192055258362e+00, 7.7278655158483680e+00, 7.9002985533514174e+00, 8.0734451357601422e+00, 8.2473332600882276e+00, 8.4219921888566009e+00, 8.5974525442855416e+00, 8.7737464113997543e+00, 8.9509074511196953e+00, 9.1289710245687488e+00, 9.3079743300090456e+00, 9.4879565540345112e+00, 9.6689590389043136e+00, 9.8510254682020655e+00, 1.0034202073365652e+01, 1.0218537864062538e+01, 1.0404084885901707e+01, 1.0590898509596441e+01, 1.0779037756447492e+01, 1.0968565665937081e+01, 1.1159549712352600e+01, 1.1352062278750141e+01, 1.1546181198293549e+01, 1.1741990375159112e+01, 1.1939580499904540e+01, 1.2139049877631299e+01, 1.2340505391648597e+01, 1.2544063630985093e+01, 1.2749852217418379e+01, 1.2958011377300066e+01, 1.3168695816190608e+01, 1.3382076971394328e+01, 1.3598345740663659e+01, 1.3817715817227148e+01, 1.4040427805805265e+01, 1.4266754357415572e+01, 1.4497006651929539e+01, 1.4731542691573273e+01, 1.4970778070582133e+01, 1.5215200197812091e+01, 1.5465387443233377e+01, 1.5722035487991715e+01, 1.5985994530572864e+01, 1.6258323432990789e+01, 1.6540371418317267e+01, 1.6833906884239585e+01, 1.7141331960462935e+01, 1.7466065985601755e+01, 1.7813298656636132e+01, 1.8191680665779813e+01, 1.8617994596540964e+01, 1.9136152632446343e+01}, + {-1.9187121982273521e+01, -1.8669419389135154e+01, -1.8243487580223828e+01, -1.7865450498614848e+01, -1.7518539259289700e+01, -1.7194110184967560e+01, -1.6886977763848531e+01, -1.6593725402038196e+01, -1.6311952890695306e+01, -1.6039893241994275e+01, -1.5776198306184138e+01, -1.5519810062439074e+01, -1.5269878987345788e+01, -1.5025709952340740e+01, -1.4786725047437830e+01, -1.4552437252279828e+01, -1.4322431304945502e+01, -1.4096349490675653e+01, -1.3873880880782780e+01, -1.3654753045730484e+01, -1.3438725577708846e+01, -1.3225584959886243e+01, -1.3015140453639436e+01, -1.2807220766151111e+01, -1.2601671323850574e+01, -1.2398352021647000e+01, -1.2197135349764665e+01, -1.1997904823149442e+01, -1.1800553655478529e+01, -1.1604983632531599e+01, -1.1411104149281471e+01, -1.1218831382380758e+01, -1.1028087575354093e+01, -1.0838800418181339e+01, -1.0650902506384885e+01, -1.0464330867440474e+01, -1.0279026544483804e+01, -1.0094934229009290e+01, -9.9120019356474849e+00, -9.7301807132353808e+00, -9.5494243873137332e+00, -9.3696893299405168e+00, -9.1909342533320295e+00, -9.0131200243591802e+00, -8.8362094973560179e+00, -8.6601673630569582e+00, -8.4849600117808954e+00, -8.3105554092350147e+00, -8.1369229835265475e+00, -7.9640335221538869e+00, -7.7918590779046193e+00, -7.6203728827216537e+00, -7.4495492687133176e+00, -7.2793635955820948e+00, -7.1097921838319138e+00, -6.9408122531878398e+00, -6.7724018657261427e+00, -6.6045398732686005e+00, -6.4372058686436739e+00, -6.2703801404598503e+00, -6.1040436310739281e+00, -5.9381778974699042e+00, -5.7727650747931136e+00, -5.6077878423099152e+00, -5.4432293915858283e+00, -5.2790733966951038e+00, -5.1153039862925711e+00, -4.9519057173944132e+00, -4.7888635507286939e+00, -4.6261628275290461e+00, -4.4637892476562113e+00, -4.3017288489422221e+00, -4.1399679876610396e+00, -3.9784933200376109e+00, -3.8172917847145760e+00, -3.6563505861024530e+00, -3.4956571785450063e+00, -3.3351992512368578e+00, -3.1749647138352097e+00, -3.0149416827118620e+00, -2.8551184677956569e+00, -2.6954835599590137e+00, -2.5360256189054007e+00, -2.3767334615175160e+00, -2.2175960506285199e+00, -2.0586024841810624e+00, -1.8997419847409271e+00, -1.7410038893340725e+00, -1.5823776395775344e+00, -1.4238527720762202e+00, -1.2654189090589871e+00, -1.1070657492286282e+00, -9.4878305880147162e-01, -7.9056066271324643e-01, -6.3238843596870120e-01, -4.7425629511315831e-01, -3.1615418980479731e-01, -1.5807209446693934e-01, -0.0000000000000000e+00, 1.5807209446693934e-01, 3.1615418980479731e-01, 4.7425629511315831e-01, 6.3238843596870120e-01, 7.9056066271324643e-01, 9.4878305880147162e-01, 1.1070657492286282e+00, 1.2654189090589871e+00, 1.4238527720762202e+00, 1.5823776395775344e+00, 1.7410038893340725e+00, 1.8997419847409271e+00, 2.0586024841810624e+00, 2.2175960506285199e+00, 2.3767334615175160e+00, 2.5360256189054007e+00, 2.6954835599590137e+00, 2.8551184677956569e+00, 3.0149416827118620e+00, 3.1749647138352097e+00, 3.3351992512368578e+00, 3.4956571785450063e+00, 3.6563505861024530e+00, 3.8172917847145760e+00, 3.9784933200376109e+00, 4.1399679876610396e+00, 4.3017288489422221e+00, 4.4637892476562113e+00, 4.6261628275290461e+00, 4.7888635507286939e+00, 4.9519057173944132e+00, 5.1153039862925711e+00, 5.2790733966951038e+00, 5.4432293915858283e+00, 5.6077878423099152e+00, 5.7727650747931136e+00, 5.9381778974699042e+00, 6.1040436310739281e+00, 6.2703801404598503e+00, 6.4372058686436739e+00, 6.6045398732686005e+00, 6.7724018657261427e+00, 6.9408122531878398e+00, 7.1097921838319138e+00, 7.2793635955820948e+00, 7.4495492687133176e+00, 7.6203728827216537e+00, 7.7918590779046193e+00, 7.9640335221538869e+00, 8.1369229835265475e+00, 8.3105554092350147e+00, 8.4849600117808954e+00, 8.6601673630569582e+00, 8.8362094973560179e+00, 9.0131200243591802e+00, 9.1909342533320295e+00, 9.3696893299405168e+00, 9.5494243873137332e+00, 9.7301807132353808e+00, 9.9120019356474849e+00, 1.0094934229009290e+01, 1.0279026544483804e+01, 1.0464330867440474e+01, 1.0650902506384885e+01, 1.0838800418181339e+01, 1.1028087575354093e+01, 1.1218831382380758e+01, 1.1411104149281471e+01, 1.1604983632531599e+01, 1.1800553655478529e+01, 1.1997904823149442e+01, 1.2197135349764665e+01, 1.2398352021647000e+01, 1.2601671323850574e+01, 1.2807220766151111e+01, 1.3015140453639436e+01, 1.3225584959886243e+01, 1.3438725577708846e+01, 1.3654753045730484e+01, 1.3873880880782780e+01, 1.4096349490675653e+01, 1.4322431304945502e+01, 1.4552437252279828e+01, 1.4786725047437830e+01, 1.5025709952340740e+01, 1.5269878987345788e+01, 1.5519810062439074e+01, 1.5776198306184138e+01, 1.6039893241994275e+01, 1.6311952890695306e+01, 1.6593725402038196e+01, 1.6886977763848531e+01, 1.7194110184967560e+01, 1.7518539259289700e+01, 1.7865450498614848e+01, 1.8243487580223828e+01, 1.8669419389135154e+01, 1.9187121982273521e+01}, + {-1.9237960440300323e+01, -1.8720710532447114e+01, -1.8295158499144485e+01, -1.7917464201364730e+01, -1.7570872373824393e+01, -1.7246746313979781e+01, -1.6939904671276931e+01, -1.6646933580854089e+01, -1.6365434743746000e+01, -1.6093642573904912e+01, -1.5830209988722080e+01, -1.5574079803690140e+01, -1.5324403166531194e+01, -1.5080485498011255e+01, -1.4841749345390438e+01, -1.4607708074467340e+01, -1.4377946753600369e+01, -1.4152107953707038e+01, -1.3929880995689542e+01, -1.3710993670057162e+01, -1.3495205764604879e+01, -1.3282303937699215e+01, -1.3072097608735946e+01, -1.2864415628348308e+01, -1.2659103553980440e+01, -1.2456021400878894e+01, -1.2255041770389502e+01, -1.2056048280588383e+01, -1.1858934241324912e+01, -1.1663601528470521e+01, -1.1469959621759649e+01, -1.1277924777921493e+01, -1.1087419316430047e+01, -1.0898370999572231e+01, -1.0710712491958864e+01, -1.0524380887307489e+01, -1.0339317292477098e+01, -1.0155466460457681e+01, -9.9727764654064881e+00, -9.7911984139496884e+00, -9.6106861878874543e+00, -9.4311962141946886e+00, -9.2526872588317186e+00, -9.0751202413947372e+00, -8.8984580680650804e+00, -8.7226654806754844e+00, -8.5477089200129779e+00, -8.3735564017325164e+00, -8.2001774034706933e+00, -8.0275427619319260e+00, -7.8556245788755001e+00, -7.6843961350654411e+00, -7.5138318113597080e+00, -7.3439070162139659e+00, -7.1745981189604136e+00, -7.0058823882959311e+00, -6.8377379354779668e+00, -6.6701436617824124e+00, -6.5030792098264039e+00, -6.3365249184017198e+00, -6.1704617805017721e+00, -6.0048714042581519e+00, -5.8397359765316308e+00, -5.6750382289281065e+00, -5.5107614060326373e+00, -5.3468892356747437e+00, -5.1834059010560054e+00, -5.0202960145867985e+00, -4.8575445932931558e+00, -4.6951370356673570e+00, -4.5330590998470743e+00, -4.3712968830180499e+00, -4.2098368019442765e+00, -4.0486655745377966e+00, -3.8877702023875300e+00, -3.7271379541730876e+00, -3.5667563498954848e+00, -3.4066131458619480e+00, -3.2466963203668557e+00, -3.0869940600152046e+00, -2.9274947466388688e+00, -2.7681869447595400e+00, -2.6090593895553744e+00, -2.4501009752913179e+00, -2.2913007441756847e+00, -2.1326478756079257e+00, -1.9741316757846794e+00, -1.8157415676330977e+00, -1.6574670810421992e+00, -1.4992978433645401e+00, -1.3412235701618946e+00, -1.1832340561698793e+00, -1.0253191664575543e+00, -8.6746882775900824e-01, -7.0967301995478616e-01, -5.5192176768174561e-01, -3.9420513205055796e-01, -2.3651320245058799e-01, -7.8836088422303746e-02, 7.8836088422303746e-02, 2.3651320245058799e-01, 3.9420513205055796e-01, 5.5192176768174561e-01, 7.0967301995478616e-01, 8.6746882775900824e-01, 1.0253191664575543e+00, 1.1832340561698793e+00, 1.3412235701618946e+00, 1.4992978433645401e+00, 1.6574670810421992e+00, 1.8157415676330977e+00, 1.9741316757846794e+00, 2.1326478756079257e+00, 2.2913007441756847e+00, 2.4501009752913179e+00, 2.6090593895553744e+00, 2.7681869447595400e+00, 2.9274947466388688e+00, 3.0869940600152046e+00, 3.2466963203668557e+00, 3.4066131458619480e+00, 3.5667563498954848e+00, 3.7271379541730876e+00, 3.8877702023875300e+00, 4.0486655745377966e+00, 4.2098368019442765e+00, 4.3712968830180499e+00, 4.5330590998470743e+00, 4.6951370356673570e+00, 4.8575445932931558e+00, 5.0202960145867985e+00, 5.1834059010560054e+00, 5.3468892356747437e+00, 5.5107614060326373e+00, 5.6750382289281065e+00, 5.8397359765316308e+00, 6.0048714042581519e+00, 6.1704617805017721e+00, 6.3365249184017198e+00, 6.5030792098264039e+00, 6.6701436617824124e+00, 6.8377379354779668e+00, 7.0058823882959311e+00, 7.1745981189604136e+00, 7.3439070162139659e+00, 7.5138318113597080e+00, 7.6843961350654411e+00, 7.8556245788755001e+00, 8.0275427619319260e+00, 8.2001774034706933e+00, 8.3735564017325164e+00, 8.5477089200129779e+00, 8.7226654806754844e+00, 8.8984580680650804e+00, 9.0751202413947372e+00, 9.2526872588317186e+00, 9.4311962141946886e+00, 9.6106861878874543e+00, 9.7911984139496884e+00, 9.9727764654064881e+00, 1.0155466460457681e+01, 1.0339317292477098e+01, 1.0524380887307489e+01, 1.0710712491958864e+01, 1.0898370999572231e+01, 1.1087419316430047e+01, 1.1277924777921493e+01, 1.1469959621759649e+01, 1.1663601528470521e+01, 1.1858934241324912e+01, 1.2056048280588383e+01, 1.2255041770389502e+01, 1.2456021400878894e+01, 1.2659103553980440e+01, 1.2864415628348308e+01, 1.3072097608735946e+01, 1.3282303937699215e+01, 1.3495205764604879e+01, 1.3710993670057162e+01, 1.3929880995689542e+01, 1.4152107953707038e+01, 1.4377946753600369e+01, 1.4607708074467340e+01, 1.4841749345390438e+01, 1.5080485498011255e+01, 1.5324403166531194e+01, 1.5574079803690140e+01, 1.5830209988722080e+01, 1.6093642573904912e+01, 1.6365434743746000e+01, 1.6646933580854089e+01, 1.6939904671276931e+01, 1.7246746313979781e+01, 1.7570872373824393e+01, 1.7917464201364730e+01, 1.8295158499144485e+01, 1.8720710532447114e+01, 1.9237960440300323e+01}, + {-1.9288669006428073e+01, -1.8771869057097732e+01, -1.8346694479614712e+01, -1.7969340846379055e+01, -1.7623066433928877e+01, -1.7299241474690692e+01, -1.6992688755677822e+01, -1.6699997125541856e+01, -1.6418770184323929e+01, -1.6147243739757997e+01, -1.5884071770266710e+01, -1.5628197922845580e+01, -1.5378774012459481e+01, -1.5135106005988732e+01, -1.4896616905233879e+01, -1.4662820459834590e+01, -1.4433302066419493e+01, -1.4207704579815282e+01, -1.3985717568940393e+01, -1.3767069042933601e+01, -1.3551518983907220e+01, -1.3338854224244356e+01, -1.3128884340266051e+01, -1.2921438325035480e+01, -1.2716361866052114e+01, -1.2513515097991551e+01, -1.2312770732455700e+01, -1.2114012489821327e+01, -1.1917133775310306e+01, -1.1722036554111044e+01, -1.1528630389965276e+01, -1.1336831618941112e+01, -1.1146562635737574e+01, -1.0957751274234692e+01, -1.0770330267425512e+01, -1.0584236774568581e+01, -1.0399411965548676e+01, -1.0215800654155213e+01, -1.0033350973375560e+01, -9.8520140869264541e+00, -9.6717439321652883e+00, -9.4924969902767238e+00, -9.3142320802515925e+00, -9.1369101736902376e+00, -8.9604942278913082e+00, -8.7849490350458534e+00, -8.6102410856578757e+00, -8.4363384445666423e+00, -8.2632106381612598e+00, -8.0908285515608398e+00, -7.9191643346894995e+00, -7.7481913163088629e+00, -7.5778839251852919e+00, -7.4082176176676109e+00, -7.2391688110363521e+00, -7.0707148220592551e+00, -6.9028338102518392e+00, -6.7355047253976705e+00, -6.5687072589316280e+00, -6.4024217988321039e+00, -6.2366293877054586e+00, -6.0713116837789416e+00, -5.9064509245471877e+00, -5.7420298928430569e+00, -5.5780318851261201e+00, -5.4144406818022057e+00, -5.2512405194051937e+00, -5.0884160644880927e+00, -4.9259523890845678e+00, -4.7638349476146598e+00, -4.6020495551197111e+00, -4.4405823667216309e+00, -4.2794198582106002e+00, -4.1185488076735286e+00, -3.9579562780827859e+00, -3.7976296007713630e+00, -3.6375563597264895e+00, -3.4777243766391046e+00, -3.3181216966513536e+00, -3.1587365747486800e+00, -2.9995574627469606e+00, -2.8405729968287345e+00, -2.6817719855857511e+00, -2.5231433985279939e+00, -2.3646763550219534e+00, -2.2063601136233109e+00, -2.0481840617713236e+00, -1.8901377058141628e+00, -1.7322106613361827e+00, -1.5743926437596774e+00, -1.4166734591950965e+00, -1.2590429955149371e+00, -1.1014912136276596e+00, -9.4400813892896185e-01, -7.8658385290862076e-01, -6.2920848489186076e-01, -4.7187220389486334e-01, -3.1456521057457892e-01, -1.5727772925344838e-01, -0.0000000000000000e+00, 1.5727772925344838e-01, 3.1456521057457892e-01, 4.7187220389486334e-01, 6.2920848489186076e-01, 7.8658385290862076e-01, 9.4400813892896185e-01, 1.1014912136276596e+00, 1.2590429955149371e+00, 1.4166734591950965e+00, 1.5743926437596774e+00, 1.7322106613361827e+00, 1.8901377058141628e+00, 2.0481840617713236e+00, 2.2063601136233109e+00, 2.3646763550219534e+00, 2.5231433985279939e+00, 2.6817719855857511e+00, 2.8405729968287345e+00, 2.9995574627469606e+00, 3.1587365747486800e+00, 3.3181216966513536e+00, 3.4777243766391046e+00, 3.6375563597264895e+00, 3.7976296007713630e+00, 3.9579562780827859e+00, 4.1185488076735286e+00, 4.2794198582106002e+00, 4.4405823667216309e+00, 4.6020495551197111e+00, 4.7638349476146598e+00, 4.9259523890845678e+00, 5.0884160644880927e+00, 5.2512405194051937e+00, 5.4144406818022057e+00, 5.5780318851261201e+00, 5.7420298928430569e+00, 5.9064509245471877e+00, 6.0713116837789416e+00, 6.2366293877054586e+00, 6.4024217988321039e+00, 6.5687072589316280e+00, 6.7355047253976705e+00, 6.9028338102518392e+00, 7.0707148220592551e+00, 7.2391688110363521e+00, 7.4082176176676109e+00, 7.5778839251852919e+00, 7.7481913163088629e+00, 7.9191643346894995e+00, 8.0908285515608398e+00, 8.2632106381612598e+00, 8.4363384445666423e+00, 8.6102410856578757e+00, 8.7849490350458534e+00, 8.9604942278913082e+00, 9.1369101736902376e+00, 9.3142320802515925e+00, 9.4924969902767238e+00, 9.6717439321652883e+00, 9.8520140869264541e+00, 1.0033350973375560e+01, 1.0215800654155213e+01, 1.0399411965548676e+01, 1.0584236774568581e+01, 1.0770330267425512e+01, 1.0957751274234692e+01, 1.1146562635737574e+01, 1.1336831618941112e+01, 1.1528630389965276e+01, 1.1722036554111044e+01, 1.1917133775310306e+01, 1.2114012489821327e+01, 1.2312770732455700e+01, 1.2513515097991551e+01, 1.2716361866052114e+01, 1.2921438325035480e+01, 1.3128884340266051e+01, 1.3338854224244356e+01, 1.3551518983907220e+01, 1.3767069042933601e+01, 1.3985717568940393e+01, 1.4207704579815282e+01, 1.4433302066419493e+01, 1.4662820459834590e+01, 1.4896616905233879e+01, 1.5135106005988732e+01, 1.5378774012459481e+01, 1.5628197922845580e+01, 1.5884071770266710e+01, 1.6147243739757997e+01, 1.6418770184323929e+01, 1.6699997125541856e+01, 1.6992688755677822e+01, 1.7299241474690692e+01, 1.7623066433928877e+01, 1.7969340846379055e+01, 1.8346694479614712e+01, 1.8771869057097732e+01, 1.9288669006428073e+01}, + {-1.9339248667911409e+01, -1.8822895980564734e+01, -1.8398096565132178e+01, -1.8021081501173168e+01, -1.7675122529961925e+01, -1.7351596779550405e+01, -1.7045331151092153e+01, -1.6752917191398179e+01, -1.6471960388762881e+01, -1.6200697936792103e+01, -1.5937784868895722e+01, -1.5682165658809755e+01, -1.5432992784892868e+01, -1.5189572756961194e+01, -1.4951329028681464e+01, -1.4717775731247299e+01, -1.4488498587572698e+01, -1.4263140734648266e+01, -1.4041391987855551e+01, -1.3822980573565543e+01, -1.3607666666938064e+01, -1.3395237273208020e+01, -1.3185502124544024e+01, -1.2978290355434069e+01, -1.2773447782488505e+01, -1.2570834658918320e+01, -1.2370323805730495e+01, -1.2171799044787127e+01, -1.1975153875897130e+01, -1.1780290352805242e+01, -1.1587118122520339e+01, -1.1395553599726039e+01, -1.1205519253636435e+01, -1.1016942989025184e+01, -1.0829757606576079e+01, -1.0643900330402785e+01, -1.0459312392733535e+01, -1.0275938667476471e+01, -1.0093727345768286e+01, -9.9126296477337945e+00, -9.7325995656019266e+00, -9.5535936340768206e+00, -9.3755707244836426e+00, -9.1984918597235552e+00, -9.0223200475008358e+00, -8.8470201296436706e+00, -8.6725586456412369e+00, -8.4989037087736055e+00, -8.3260248934261227e+00, -8.1538931323624819e+00, -7.9824806228866425e+00, -7.8117607409569434e+00, -7.6417079624302628e+00, -7.4722977907127222e+00, -7.3035066901782200e+00, -7.1353120247902524e+00, -6.9676920014260446e+00, -6.8006256174581203e+00, -6.6340926121968646e+00, -6.4680734218403675e+00, -6.3025491376151397e+00, -6.1375014668241503e+00, -5.9729126965475468e+00, -5.8087656597670589e+00, -5.6450437037075716e+00, -5.4817306602094709e+00, -5.3188108179631426e+00, -5.1562688964529020e+00, -4.9940900214715160e+00, -4.8322597020794342e+00, -4.6707638088937005e+00, -4.5095885536020024e+00, -4.3487204696060182e+00, -4.1881463937064671e+00, -4.0278534487497097e+00, -3.8678290271620543e+00, -3.7080607753039518e+00, -3.5485365785817580e+00, -3.3892445472592136e+00, -3.2301730029155085e+00, -3.0713104655004981e+00, -2.9126456409412849e+00, -2.7541674092575419e+00, -2.5958648131459636e+00, -2.4377270469968155e+00, -2.2797434463078550e+00, -2.1219034774632650e+00, -1.9641967278469044e+00, -1.8066128962612460e+00, -1.6491417836246915e+00, -1.4917732839215128e+00, -1.3344973753799896e+00, -1.1773041118552243e+00, -1.0201836143944896e+00, -8.6312606296338723e-01, -7.0612168831240074e-01, -5.4916076396359503e-01, -3.9223359829815591e-01, -2.3533052672581237e-01, -7.8441903917412792e-02, 7.8441903917412792e-02, 2.3533052672581237e-01, 3.9223359829815591e-01, 5.4916076396359503e-01, 7.0612168831240074e-01, 8.6312606296338723e-01, 1.0201836143944896e+00, 1.1773041118552243e+00, 1.3344973753799896e+00, 1.4917732839215128e+00, 1.6491417836246915e+00, 1.8066128962612460e+00, 1.9641967278469044e+00, 2.1219034774632650e+00, 2.2797434463078550e+00, 2.4377270469968155e+00, 2.5958648131459636e+00, 2.7541674092575419e+00, 2.9126456409412849e+00, 3.0713104655004981e+00, 3.2301730029155085e+00, 3.3892445472592136e+00, 3.5485365785817580e+00, 3.7080607753039518e+00, 3.8678290271620543e+00, 4.0278534487497097e+00, 4.1881463937064671e+00, 4.3487204696060182e+00, 4.5095885536020024e+00, 4.6707638088937005e+00, 4.8322597020794342e+00, 4.9940900214715160e+00, 5.1562688964529020e+00, 5.3188108179631426e+00, 5.4817306602094709e+00, 5.6450437037075716e+00, 5.8087656597670589e+00, 5.9729126965475468e+00, 6.1375014668241503e+00, 6.3025491376151397e+00, 6.4680734218403675e+00, 6.6340926121968646e+00, 6.8006256174581203e+00, 6.9676920014260446e+00, 7.1353120247902524e+00, 7.3035066901782200e+00, 7.4722977907127222e+00, 7.6417079624302628e+00, 7.8117607409569434e+00, 7.9824806228866425e+00, 8.1538931323624819e+00, 8.3260248934261227e+00, 8.4989037087736055e+00, 8.6725586456412369e+00, 8.8470201296436706e+00, 9.0223200475008358e+00, 9.1984918597235552e+00, 9.3755707244836426e+00, 9.5535936340768206e+00, 9.7325995656019266e+00, 9.9126296477337945e+00, 1.0093727345768286e+01, 1.0275938667476471e+01, 1.0459312392733535e+01, 1.0643900330402785e+01, 1.0829757606576079e+01, 1.1016942989025184e+01, 1.1205519253636435e+01, 1.1395553599726039e+01, 1.1587118122520339e+01, 1.1780290352805242e+01, 1.1975153875897130e+01, 1.2171799044787127e+01, 1.2370323805730495e+01, 1.2570834658918320e+01, 1.2773447782488505e+01, 1.2978290355434069e+01, 1.3185502124544024e+01, 1.3395237273208020e+01, 1.3607666666938064e+01, 1.3822980573565543e+01, 1.4041391987855551e+01, 1.4263140734648266e+01, 1.4488498587572698e+01, 1.4717775731247299e+01, 1.4951329028681464e+01, 1.5189572756961194e+01, 1.5432992784892868e+01, 1.5682165658809755e+01, 1.5937784868895722e+01, 1.6200697936792103e+01, 1.6471960388762881e+01, 1.6752917191398179e+01, 1.7045331151092153e+01, 1.7351596779550405e+01, 1.7675122529961925e+01, 1.8021081501173168e+01, 1.8398096565132178e+01, 1.8822895980564734e+01, 1.9339248667911409e+01}, +} + +// wCache computed from Chebfun. +var wCacheHermite = [][]float64{ + {1.7724538509055159e+00}, + {8.8622692545275794e-01, 8.8622692545275794e-01}, + {2.9540897515091952e-01, 1.1816359006036770e+00, 2.9540897515091952e-01}, + {8.1312835447245130e-02, 8.0491409000551273e-01, 8.0491409000551273e-01, 8.1312835447245130e-02}, + {1.9953242059045879e-02, 3.9361932315224107e-01, 9.4530872048294201e-01, 3.9361932315224107e-01, 1.9953242059045879e-02}, + {4.5300099055088682e-03, 1.5706732032285645e-01, 7.2462959522439263e-01, 7.2462959522439263e-01, 1.5706732032285645e-01, 4.5300099055088682e-03}, + {9.7178124509951806e-04, 5.4515582819127072e-02, 4.2560725261012772e-01, 8.1026461755680723e-01, 4.2560725261012772e-01, 5.4515582819127072e-02, 9.7178124509951806e-04}, + {1.9960407221136889e-04, 1.7077983007413408e-02, 2.0780232581489197e-01, 6.6114701255824115e-01, 6.6114701255824115e-01, 2.0780232581489197e-01, 1.7077983007413408e-02, 1.9960407221136889e-04}, + {3.9606977263264351e-05, 4.9436242755369481e-03, 8.8474527394376584e-02, 4.3265155900255570e-01, 7.2023521560605097e-01, 4.3265155900255570e-01, 8.8474527394376584e-02, 4.9436242755369481e-03, 3.9606977263264351e-05}, + {7.6404328552325936e-06, 1.3436457467812385e-03, 3.3874394455481120e-02, 2.4013861108231432e-01, 6.1086263373532612e-01, 6.1086263373532612e-01, 2.4013861108231432e-01, 3.3874394455481120e-02, 1.3436457467812385e-03, 7.6404328552325936e-06}, + {1.4395603937142598e-06, 3.4681946632334550e-04, 1.1911395444911524e-02, 1.1722787516770818e-01, 4.2935975235612489e-01, 6.5475928691459262e-01, 4.2935975235612489e-01, 1.1722787516770818e-01, 1.1911395444911524e-02, 3.4681946632334550e-04, 1.4395603937142598e-06}, + {2.6585516843563055e-07, 8.5736870435878019e-05, 3.9053905846290599e-03, 5.1607985615883964e-02, 2.6049231026416109e-01, 5.7013523626247942e-01, 5.7013523626247942e-01, 2.6049231026416109e-01, 5.1607985615883964e-02, 3.9053905846290599e-03, 8.5736870435878019e-05, 2.6585516843563055e-07}, + {4.8257318500731284e-08, 2.0430360402707074e-05, 1.2074599927193832e-03, 2.0862775296169932e-02, 1.4032332068702327e-01, 4.2161629689854296e-01, 6.0439318792116203e-01, 4.2161629689854296e-01, 1.4032332068702327e-01, 2.0862775296169932e-02, 1.2074599927193832e-03, 2.0430360402707074e-05, 4.8257318500731284e-08}, + {8.6285911681251554e-09, 4.7164843550189453e-06, 3.5509261355192302e-04, 7.8500547264579047e-03, 6.8505534223465281e-02, 2.7310560906424641e-01, 5.3640590971209023e-01, 5.3640590971209023e-01, 2.7310560906424641e-01, 6.8505534223465281e-02, 7.8500547264579047e-03, 3.5509261355192302e-04, 4.7164843550189453e-06, 8.6285911681251554e-09}, + {1.5224758042535219e-09, 1.0591155477110612e-06, 1.0000444123249973e-04, 2.7780688429127598e-03, 3.0780033872546117e-02, 1.5848891579593580e-01, 4.1202868749889832e-01, 5.6410030872641814e-01, 4.1202868749889832e-01, 1.5848891579593580e-01, 3.0780033872546117e-02, 2.7780688429127598e-03, 1.0000444123249973e-04, 1.0591155477110612e-06, 1.5224758042535219e-09}, + {2.6548074740111957e-10, 2.3209808448652080e-07, 2.7118600925378922e-05, 9.3228400862418201e-04, 1.2880311535509982e-02, 8.3810041398985943e-02, 2.8064745852853384e-01, 5.0792947901661334e-01, 5.0792947901661334e-01, 2.8064745852853384e-01, 8.3810041398985943e-02, 1.2880311535509982e-02, 9.3228400862418201e-04, 2.7118600925378922e-05, 2.3209808448652080e-07, 2.6548074740111957e-10}, + {4.5805789307986523e-11, 4.9770789816307401e-08, 7.1122891400212805e-06, 2.9864328669775215e-04, 5.0673499576275429e-03, 4.0920034149756306e-02, 1.7264829767009740e-01, 4.0182646947041184e-01, 5.3091793762486328e-01, 4.0182646947041184e-01, 1.7264829767009740e-01, 4.0920034149756306e-02, 5.0673499576275429e-03, 2.9864328669775215e-04, 7.1122891400212805e-06, 4.9770789816307401e-08, 4.5805789307986523e-11}, + {7.8281997721158175e-12, 1.0467205795791975e-08, 1.8106544810934246e-06, 9.1811268679294544e-05, 1.8885226302684155e-03, 1.8640042387544645e-02, 9.7301747641315411e-02, 2.8480728566997937e-01, 4.8349569472545578e-01, 4.8349569472545578e-01, 2.8480728566997937e-01, 9.7301747641315411e-02, 1.8640042387544645e-02, 1.8885226302684155e-03, 9.1811268679294544e-05, 1.8106544810934246e-06, 1.0467205795791975e-08, 7.8281997721158175e-12}, + {1.3262970944985103e-12, 2.1630510098635541e-09, 4.4882431472231438e-07, 2.7209197763161644e-05, 6.7087752140718431e-04, 7.9888667777229892e-03, 5.0810386909052110e-02, 1.8363270130699696e-01, 3.9160898861302956e-01, 5.0297488827618764e-01, 3.9160898861302956e-01, 1.8363270130699696e-01, 5.0810386909052110e-02, 7.9888667777229892e-03, 6.7087752140718431e-04, 2.7209197763161644e-05, 4.4882431472231438e-07, 2.1630510098635541e-09, 1.3262970944985103e-12}, + {2.2293936455341389e-13, 4.3993409922731442e-10, 1.0860693707692744e-07, 7.8025564785320785e-06, 2.2833863601635308e-04, 3.2437733422378532e-03, 2.4810520887463654e-02, 1.0901720602002316e-01, 2.8667550536283426e-01, 4.6224366960061009e-01, 4.6224366960061009e-01, 2.8667550536283426e-01, 1.0901720602002316e-01, 2.4810520887463654e-02, 3.2437733422378532e-03, 2.2833863601635308e-04, 7.8025564785320785e-06, 1.0860693707692744e-07, 4.3993409922731442e-10, 2.2293936455341389e-13}, + {3.7203650688184023e-14, 8.8186112420499177e-11, 2.5712301800593246e-08, 2.1718848980566754e-06, 7.4783988673100723e-05, 1.2549820417264148e-03, 1.1414065837434373e-02, 6.0179646658912296e-02, 1.9212032406699767e-01, 3.8166907361350205e-01, 4.7902370312017756e-01, 3.8166907361350205e-01, 1.9212032406699767e-01, 6.0179646658912296e-02, 1.1414065837434373e-02, 1.2549820417264148e-03, 7.4783988673100723e-05, 2.1718848980566754e-06, 2.5712301800593246e-08, 8.8186112420499177e-11, 3.7203650688184023e-14}, + {6.1671834244041516e-15, 1.7443390075479748e-11, 5.9669909860596536e-09, 5.8842875633009930e-07, 2.3655128552510423e-05, 4.6488505088425271e-04, 4.9783993350516510e-03, 3.1140370884423854e-02, 1.1910236095878249e-01, 2.8697143324690705e-01, 4.4354522643495936e-01, 4.4354522643495936e-01, 2.8697143324690705e-01, 1.1910236095878249e-01, 3.1140370884423854e-02, 4.9783993350516510e-03, 4.6488505088425271e-04, 2.3655128552510423e-05, 5.8842875633009930e-07, 5.9669909860596536e-09, 1.7443390075479748e-11, 6.1671834244041516e-15}, + {1.0160384616453285e-15, 3.4083140980305419e-12, 1.3596296504028875e-09, 1.5553393291457709e-07, 7.2492959180022684e-06, 1.6556169914187465e-04, 2.0695678749606356e-03, 1.5207084004484164e-02, 6.8890289429087329e-02, 1.9864489857802253e-01, 3.7214382487756476e-01, 4.5819658559321297e-01, 3.7214382487756476e-01, 1.9864489857802253e-01, 6.8890289429087329e-02, 1.5207084004484164e-02, 2.0695678749606356e-03, 1.6556169914187465e-04, 7.2492959180022684e-06, 1.5553393291457709e-07, 1.3596296504028875e-09, 3.4083140980305419e-12, 1.0160384616453285e-15}, + {1.6643684964891445e-16, 6.5846202430781003e-13, 3.0462542699875441e-10, 4.0189711749414533e-08, 2.1582457049023422e-06, 5.6886916364043827e-05, 8.2369248268841886e-04, 7.0483558100726791e-03, 3.7445470503230750e-02, 1.2773962178455914e-01, 2.8617953534644303e-01, 4.2693116386869923e-01, 4.2693116386869923e-01, 2.8617953534644303e-01, 1.2773962178455914e-01, 3.7445470503230750e-02, 7.0483558100726791e-03, 8.2369248268841886e-04, 5.6886916364043827e-05, 2.1582457049023422e-06, 4.0189711749414533e-08, 3.0462542699875441e-10, 6.5846202430781003e-13, 1.6643684964891445e-16}, + {2.7119235127587269e-17, 1.2588149877465385e-13, 6.7196384177062396e-11, 1.0170382503018480e-08, 6.2570324996911171e-07, 1.8915972957340510e-05, 3.1508363874548464e-04, 3.1157087201256362e-03, 1.9243098965408916e-02, 7.6888995175808827e-02, 2.0362113667812395e-01, 3.6308898927589056e-01, 4.3986872216948475e-01, 3.6308898927589056e-01, 2.0362113667812395e-01, 7.6888995175808827e-02, 1.9243098965408916e-02, 3.1157087201256362e-03, 3.1508363874548464e-04, 1.8915972957340510e-05, 6.2570324996911171e-07, 1.0170382503018480e-08, 6.7196384177062396e-11, 1.2588149877465385e-13, 2.7119235127587269e-17}, + {4.3969160947540168e-18, 2.3831486593721262e-14, 1.4609999339816088e-11, 2.5244940344905425e-09, 1.7701063373973562e-07, 6.1032917173960523e-06, 1.1622970160311058e-04, 1.3190647223238600e-03, 9.3979012911595897e-03, 4.3598227217250818e-02, 1.3511332791178782e-01, 2.8463224117678448e-01, 4.1204365059036946e-01, 4.1204365059036946e-01, 2.8463224117678448e-01, 1.3511332791178782e-01, 4.3598227217250818e-02, 9.3979012911595897e-03, 1.3190647223238600e-03, 1.1622970160311058e-04, 6.1032917173960523e-06, 1.7701063373973562e-07, 2.5244940344905425e-09, 1.4609999339816088e-11, 2.3831486593721262e-14, 4.3969160947540168e-18}, + {7.0957792932592773e-19, 4.4707724573930981e-15, 3.1341176136230566e-12, 6.1550315782317765e-10, 4.8954004096995851e-08, 1.9152809005953010e-06, 4.1467580043841186e-05, 5.3676961568811289e-04, 4.3812798357925394e-03, 2.3415933625341907e-02, 8.4173081084051971e-02, 2.0737048075100944e-01, 3.5451730409975396e-01, 4.2357728801505945e-01, 3.5451730409975396e-01, 2.0737048075100944e-01, 8.4173081084051971e-02, 2.3415933625341907e-02, 4.3812798357925394e-03, 5.3676961568811289e-04, 4.1467580043841186e-05, 1.9152809005953010e-06, 4.8954004096995851e-08, 6.1550315782317765e-10, 3.1341176136230566e-12, 4.4707724573930981e-15, 7.0957792932592773e-19}, + {1.1401393479036859e-19, 8.3159379512068002e-16, 6.6394367149096827e-13, 1.4758531682776914e-10, 1.3256825015417164e-08, 5.8577197209929782e-07, 1.4345504229714394e-05, 2.1061810002403312e-04, 1.9573312944089908e-03, 1.1968423214354838e-02, 4.9514889289898188e-02, 1.4139460978695487e-01, 2.8256139125938867e-01, 3.9860471782645146e-01, 3.9860471782645146e-01, 2.8256139125938867e-01, 1.4139460978695487e-01, 4.9514889289898188e-02, 1.1968423214354838e-02, 1.9573312944089908e-03, 2.1061810002403312e-04, 1.4345504229714394e-05, 5.8577197209929782e-07, 1.3256825015417164e-08, 1.4758531682776914e-10, 6.6394367149096827e-13, 8.3159379512068002e-16, 1.1401393479036859e-19}, + {1.8244608516739659e-20, 1.5345004446053123e-16, 1.3901072714496111e-13, 3.4841301613084286e-11, 3.5203123276007155e-09, 1.7492291299499463e-07, 4.8230734976477891e-06, 7.9909203545218356e-05, 8.4079250614026418e-04, 5.8455035452715061e-03, 2.7639655592023655e-02, 9.0768842215578197e-02, 2.1014269444921063e-01, 3.4641893907167015e-01, 4.0897117463522970e-01, 3.4641893907167015e-01, 2.1014269444921063e-01, 9.0768842215578197e-02, 2.7639655592023655e-02, 5.8455035452715061e-03, 8.4079250614026418e-04, 7.9909203545218356e-05, 4.8230734976477891e-06, 1.7492291299499463e-07, 3.5203123276007155e-09, 3.4841301613084286e-11, 1.3901072714496111e-13, 1.5345004446053123e-16, 1.8244608516739659e-20}, + {2.9082547001312504e-21, 2.8103336027509541e-17, 2.8786070805487377e-14, 8.1061862974630246e-12, 9.1785804243785856e-10, 5.1085224507759746e-08, 1.5790948873247135e-06, 2.9387252289229863e-05, 3.4831012431868588e-04, 2.7379224730676621e-03, 1.4703829704826692e-02, 5.5144176870234256e-02, 1.4673584754089000e-01, 2.8013093083921248e-01, 3.8639488954181417e-01, 3.8639488954181417e-01, 2.8013093083921248e-01, 1.4673584754089000e-01, 5.5144176870234256e-02, 1.4703829704826692e-02, 2.7379224730676621e-03, 3.4831012431868588e-04, 2.9387252289229863e-05, 1.5790948873247135e-06, 5.1085224507759746e-08, 9.1785804243785856e-10, 8.1061862974630246e-12, 2.8786070805487377e-14, 2.8103336027509541e-17, 2.9082547001312504e-21}, + {4.6189683913871598e-22, 5.1106090079270951e-18, 5.8995564987539112e-15, 1.8603735214521663e-12, 2.3524920032086692e-10, 1.4611988344910622e-08, 5.0437125589397732e-07, 1.0498602757675620e-05, 1.3952090395047032e-04, 1.2336833073068893e-03, 7.4827999140352043e-03, 3.1847230731300323e-02, 9.6717948160870412e-02, 2.1213278866876470e-01, 3.3877265789410776e-01, 3.9577855609860946e-01, 3.3877265789410776e-01, 2.1213278866876470e-01, 9.6717948160870412e-02, 3.1847230731300323e-02, 7.4827999140352043e-03, 1.2336833073068893e-03, 1.3952090395047032e-04, 1.0498602757675620e-05, 5.0437125589397732e-07, 1.4611988344910622e-08, 2.3524920032086692e-10, 1.8603735214521663e-12, 5.8995564987539112e-15, 5.1106090079270951e-18, 4.6189683913871598e-22}, + {7.3106764273841909e-23, 9.2317365365181365e-19, 1.1973440170928574e-15, 4.2150102113264756e-13, 5.9332914633966556e-11, 4.0988321647708776e-09, 1.5741677925455937e-07, 3.6505851295623875e-06, 5.4165840618199778e-05, 5.3626836552797335e-04, 3.6548903266544271e-03, 1.7553428831573435e-02, 6.0458130955912612e-02, 1.5126973407664251e-01, 2.7745814230252980e-01, 3.7523835259280258e-01, 3.7523835259280258e-01, 2.7745814230252980e-01, 1.5126973407664251e-01, 6.0458130955912612e-02, 1.7553428831573435e-02, 3.6548903266544271e-03, 5.3626836552797335e-04, 5.4165840618199778e-05, 3.6505851295623875e-06, 1.5741677925455937e-07, 4.0988321647708776e-09, 5.9332914633966556e-11, 4.2150102113264756e-13, 1.1973440170928574e-15, 9.2317365365181365e-19, 7.3106764273841909e-23}, + {1.1533162176980265e-23, 1.6570947415336692e-19, 2.4077856795579959e-16, 9.4348141590150248e-14, 1.4739809370924901e-11, 1.1289222471083366e-09, 4.8077456763232087e-08, 1.2376933672012150e-06, 2.0423684051423809e-05, 2.2544277059632773e-04, 1.7184546377609299e-03, 9.2656899706852411e-03, 3.5987982318576993e-02, 1.0206907999554145e-01, 2.1349393115029186e-01, 3.3155200075074132e-01, 3.8378526651986389e-01, 3.3155200075074132e-01, 2.1349393115029186e-01, 1.0206907999554145e-01, 3.5987982318576993e-02, 9.2656899706852411e-03, 1.7184546377609299e-03, 2.2544277059632773e-04, 2.0423684051423809e-05, 1.2376933672012150e-06, 4.8077456763232087e-08, 1.1289222471083366e-09, 1.4739809370924901e-11, 9.4348141590150248e-14, 2.4077856795579959e-16, 1.6570947415336692e-19, 1.1533162176980265e-23}, + {1.8138001119597749e-24, 2.9567089223605576e-20, 4.7999019978948293e-17, 2.0878403731160143e-14, 3.6098817474860888e-12, 3.0562520419155053e-10, 1.4387732912539959e-08, 4.0979740352245880e-07, 7.4934487833022770e-06, 9.1861189828724009e-05, 7.7981759962319987e-04, 4.6984636292665893e-03, 2.0473151727019457e-02, 6.5445134108752731e-02, 1.5511041662330927e-01, 2.7462771563513722e-01, 3.6499244699664513e-01, 3.6499244699664513e-01, 2.7462771563513722e-01, 1.5511041662330927e-01, 6.5445134108752731e-02, 2.0473151727019457e-02, 4.6984636292665893e-03, 7.7981759962319987e-04, 9.1861189828724009e-05, 7.4934487833022770e-06, 4.0979740352245880e-07, 1.4387732912539959e-08, 3.0562520419155053e-10, 3.6098817474860888e-12, 2.0878403731160143e-14, 4.7999019978948293e-17, 2.9567089223605576e-20, 1.8138001119597749e-24}, + {2.8441134634327172e-25, 5.2456527291743166e-21, 9.4898848794730163e-18, 4.5704441904182093e-15, 8.7225260125370039e-13, 8.1406956866777238e-11, 4.2239761300094312e-09, 1.3269405173066746e-07, 2.6798156546135386e-06, 3.6352769174157649e-05, 3.4234009319960727e-04, 2.2950283295840954e-03, 1.1166806590265730e-02, 4.0024775133100314e-02, 1.0687290695546242e-01, 2.1434719059607343e-01, 3.2472872157456961e-01, 3.7281997319072468e-01, 3.2472872157456961e-01, 2.1434719059607343e-01, 1.0687290695546242e-01, 4.0024775133100314e-02, 1.1166806590265730e-02, 2.2950283295840954e-03, 3.4234009319960727e-04, 3.6352769174157649e-05, 2.6798156546135386e-06, 1.3269405173066746e-07, 4.2239761300094312e-09, 8.1406956866777238e-11, 8.7225260125370039e-13, 4.5704441904182093e-15, 9.4898848794730163e-18, 5.2456527291743166e-21, 2.8441134634327172e-25}, + {4.4471534175756294e-26, 9.2564030835581952e-22, 1.8615979878080060e-18, 9.9029016869062119e-16, 2.0809126742868747e-13, 2.1353541817845700e-11, 1.2178678209557312e-09, 4.2074913231090725e-08, 9.3555700897732196e-07, 1.3997029220328986e-05, 1.4569615962636070e-04, 1.0825347566868020e-03, 5.8564259865595538e-03, 2.3425767509731743e-02, 7.0104750105177666e-02, 1.5835545375116650e-01, 2.7170124700952736e-01, 3.5554007427370893e-01, 3.5554007427370893e-01, 2.7170124700952736e-01, 1.5835545375116650e-01, 7.0104750105177666e-02, 2.3425767509731743e-02, 5.8564259865595538e-03, 1.0825347566868020e-03, 1.4569615962636070e-04, 1.3997029220328986e-05, 9.3555700897732196e-07, 4.2074913231090725e-08, 1.2178678209557312e-09, 2.1353541817845700e-11, 2.0809126742868747e-13, 9.9029016869062119e-16, 1.8615979878080060e-18, 9.2564030835581952e-22, 4.4471534175756294e-26}, + {6.9350835444886530e-27, 1.6249853271916221e-22, 3.6247269512444368e-19, 2.1248851941314958e-16, 4.9047393641852124e-14, 5.5203972646374721e-12, 3.4519062272121333e-10, 1.3079698821802362e-08, 3.1928854810032377e-07, 5.2521435771200543e-06, 6.0226951652674167e-05, 4.9417150121469438e-04, 2.9608001846029054e-03, 1.3160179977211566e-02, 4.3931362299539353e-02, 1.1117916510719518e-01, 2.1478887596478388e-01, 3.1827467975443136e-01, 3.6274375769908357e-01, 3.1827467975443136e-01, 2.1478887596478388e-01, 1.1117916510719518e-01, 4.3931362299539353e-02, 1.3160179977211566e-02, 2.9608001846029054e-03, 4.9417150121469438e-04, 6.0226951652674167e-05, 5.2521435771200543e-06, 3.1928854810032377e-07, 1.3079698821802362e-08, 3.4519062272121333e-10, 5.5203972646374721e-12, 4.9047393641852124e-14, 2.1248851941314958e-16, 3.6247269512444368e-19, 1.6249853271916221e-22, 6.9350835444886530e-27}, + {1.0787188820741241e-27, 2.8387387532094075e-23, 7.0078433305584917e-20, 4.5173712236048158e-17, 1.1428616750256895e-14, 1.4076333438452520e-12, 9.6270292926054501e-11, 3.9906528856889178e-09, 1.0665865704409148e-07, 1.9234656867323990e-06, 2.4223415120935207e-05, 2.1875759533939115e-04, 1.4463071215627061e-03, 7.1152368261340193e-03, 2.6380533520486894e-02, 7.4443983368238764e-02, 1.6108797149548099e-01, 2.6872376002892800e-01, 3.4678411786878038e-01, 3.4678411786878038e-01, 2.6872376002892800e-01, 1.6108797149548099e-01, 7.4443983368238764e-02, 2.6380533520486894e-02, 7.1152368261340193e-03, 1.4463071215627061e-03, 2.1875759533939115e-04, 2.4223415120935207e-05, 1.9234656867323990e-06, 1.0665865704409148e-07, 3.9906528856889178e-09, 9.6270292926054501e-11, 1.4076333438452520e-12, 1.1428616750256895e-14, 4.5173712236048158e-17, 7.0078433305584917e-20, 2.8387387532094075e-23, 1.0787188820741241e-27}, + {1.6737892441539538e-28, 4.9359073375904207e-24, 1.3457268201343837e-20, 9.5193204821162674e-18, 2.6340961107224671e-15, 3.5426508019791487e-13, 2.6440048769930072e-11, 1.1961664237667613e-09, 3.4915088439108438e-08, 6.8844204093401453e-07, 9.4942995361418356e-06, 9.4077279467672325e-05, 6.8405759521855724e-04, 3.7112302317141572e-03, 1.5221980837289402e-02, 4.7690071331635359e-02, 1.1503504579976950e-01, 2.1489607677746486e-01, 3.1216284886717011e-01, 3.5344263570679940e-01, 3.1216284886717011e-01, 2.1489607677746486e-01, 1.1503504579976950e-01, 4.7690071331635359e-02, 1.5221980837289402e-02, 3.7112302317141572e-03, 6.8405759521855724e-04, 9.4077279467672325e-05, 9.4942995361418356e-06, 6.8844204093401453e-07, 3.4915088439108438e-08, 1.1961664237667613e-09, 2.6440048769930072e-11, 3.5426508019791487e-13, 2.6340961107224671e-15, 9.5193204821162674e-18, 1.3457268201343837e-20, 4.9359073375904207e-24, 1.6737892441539538e-28}, + {2.5910437138470431e-29, 8.5440569637751720e-25, 2.5675933654117104e-21, 1.9891810121165382e-18, 6.0083587894908697e-16, 8.8057076452162173e-14, 7.1565280526903396e-12, 3.5256207913654460e-10, 1.1212360832275973e-08, 2.4111441636705294e-07, 3.6315761506930362e-06, 3.9369339810924932e-05, 3.1385359454133192e-04, 1.8714968295979542e-03, 8.4608880082581352e-03, 2.9312565536172355e-02, 7.8474605865404390e-02, 1.6337873271327136e-01, 2.6572825187737692e-01, 3.3864327742558936e-01, 3.3864327742558936e-01, 2.6572825187737692e-01, 1.6337873271327136e-01, 7.8474605865404390e-02, 2.9312565536172355e-02, 8.4608880082581352e-03, 1.8714968295979542e-03, 3.1385359454133192e-04, 3.9369339810924932e-05, 3.6315761506930362e-06, 2.4111441636705294e-07, 1.1212360832275973e-08, 3.5256207913654460e-10, 7.1565280526903396e-12, 8.8057076452162173e-14, 6.0083587894908697e-16, 1.9891810121165382e-18, 2.5675933654117104e-21, 8.5440569637751720e-25, 2.5910437138470431e-29}, + {4.0019596605455888e-30, 1.4726537286520423e-25, 4.8687379360130589e-22, 4.1234085375315004e-19, 1.3569875295861202e-16, 2.1629872471750215e-14, 1.9103833646809321e-12, 1.0226798927782354e-10, 3.5356816483807076e-09, 8.2726584187498191e-08, 1.3573781404870848e-06, 1.6055965736677200e-05, 1.3993025659674152e-04, 9.1423425632870857e-04, 4.5403929873032720e-03, 1.7330881362116784e-02, 5.1289872397094663e-02, 1.1848439124684401e-01, 2.1473086449008444e-01, 3.0636781693785120e-01, 3.4482208361638955e-01, 3.0636781693785120e-01, 2.1473086449008444e-01, 1.1848439124684401e-01, 5.1289872397094663e-02, 1.7330881362116784e-02, 4.5403929873032720e-03, 9.1423425632870857e-04, 1.3993025659674152e-04, 1.6055965736677200e-05, 1.3573781404870848e-06, 8.2726584187498191e-08, 3.5356816483807076e-09, 1.0226798927782354e-10, 1.9103833646809321e-12, 2.1629872471750215e-14, 1.3569875295861202e-16, 4.1234085375315004e-19, 4.8687379360130589e-22, 1.4726537286520423e-25, 4.0019596605455888e-30}, + {6.1678589258109773e-31, 2.5278698640534739e-26, 9.1778906956924963e-23, 8.4821520800863616e-20, 3.0358903478107461e-17, 5.2533377155686787e-15, 5.0327055821840466e-13, 2.9217288372333376e-11, 1.0958052288078504e-09, 2.7834715265490800e-08, 4.9636593935798231e-07, 6.3902459677354328e-06, 6.0719621077883790e-05, 4.3341227172125611e-04, 2.3571613945963252e-03, 9.8795240531885219e-03, 3.2202101288907867e-02, 8.2211269303293782e-02, 1.6528800127466756e-01, 2.6273890678229461e-01, 3.3104891389085667e-01, 3.3104891389085667e-01, 2.6273890678229461e-01, 1.6528800127466756e-01, 8.2211269303293782e-02, 3.2202101288907867e-02, 9.8795240531885219e-03, 2.3571613945963252e-03, 4.3341227172125611e-04, 6.0719621077883790e-05, 6.3902459677354328e-06, 4.9636593935798231e-07, 2.7834715265490800e-08, 1.0958052288078504e-09, 2.9217288372333376e-11, 5.0327055821840466e-13, 5.2533377155686787e-15, 3.0358903478107461e-17, 8.4821520800863616e-20, 9.1778906956924963e-23, 2.5278698640534739e-26, 6.1678589258109773e-31}, + {9.4863063307486296e-32, 4.3221460599337345e-27, 1.7203368260282161e-23, 1.7320753790913467e-20, 6.7308117032428195e-18, 1.2622032209758195e-15, 1.3092104166584946e-13, 8.2271061208164963e-12, 3.3407179153175535e-10, 9.1931960675404414e-09, 1.7777830445479720e-07, 2.4851377424115403e-06, 2.5680573077056677e-05, 1.9972435671322962e-04, 1.1860700927674253e-03, 5.4414552932418097e-03, 1.9468160151101737e-02, 5.4724809081874805e-02, 1.2156737988638795e-01, 2.1434349700188368e-01, 3.0086599386765978e-01, 3.3680296539275278e-01, 3.0086599386765978e-01, 2.1434349700188368e-01, 1.2156737988638795e-01, 5.4724809081874805e-02, 1.9468160151101737e-02, 5.4414552932418097e-03, 1.1860700927674253e-03, 1.9972435671322962e-04, 2.5680573077056677e-05, 2.4851377424115403e-06, 1.7777830445479720e-07, 9.1931960675404414e-09, 3.3407179153175535e-10, 8.2271061208164963e-12, 1.3092104166584946e-13, 1.2622032209758195e-15, 6.7308117032428195e-18, 1.7320753790913467e-20, 1.7203368260282161e-23, 4.3221460599337345e-27, 9.4863063307486296e-32}, + {1.4561153081762322e-32, 7.3621261042968285e-28, 3.2072216919050275e-24, 3.5121449558365656e-21, 1.4794099758171669e-18, 3.0015214029808191e-16, 3.3650356127923192e-14, 2.2848078971220373e-12, 1.0026000778909185e-10, 2.9831210190396358e-09, 6.2427245062815072e-08, 9.4545385422855902e-07, 1.0600171772517656e-05, 8.9597973640616782e-05, 5.7942043271566558e-04, 2.9012937752966299e-03, 1.1357866939069948e-02, 3.5033757109687119e-02, 8.5670187300246295e-02, 1.6686716582564590e-01, 2.5977339611588807e-01, 3.2394262884199604e-01, 3.2394262884199604e-01, 2.5977339611588807e-01, 1.6686716582564590e-01, 8.5670187300246295e-02, 3.5033757109687119e-02, 1.1357866939069948e-02, 2.9012937752966299e-03, 5.7942043271566558e-04, 8.9597973640616782e-05, 1.0600171772517656e-05, 9.4545385422855902e-07, 6.2427245062815072e-08, 2.9831210190396358e-09, 1.0026000778909185e-10, 2.2848078971220373e-12, 3.3650356127923192e-14, 3.0015214029808191e-16, 1.4794099758171669e-18, 3.5121449558365656e-21, 3.2072216919050275e-24, 7.3621261042968285e-28, 1.4561153081762322e-32}, + {2.2308126593779868e-33, 1.2494829120559801e-28, 5.9481747159233458e-25, 7.0737246502696336e-22, 3.2248298707326610e-19, 7.0674619157542681e-17, 8.5500874663703821e-15, 6.2620383158353876e-13, 2.9642049893157670e-11, 9.5182669412336419e-10, 2.1512839074194501e-08, 3.5225192415065300e-07, 4.2754558863972689e-06, 3.9183295448819551e-05, 2.7524242709953090e-04, 1.5001278829297612e-03, 6.4070706562040147e-03, 2.1617644433765643e-02, 5.7992746631628803e-02, 1.2432050192893590e-01, 2.1377487850201790e-01, 2.9563565196662861e-01, 3.2931845505069163e-01, 2.9563565196662861e-01, 2.1377487850201790e-01, 1.2432050192893590e-01, 5.7992746631628803e-02, 2.1617644433765643e-02, 6.4070706562040147e-03, 1.5001278829297612e-03, 2.7524242709953090e-04, 3.9183295448819551e-05, 4.2754558863972689e-06, 3.5225192415065300e-07, 2.1512839074194501e-08, 9.5182669412336419e-10, 2.9642049893157670e-11, 6.2620383158353876e-13, 8.5500874663703821e-15, 7.0674619157542681e-17, 3.2248298707326610e-19, 7.0737246502696336e-22, 5.9481747159233458e-25, 1.2494829120559801e-28, 2.2308126593779868e-33}, + {3.4113792299096508e-34, 2.1132014962696289e-29, 1.0976558019968051e-25, 1.4155042016755176e-22, 6.9737995966949200e-20, 1.6484447389507407e-17, 2.1486472823678717e-15, 1.6947076167749986e-13, 8.6391402914483532e-12, 2.9885455879923381e-10, 7.2816347565639946e-09, 1.2865324130563406e-07, 1.6869468397355139e-06, 1.6725935920653945e-05, 1.2731983755106949e-04, 7.5339673454313967e-04, 3.5010578505227864e-03, 1.2883487559777229e-02, 3.7795830992247079e-02, 8.8868227566005320e-02, 1.6816012736212269e-01, 2.5684454350651975e-01, 3.1727438491816684e-01, 3.1727438491816684e-01, 2.5684454350651975e-01, 1.6816012736212269e-01, 8.8868227566005320e-02, 3.7795830992247079e-02, 1.2883487559777229e-02, 3.5010578505227864e-03, 7.5339673454313967e-04, 1.2731983755106949e-04, 1.6725935920653945e-05, 1.6869468397355139e-06, 1.2865324130563406e-07, 7.2816347565639946e-09, 2.9885455879923381e-10, 8.6391402914483532e-12, 1.6947076167749986e-13, 2.1486472823678717e-15, 1.6484447389507407e-17, 6.9737995966949200e-20, 1.4155042016755176e-22, 1.0976558019968051e-25, 2.1132014962696289e-29, 3.4113792299096508e-34}, + {5.2074550840354642e-35, 3.5619817807815819e-30, 2.0158558166547157e-26, 2.8149547423920401e-23, 1.4966299166256593e-20, 3.8101463479230325e-18, 5.3428423961486667e-16, 4.5312676467479057e-14, 2.4836135431247532e-12, 9.2402978883643831e-11, 2.4228134937243909e-09, 4.6104364856635215e-08, 6.5181055230401887e-07, 6.9771079617906096e-06, 5.7425938238321535e-05, 3.6806169587486260e-04, 1.8562527788732503e-03, 7.4296915378901547e-03, 2.3765555762406108e-02, 6.1094386221801737e-02, 1.2677670015500209e-01, 2.1305846026514422e-01, 2.9065687385124467e-01, 3.2231167941131522e-01, 2.9065687385124467e-01, 2.1305846026514422e-01, 1.2677670015500209e-01, 6.1094386221801737e-02, 2.3765555762406108e-02, 7.4296915378901547e-03, 1.8562527788732503e-03, 3.6806169587486260e-04, 5.7425938238321535e-05, 6.9771079617906096e-06, 6.5181055230401887e-07, 4.6104364856635215e-08, 2.4228134937243909e-09, 9.2402978883643831e-11, 2.4836135431247532e-12, 4.5312676467479057e-14, 5.3428423961486667e-16, 3.8101463479230325e-18, 1.4966299166256593e-20, 2.8149547423920401e-23, 2.0158558166547157e-26, 3.5619817807815819e-30, 5.2074550840354642e-35}, + {7.9355514607740056e-36, 5.9846126933135906e-31, 3.6850360801506979e-27, 5.5645774689023294e-24, 3.1883873235051506e-21, 8.7301596011867662e-19, 1.3151596226583889e-16, 1.1975898654791956e-14, 7.0469325815459271e-13, 2.8152965378381835e-11, 7.9304674951654092e-10, 1.6225141358957786e-08, 2.4686589936697532e-07, 2.8472586917348417e-06, 2.5285990277484952e-05, 1.7515043180117349e-04, 9.5639231981941610e-04, 4.1530049119775534e-03, 1.4444961574981133e-02, 4.0479676984603939e-02, 9.1822297079285201e-02, 1.6920447194564109e-01, 2.5396154266475901e-01, 3.1100103037796278e-01, 3.1100103037796278e-01, 2.5396154266475901e-01, 1.6920447194564109e-01, 9.1822297079285201e-02, 4.0479676984603939e-02, 1.4444961574981133e-02, 4.1530049119775534e-03, 9.5639231981941610e-04, 1.7515043180117349e-04, 2.5285990277484952e-05, 2.8472586917348417e-06, 2.4686589936697532e-07, 1.6225141358957786e-08, 7.9304674951654092e-10, 2.8152965378381835e-11, 7.0469325815459271e-13, 1.1975898654791956e-14, 1.3151596226583889e-16, 8.7301596011867662e-19, 3.1883873235051506e-21, 5.5645774689023294e-24, 3.6850360801506979e-27, 5.9846126933135906e-31, 7.9355514607740056e-36}, + {1.2072872864975299e-36, 1.0023613427435658e-31, 6.7063563353463921e-28, 1.0936809436127891e-24, 6.7446743456588804e-22, 1.9836416602794039e-19, 3.2059589524003601e-17, 3.1301391441242865e-15, 1.9744849360632020e-13, 8.4575241714312574e-12, 2.5554702439987741e-10, 5.6118428733874883e-09, 9.1729613211703643e-08, 1.1378411996774051e-06, 1.0881805485674181e-05, 8.1291046453153734e-05, 4.7952088600477827e-04, 2.2536737753387727e-03, 8.5018075629547680e-03, 2.5900304438342722e-02, 6.4032496212210105e-02, 1.2896559830848855e-01, 2.1222171925816707e-01, 2.8591145169466448e-01, 3.1573389003557428e-01, 2.8591145169466448e-01, 2.1222171925816707e-01, 1.2896559830848855e-01, 6.4032496212210105e-02, 2.5900304438342722e-02, 8.5018075629547680e-03, 2.2536737753387727e-03, 4.7952088600477827e-04, 8.1291046453153734e-05, 1.0881805485674181e-05, 1.1378411996774051e-06, 9.1729613211703643e-08, 5.6118428733874883e-09, 2.5554702439987741e-10, 8.4575241714312574e-12, 1.9744849360632020e-13, 3.1301391441242865e-15, 3.2059589524003601e-17, 1.9836416602794039e-19, 6.7446743456588804e-22, 1.0936809436127891e-24, 6.7063563353463921e-28, 1.0023613427435658e-31, 1.2072872864975299e-36}, + {1.8337940485734247e-37, 1.6738016679078003e-32, 1.2152441234045103e-28, 2.1376583083600910e-25, 1.4170935995734126e-22, 4.4709843654079433e-20, 7.7423829570434533e-18, 8.0942618934651918e-16, 5.4659440318156410e-14, 2.5066555238996801e-12, 8.1118773649302876e-11, 1.9090405438119032e-09, 3.3467934040214541e-08, 4.4570299668178385e-07, 4.5816827079555368e-06, 3.6840190537807232e-05, 2.3426989210925618e-04, 1.1890117817496457e-03, 4.8532638261719538e-03, 1.6031941068412211e-02, 4.3079159156765599e-02, 9.4548935477086246e-02, 1.7003245567716402e-01, 2.5113085633200216e-01, 3.0508512920439906e-01, 3.0508512920439906e-01, 2.5113085633200216e-01, 1.7003245567716402e-01, 9.4548935477086246e-02, 4.3079159156765599e-02, 1.6031941068412211e-02, 4.8532638261719538e-03, 1.1890117817496457e-03, 2.3426989210925618e-04, 3.6840190537807232e-05, 4.5816827079555368e-06, 4.4570299668178385e-07, 3.3467934040214541e-08, 1.9090405438119032e-09, 8.1118773649302876e-11, 2.5066555238996801e-12, 5.4659440318156410e-14, 8.0942618934651918e-16, 7.7423829570434533e-18, 4.4709843654079433e-20, 1.4170935995734126e-22, 2.1376583083600910e-25, 1.2152441234045103e-28, 1.6738016679078003e-32, 1.8337940485734247e-37}, + {2.7811222326645344e-38, 2.7868913296983680e-33, 2.1929968310380126e-29, 4.1558650081686601e-26, 2.9579544865762534e-23, 9.9993599745434670e-21, 1.8530303241143367e-18, 2.0717064275729557e-16, 1.4956863300607063e-14, 7.3335422940638437e-13, 2.5381498317560184e-11, 6.3917274853532610e-10, 1.1999326533873204e-08, 1.7127604128737511e-07, 1.8891833940946794e-06, 1.6319954290330701e-05, 1.1165708931911324e-04, 6.1070259874041984e-04, 2.6911086058640649e-03, 9.6161203333211508e-03, 2.8012262602063957e-02, 6.6811317318844293e-02, 1.3091376937688559e-01, 2.1128731588244376e-01, 2.8138276384359967e-01, 3.0954302944664125e-01, 2.8138276384359967e-01, 2.1128731588244376e-01, 1.3091376937688559e-01, 6.6811317318844293e-02, 2.8012262602063957e-02, 9.6161203333211508e-03, 2.6911086058640649e-03, 6.1070259874041984e-04, 1.1165708931911324e-04, 1.6319954290330701e-05, 1.8891833940946794e-06, 1.7127604128737511e-07, 1.1999326533873204e-08, 6.3917274853532610e-10, 2.5381498317560184e-11, 7.3335422940638437e-13, 1.4956863300607063e-14, 2.0717064275729557e-16, 1.8530303241143367e-18, 9.9993599745434670e-21, 2.9579544865762534e-23, 4.1558650081686601e-26, 2.1929968310380126e-29, 2.7868913296983680e-33, 2.7811222326645344e-38}, + {4.2115420614105446e-39, 4.6271645012802355e-34, 3.9415951369162550e-30, 8.0378813038410338e-27, 6.1353803600426939e-24, 2.2196939309444735e-21, 4.3966970036273617e-19, 5.2503117409060339e-17, 4.0473768240447191e-15, 2.1189539626185899e-13, 7.8326447571213533e-12, 2.1076390184671402e-10, 4.2306685774284424e-09, 6.4623052172886120e-08, 7.6355680403038401e-07, 7.0741004987582161e-06, 5.1975998082926043e-05, 3.0574624681119092e-04, 1.4514479978625793e-03, 5.5977022679341544e-03, 1.7635166965733341e-02, 4.5590184103438805e-02, 9.7064055572858784e-02, 1.7067182934440731e-01, 2.4835688537420786e-01, 2.9949402485158516e-01, 2.9949402485158516e-01, 2.4835688537420786e-01, 1.7067182934440731e-01, 9.7064055572858784e-02, 4.5590184103438805e-02, 1.7635166965733341e-02, 5.5977022679341544e-03, 1.4514479978625793e-03, 3.0574624681119092e-04, 5.1975998082926043e-05, 7.0741004987582161e-06, 7.6355680403038401e-07, 6.4623052172886120e-08, 4.2306685774284424e-09, 2.1076390184671402e-10, 7.8326447571213533e-12, 2.1189539626185899e-13, 4.0473768240447191e-15, 5.2503117409060339e-17, 4.3966970036273617e-19, 2.2196939309444735e-21, 6.1353803600426939e-24, 8.0378813038410338e-27, 3.9415951369162550e-30, 4.6271645012802355e-34, 4.2115420614105446e-39}, + {6.3684623301529066e-40, 7.6617679179706699e-35, 7.0570663748570958e-31, 1.5468771288046908e-27, 1.2648661239395541e-24, 4.8919455331107564e-22, 1.0345305017520525e-19, 1.3179732316466649e-17, 1.0835445640249948e-15, 6.0495805864229647e-14, 2.3852254108327101e-12, 6.8487736158296791e-11, 1.4678463337326563e-09, 2.3957838556591937e-08, 3.0275650879319551e-07, 3.0032131335980235e-06, 2.3654729185615187e-05, 1.4937604708377004e-04, 7.6242846753152228e-04, 3.1668653729621131e-03, 1.0765666029311394e-02, 3.0093535038790555e-02, 6.9436105549292540e-02, 1.3264501499247186e-01, 2.1027400626010295e-01, 2.7705564403537380e-01, 3.0370259492878027e-01, 2.7705564403537380e-01, 2.1027400626010295e-01, 1.3264501499247186e-01, 6.9436105549292540e-02, 3.0093535038790555e-02, 1.0765666029311394e-02, 3.1668653729621131e-03, 7.6242846753152228e-04, 1.4937604708377004e-04, 2.3654729185615187e-05, 3.0032131335980235e-06, 3.0275650879319551e-07, 2.3957838556591937e-08, 1.4678463337326563e-09, 6.8487736158296791e-11, 2.3852254108327101e-12, 6.0495805864229647e-14, 1.0835445640249948e-15, 1.3179732316466649e-17, 1.0345305017520525e-19, 4.8919455331107564e-22, 1.2648661239395541e-24, 1.5468771288046908e-27, 7.0570663748570958e-31, 7.6617679179706699e-35, 6.3684623301529066e-40}, + {9.6165697698301258e-41, 1.2653200760168758e-35, 1.2587808691128722e-31, 2.9626275871495710e-28, 2.5923371557456032e-25, 1.0706490586422193e-22, 2.4146919999727056e-20, 3.2782519697898691e-18, 2.8709892632049820e-16, 1.7073406733468467e-14, 7.1713449978551876e-13, 2.1943984676811026e-11, 5.0147398704735039e-10, 8.7334448358337394e-09, 1.1786188465819090e-07, 1.2498100284112936e-06, 1.0535444441825744e-05, 7.1294347272485073e-05, 3.9051617266315898e-04, 1.7435254219654911e-03, 6.3820594170464536e-03, 1.9246441370539501e-02, 4.8010306161295493e-02, 9.9382787160472649e-02, 1.7114652799601413e-01, 2.4564247050424473e-01, 2.9419908452729160e-01, 2.9419908452729160e-01, 2.4564247050424473e-01, 1.7114652799601413e-01, 9.9382787160472649e-02, 4.8010306161295493e-02, 1.9246441370539501e-02, 6.3820594170464536e-03, 1.7435254219654911e-03, 3.9051617266315898e-04, 7.1294347272485073e-05, 1.0535444441825744e-05, 1.2498100284112936e-06, 1.1786188465819090e-07, 8.7334448358337394e-09, 5.0147398704735039e-10, 2.1943984676811026e-11, 7.1713449978551876e-13, 1.7073406733468467e-14, 2.8709892632049820e-16, 3.2782519697898691e-18, 2.4146919999727056e-20, 1.0706490586422193e-22, 2.5923371557456032e-25, 2.9626275871495710e-28, 1.2587808691128722e-31, 1.2653200760168758e-35, 9.6165697698301258e-41}, + {1.4501627690036662e-41, 2.0843249634724133e-36, 2.2371881417054147e-32, 5.6477366517509067e-29, 5.2828491369827090e-26, 2.3275184070080019e-23, 5.5924703344128403e-21, 8.0822735455939761e-19, 7.5316452507313807e-17, 4.7652984604189149e-15, 2.1297535284773726e-13, 6.9364439628016448e-12, 1.6879993347401012e-10, 3.1324958261028878e-09, 4.5081881972300138e-08, 5.1027034733995817e-07, 4.5962183144073910e-06, 3.3274977701846682e-05, 1.9525422369452320e-04, 9.3526439804451304e-04, 3.6789367196008232e-03, 1.1943896271882769e-02, 3.2137739232619873e-02, 7.1912783366758826e-02, 1.3418063914176925e-01, 2.0919736551904625e-01, 2.7291625193942631e-01, 2.9818072956643887e-01, 2.7291625193942631e-01, 2.0919736551904625e-01, 1.3418063914176925e-01, 7.1912783366758826e-02, 3.2137739232619873e-02, 1.1943896271882769e-02, 3.6789367196008232e-03, 9.3526439804451304e-04, 1.9525422369452320e-04, 3.3274977701846682e-05, 4.5962183144073910e-06, 5.1027034733995817e-07, 4.5081881972300138e-08, 3.1324958261028878e-09, 1.6879993347401012e-10, 6.9364439628016448e-12, 2.1297535284773726e-13, 4.7652984604189149e-15, 7.5316452507313807e-17, 8.0822735455939761e-19, 5.5924703344128403e-21, 2.3275184070080019e-23, 5.2828491369827090e-26, 5.6477366517509067e-29, 2.2371881417054147e-32, 2.0843249634724133e-36, 1.4501627690036662e-41}, + {2.1839473796203715e-42, 3.4249840843882790e-37, 3.9621540898960065e-33, 1.0717993883210793e-29, 1.0706713589643687e-26, 5.0270999187295385e-24, 1.2855363897049299e-21, 1.9756668115390835e-19, 1.9569261785647621e-17, 1.3158561251396991e-15, 6.2504456297525029e-14, 2.1641925885012134e-12, 5.6013978504685036e-11, 1.1062006976882208e-09, 1.6954324255991913e-08, 2.0454464536460739e-07, 1.9657534004009810e-06, 1.5201081492284489e-05, 9.5395991047773378e-05, 4.8937293565704996e-04, 2.0647475636031381e-03, 7.2020522320410518e-03, 2.0858574140157814e-02, 5.0338397424815960e-02, 1.0151939271798682e-01, 1.7147724762127156e-01, 2.4298927099272355e-01, 2.8917508433514816e-01, 2.8917508433514816e-01, 2.4298927099272355e-01, 1.7147724762127156e-01, 1.0151939271798682e-01, 5.0338397424815960e-02, 2.0858574140157814e-02, 7.2020522320410518e-03, 2.0647475636031381e-03, 4.8937293565704996e-04, 9.5395991047773378e-05, 1.5201081492284489e-05, 1.9657534004009810e-06, 2.0454464536460739e-07, 1.6954324255991913e-08, 1.1062006976882208e-09, 5.6013978504685036e-11, 2.1641925885012134e-12, 6.2504456297525029e-14, 1.3158561251396991e-15, 1.9569261785647621e-17, 1.9756668115390835e-19, 1.2855363897049299e-21, 5.0270999187295385e-24, 1.0706713589643687e-26, 1.0717993883210793e-29, 3.9621540898960065e-33, 3.4249840843882790e-37, 2.1839473796203715e-42}, + {3.2848343922234264e-43, 5.6145192176094857e-38, 6.9933335612180924e-34, 2.0251468211785233e-30, 2.1584037474070782e-27, 1.0789794198158127e-24, 2.9336812927661561e-22, 4.7897086011228863e-20, 5.0376705984946099e-18, 3.5961584198415702e-16, 1.8135512160129682e-14, 6.6680503871104131e-13, 1.8333727853050702e-11, 3.8483200507286178e-10, 6.2732332422802088e-09, 8.0560041690845556e-08, 8.2486418628805857e-07, 6.8030638512964077e-06, 4.5587459694050582e-05, 2.5003668451320217e-04, 1.1295333257645079e-03, 4.2250842236442390e-03, 1.3144726459581649e-02, 3.4139801128400288e-02, 7.4247675370613914e-02, 1.3553970687329148e-01, 2.0807036460654699e-01, 2.6895194980711801e-01, 2.9294948869685189e-01, 2.6895194980711801e-01, 2.0807036460654699e-01, 1.3553970687329148e-01, 7.4247675370613914e-02, 3.4139801128400288e-02, 1.3144726459581649e-02, 4.2250842236442390e-03, 1.1295333257645079e-03, 2.5003668451320217e-04, 4.5587459694050582e-05, 6.8030638512964077e-06, 8.2486418628805857e-07, 8.0560041690845556e-08, 6.2732332422802088e-09, 3.8483200507286178e-10, 1.8333727853050702e-11, 6.6680503871104131e-13, 1.8135512160129682e-14, 3.5961584198415702e-16, 5.0376705984946099e-18, 4.7897086011228863e-20, 2.9336812927661561e-22, 1.0789794198158127e-24, 2.1584037474070782e-27, 2.0251468211785233e-30, 6.9933335612180924e-34, 5.6145192176094857e-38, 3.2848343922234264e-43}, + {4.9345427975166703e-44, 9.1824526100660134e-39, 1.2302868650409080e-34, 3.8103303738430430e-31, 4.3288355988163862e-28, 2.3018029777481733e-25, 6.6480276615029978e-23, 1.1519651049881098e-20, 1.2852645022546249e-18, 9.7305218355116897e-17, 5.2042716465726346e-15, 2.0297402247949017e-13, 5.9217773854289703e-12, 1.3196011058824996e-10, 2.2850766766300011e-09, 3.1195246571716635e-08, 3.3984745324530809e-07, 2.9851306091787731e-06, 2.1327339454200749e-05, 1.2486893055641099e-04, 6.0296061313673489e-04, 2.4143454547297083e-03, 8.0534582747568747e-03, 2.2465314158278335e-02, 5.2574374089316610e-02, 1.0348723259331935e-01, 1.7168192789310016e-01, 2.4039805219536928e-01, 2.8439970531426456e-01, 2.8439970531426456e-01, 2.4039805219536928e-01, 1.7168192789310016e-01, 1.0348723259331935e-01, 5.2574374089316610e-02, 2.2465314158278335e-02, 8.0534582747568747e-03, 2.4143454547297083e-03, 6.0296061313673489e-04, 1.2486893055641099e-04, 2.1327339454200749e-05, 2.9851306091787731e-06, 3.3984745324530809e-07, 3.1195246571716635e-08, 2.2850766766300011e-09, 1.3196011058824996e-10, 5.9217773854289703e-12, 2.0297402247949017e-13, 5.2042716465726346e-15, 9.7305218355116897e-17, 1.2852645022546249e-18, 1.1519651049881098e-20, 6.6480276615029978e-23, 2.3018029777481733e-25, 4.3288355988163862e-28, 3.8103303738430430e-31, 1.2302868650409080e-34, 9.1824526100660134e-39, 4.9345427975166703e-44}, + {7.4038563068673450e-45, 1.4983962534795572e-39, 2.1574506027269642e-35, 7.1398344998607888e-32, 8.6385560494218303e-29, 4.8816444464632883e-26, 1.4963121942445614e-23, 2.7492726789010400e-21, 3.2508143970587746e-19, 2.6076354448061946e-17, 1.4776310161414783e-15, 6.1066717751743867e-14, 1.8884472351365658e-12, 4.4624672633249920e-11, 8.1989628692240572e-10, 1.1884210228039399e-08, 1.3757431403862670e-07, 1.2852403270784334e-06, 9.7761956199732341e-06, 6.1008880084875632e-05, 3.1439538907451493e-04, 1.3453332060777454e-03, 4.8029120328152543e-03, 1.4362559357587188e-02, 3.6095769719147547e-02, 7.6447309674074940e-02, 1.3673928335964028e-01, 2.0690383287647826e-01, 2.6515118763397444e-01, 2.8798424312571891e-01, 2.6515118763397444e-01, 2.0690383287647826e-01, 1.3673928335964028e-01, 7.6447309674074940e-02, 3.6095769719147547e-02, 1.4362559357587188e-02, 4.8029120328152543e-03, 1.3453332060777454e-03, 3.1439538907451493e-04, 6.1008880084875632e-05, 9.7761956199732341e-06, 1.2852403270784334e-06, 1.3757431403862670e-07, 1.1884210228039399e-08, 8.1989628692240572e-10, 4.4624672633249920e-11, 1.8884472351365658e-12, 6.1066717751743867e-14, 1.4776310161414783e-15, 2.6076354448061946e-17, 3.2508143970587746e-19, 2.7492726789010400e-21, 1.4963121942445614e-23, 4.8816444464632883e-26, 8.6385560494218303e-29, 7.1398344998607888e-32, 2.1574506027269642e-35, 1.4983962534795572e-39, 7.4038563068673450e-45}, + {1.1095872479683389e-45, 2.4397475881451687e-40, 3.7716267271207567e-36, 1.3325596117642357e-32, 1.7155731476717639e-29, 1.0294059971650915e-26, 3.3457569557525580e-24, 6.5125672574964802e-22, 8.1536404730238284e-20, 6.9232479095776861e-18, 4.1524441096940554e-16, 1.8166245762596555e-14, 5.9484305160561044e-13, 1.4889573490628030e-11, 2.8993590128077474e-10, 4.4568227752259551e-09, 5.4755546192766962e-08, 5.4335161342049202e-07, 4.3942869362670327e-06, 2.9187419041555301e-05, 1.6027733468184521e-04, 7.3177355696550823e-04, 2.7913248289530633e-03, 8.9321783603078207e-03, 2.4061272766109355e-02, 5.4718970932182816e-02, 1.0529876369778575e-01, 1.7177615691888495e-01, 2.3786890495865878e-01, 2.7985311752282899e-01, 2.7985311752282899e-01, 2.3786890495865878e-01, 1.7177615691888495e-01, 1.0529876369778575e-01, 5.4718970932182816e-02, 2.4061272766109355e-02, 8.9321783603078207e-03, 2.7913248289530633e-03, 7.3177355696550823e-04, 1.6027733468184521e-04, 2.9187419041555301e-05, 4.3942869362670327e-06, 5.4335161342049202e-07, 5.4755546192766962e-08, 4.4568227752259551e-09, 2.8993590128077474e-10, 1.4889573490628030e-11, 5.9484305160561044e-13, 1.8166245762596555e-14, 4.1524441096940554e-16, 6.9232479095776861e-18, 8.1536404730238284e-20, 6.5125672574964802e-22, 3.3457569557525580e-24, 1.0294059971650915e-26, 1.7155731476717639e-29, 1.3325596117642357e-32, 3.7716267271207567e-36, 2.4397475881451687e-40, 1.1095872479683389e-45}, + {1.6610070486206728e-46, 3.9640620009950677e-41, 6.5736876067220763e-37, 2.4774746124224036e-33, 3.3910839755167296e-30, 2.1587655850502334e-27, 7.4335800238463694e-25, 1.5315980968945761e-22, 2.0285571447032586e-20, 1.8216160573946239e-18, 1.1553699025986796e-16, 5.3454835391987630e-15, 1.8515162945489592e-13, 4.9041814317738659e-12, 1.0110041892763622e-10, 1.6462612023799091e-09, 2.1440032177267756e-08, 2.2570860520414515e-07, 1.9382734960996544e-06, 1.3684069297535329e-05, 7.9958097609494878e-05, 3.8892085371592777e-04, 1.5825583090958971e-03, 5.4099296624677247e-03, 1.5592290312662006e-02, 3.8002651439240136e-02, 7.8518270158397185e-02, 1.3779465152760539e-01, 2.0570683105394089e-01, 2.6150339781427412e-01, 2.8326318995972372e-01, 2.6150339781427412e-01, 2.0570683105394089e-01, 1.3779465152760539e-01, 7.8518270158397185e-02, 3.8002651439240136e-02, 1.5592290312662006e-02, 5.4099296624677247e-03, 1.5825583090958971e-03, 3.8892085371592777e-04, 7.9958097609494878e-05, 1.3684069297535329e-05, 1.9382734960996544e-06, 2.2570860520414515e-07, 2.1440032177267756e-08, 1.6462612023799091e-09, 1.0110041892763622e-10, 4.9041814317738659e-12, 1.8515162945489592e-13, 5.3454835391987630e-15, 1.1553699025986796e-16, 1.8216160573946239e-18, 2.0285571447032586e-20, 1.5315980968945761e-22, 7.4335800238463694e-25, 2.1587655850502334e-27, 3.3910839755167296e-30, 2.4774746124224036e-33, 6.5736876067220763e-37, 3.9640620009950677e-41, 1.6610070486206728e-46}, + {2.4837138180536654e-47, 6.4274569671736483e-42, 1.1424028966725505e-37, 4.5888574043976661e-34, 6.6725110959391675e-31, 4.5029239074522869e-28, 1.6414116353925588e-25, 3.5767852999576706e-23, 5.0073739324943669e-21, 4.7513038441234886e-19, 3.1838887747718650e-17, 1.5564176512276732e-15, 5.6970949884188746e-14, 1.5952148801760892e-12, 3.4779437587729222e-11, 5.9926928642653631e-10, 8.2638647618516911e-09, 9.2185737335790556e-08, 8.3956368818335782e-07, 6.2919256841286273e-06, 3.9066932688710276e-05, 2.0215217999457319e-04, 8.7616004129601344e-04, 3.1945104951283309e-03, 9.8342822671495106e-03, 2.5641844544669879e-02, 5.6773556441129344e-02, 1.0696556035928920e-01, 1.7177351127893237e-01, 2.3540141376649018e-01, 2.7551763457131306e-01, 2.7551763457131306e-01, 2.3540141376649018e-01, 1.7177351127893237e-01, 1.0696556035928920e-01, 5.6773556441129344e-02, 2.5641844544669879e-02, 9.8342822671495106e-03, 3.1945104951283309e-03, 8.7616004129601344e-04, 2.0215217999457319e-04, 3.9066932688710276e-05, 6.2919256841286273e-06, 8.3956368818335782e-07, 9.2185737335790556e-08, 8.2638647618516911e-09, 5.9926928642653631e-10, 3.4779437587729222e-11, 1.5952148801760892e-12, 5.6970949884188746e-14, 1.5564176512276732e-15, 3.1838887747718650e-17, 4.7513038441234886e-19, 5.0073739324943669e-21, 3.5767852999576706e-23, 1.6414116353925588e-25, 4.5029239074522869e-28, 6.6725110959391675e-31, 4.5888574043976661e-34, 1.1424028966725505e-37, 6.4274569671736483e-42, 2.4837138180536654e-47}, + {3.7099206361930349e-48, 1.0400778615224128e-42, 1.9796804708319897e-38, 8.4687478191905945e-35, 1.3071305930820806e-31, 9.3437837175659029e-29, 3.6027426635285024e-26, 8.2963863116210883e-24, 1.2266629909143781e-21, 1.2288435628835336e-19, 8.6925536958459408e-18, 4.4857058689315790e-16, 1.7335817955789140e-14, 5.1265062385198317e-13, 1.1808921844569749e-11, 2.1508698297874976e-10, 3.1371929535383148e-09, 3.7041625984897139e-08, 3.5734732949990906e-07, 2.8393114498469317e-06, 1.8709113003788699e-05, 1.0284880800685653e-04, 4.7411702610320811e-04, 1.8409222622442125e-03, 6.0436044551375788e-03, 1.6829299199652096e-02, 3.9858264027817066e-02, 8.0467087994200825e-02, 1.3871950817658463e-01, 2.0448695346897386e-01, 2.5799889943138321e-01, 2.7876694884925185e-01, 2.5799889943138321e-01, 2.0448695346897386e-01, 1.3871950817658463e-01, 8.0467087994200825e-02, 3.9858264027817066e-02, 1.6829299199652096e-02, 6.0436044551375788e-03, 1.8409222622442125e-03, 4.7411702610320811e-04, 1.0284880800685653e-04, 1.8709113003788699e-05, 2.8393114498469317e-06, 3.5734732949990906e-07, 3.7041625984897139e-08, 3.1371929535383148e-09, 2.1508698297874976e-10, 1.1808921844569749e-11, 5.1265062385198317e-13, 1.7335817955789140e-14, 4.4857058689315790e-16, 8.6925536958459408e-18, 1.2288435628835336e-19, 1.2266629909143781e-21, 8.2963863116210883e-24, 3.6027426635285024e-26, 9.3437837175659029e-29, 1.3071305930820806e-31, 8.4687478191905945e-35, 1.9796804708319897e-38, 1.0400778615224128e-42, 3.7099206361930349e-48}, + {5.5357065358570184e-49, 1.6797479901081275e-43, 3.4211380112558623e-39, 1.5573906246297621e-35, 2.5496608991129390e-32, 1.9291035954649827e-29, 7.8617977889259561e-27, 1.9117068833006383e-24, 2.9828627842798555e-22, 3.1522545665038165e-20, 2.3518847106758435e-18, 1.2800933913224359e-16, 5.2186237265908379e-15, 1.6283407307097284e-13, 3.9591777669477542e-12, 7.6152172501454727e-11, 1.1736167423215493e-09, 1.4651253164761138e-08, 1.4955329367272515e-07, 1.2583402510311900e-06, 8.7884992308503793e-06, 5.1259291357862856e-05, 2.5098369851306242e-04, 1.0363290995075809e-03, 3.6225869785344623e-03, 1.0756040509879146e-02, 2.7203128953688913e-02, 5.8739981964099283e-02, 1.0849834930618682e-01, 1.7168584234908363e-01, 2.3299478606267793e-01, 2.7137742494130401e-01, 2.7137742494130401e-01, 2.3299478606267793e-01, 1.7168584234908363e-01, 1.0849834930618682e-01, 5.8739981964099283e-02, 2.7203128953688913e-02, 1.0756040509879146e-02, 3.6225869785344623e-03, 1.0363290995075809e-03, 2.5098369851306242e-04, 5.1259291357862856e-05, 8.7884992308503793e-06, 1.2583402510311900e-06, 1.4955329367272515e-07, 1.4651253164761138e-08, 1.1736167423215493e-09, 7.6152172501454727e-11, 3.9591777669477542e-12, 1.6283407307097284e-13, 5.2186237265908379e-15, 1.2800933913224359e-16, 2.3518847106758435e-18, 3.1522545665038165e-20, 2.9828627842798555e-22, 1.9117068833006383e-24, 7.8617977889259561e-27, 1.9291035954649827e-29, 2.5496608991129390e-32, 1.5573906246297621e-35, 3.4211380112558623e-39, 1.6797479901081275e-43, 5.5357065358570184e-49}, + {8.2516107962538437e-50, 2.7076758452831307e-44, 5.8962844659788279e-40, 2.8541849032786616e-36, 4.9525862550205175e-33, 3.9632869870747322e-30, 1.7059115810757949e-27, 4.3769741948718935e-25, 7.2016107891350715e-23, 8.0222187354240242e-21, 6.3078910455861518e-19, 3.6181996190429121e-17, 1.5546635722380968e-15, 5.1139174817165822e-14, 1.3112516106390246e-12, 2.6608653477929730e-11, 4.3286561534485417e-10, 5.7075829327787572e-09, 6.1577962214505752e-08, 5.4804560350180002e-07, 4.0522493910237441e-06, 2.5045342890495838e-05, 1.3008291629845118e-04, 5.7039896752377221e-04, 2.1199816320368434e-03, 6.7014045380057391e-03, 1.8069433112703592e-02, 4.1661108762478506e-02, 8.2300163369735294e-02, 1.3952613948284390e-01, 2.0325057415444170e-01, 2.5462881185279007e-01, 2.7447822655926341e-01, 2.5462881185279007e-01, 2.0325057415444170e-01, 1.3952613948284390e-01, 8.2300163369735294e-02, 4.1661108762478506e-02, 1.8069433112703592e-02, 6.7014045380057391e-03, 2.1199816320368434e-03, 5.7039896752377221e-04, 1.3008291629845118e-04, 2.5045342890495838e-05, 4.0522493910237441e-06, 5.4804560350180002e-07, 6.1577962214505752e-08, 5.7075829327787572e-09, 4.3286561534485417e-10, 2.6608653477929730e-11, 1.3112516106390246e-12, 5.1139174817165822e-14, 1.5546635722380968e-15, 3.6181996190429121e-17, 6.3078910455861518e-19, 8.0222187354240242e-21, 7.2016107891350715e-23, 4.3769741948718935e-25, 1.7059115810757949e-27, 3.9632869870747322e-30, 4.9525862550205175e-33, 2.8541849032786616e-36, 5.8962844659788279e-40, 2.7076758452831307e-44, 8.2516107962538437e-50}, + {1.2287768797135238e-50, 4.3565748909654033e-45, 1.0135609150438053e-40, 5.2133092407201474e-37, 9.5811571508986169e-34, 8.1036840367508257e-31, 3.6813492354788247e-28, 9.9592645616067056e-26, 1.7266548206330479e-23, 2.0259038600763283e-21, 1.6775151863814584e-19, 1.0132362352411122e-17, 4.5848634437116816e-16, 1.5885532676287405e-14, 4.2916420558156765e-13, 9.1795670585092616e-12, 1.5747988216738595e-10, 2.1910095676436381e-09, 2.4958591861839229e-08, 2.3470996573719479e-07, 1.8351979221091958e-06, 1.2005278344250187e-05, 6.6061130219886947e-05, 3.0721561121964142e-04, 1.2123596600232957e-03, 4.0741349478589858e-03, 1.1693944851274627e-02, 2.8741855098732765e-02, 6.0620459149597836e-02, 1.0990705313380535e-01, 1.7152351798443127e-01, 2.3064795199119065e-01, 2.6741826939146512e-01, 2.6741826939146512e-01, 2.3064795199119065e-01, 1.7152351798443127e-01, 1.0990705313380535e-01, 6.0620459149597836e-02, 2.8741855098732765e-02, 1.1693944851274627e-02, 4.0741349478589858e-03, 1.2123596600232957e-03, 3.0721561121964142e-04, 6.6061130219886947e-05, 1.2005278344250187e-05, 1.8351979221091958e-06, 2.3470996573719479e-07, 2.4958591861839229e-08, 2.1910095676436381e-09, 1.5747988216738595e-10, 9.1795670585092616e-12, 4.2916420558156765e-13, 1.5885532676287405e-14, 4.5848634437116816e-16, 1.0132362352411122e-17, 1.6775151863814584e-19, 2.0259038600763283e-21, 1.7266548206330479e-23, 9.9592645616067056e-26, 3.6813492354788247e-28, 8.1036840367508257e-31, 9.5811571508986169e-34, 5.2133092407201474e-37, 1.0135609150438053e-40, 4.3565748909654033e-45, 1.2287768797135238e-50}, + {1.8280449098224982e-51, 6.9969776104465074e-46, 1.7378601313821812e-41, 9.4914073654790101e-38, 1.8462398438517290e-34, 1.6492772853150654e-31, 7.9020561032723045e-29, 2.2524636987884908e-26, 4.1119507972824725e-24, 5.0779932729853307e-22, 4.4245805201641825e-20, 2.8120140377689001e-18, 1.3389362360428643e-16, 4.8824398317753951e-15, 1.3886060911907966e-13, 3.1279303248480510e-12, 5.6537332414960619e-11, 8.2920364429410743e-10, 9.9634336551576826e-09, 9.8898818048931736e-08, 8.1685444112022656e-07, 5.6493811974978918e-06, 3.2895750894750603e-05, 1.6204473635815332e-04, 6.7809290318947399e-04, 2.4191591440605796e-03, 7.3808332831545517e-03, 1.9308982903048826e-02, 4.3410259562275427e-02, 8.4023710374037747e-02, 1.4022557730554358e-01, 2.0200304815121278e-01, 2.5138497704677004e-01, 2.7038153661061759e-01, 2.5138497704677004e-01, 2.0200304815121278e-01, 1.4022557730554358e-01, 8.4023710374037747e-02, 4.3410259562275427e-02, 1.9308982903048826e-02, 7.3808332831545517e-03, 2.4191591440605796e-03, 6.7809290318947399e-04, 1.6204473635815332e-04, 3.2895750894750603e-05, 5.6493811974978918e-06, 8.1685444112022656e-07, 9.8898818048931736e-08, 9.9634336551576826e-09, 8.2920364429410743e-10, 5.6537332414960619e-11, 3.1279303248480510e-12, 1.3886060911907966e-13, 4.8824398317753951e-15, 1.3389362360428643e-16, 2.8120140377689001e-18, 4.4245805201641825e-20, 5.0779932729853307e-22, 4.1119507972824725e-24, 2.2524636987884908e-26, 7.9020561032723045e-29, 1.6492772853150654e-31, 1.8462398438517290e-34, 9.4914073654790101e-38, 1.7378601313821812e-41, 6.9969776104465074e-46, 1.8280449098224982e-51}, + {2.7170067116730165e-52, 1.1217925177026293e-46, 2.9723642655668546e-42, 1.7225457466828413e-38, 3.5439568636689488e-35, 3.3415178524750795e-32, 1.6874060730443393e-29, 5.0645263679858964e-27, 9.7283658177698223e-25, 1.2635945997114491e-22, 1.1577247535043669e-20, 7.7362132775431355e-19, 3.8731516902515290e-17, 1.4852494321530914e-15, 4.4433093884802028e-14, 1.0531630647084200e-12, 2.0038587880644725e-11, 3.0952986928769617e-10, 3.9193048318854111e-09, 4.1023319776043747e-08, 3.5754993018691617e-07, 2.6114965376035973e-06, 1.6073154232928773e-05, 8.3767928571091071e-05, 3.7124104714178821e-04, 1.4042112162131032e-03, 4.5476632686124660e-03, 1.2644719871722365e-02, 3.0255311010248965e-02, 6.2417460794691487e-02, 1.1120083831262205e-01, 1.7129562704597320e-01, 2.2835964147332644e-01, 2.6362735600964210e-01, 2.6362735600964210e-01, 2.2835964147332644e-01, 1.7129562704597320e-01, 1.1120083831262205e-01, 6.2417460794691487e-02, 3.0255311010248965e-02, 1.2644719871722365e-02, 4.5476632686124660e-03, 1.4042112162131032e-03, 3.7124104714178821e-04, 8.3767928571091071e-05, 1.6073154232928773e-05, 2.6114965376035973e-06, 3.5754993018691617e-07, 4.1023319776043747e-08, 3.9193048318854111e-09, 3.0952986928769617e-10, 2.0038587880644725e-11, 1.0531630647084200e-12, 4.4433093884802028e-14, 1.4852494321530914e-15, 3.8731516902515290e-17, 7.7362132775431355e-19, 1.1577247535043669e-20, 1.2635945997114491e-22, 9.7283658177698223e-25, 5.0645263679858964e-27, 1.6874060730443393e-29, 3.3415178524750795e-32, 3.5439568636689488e-35, 1.7225457466828413e-38, 2.9723642655668546e-42, 1.1217925177026293e-46, 2.7170067116730165e-52}, + {4.0345457983197185e-53, 1.7954384298058220e-47, 5.0715303590978945e-43, 3.1165183087668226e-39, 6.7773962594083074e-36, 6.7403932258482419e-33, 3.5851439372856567e-30, 1.1322450883416873e-27, 2.2869723112554000e-25, 3.1221586704548222e-23, 3.0058381695419005e-21, 2.1103468793130292e-19, 1.1100994988590987e-17, 4.4732478501982463e-16, 1.4065409569369246e-14, 3.5050786947688594e-13, 7.0144682351913210e-12, 1.1401392553489413e-10, 1.5199381740983112e-09, 1.6759992864221019e-08, 1.5399292502874990e-07, 1.1865872353918687e-06, 7.7110412769679424e-06, 4.2469576433922949e-05, 1.9909609055329152e-04, 7.9743820114063489e-04, 2.7377658998792736e-03, 8.0794563303749761e-03, 2.0544655922552182e-02, 4.5105267291699995e-02, 8.5643719556781017e-02, 1.4082773794401451e-01, 2.0074887688731419e-01, 2.4825988992112150e-01, 2.6646296361626087e-01, 2.4825988992112150e-01, 2.0074887688731419e-01, 1.4082773794401451e-01, 8.5643719556781017e-02, 4.5105267291699995e-02, 2.0544655922552182e-02, 8.0794563303749761e-03, 2.7377658998792736e-03, 7.9743820114063489e-04, 1.9909609055329152e-04, 4.2469576433922949e-05, 7.7110412769679424e-06, 1.1865872353918687e-06, 1.5399292502874990e-07, 1.6759992864221019e-08, 1.5199381740983112e-09, 1.1401392553489413e-10, 7.0144682351913210e-12, 3.5050786947688594e-13, 1.4065409569369246e-14, 4.4732478501982463e-16, 1.1100994988590987e-17, 2.1103468793130292e-19, 3.0058381695419005e-21, 3.1221586704548222e-23, 2.2869723112554000e-25, 1.1322450883416873e-27, 3.5851439372856567e-30, 6.7403932258482419e-33, 6.7773962594083074e-36, 3.1165183087668226e-39, 5.0715303590978945e-43, 1.7954384298058220e-47, 4.0345457983197185e-53}, + {5.9856092466933942e-54, 2.8688168912332612e-48, 8.6328113687066931e-44, 5.6216222243961033e-40, 1.2913788025337670e-36, 1.3538428107777088e-33, 7.5798318604310986e-31, 2.5172693785018537e-28, 5.3430216209626571e-26, 7.6615923972613038e-24, 7.7454736745174986e-22, 5.7095124323046545e-20, 3.1533210598724162e-18, 1.3342434681247850e-16, 4.4061175397950322e-15, 1.1534952560183679e-13, 2.4259623022354819e-12, 4.1457910332486197e-11, 5.8137344484280929e-10, 6.7473312881324816e-09, 6.5292934189484169e-08, 5.3024856335051780e-07, 3.6344904047182492e-06, 2.1131233267306212e-05, 1.0466994285006789e-04, 4.4339999663332603e-04, 1.6117353953558448e-03, 5.0416367476379337e-03, 1.3605327560618538e-02, 3.1741278190050709e-02, 6.4133640985369098e-02, 1.1238816501981971e-01, 1.7101015293603891e-01, 2.2612844383734518e-01, 2.5999310620316046e-01, 2.5999310620316046e-01, 2.2612844383734518e-01, 1.7101015293603891e-01, 1.1238816501981971e-01, 6.4133640985369098e-02, 3.1741278190050709e-02, 1.3605327560618538e-02, 5.0416367476379337e-03, 1.6117353953558448e-03, 4.4339999663332603e-04, 1.0466994285006789e-04, 2.1131233267306212e-05, 3.6344904047182492e-06, 5.3024856335051780e-07, 6.5292934189484169e-08, 6.7473312881324816e-09, 5.8137344484280929e-10, 4.1457910332486197e-11, 2.4259623022354819e-12, 1.1534952560183679e-13, 4.4061175397950322e-15, 1.3342434681247850e-16, 3.1533210598724162e-18, 5.7095124323046545e-20, 7.7454736745174986e-22, 7.6615923972613038e-24, 5.3430216209626571e-26, 2.5172693785018537e-28, 7.5798318604310986e-31, 1.3538428107777088e-33, 1.2913788025337670e-36, 5.6216222243961033e-40, 8.6328113687066931e-44, 2.8688168912332612e-48, 5.9856092466933942e-54}, + {8.8724008630942898e-55, 4.5764336789075590e-49, 1.4661118038718265e-44, 1.0110662325251453e-40, 2.4518913381167023e-37, 2.7079520650401302e-34, 1.5949041770861358e-31, 5.5663539164360154e-29, 1.2407683405472676e-26, 1.8675901831656063e-24, 1.9812686302523555e-22, 1.5323733317270031e-20, 8.8796168315044913e-19, 3.9423704233496054e-17, 1.3663145902821194e-15, 3.7548696680658361e-14, 8.2926419028182389e-13, 1.4887527478920644e-11, 2.1942330999743630e-10, 2.6779761171072075e-09, 2.7267833016134243e-08, 2.3316541347245123e-07, 1.6840172739131284e-06, 1.0325059077129107e-05, 5.3979561403797981e-05, 2.4157232920980263e-04, 9.2859086457657155e-04, 3.0750221611855083e-03, 8.7949222136699829e-03, 2.1773546737772456e-02, 4.6746077576099838e-02, 8.7165933915876653e-02, 1.4134154505606342e-01, 1.9949184460058894e-01, 2.4524663594920437e-01, 2.6270996412870795e-01, 2.4524663594920437e-01, 1.9949184460058894e-01, 1.4134154505606342e-01, 8.7165933915876653e-02, 4.6746077576099838e-02, 2.1773546737772456e-02, 8.7949222136699829e-03, 3.0750221611855083e-03, 9.2859086457657155e-04, 2.4157232920980263e-04, 5.3979561403797981e-05, 1.0325059077129107e-05, 1.6840172739131284e-06, 2.3316541347245123e-07, 2.7267833016134243e-08, 2.6779761171072075e-09, 2.1942330999743630e-10, 1.4887527478920644e-11, 8.2926419028182389e-13, 3.7548696680658361e-14, 1.3663145902821194e-15, 3.9423704233496054e-17, 8.8796168315044913e-19, 1.5323733317270031e-20, 1.9812686302523555e-22, 1.8675901831656063e-24, 1.2407683405472676e-26, 5.5663539164360154e-29, 1.5949041770861358e-31, 2.7079520650401302e-34, 2.4518913381167023e-37, 1.0110662325251453e-40, 1.4661118038718265e-44, 4.5764336789075590e-49, 8.8724008630942898e-55}, + {1.3140200635759138e-55, 7.2888760600699374e-50, 2.4843223778452137e-45, 1.8132393982490279e-41, 4.6392142210443241e-38, 5.3944805170903356e-35, 3.3402996562304201e-32, 1.2244058147622891e-29, 2.8644542990100537e-27, 4.5229388132654362e-25, 5.0319775906458023e-23, 4.0808135693241622e-21, 2.4793963766166604e-19, 1.1542667556483506e-17, 4.1953024073558444e-16, 1.2094094650388391e-14, 2.8026693289669983e-13, 5.2816149659273362e-12, 8.1749589868013172e-11, 1.0483088420892190e-09, 1.1221758911496157e-08, 1.0094315168892042e-07, 7.6747273751899334e-07, 4.9572490208738044e-06, 2.7325285268221331e-05, 1.2904853700328517e-04, 5.2397811821303173e-04, 1.8346879155592502e-03, 5.5544997811365557e-03, 1.4572966566065007e-02, 3.3197971745097789e-02, 6.5771771087721614e-02, 1.1347683695023611e-01, 1.7067412122709255e-01, 2.2395285395671372e-01, 2.5650502626034899e-01, 2.5650502626034899e-01, 2.2395285395671372e-01, 1.7067412122709255e-01, 1.1347683695023611e-01, 6.5771771087721614e-02, 3.3197971745097789e-02, 1.4572966566065007e-02, 5.5544997811365557e-03, 1.8346879155592502e-03, 5.2397811821303173e-04, 1.2904853700328517e-04, 2.7325285268221331e-05, 4.9572490208738044e-06, 7.6747273751899334e-07, 1.0094315168892042e-07, 1.1221758911496157e-08, 1.0483088420892190e-09, 8.1749589868013172e-11, 5.2816149659273362e-12, 2.8026693289669983e-13, 1.2094094650388391e-14, 4.1953024073558444e-16, 1.1542667556483506e-17, 2.4793963766166604e-19, 4.0808135693241622e-21, 5.0319775906458023e-23, 4.5229388132654362e-25, 2.8644542990100537e-27, 1.2244058147622891e-29, 3.3402996562304201e-32, 5.3944805170903356e-35, 4.6392142210443241e-38, 1.8132393982490279e-41, 2.4843223778452137e-45, 7.2888760600699374e-50, 1.3140200635759138e-55}, + {1.9444622230234342e-56, 1.1590959320007943e-50, 4.2004740254236363e-46, 3.2427888315124139e-42, 8.7482381269078278e-39, 1.0703814562172511e-35, 6.9640785632250250e-33, 2.6794918791965289e-30, 6.5751748013020018e-28, 1.0884570120961755e-25, 1.2691625603633038e-23, 1.0785433636173751e-21, 6.8663309606135431e-20, 3.3495959873429566e-18, 1.2758954586949696e-16, 3.8555242748433330e-15, 9.3683796134838034e-14, 1.8518064702871477e-12, 3.0076840393622017e-11, 4.0491316393465588e-10, 4.5529601729418187e-09, 4.3045713494096147e-08, 3.4420843484101099e-07, 2.3399997161498497e-06, 1.3586053874631190e-05, 6.7639272623934896e-05, 2.8977924888595573e-04, 1.0716281610696826e-03, 3.4300764387647066e-03, 9.5249775695009746e-03, 2.2993107110436964e-02, 4.8332960504809425e-02, 8.8595835021937436e-02, 1.4177503840549346e-01, 1.9823513131250983e-01, 2.4233883536068279e-01, 2.5911119749680783e-01, 2.4233883536068279e-01, 1.9823513131250983e-01, 1.4177503840549346e-01, 8.8595835021937436e-02, 4.8332960504809425e-02, 2.2993107110436964e-02, 9.5249775695009746e-03, 3.4300764387647066e-03, 1.0716281610696826e-03, 2.8977924888595573e-04, 6.7639272623934896e-05, 1.3586053874631190e-05, 2.3399997161498497e-06, 3.4420843484101099e-07, 4.3045713494096147e-08, 4.5529601729418187e-09, 4.0491316393465588e-10, 3.0076840393622017e-11, 1.8518064702871477e-12, 9.3683796134838034e-14, 3.8555242748433330e-15, 1.2758954586949696e-16, 3.3495959873429566e-18, 6.8663309606135431e-20, 1.0785433636173751e-21, 1.2691625603633038e-23, 1.0884570120961755e-25, 6.5751748013020018e-28, 2.6794918791965289e-30, 6.9640785632250250e-33, 1.0703814562172511e-35, 8.7482381269078278e-39, 3.2427888315124139e-42, 4.2004740254236363e-46, 1.1590959320007943e-50, 1.9444622230234342e-56}, + {2.8750275727924455e-57, 1.8404303463880958e-51, 7.0869721836637015e-47, 5.7836152624626662e-43, 1.6442414677949876e-39, 2.1156822123723002e-36, 1.4455024437001548e-33, 5.8345675304162565e-31, 1.5008973228057372e-28, 2.6033049503053747e-26, 3.1794998286708481e-24, 2.8296018603048517e-22, 1.8863727782270500e-20, 9.6365678168475681e-19, 3.8443430855465295e-17, 1.2168900581339222e-15, 3.0981886195643928e-14, 6.4188571380482567e-13, 1.0931590521335809e-11, 1.5438256127811863e-10, 1.8219509376836273e-09, 1.8089441547445238e-08, 1.5199860776329110e-07, 1.0865550828327965e-06, 6.6384540614267379e-06, 3.4806103755504017e-05, 1.5717296348585755e-04, 6.1320670594855193e-04, 2.0727405318696742e-03, 6.0846962089377739e-03, 1.5545067446090813e-02, 3.4623986133714632e-02, 6.7334688728284187e-02, 1.1447404988622129e-01, 1.7029372558220210e-01, 2.2183130791546488e-01, 2.5315358016164968e-01, 2.5315358016164968e-01, 2.2183130791546488e-01, 1.7029372558220210e-01, 1.1447404988622129e-01, 6.7334688728284187e-02, 3.4623986133714632e-02, 1.5545067446090813e-02, 6.0846962089377739e-03, 2.0727405318696742e-03, 6.1320670594855193e-04, 1.5717296348585755e-04, 3.4806103755504017e-05, 6.6384540614267379e-06, 1.0865550828327965e-06, 1.5199860776329110e-07, 1.8089441547445238e-08, 1.8219509376836273e-09, 1.5438256127811863e-10, 1.0931590521335809e-11, 6.4188571380482567e-13, 3.0981886195643928e-14, 1.2168900581339222e-15, 3.8443430855465295e-17, 9.6365678168475681e-19, 1.8863727782270500e-20, 2.8296018603048517e-22, 3.1794998286708481e-24, 2.6033049503053747e-26, 1.5008973228057372e-28, 5.8345675304162565e-31, 1.4455024437001548e-33, 2.1156822123723002e-36, 1.6442414677949876e-39, 5.7836152624626662e-43, 7.0869721836637015e-47, 1.8404303463880958e-51, 2.8750275727924455e-57}, + {4.2475403944235563e-58, 2.9179360026092975e-52, 1.1932102199256711e-47, 1.0287869477179010e-43, 3.0804483195558287e-40, 4.1660662393372492e-37, 2.9874354212480538e-34, 1.2642951712027768e-31, 3.4074887052468082e-29, 6.1891475308279466e-27, 7.9129760878551264e-25, 7.3704570195170156e-23, 5.1421792395941592e-21, 2.7491455795179009e-19, 1.1478770068871720e-17, 3.8036255791351365e-16, 1.0139883410013013e-14, 2.2003659842875677e-13, 3.9263803072919160e-12, 5.8125114501326569e-11, 7.1939577649798698e-10, 7.4947098368604126e-09, 6.6118669991811844e-08, 4.9655916977568413e-07, 3.1895150634568674e-06, 1.7594600636505465e-05, 8.3660559585237938e-05, 3.4399085887424382e-04, 1.2265540580803703e-03, 3.8020227522452721e-03, 1.0267477817470316e-02, 2.4201116175054306e-02, 4.9866450712457495e-02, 8.9938636734284719e-02, 1.4213547000895149e-01, 1.9698140672796691e-01, 2.3953059321276829e-01, 2.5565638153018372e-01, 2.3953059321276829e-01, 1.9698140672796691e-01, 1.4213547000895149e-01, 8.9938636734284719e-02, 4.9866450712457495e-02, 2.4201116175054306e-02, 1.0267477817470316e-02, 3.8020227522452721e-03, 1.2265540580803703e-03, 3.4399085887424382e-04, 8.3660559585237938e-05, 1.7594600636505465e-05, 3.1895150634568674e-06, 4.9655916977568413e-07, 6.6118669991811844e-08, 7.4947098368604126e-09, 7.1939577649798698e-10, 5.8125114501326569e-11, 3.9263803072919160e-12, 2.2003659842875677e-13, 1.0139883410013013e-14, 3.8036255791351365e-16, 1.1478770068871720e-17, 2.7491455795179009e-19, 5.1421792395941592e-21, 7.3704570195170156e-23, 7.9129760878551264e-25, 6.1891475308279466e-27, 3.4074887052468082e-29, 1.2642951712027768e-31, 2.9874354212480538e-34, 4.1660662393372492e-37, 3.0804483195558287e-40, 1.0287869477179010e-43, 1.1932102199256711e-47, 2.9179360026092975e-52, 4.2475403944235563e-58}, + {6.2703784480694208e-59, 4.6195869591589206e-53, 2.0048780070281735e-48, 1.8252564480138844e-44, 5.7530583850395732e-41, 8.1734457929853433e-38, 6.1482072743115000e-35, 2.7266171296454801e-32, 7.6951427469170207e-30, 1.4628329302419815e-27, 1.9567429736662381e-25, 1.9064520843927174e-23, 1.3911463582850983e-21, 7.7788589853855015e-20, 3.3973551764091287e-18, 1.1777094633733961e-16, 3.2852244087268414e-15, 7.4617858659486148e-14, 1.3941377125806722e-12, 2.1618054623290873e-11, 2.8038686778996357e-10, 3.0626832246516170e-09, 2.8344707359971740e-08, 2.2345250981121576e-07, 1.5076264668245447e-06, 8.7420837008076225e-06, 4.3727831577546010e-05, 1.8929762178671690e-04, 7.1126362441827832e-04, 2.3254926708230895e-03, 6.6306857259903285e-03, 1.6519285009994170e-02, 3.6018246356681126e-02, 6.8825257394126579e-02, 1.1538643824874496e-01, 1.6987443543948361e-01, 2.1976221051624720e-01, 2.4993008013933904e-01, 2.4993008013933904e-01, 2.1976221051624720e-01, 1.6987443543948361e-01, 1.1538643824874496e-01, 6.8825257394126579e-02, 3.6018246356681126e-02, 1.6519285009994170e-02, 6.6306857259903285e-03, 2.3254926708230895e-03, 7.1126362441827832e-04, 1.8929762178671690e-04, 4.3727831577546010e-05, 8.7420837008076225e-06, 1.5076264668245447e-06, 2.2345250981121576e-07, 2.8344707359971740e-08, 3.0626832246516170e-09, 2.8038686778996357e-10, 2.1618054623290873e-11, 1.3941377125806722e-12, 7.4617858659486148e-14, 3.2852244087268414e-15, 1.1777094633733961e-16, 3.3973551764091287e-18, 7.7788589853855015e-20, 1.3911463582850983e-21, 1.9064520843927174e-23, 1.9567429736662381e-25, 1.4628329302419815e-27, 7.6951427469170207e-30, 2.7266171296454801e-32, 6.1482072743115000e-35, 8.1734457929853433e-38, 5.7530583850395732e-41, 1.8252564480138844e-44, 2.0048780070281735e-48, 4.6195869591589206e-53, 6.2703784480694208e-59}, + {9.2494982219878178e-60, 7.3032412797370021e-54, 3.3619702764053515e-49, 3.2301359968277160e-45, 1.0711545066976377e-41, 1.5978109726748470e-38, 1.2601224816663446e-35, 5.8531004842511326e-33, 1.7288387765755684e-30, 3.4377966700873511e-28, 4.8085158087733593e-26, 4.8977600911363362e-24, 3.7358525784193159e-22, 2.1835856119475800e-20, 9.9692083309512582e-19, 3.6131260931106432e-17, 1.0539595203667931e-15, 2.5039803161790368e-14, 4.8951189293680036e-13, 7.9452485251106098e-12, 1.0791168663568375e-10, 1.2349280054594245e-09, 1.1980389793173491e-08, 9.9059473817560524e-08, 7.0144004582899757e-07, 4.2716344520701190e-06, 2.2456298833005965e-05, 1.0225119927510267e-04, 4.0444792546155510e-04, 1.3933051824601373e-03, 4.1899160223157692e-03, 1.1020394106207396e-02, 2.5395651463267135e-02, 5.1347296466210786e-02, 9.1199284542961764e-02, 1.4242938912607919e-01, 1.9573290855318265e-01, 2.3681645470932214e-01, 2.5233616878303844e-01, 2.3681645470932214e-01, 1.9573290855318265e-01, 1.4242938912607919e-01, 9.1199284542961764e-02, 5.1347296466210786e-02, 2.5395651463267135e-02, 1.1020394106207396e-02, 4.1899160223157692e-03, 1.3933051824601373e-03, 4.0444792546155510e-04, 1.0225119927510267e-04, 2.2456298833005965e-05, 4.2716344520701190e-06, 7.0144004582899757e-07, 9.9059473817560524e-08, 1.1980389793173491e-08, 1.2349280054594245e-09, 1.0791168663568375e-10, 7.9452485251106098e-12, 4.8951189293680036e-13, 2.5039803161790368e-14, 1.0539595203667931e-15, 3.6131260931106432e-17, 9.9692083309512582e-19, 2.1835856119475800e-20, 3.7358525784193159e-22, 4.8977600911363362e-24, 4.8085158087733593e-26, 3.4377966700873511e-28, 1.7288387765755684e-30, 5.8531004842511326e-33, 1.2601224816663446e-35, 1.5978109726748470e-38, 1.0711545066976377e-41, 3.2301359968277160e-45, 3.3619702764053515e-49, 7.3032412797370021e-54, 9.2494982219878178e-60}, + {1.3633833300020003e-60, 1.1529935596394474e-54, 5.6267053619996539e-50, 5.7021852730627675e-46, 1.9884044482437607e-42, 3.1126000220972273e-39, 2.5723712996578709e-36, 1.2507839519363874e-33, 3.8645811266244288e-31, 8.0343028910788638e-29, 1.1744629608333255e-26, 1.2499248537371909e-24, 9.9604705585733289e-23, 6.0820538195831629e-21, 2.9010288549385599e-19, 1.0985973435650033e-17, 3.3490712214349002e-16, 8.3173189675616162e-15, 1.7001957813551391e-13, 2.8865604962002583e-12, 4.1025651516570179e-11, 4.9151895982232822e-10, 4.9945929385487262e-09, 4.3280820924798808e-08, 3.2138167253993492e-07, 2.0537028582318748e-06, 1.1336998395832870e-05, 5.4246298804851998e-05, 2.2565979982055683e-04, 8.1827502694065590e-04, 2.5924825356809312e-03, 7.1909572204228826e-03, 1.7493488621590211e-02, 3.7379964305875417e-02, 7.0246334697072893e-02, 1.1622011916471321e-01, 1.6942108833811217e-01, 2.1774395641632643e-01, 2.4682659213344721e-01, 2.4682659213344721e-01, 2.1774395641632643e-01, 1.6942108833811217e-01, 1.1622011916471321e-01, 7.0246334697072893e-02, 3.7379964305875417e-02, 1.7493488621590211e-02, 7.1909572204228826e-03, 2.5924825356809312e-03, 8.1827502694065590e-04, 2.2565979982055683e-04, 5.4246298804851998e-05, 1.1336998395832870e-05, 2.0537028582318748e-06, 3.2138167253993492e-07, 4.3280820924798808e-08, 4.9945929385487262e-09, 4.9151895982232822e-10, 4.1025651516570179e-11, 2.8865604962002583e-12, 1.7001957813551391e-13, 8.3173189675616162e-15, 3.3490712214349002e-16, 1.0985973435650033e-17, 2.9010288549385599e-19, 6.0820538195831629e-21, 9.9604705585733289e-23, 1.2499248537371909e-24, 1.1744629608333255e-26, 8.0343028910788638e-29, 3.8645811266244288e-31, 1.2507839519363874e-33, 2.5723712996578709e-36, 3.1126000220972273e-39, 1.9884044482437607e-42, 5.7021852730627675e-46, 5.6267053619996539e-50, 1.1529935596394474e-54, 1.3633833300020003e-60}, + {2.0081683556012850e-61, 1.8178162551753148e-55, 9.3991295413480502e-51, 1.0041756149620635e-46, 3.6803258437880526e-43, 6.0427427569366402e-40, 5.2306055163095921e-37, 2.6610906118130193e-34, 8.5963278572927171e-32, 1.8674862726204788e-29, 2.8515675215544967e-27, 3.1692521338966959e-25, 2.6370712657175804e-23, 1.6812873372296920e-21, 8.3735311688359131e-20, 3.3113569430928055e-18, 1.0543294854998749e-16, 2.7353878696405856e-15, 5.8430667493651178e-14, 1.0369888470878425e-12, 1.5412284525394938e-11, 1.9317783962508064e-10, 2.0546146868576734e-09, 1.8645196384240901e-08, 1.4507140693109981e-07, 9.7197681673778427e-07, 5.6294099461087388e-06, 2.8280775482696968e-05, 1.2361276486093516e-04, 4.7135721157038344e-04, 1.5717570688376730e-03, 4.5927856260634522e-03, 1.1781817217642985e-02, 2.6575061210558436e-02, 5.2776416531222697e-02, 9.2382459021801644e-02, 1.4266271740044509e-01, 1.9449150803253865e-01, 2.3419136519193123e-01, 2.4914204006426580e-01, 2.3419136519193123e-01, 1.9449150803253865e-01, 1.4266271740044509e-01, 9.2382459021801644e-02, 5.2776416531222697e-02, 2.6575061210558436e-02, 1.1781817217642985e-02, 4.5927856260634522e-03, 1.5717570688376730e-03, 4.7135721157038344e-04, 1.2361276486093516e-04, 2.8280775482696968e-05, 5.6294099461087388e-06, 9.7197681673778427e-07, 1.4507140693109981e-07, 1.8645196384240901e-08, 2.0546146868576734e-09, 1.9317783962508064e-10, 1.5412284525394938e-11, 1.0369888470878425e-12, 5.8430667493651178e-14, 2.7353878696405856e-15, 1.0543294854998749e-16, 3.3113569430928055e-18, 8.3735311688359131e-20, 1.6812873372296920e-21, 2.6370712657175804e-23, 3.1692521338966959e-25, 2.8515675215544967e-27, 1.8674862726204788e-29, 8.5963278572927171e-32, 2.6610906118130193e-34, 5.2306055163095921e-37, 6.0427427569366402e-40, 3.6803258437880526e-43, 1.0041756149620635e-46, 9.3991295413480502e-51, 1.8178162551753148e-55, 2.0081683556012850e-61}, + {2.9557746032980847e-62, 2.8621845857326094e-56, 1.5671564937749406e-51, 1.7642057043388989e-47, 6.7924330161546228e-44, 1.1692076998197370e-40, 1.0595146928277511e-37, 5.6371927794771982e-35, 1.9029906100319421e-32, 4.3178173430220290e-30, 6.8834570436337191e-28, 7.9851871981733358e-26, 6.9341198195289992e-24, 4.6134710745539610e-22, 2.3978402756179082e-20, 9.8965289896201795e-19, 3.2891620143645649e-17, 8.9094610406663587e-16, 1.9875208346984979e-14, 3.6848498201591518e-13, 5.7232797185020048e-12, 7.4997199146582833e-11, 8.3430559260867452e-10, 7.9229232891502669e-09, 6.4544629501196559e-08, 4.5305355658612973e-07, 2.7507246274012478e-06, 1.4496444191129691e-05, 6.6517412418153150e-05, 2.6647788669335111e-04, 9.3431768696117658e-04, 2.8731975330897244e-03, 7.7640394053996482e-03, 1.8465751154427907e-02, 3.8708599914838084e-02, 7.1600747691843394e-02, 1.1698073380429937e-01, 1.6893796927590174e-01, 2.1577494627433041e-01, 2.4383585380721171e-01, 2.4383585380721171e-01, 2.1577494627433041e-01, 1.6893796927590174e-01, 1.1698073380429937e-01, 7.1600747691843394e-02, 3.8708599914838084e-02, 1.8465751154427907e-02, 7.7640394053996482e-03, 2.8731975330897244e-03, 9.3431768696117658e-04, 2.6647788669335111e-04, 6.6517412418153150e-05, 1.4496444191129691e-05, 2.7507246274012478e-06, 4.5305355658612973e-07, 6.4544629501196559e-08, 7.9229232891502669e-09, 8.3430559260867452e-10, 7.4997199146582833e-11, 5.7232797185020048e-12, 3.6848498201591518e-13, 1.9875208346984979e-14, 8.9094610406663587e-16, 3.2891620143645649e-17, 9.8965289896201795e-19, 2.3978402756179082e-20, 4.6134710745539610e-22, 6.9341198195289992e-24, 7.9851871981733358e-26, 6.8834570436337191e-28, 4.3178173430220290e-30, 1.9029906100319421e-32, 5.6371927794771982e-35, 1.0595146928277511e-37, 1.1692076998197370e-40, 6.7924330161546228e-44, 1.7642057043388989e-47, 1.5671564937749406e-51, 2.8621845857326094e-56, 2.9557746032980847e-62}, + {4.3474845662635656e-63, 4.5007211282481250e-57, 2.6082298377217237e-52, 3.0923065202135848e-48, 1.2501139575481106e-44, 2.2549072526181938e-41, 2.1381421402290456e-38, 1.1891459359657575e-35, 4.1929734266120318e-33, 9.9316879214599191e-31, 1.6522218331862429e-28, 1.9995631822582135e-26, 1.8111771920709664e-24, 1.2568606780858601e-22, 6.8135449122040696e-21, 2.9333425183931587e-19, 1.0170733571061197e-17, 2.8746837567251872e-16, 6.6931269313103119e-15, 1.2955204220510481e-13, 2.1014796586114549e-12, 2.8770619925838150e-11, 3.3453423873608581e-10, 3.3221419859886598e-09, 2.8316197051829986e-08, 2.0807020978532919e-07, 1.3232911149144323e-06, 7.3096953196703488e-06, 3.5180651840387621e-05, 1.4793874164100584e-04, 5.4489132381766836e-04, 1.7617305058156662e-03, 5.0096471937478518e-03, 1.2549959027149010e-02, 2.7737938219946516e-02, 5.4154863728585530e-02, 9.3492582227695284e-02, 1.4284081532237788e-01, 1.9325876496080116e-01, 2.3165063428423818e-01, 2.4606621240915144e-01, 2.3165063428423818e-01, 1.9325876496080116e-01, 1.4284081532237788e-01, 9.3492582227695284e-02, 5.4154863728585530e-02, 2.7737938219946516e-02, 1.2549959027149010e-02, 5.0096471937478518e-03, 1.7617305058156662e-03, 5.4489132381766836e-04, 1.4793874164100584e-04, 3.5180651840387621e-05, 7.3096953196703488e-06, 1.3232911149144323e-06, 2.0807020978532919e-07, 2.8316197051829986e-08, 3.3221419859886598e-09, 3.3453423873608581e-10, 2.8770619925838150e-11, 2.1014796586114549e-12, 1.2955204220510481e-13, 6.6931269313103119e-15, 2.8746837567251872e-16, 1.0170733571061197e-17, 2.9333425183931587e-19, 6.8135449122040696e-21, 1.2568606780858601e-22, 1.8111771920709664e-24, 1.9995631822582135e-26, 1.6522218331862429e-28, 9.9316879214599191e-31, 4.1929734266120318e-33, 1.1891459359657575e-35, 2.1381421402290456e-38, 2.2549072526181938e-41, 1.2501139575481106e-44, 3.0923065202135848e-48, 2.6082298377217237e-52, 4.5007211282481250e-57, 4.3474845662635656e-63}, + {6.3900846179356680e-64, 7.0683040654635165e-58, 4.3331628156671634e-53, 5.4079341607686490e-49, 2.2944871434121997e-45, 4.3348761233697938e-42, 4.2990971075609177e-39, 2.4981476114804934e-36, 9.1963660505689469e-34, 2.2729303616459228e-31, 3.9439087540838148e-29, 4.9770348134757658e-27, 4.7000291498915663e-25, 3.4001352768447133e-23, 1.9215431432889354e-21, 8.6245303609378974e-20, 3.1179884254074804e-18, 9.1905096520186247e-17, 2.2320593837338383e-15, 4.5078424718756776e-14, 7.6319902510210860e-13, 1.0909613183044814e-11, 1.3250311215425566e-10, 1.3750709116496800e-09, 1.2253983047111421e-08, 9.4193245001969527e-08, 6.2702226836829128e-07, 3.6275480887435970e-06, 1.8297490531324017e-05, 8.0695629747031377e-05, 3.1195003282250721e-04, 1.0594217898549964e-03, 3.1670839271362595e-03, 8.3485090964466376e-03, 1.9434337138642246e-02, 4.0003826723007251e-02, 7.2891273924741068e-02, 1.1767348589341342e-01, 1.6842887908813681e-01, 2.1385359898330383e-01, 2.4095120319809515e-01, 2.4095120319809515e-01, 2.1385359898330383e-01, 1.6842887908813681e-01, 1.1767348589341342e-01, 7.2891273924741068e-02, 4.0003826723007251e-02, 1.9434337138642246e-02, 8.3485090964466376e-03, 3.1670839271362595e-03, 1.0594217898549964e-03, 3.1195003282250721e-04, 8.0695629747031377e-05, 1.8297490531324017e-05, 3.6275480887435970e-06, 6.2702226836829128e-07, 9.4193245001969527e-08, 1.2253983047111421e-08, 1.3750709116496800e-09, 1.3250311215425566e-10, 1.0909613183044814e-11, 7.6319902510210860e-13, 4.5078424718756776e-14, 2.2320593837338383e-15, 9.1905096520186247e-17, 3.1179884254074804e-18, 8.6245303609378974e-20, 1.9215431432889354e-21, 3.4001352768447133e-23, 4.7000291498915663e-25, 4.9770348134757658e-27, 3.9439087540838148e-29, 2.2729303616459228e-31, 9.1963660505689469e-34, 2.4981476114804934e-36, 4.2990971075609177e-39, 4.3348761233697938e-42, 2.2944871434121997e-45, 5.4079341607686490e-49, 4.3331628156671634e-53, 7.0683040654635165e-58, 6.3900846179356680e-64}, + {9.3860543034002427e-65, 1.1086857074759456e-58, 7.1863132033979924e-54, 9.4366281490374702e-50, 4.2000954414179859e-46, 8.3074192361133957e-43, 8.6131947009295395e-40, 5.2269922366851146e-37, 2.0080025620200044e-34, 5.1761145427794598e-32, 9.3634938532685839e-30, 1.2315531785339706e-27, 1.2119297214386231e-25, 9.1354157424215784e-24, 5.3793647773372928e-22, 2.5158646274622071e-20, 9.4786222458398701e-19, 2.9120616998176371e-17, 7.3730974398680154e-16, 1.5527783781178122e-14, 2.7422533133249144e-13, 4.0903372275217891e-12, 5.1859074150534959e-11, 5.6202961151004291e-10, 5.2329996549801057e-09, 4.2048817138133669e-08, 2.9276307349429699e-07, 1.7725651070157471e-06, 9.3629045679147633e-06, 4.3270500380986358e-05, 1.7541290219541701e-04, 6.2518907824834233e-04, 1.9629978285824797e-03, 5.4395127563656737e-03, 1.3323152028369395e-02, 2.8883095437764291e-02, 5.5483794234023616e-02, 9.4533826153130718e-02, 1.4296854105472981e-01, 1.9203597399663150e-01, 2.2918990372570339e-01, 2.4310155924759538e-01, 2.2918990372570339e-01, 1.9203597399663150e-01, 1.4296854105472981e-01, 9.4533826153130718e-02, 5.5483794234023616e-02, 2.8883095437764291e-02, 1.3323152028369395e-02, 5.4395127563656737e-03, 1.9629978285824797e-03, 6.2518907824834233e-04, 1.7541290219541701e-04, 4.3270500380986358e-05, 9.3629045679147633e-06, 1.7725651070157471e-06, 2.9276307349429699e-07, 4.2048817138133669e-08, 5.2329996549801057e-09, 5.6202961151004291e-10, 5.1859074150534959e-11, 4.0903372275217891e-12, 2.7422533133249144e-13, 1.5527783781178122e-14, 7.3730974398680154e-16, 2.9120616998176371e-17, 9.4786222458398701e-19, 2.5158646274622071e-20, 5.3793647773372928e-22, 9.1354157424215784e-24, 1.2119297214386231e-25, 1.2315531785339706e-27, 9.3634938532685839e-30, 5.1761145427794598e-32, 2.0080025620200044e-34, 5.2269922366851146e-37, 8.6131947009295395e-40, 8.3074192361133957e-43, 4.2000954414179859e-46, 9.4366281490374702e-50, 7.1863132033979924e-54, 1.1086857074759456e-58, 9.3860543034002427e-65}, + {1.3777591125358009e-65, 1.7368921661372738e-59, 1.1897755678170730e-54, 1.6430818957997274e-50, 7.6682284731962107e-47, 1.5871807417910754e-43, 1.7196165366502119e-40, 1.0893693911932259e-37, 4.3652562606795252e-35, 1.1730726684546622e-32, 2.2113391943206024e-30, 3.0299940661257904e-28, 3.1056775475544893e-26, 2.4381144772606556e-24, 1.4951761449964922e-22, 7.2828478980006098e-21, 2.8579464976920660e-19, 9.1468094747747248e-18, 2.4130464210357486e-16, 5.2963672903976192e-15, 9.7511119835367196e-14, 1.5167942114683800e-12, 2.0061976506906991e-11, 2.2691700569827051e-10, 2.2060316533485200e-09, 1.8517359090727501e-08, 1.3475150826592070e-07, 8.5321092475315403e-07, 4.7158906386790063e-06, 2.2820419642920848e-05, 9.6932540256516268e-05, 3.6225322463531061e-04, 1.1935740511675038e-03, 3.4735556703184827e-03, 8.9429974621500780e-03, 2.0397690515966099e-02, 4.1265501456996284e-02, 7.4120627126827321e-02, 1.1830317740926892e-01, 1.6789719350811264e-01, 2.1197836082996782e-01, 2.3816651641238701e-01, 2.3816651641238701e-01, 2.1197836082996782e-01, 1.6789719350811264e-01, 1.1830317740926892e-01, 7.4120627126827321e-02, 4.1265501456996284e-02, 2.0397690515966099e-02, 8.9429974621500780e-03, 3.4735556703184827e-03, 1.1935740511675038e-03, 3.6225322463531061e-04, 9.6932540256516268e-05, 2.2820419642920848e-05, 4.7158906386790063e-06, 8.5321092475315403e-07, 1.3475150826592070e-07, 1.8517359090727501e-08, 2.2060316533485200e-09, 2.2691700569827051e-10, 2.0061976506906991e-11, 1.5167942114683800e-12, 9.7511119835367196e-14, 5.2963672903976192e-15, 2.4130464210357486e-16, 9.1468094747747248e-18, 2.8579464976920660e-19, 7.2828478980006098e-21, 1.4951761449964922e-22, 2.4381144772606556e-24, 3.1056775475544893e-26, 3.0299940661257904e-28, 2.2113391943206024e-30, 1.1730726684546622e-32, 4.3652562606795252e-35, 1.0893693911932259e-37, 1.7196165366502119e-40, 1.5871807417910754e-43, 7.6682284731962107e-47, 1.6430818957997274e-50, 1.1897755678170730e-54, 1.7368921661372738e-59, 1.3777591125358009e-65}, + {2.0210775781982523e-66, 2.7178104548553350e-60, 1.9665137729345701e-55, 2.8548162606098395e-51, 1.3964239783926081e-47, 3.0233321269411514e-44, 3.4214653414754691e-41, 2.2616501773134073e-38, 9.4491938966483701e-36, 2.6460383187052969e-33, 5.1955440071780227e-31, 7.4129920915228913e-29, 7.9104233673873923e-27, 6.4645977792616403e-25, 4.1267488231576369e-23, 2.0924604014548367e-21, 8.5484498659455372e-20, 2.8486537373202696e-18, 7.8262318929365957e-17, 1.7892942386135024e-15, 3.4323564970059177e-14, 5.5646126660265747e-13, 7.6736928514695270e-12, 9.0529279992180488e-11, 9.1835433159763121e-10, 8.0473976876877841e-09, 6.1165350599767583e-08, 4.0472265409701691e-07, 2.3390768958015489e-06, 1.1842716592385991e-05, 5.2665815424842040e-05, 2.0620794316657292e-04, 7.1235629871549161e-04, 2.1752890413369533e-03, 5.8813993717320096e-03, 1.4099847351552907e-02, 3.0009543309201085e-02, 5.6764441788522510e-02, 9.5510122550246740e-02, 1.4305030254196435e-01, 1.9082420376099704e-01, 2.2680511848210408e-01, 2.4024154090350588e-01, 2.2680511848210408e-01, 1.9082420376099704e-01, 1.4305030254196435e-01, 9.5510122550246740e-02, 5.6764441788522510e-02, 3.0009543309201085e-02, 1.4099847351552907e-02, 5.8813993717320096e-03, 2.1752890413369533e-03, 7.1235629871549161e-04, 2.0620794316657292e-04, 5.2665815424842040e-05, 1.1842716592385991e-05, 2.3390768958015489e-06, 4.0472265409701691e-07, 6.1165350599767583e-08, 8.0473976876877841e-09, 9.1835433159763121e-10, 9.0529279992180488e-11, 7.6736928514695270e-12, 5.5646126660265747e-13, 3.4323564970059177e-14, 1.7892942386135024e-15, 7.8262318929365957e-17, 2.8486537373202696e-18, 8.5484498659455372e-20, 2.0924604014548367e-21, 4.1267488231576369e-23, 6.4645977792616403e-25, 7.9104233673873923e-27, 7.4129920915228913e-29, 5.1955440071780227e-31, 2.6460383187052969e-33, 9.4491938966483701e-36, 2.2616501773134073e-38, 3.4214653414754691e-41, 3.0233321269411514e-44, 1.3964239783926081e-47, 2.8548162606098395e-51, 1.9665137729345701e-55, 2.7178104548553350e-60, 2.0210775781982523e-66}, + {2.9629045151469795e-67, 4.2477382853725514e-61, 3.2450153429194443e-56, 4.9498576868697659e-52, 2.5365833564005594e-48, 5.7421164166187080e-45, 6.7848084979774069e-42, 4.6777688454197694e-39, 2.0368541188744583e-36, 5.9410439274149082e-34, 1.2145487671367711e-31, 1.8036964134319502e-29, 2.0029387907481775e-27, 1.7031624106751895e-25, 1.1312252871807839e-23, 5.9680464287706203e-22, 2.5370441167173625e-20, 8.7983250076979868e-19, 2.5159793892190254e-17, 5.9885746170489713e-16, 1.1962793877597350e-14, 2.0202353514446467e-13, 2.9029728072990475e-12, 3.5699318546714651e-11, 3.7765043235634349e-10, 3.4525199163835126e-09, 2.7390187380396967e-08, 1.8926893464082190e-07, 1.1429783024859512e-06, 6.0502321414091725e-06, 2.8148083952665619e-05, 1.1537557343902387e-04, 4.1754273548549582e-04, 1.3367210462102556e-03, 3.7920023944900709e-03, 9.5461945478795308e-03, 2.1354422319535372e-02, 4.2493637239894133e-02, 7.5291446661321912e-02, 1.1887424153508566e-01, 1.6734591429857545e-01, 2.1014771223832399e-01, 2.3547615304001107e-01, 2.3547615304001107e-01, 2.1014771223832399e-01, 1.6734591429857545e-01, 1.1887424153508566e-01, 7.5291446661321912e-02, 4.2493637239894133e-02, 2.1354422319535372e-02, 9.5461945478795308e-03, 3.7920023944900709e-03, 1.3367210462102556e-03, 4.1754273548549582e-04, 1.1537557343902387e-04, 2.8148083952665619e-05, 6.0502321414091725e-06, 1.1429783024859512e-06, 1.8926893464082190e-07, 2.7390187380396967e-08, 3.4525199163835126e-09, 3.7765043235634349e-10, 3.5699318546714651e-11, 2.9029728072990475e-12, 2.0202353514446467e-13, 1.1962793877597350e-14, 5.9885746170489713e-16, 2.5159793892190254e-17, 8.7983250076979868e-19, 2.5370441167173625e-20, 5.9680464287706203e-22, 1.1312252871807839e-23, 1.7031624106751895e-25, 2.0029387907481775e-27, 1.8036964134319502e-29, 1.2145487671367711e-31, 5.9410439274149082e-34, 2.0368541188744583e-36, 4.6777688454197694e-39, 6.7848084979774069e-42, 5.7421164166187080e-45, 2.5365833564005594e-48, 4.9498576868697659e-52, 3.2450153429194443e-56, 4.2477382853725514e-61, 2.9629045151469795e-67}, + {4.3409286059314790e-68, 6.6312997992786490e-62, 5.3461191685641914e-57, 8.5648796438497824e-53, 4.5963493020491623e-49, 1.0874550734954457e-45, 1.3410304270363433e-42, 9.6394008578235831e-40, 4.3726474538903734e-37, 1.3279095802116780e-34, 2.8252406271755742e-32, 4.3652040547608271e-30, 5.0421784821017282e-28, 4.4592405404333692e-26, 3.0802364578690691e-24, 1.6900522980387141e-22, 7.4723281435460732e-21, 2.6954831586023608e-19, 8.0190167662890588e-18, 1.9861050466676079e-16, 4.1293419627929950e-15, 7.2600749267287114e-14, 1.0864518129258071e-12, 1.3919025655825987e-11, 1.5345768250281952e-10, 1.4627430245954727e-09, 1.2104826477830397e-08, 8.7294781098733113e-08, 5.5045426913594814e-07, 3.0442062696033981e-06, 1.4805735210956500e-05, 6.3482017172793501e-05, 2.4048437850905004e-04, 8.0646696699679095e-04, 2.3982976827574042e-03, 6.3343363657207474e-03, 1.4878611633370075e-02, 3.1116468918540825e-02, 5.7998096102851303e-02, 9.6425173608541109e-02, 1.4309010371318212e-01, 1.8962432993080802e-01, 2.2449250076685384e-01, 2.3748014388162669e-01, 2.2449250076685384e-01, 1.8962432993080802e-01, 1.4309010371318212e-01, 9.6425173608541109e-02, 5.7998096102851303e-02, 3.1116468918540825e-02, 1.4878611633370075e-02, 6.3343363657207474e-03, 2.3982976827574042e-03, 8.0646696699679095e-04, 2.4048437850905004e-04, 6.3482017172793501e-05, 1.4805735210956500e-05, 3.0442062696033981e-06, 5.5045426913594814e-07, 8.7294781098733113e-08, 1.2104826477830397e-08, 1.4627430245954727e-09, 1.5345768250281952e-10, 1.3919025655825987e-11, 1.0864518129258071e-12, 7.2600749267287114e-14, 4.1293419627929950e-15, 1.9861050466676079e-16, 8.0190167662890588e-18, 2.6954831586023608e-19, 7.4723281435460732e-21, 1.6900522980387141e-22, 3.0802364578690691e-24, 4.4592405404333692e-26, 5.0421784821017282e-28, 4.3652040547608271e-30, 2.8252406271755742e-32, 1.3279095802116780e-34, 4.3726474538903734e-37, 9.6394008578235831e-40, 1.3410304270363433e-42, 1.0874550734954457e-45, 4.5963493020491623e-49, 8.5648796438497824e-53, 5.3461191685641914e-57, 6.6312997992786490e-62, 4.3409286059314790e-68}, + {6.3559888804815291e-69, 1.0340740401651512e-62, 8.7937979910383930e-58, 1.4790458246095511e-53, 8.3086543388025186e-50, 2.0536646110581859e-46, 2.6420736294829820e-43, 1.9792151722732658e-40, 9.3494545988123451e-38, 2.9549868117171349e-35, 6.5403217012580441e-33, 1.0509161650154305e-30, 1.2621393343519558e-28, 1.1604245678013870e-26, 8.3325690961981494e-25, 4.7526132981917159e-23, 2.1844800072999790e-21, 8.1927992139953961e-20, 2.5344499212676499e-18, 6.5284978547093747e-17, 1.4120140414140493e-15, 2.5832194339375668e-14, 4.0236781196418743e-13, 5.3673492268073417e-12, 6.1636566122784830e-11, 6.1219783545440359e-10, 5.2813629715600939e-09, 3.9723156884506070e-08, 2.6137484697367874e-07, 1.5091682442228327e-06, 7.6676762452478550e-06, 3.4365246906918278e-05, 1.3616684443587397e-04, 4.7795191142819410e-04, 1.4887726540954260e-03, 4.1217965699966519e-03, 1.0156852342094170e-02, 2.2303298514796874e-02, 4.3688380057289714e-02, 7.6406289996198792e-02, 1.1939077299329898e-01, 1.6677771361921795e-01, 2.0836017261496417e-01, 2.3287490818454673e-01, 2.3287490818454673e-01, 2.0836017261496417e-01, 1.6677771361921795e-01, 1.1939077299329898e-01, 7.6406289996198792e-02, 4.3688380057289714e-02, 2.2303298514796874e-02, 1.0156852342094170e-02, 4.1217965699966519e-03, 1.4887726540954260e-03, 4.7795191142819410e-04, 1.3616684443587397e-04, 3.4365246906918278e-05, 7.6676762452478550e-06, 1.5091682442228327e-06, 2.6137484697367874e-07, 3.9723156884506070e-08, 5.2813629715600939e-09, 6.1219783545440359e-10, 6.1636566122784830e-11, 5.3673492268073417e-12, 4.0236781196418743e-13, 2.5832194339375668e-14, 1.4120140414140493e-15, 6.5284978547093747e-17, 2.5344499212676499e-18, 8.1927992139953961e-20, 2.1844800072999790e-21, 4.7526132981917159e-23, 8.3325690961981494e-25, 1.1604245678013870e-26, 1.2621393343519558e-28, 1.0509161650154305e-30, 6.5403217012580441e-33, 2.9549868117171349e-35, 9.3494545988123451e-38, 1.9792151722732658e-40, 2.6420736294829820e-43, 2.0536646110581859e-46, 8.3086543388025186e-50, 1.4790458246095511e-53, 8.7937979910383930e-58, 1.0340740401651512e-62, 6.3559888804815291e-69}, + {9.3008818390890492e-70, 1.6107424492415425e-63, 1.4442544724939497e-58, 2.5491245644508241e-54, 1.4983841626026885e-50, 3.8676878782479128e-47, 5.1890175350658309e-44, 4.0494895783343356e-41, 1.9912326515858821e-38, 6.5473365822875601e-36, 1.5069227943967880e-33, 2.5171173318424500e-31, 3.1418754018247846e-29, 3.0018077177700208e-27, 2.2397389074987337e-25, 1.3273883998725675e-23, 6.3398444713628853e-22, 2.4709662681137447e-20, 7.9447537335212530e-19, 2.1273958174343124e-17, 4.7841544346425597e-16, 9.1026391570176184e-15, 1.4750035153523922e-13, 2.0475389185298693e-12, 2.4477459246779186e-11, 2.5318768471063941e-10, 2.2756270244146732e-09, 1.7840153336747013e-08, 1.2241314031279016e-07, 7.3745467763804806e-07, 3.9114112665063118e-06, 1.8311113911126260e-05, 7.5833505293245319e-05, 2.7838967822704579e-04, 9.0756465037858196e-04, 2.6316863728237144e-03, 6.7973713273565750e-03, 1.5658123034423620e-02, 3.2203216875107243e-02, 5.9186084836389256e-02, 9.7282463095519897e-02, 1.4309158549116330e-01, 1.8843706331894564e-01, 2.2224852664936542e-01, 2.3481182765823758e-01, 2.2224852664936542e-01, 1.8843706331894564e-01, 1.4309158549116330e-01, 9.7282463095519897e-02, 5.9186084836389256e-02, 3.2203216875107243e-02, 1.5658123034423620e-02, 6.7973713273565750e-03, 2.6316863728237144e-03, 9.0756465037858196e-04, 2.7838967822704579e-04, 7.5833505293245319e-05, 1.8311113911126260e-05, 3.9114112665063118e-06, 7.3745467763804806e-07, 1.2241314031279016e-07, 1.7840153336747013e-08, 2.2756270244146732e-09, 2.5318768471063941e-10, 2.4477459246779186e-11, 2.0475389185298693e-12, 1.4750035153523922e-13, 9.1026391570176184e-15, 4.7841544346425597e-16, 2.1273958174343124e-17, 7.9447537335212530e-19, 2.4709662681137447e-20, 6.3398444713628853e-22, 1.3273883998725675e-23, 2.2397389074987337e-25, 3.0018077177700208e-27, 3.1418754018247846e-29, 2.5171173318424500e-31, 1.5069227943967880e-33, 6.5473365822875601e-36, 1.9912326515858821e-38, 4.0494895783343356e-41, 5.1890175350658309e-44, 3.8676878782479128e-47, 1.4983841626026885e-50, 2.5491245644508241e-54, 1.4442544724939497e-58, 1.6107424492415425e-63, 9.3008818390890492e-70}, + {1.3602242492354518e-70, 2.5062893896000025e-64, 2.3683907001837810e-59, 4.3849662998245842e-55, 2.6959438737993594e-51, 7.2644220875022382e-48, 1.0159844536444225e-44, 8.2566412936940675e-42, 4.2246144598021515e-39, 1.4445590039286314e-36, 3.4560072588078828e-34, 5.9987185516144465e-32, 7.7788491872908368e-30, 7.7199678213751262e-28, 5.9827510138490597e-26, 3.6826729053156295e-24, 1.8269179382831153e-22, 7.3963423583597857e-21, 2.4705505922880106e-19, 6.8737797990960140e-18, 1.6064742942702627e-16, 3.1773129599637848e-15, 5.3533724861984214e-14, 7.7293031086018118e-13, 9.6137828691596686e-12, 1.0350233726240316e-10, 9.6863849248805751e-10, 7.9104166149104796e-09, 5.6567852900930044e-08, 3.5533045829496680e-07, 1.9661408494659142e-06, 9.6077760741794566e-06, 4.1557921102543606e-05, 1.5944214368480690e-04, 5.4359224952962480e-04, 1.6496055361812409e-03, 4.4622998595035017e-03, 1.0773786624642434e-02, 2.3243228173755130e-02, 4.4849988132390606e-02, 7.7467627605512762e-02, 1.1985655590239072e-01, 1.6619497260995916e-01, 2.0661430370392464e-01, 2.3035797018194470e-01, 2.3035797018194470e-01, 2.0661430370392464e-01, 1.6619497260995916e-01, 1.1985655590239072e-01, 7.7467627605512762e-02, 4.4849988132390606e-02, 2.3243228173755130e-02, 1.0773786624642434e-02, 4.4622998595035017e-03, 1.6496055361812409e-03, 5.4359224952962480e-04, 1.5944214368480690e-04, 4.1557921102543606e-05, 9.6077760741794566e-06, 1.9661408494659142e-06, 3.5533045829496680e-07, 5.6567852900930044e-08, 7.9104166149104796e-09, 9.6863849248805751e-10, 1.0350233726240316e-10, 9.6137828691596686e-12, 7.7293031086018118e-13, 5.3533724861984214e-14, 3.1773129599637848e-15, 1.6064742942702627e-16, 6.8737797990960140e-18, 2.4705505922880106e-19, 7.3963423583597857e-21, 1.8269179382831153e-22, 3.6826729053156295e-24, 5.9827510138490597e-26, 7.7199678213751262e-28, 7.7788491872908368e-30, 5.9987185516144465e-32, 3.4560072588078828e-34, 1.4445590039286314e-36, 4.2246144598021515e-39, 8.2566412936940675e-42, 1.0159844536444225e-44, 7.2644220875022382e-48, 2.6959438737993594e-51, 4.3849662998245842e-55, 2.3683907001837810e-59, 2.5062893896000025e-64, 1.3602242492354518e-70}, + {1.9881401943823065e-71, 3.8956133082883524e-65, 3.8780907613890165e-60, 7.5287596024697438e-56, 4.8396443307633869e-52, 1.3608233728823463e-48, 1.9832504849666674e-45, 1.6777720088426207e-42, 8.9292665279968075e-40, 3.1739897948436054e-37, 7.8902747437194502e-35, 1.4225885948951900e-32, 1.9157413956045486e-30, 1.9741018729702676e-28, 1.5883597138828314e-26, 1.0150605078465530e-24, 5.2280336522983695e-23, 2.1976422794092572e-21, 7.6226000038011678e-20, 2.2026235762112506e-18, 5.3473142908729109e-17, 1.0988447789132501e-15, 1.9241100890740006e-14, 2.8879825636852583e-13, 3.7354214836948911e-12, 4.1834945759406555e-11, 4.0743696574618951e-10, 3.4640710439123456e-09, 2.5801094931709852e-08, 1.6888360171753998e-07, 9.7426112561417961e-07, 4.9661767693609960e-06, 2.2420154669404182e-05, 8.9832774694917811e-05, 3.2005763736769638e-04, 1.0156641399211783e-03, 2.8750919999992967e-03, 7.2695749936617917e-03, 1.6437166647437267e-02, 3.3269271876221002e-02, 6.0329758617287225e-02, 9.8085267668094472e-02, 1.4305806223178333e-01, 1.8726297375534309e-01, 2.2006990496442211e-01, 2.3223147790375134e-01, 2.2006990496442211e-01, 1.8726297375534309e-01, 1.4305806223178333e-01, 9.8085267668094472e-02, 6.0329758617287225e-02, 3.3269271876221002e-02, 1.6437166647437267e-02, 7.2695749936617917e-03, 2.8750919999992967e-03, 1.0156641399211783e-03, 3.2005763736769638e-04, 8.9832774694917811e-05, 2.2420154669404182e-05, 4.9661767693609960e-06, 9.7426112561417961e-07, 1.6888360171753998e-07, 2.5801094931709852e-08, 3.4640710439123456e-09, 4.0743696574618951e-10, 4.1834945759406555e-11, 3.7354214836948911e-12, 2.8879825636852583e-13, 1.9241100890740006e-14, 1.0988447789132501e-15, 5.3473142908729109e-17, 2.2026235762112506e-18, 7.6226000038011678e-20, 2.1976422794092572e-21, 5.2280336522983695e-23, 1.0150605078465530e-24, 1.5883597138828314e-26, 1.9741018729702676e-28, 1.9157413956045486e-30, 1.4225885948951900e-32, 7.8902747437194502e-35, 3.1739897948436054e-37, 8.9292665279968075e-40, 1.6777720088426207e-42, 1.9832504849666674e-45, 1.3608233728823463e-48, 4.8396443307633869e-52, 7.5287596024697438e-56, 3.8780907613890165e-60, 3.8956133082883524e-65, 1.9881401943823065e-71}, + {2.9042780793285192e-72, 6.0487911085991875e-66, 6.3408840552698421e-61, 1.2902630736739495e-56, 8.6686227081665284e-53, 2.5425883339495936e-49, 3.8599589978240019e-46, 3.3979613434850632e-43, 1.8803612804682350e-40, 6.9456401083003465e-38, 1.7934288277345599e-35, 3.3574581848271432e-33, 4.6935588729781351e-31, 5.0199340944280284e-29, 4.1917802591871942e-27, 2.7800091791127284e-25, 1.4859465721519723e-23, 6.4827357579899811e-22, 2.3339160328683892e-20, 7.0010683610304173e-19, 1.7647313333962599e-17, 3.7660828360044482e-16, 6.8501492079314778e-15, 1.0683188551398555e-13, 1.4362003723050719e-12, 1.6723593784919510e-11, 1.6940433392992703e-10, 1.4986355561051177e-09, 1.1619214278627516e-08, 7.9204993538763526e-08, 4.7607676418369897e-07, 2.5297850142327841e-06, 1.1912329247318932e-05, 4.9812715968551620e-05, 1.8533007239769129e-04, 6.1455372697219728e-04, 1.8190665842030779e-03, 4.8128687057527163e-03, 1.1395877807434502e-02, 2.4173252104118973e-02, 4.5978813889354229e-02, 7.8477839811903538e-02, 1.2027508931592504e-01, 1.6559981501591434e-01, 2.0490871177338488e-01, 2.2792088322788109e-01, 2.2792088322788109e-01, 2.0490871177338488e-01, 1.6559981501591434e-01, 1.2027508931592504e-01, 7.8477839811903538e-02, 4.5978813889354229e-02, 2.4173252104118973e-02, 1.1395877807434502e-02, 4.8128687057527163e-03, 1.8190665842030779e-03, 6.1455372697219728e-04, 1.8533007239769129e-04, 4.9812715968551620e-05, 1.1912329247318932e-05, 2.5297850142327841e-06, 4.7607676418369897e-07, 7.9204993538763526e-08, 1.1619214278627516e-08, 1.4986355561051177e-09, 1.6940433392992703e-10, 1.6723593784919510e-11, 1.4362003723050719e-12, 1.0683188551398555e-13, 6.8501492079314778e-15, 3.7660828360044482e-16, 1.7647313333962599e-17, 7.0010683610304173e-19, 2.3339160328683892e-20, 6.4827357579899811e-22, 1.4859465721519723e-23, 2.7800091791127284e-25, 4.1917802591871942e-27, 5.0199340944280284e-29, 4.6935588729781351e-31, 3.3574581848271432e-33, 1.7934288277345599e-35, 6.9456401083003465e-38, 1.8803612804682350e-40, 3.3979613434850632e-43, 3.8599589978240019e-46, 2.5425883339495936e-49, 8.6686227081665284e-53, 1.2902630736739495e-56, 6.3408840552698421e-61, 6.0487911085991875e-66, 2.9042780793285192e-72}, + {4.2402214052951246e-73, 9.3824834253827312e-67, 1.0352869434490524e-61, 2.2072219195734482e-57, 1.5493136809731731e-53, 4.7385536981365373e-50, 7.4907905142626159e-47, 6.8594377885386513e-44, 3.9454427601608861e-41, 1.5138792655234332e-38, 4.0587293642249081e-36, 7.8867039514681461e-34, 1.1440858552314813e-31, 1.2695564683626133e-29, 1.0997785424357608e-27, 7.5663389636387123e-26, 4.1954427268621758e-24, 1.8988470634740822e-22, 7.0927393378883720e-21, 2.2077343775414074e-19, 5.7754643743238307e-18, 1.2794126341282052e-16, 2.4162049041525693e-15, 3.9134647294064509e-14, 5.4654903154799270e-13, 6.6135809154494093e-12, 6.9642829049519196e-11, 6.4070330827294555e-10, 5.1680095336388813e-09, 3.6666857282366239e-08, 2.2949550926387024e-07, 1.2704896429597333e-06, 6.2359369667152816e-06, 2.7195889773576724e-05, 1.0558960284417518e-04, 3.6560795714255136e-04, 1.1307532404246092e-03, 3.1281305245610394e-03, 7.7500451541012766e-03, 1.7214629493700298e-02, 3.4314242859408567e-02, 6.1430478646654310e-02, 9.8836668138780004e-02, 1.4299255414069270e-01, 1.8610251044108347e-01, 2.1795355826999802e-01, 2.2973436523811983e-01, 2.1795355826999802e-01, 1.8610251044108347e-01, 1.4299255414069270e-01, 9.8836668138780004e-02, 6.1430478646654310e-02, 3.4314242859408567e-02, 1.7214629493700298e-02, 7.7500451541012766e-03, 3.1281305245610394e-03, 1.1307532404246092e-03, 3.6560795714255136e-04, 1.0558960284417518e-04, 2.7195889773576724e-05, 6.2359369667152816e-06, 1.2704896429597333e-06, 2.2949550926387024e-07, 3.6666857282366239e-08, 5.1680095336388813e-09, 6.4070330827294555e-10, 6.9642829049519196e-11, 6.6135809154494093e-12, 5.4654903154799270e-13, 3.9134647294064509e-14, 2.4162049041525693e-15, 1.2794126341282052e-16, 5.7754643743238307e-18, 2.2077343775414074e-19, 7.0927393378883720e-21, 1.8988470634740822e-22, 4.1954427268621758e-24, 7.5663389636387123e-26, 1.0997785424357608e-27, 1.2695564683626133e-29, 1.1440858552314813e-31, 7.8867039514681461e-34, 4.0587293642249081e-36, 1.5138792655234332e-38, 3.9454427601608861e-41, 6.8594377885386513e-44, 7.4907905142626159e-47, 4.7385536981365373e-50, 1.5493136809731731e-53, 2.2072219195734482e-57, 1.0352869434490524e-61, 9.3824834253827312e-67, 4.2402214052951246e-73}, + {6.1873167292600330e-74, 1.4538901947049863e-67, 1.6879603995600424e-62, 3.7691324369200321e-58, 2.7631164912569130e-54, 8.8091139694466722e-51, 1.4495623366344723e-47, 1.3802919462863240e-44, 8.2491698349502409e-42, 3.2868281039958480e-39, 9.1463558192668670e-37, 1.8440635697521863e-34, 2.7749265480534503e-32, 3.1936039953280896e-30, 2.8689474946571079e-28, 2.0467667970915599e-26, 1.1768586219954579e-24, 5.5235547418541776e-23, 2.1397391826730893e-21, 6.9081875027574077e-20, 1.8747446593629021e-18, 4.3090894092529427e-17, 8.4454653993109795e-16, 1.4199548095965024e-14, 2.0591425994119171e-13, 2.5880423909347226e-12, 2.8316127909785268e-11, 2.7076622359247714e-10, 2.2709635043178179e-09, 1.6760660123885240e-08, 1.0917307724251056e-07, 6.2927723529831787e-07, 3.2175123782368650e-06, 1.4625147457368242e-05, 5.9216205461426278e-05, 2.1395132199714689e-04, 6.9090534092963924e-04, 1.9969762869401319e-03, 5.1728592008298650e-03, 1.2022070950665343e-02, 2.5092532015162070e-02, 4.7075288211797156e-02, 7.9439215172105435e-02, 1.2064961060726002e-01, 1.6499413655200360e-01, 2.0324204888941669e-01, 2.2555951425452636e-01, 2.2555951425452636e-01, 2.0324204888941669e-01, 1.6499413655200360e-01, 1.2064961060726002e-01, 7.9439215172105435e-02, 4.7075288211797156e-02, 2.5092532015162070e-02, 1.2022070950665343e-02, 5.1728592008298650e-03, 1.9969762869401319e-03, 6.9090534092963924e-04, 2.1395132199714689e-04, 5.9216205461426278e-05, 1.4625147457368242e-05, 3.2175123782368650e-06, 6.2927723529831787e-07, 1.0917307724251056e-07, 1.6760660123885240e-08, 2.2709635043178179e-09, 2.7076622359247714e-10, 2.8316127909785268e-11, 2.5880423909347226e-12, 2.0591425994119171e-13, 1.4199548095965024e-14, 8.4454653993109795e-16, 4.3090894092529427e-17, 1.8747446593629021e-18, 6.9081875027574077e-20, 2.1397391826730893e-21, 5.5235547418541776e-23, 1.1768586219954579e-24, 2.0467667970915599e-26, 2.8689474946571079e-28, 3.1936039953280896e-30, 2.7749265480534503e-32, 1.8440635697521863e-34, 9.1463558192668670e-37, 3.2868281039958480e-39, 8.2491698349502409e-42, 1.3802919462863240e-44, 1.4495623366344723e-47, 8.8091139694466722e-51, 2.7631164912569130e-54, 3.7691324369200321e-58, 1.6879603995600424e-62, 1.4538901947049863e-67, 6.1873167292600330e-74}, + {9.0236831042710006e-75, 2.2507013266634397e-68, 2.7483088481763178e-63, 6.4250837772781210e-59, 4.9175305451785707e-55, 1.6336381889925197e-51, 2.7972683193869001e-48, 2.7688066162395138e-45, 1.7187588390664908e-42, 7.1089100355543671e-40, 2.0525562261562526e-37, 4.2923202100065188e-35, 6.6976892723501377e-33, 7.9915865248767542e-31, 7.4422174735850754e-29, 5.5036367600342068e-27, 3.2802180350829561e-25, 1.5959112775571386e-23, 6.4090652642750824e-22, 2.1453091893671746e-20, 6.0370235645633800e-19, 1.4391241588665120e-17, 2.9258946262067771e-16, 5.1042859875473367e-15, 7.6822356519145676e-14, 1.0023990331996466e-12, 1.1389647007504889e-11, 1.1314327929338598e-10, 9.8619913092006371e-10, 7.5672777489105014e-09, 5.1267694307391355e-08, 3.0750156860401326e-07, 1.6368618884967503e-06, 7.7499739996840847e-06, 3.2702654980222023e-05, 1.2321031502033358e-04, 4.1514601828721595e-04, 1.2527946608682095e-03, 3.3904013872216063e-03, 8.2379096963313674e-03, 1.7989495266934163e-02, 3.5337848644927512e-02, 6.2489606495141174e-02, 9.9539560539641095e-02, 1.4289781614596173e-01, 1.8495601933162914e-01, 2.1589660563060412e-01, 2.2731610876192898e-01, 2.1589660563060412e-01, 1.8495601933162914e-01, 1.4289781614596173e-01, 9.9539560539641095e-02, 6.2489606495141174e-02, 3.5337848644927512e-02, 1.7989495266934163e-02, 8.2379096963313674e-03, 3.3904013872216063e-03, 1.2527946608682095e-03, 4.1514601828721595e-04, 1.2321031502033358e-04, 3.2702654980222023e-05, 7.7499739996840847e-06, 1.6368618884967503e-06, 3.0750156860401326e-07, 5.1267694307391355e-08, 7.5672777489105014e-09, 9.8619913092006371e-10, 1.1314327929338598e-10, 1.1389647007504889e-11, 1.0023990331996466e-12, 7.6822356519145676e-14, 5.1042859875473367e-15, 2.9258946262067771e-16, 1.4391241588665120e-17, 6.0370235645633800e-19, 2.1453091893671746e-20, 6.4090652642750824e-22, 1.5959112775571386e-23, 3.2802180350829561e-25, 5.5036367600342068e-27, 7.4422174735850754e-29, 7.9915865248767542e-31, 6.6976892723501377e-33, 4.2923202100065188e-35, 2.0525562261562526e-37, 7.1089100355543671e-40, 1.7187588390664908e-42, 2.7688066162395138e-45, 2.7972683193869001e-48, 1.6336381889925197e-51, 4.9175305451785707e-55, 6.4250837772781210e-59, 2.7483088481763178e-63, 2.2507013266634397e-68, 9.0236831042710006e-75}, + {1.3153371477011018e-75, 3.4808413877180985e-69, 4.4687024216810169e-64, 1.0933824737518103e-59, 8.7337328359193298e-56, 3.0222939315022155e-52, 5.3832225069701608e-49, 5.5370648197825761e-46, 3.5689385617810602e-43, 1.5317989647111863e-40, 4.5874016658583215e-38, 9.9468000592214207e-36, 1.6088732079384737e-33, 1.9895468942695488e-31, 1.9199707067949033e-29, 1.4712415549741861e-27, 9.0859656470487372e-26, 4.5806010985499422e-24, 1.9062601886875492e-22, 6.6129511764811165e-21, 1.9288793268371580e-19, 4.7668311711866824e-18, 1.0049051491574811e-16, 1.8181691304932292e-15, 2.8387673951693530e-14, 3.8436817248766534e-13, 4.5333033745839362e-12, 4.6760103859850812e-11, 4.2335937835110236e-10, 3.3755847311277282e-09, 2.3773662147574315e-08, 1.4829694050050112e-07, 8.2135445478328264e-07, 4.0482331787772522e-06, 1.7791805918220274e-05, 6.9854324445415533e-05, 2.4541809273052672e-04, 7.7269582168165273e-04, 2.1831319760967165e-03, 5.5416312894389780e-03, 1.2651375112800185e-02, 2.6000340271244451e-02, 4.8139906731089997e-02, 8.0353950080642028e-02, 1.2098311686251535e-01, 1.6437963059849708e-01, 2.0161301347923419e-01, 2.2327002349753469e-01, 2.2327002349753469e-01, 2.0161301347923419e-01, 1.6437963059849708e-01, 1.2098311686251535e-01, 8.0353950080642028e-02, 4.8139906731089997e-02, 2.6000340271244451e-02, 1.2651375112800185e-02, 5.5416312894389780e-03, 2.1831319760967165e-03, 7.7269582168165273e-04, 2.4541809273052672e-04, 6.9854324445415533e-05, 1.7791805918220274e-05, 4.0482331787772522e-06, 8.2135445478328264e-07, 1.4829694050050112e-07, 2.3773662147574315e-08, 3.3755847311277282e-09, 4.2335937835110236e-10, 4.6760103859850812e-11, 4.5333033745839362e-12, 3.8436817248766534e-13, 2.8387673951693530e-14, 1.8181691304932292e-15, 1.0049051491574811e-16, 4.7668311711866824e-18, 1.9288793268371580e-19, 6.6129511764811165e-21, 1.9062601886875492e-22, 4.5806010985499422e-24, 9.0859656470487372e-26, 1.4712415549741861e-27, 1.9199707067949033e-29, 1.9895468942695488e-31, 1.6088732079384737e-33, 9.9468000592214207e-36, 4.5874016658583215e-38, 1.5317989647111863e-40, 3.5689385617810602e-43, 5.5370648197825761e-46, 5.3832225069701608e-49, 3.0222939315022155e-52, 8.7337328359193298e-56, 1.0933824737518103e-59, 4.4687024216810169e-64, 3.4808413877180985e-69, 1.3153371477011018e-75}, + {1.9163113126364858e-76, 5.3782147987051925e-70, 7.2563879227687952e-65, 1.8575257861979059e-60, 1.5480113585024239e-56, 5.5781996438680938e-53, 1.0331986095466757e-49, 1.1039698088171895e-46, 7.3860282667906572e-44, 3.2885519707581838e-41, 1.0211695752712912e-38, 2.2950262940501390e-36, 3.8466556677503065e-34, 4.9282126606183490e-32, 4.9266058774066898e-30, 3.9104187247799965e-28, 2.5014139383687256e-26, 1.3062311410367629e-24, 5.6310279110780034e-23, 2.0237140711644305e-21, 6.1159230112779824e-20, 1.5662392354042098e-18, 3.4222031640236014e-17, 6.4188994417848841e-16, 1.0392178377829332e-14, 1.4594559933116930e-13, 1.7858814626910534e-12, 1.9118156866346926e-11, 1.7970567599571068e-10, 1.4881403983681883e-09, 1.0889411432936255e-08, 7.0605103886976605e-08, 4.0665248009122635e-07, 2.0852201445349388e-06, 9.5392954689367993e-06, 3.9005661581998708e-05, 1.4279713128781597e-04, 4.6876282593032669e-04, 1.3817279615374414e-03, 3.6614915226082989e-03, 8.7323289056329013e-03, 1.8760838951499537e-02, 3.6339904964249992e-02, 6.3508495757082825e-02, 1.0019666687230201e-01, 1.4277636364566415e-01, 1.8382375801093334e-01, 2.1389634702935822e-01, 2.2497264372314615e-01, 2.1389634702935822e-01, 1.8382375801093334e-01, 1.4277636364566415e-01, 1.0019666687230201e-01, 6.3508495757082825e-02, 3.6339904964249992e-02, 1.8760838951499537e-02, 8.7323289056329013e-03, 3.6614915226082989e-03, 1.3817279615374414e-03, 4.6876282593032669e-04, 1.4279713128781597e-04, 3.9005661581998708e-05, 9.5392954689367993e-06, 2.0852201445349388e-06, 4.0665248009122635e-07, 7.0605103886976605e-08, 1.0889411432936255e-08, 1.4881403983681883e-09, 1.7970567599571068e-10, 1.9118156866346926e-11, 1.7858814626910534e-12, 1.4594559933116930e-13, 1.0392178377829332e-14, 6.4188994417848841e-16, 3.4222031640236014e-17, 1.5662392354042098e-18, 6.1159230112779824e-20, 2.0237140711644305e-21, 5.6310279110780034e-23, 1.3062311410367629e-24, 2.5014139383687256e-26, 3.9104187247799965e-28, 4.9266058774066898e-30, 4.9282126606183490e-32, 3.8466556677503065e-34, 2.2950262940501390e-36, 1.0211695752712912e-38, 3.2885519707581838e-41, 7.3860282667906572e-44, 1.1039698088171895e-46, 1.0331986095466757e-49, 5.5781996438680938e-53, 1.5480113585024239e-56, 1.8575257861979059e-60, 7.2563879227687952e-65, 5.3782147987051925e-70, 1.9163113126364858e-76}, + {2.7904525118679737e-77, 8.3020782212471425e-71, 1.1767736856636937e-65, 3.1505048454950654e-61, 2.7383297861245024e-57, 1.0271804264134620e-53, 1.9777901946758928e-50, 2.1945724897613748e-47, 1.5235549200899557e-44, 7.0346474438870195e-42, 2.2642373940609524e-39, 5.2728051887223330e-37, 9.1548141716730934e-35, 1.2147369169275739e-32, 1.2575027798926635e-30, 1.0335182999889521e-28, 6.8454256421150675e-27, 3.7013456293648089e-25, 1.6522412624655730e-23, 6.1491894101104838e-22, 1.9247067870562822e-20, 5.1057396537975428e-19, 1.1557955215269003e-17, 2.2464616952811288e-16, 3.7697131696054083e-15, 5.4886703549372233e-14, 6.9650658814205409e-13, 7.7347769030963229e-12, 7.5445969018975008e-11, 6.4855152005816811e-10, 4.9282840753506927e-09, 3.3196572232173258e-08, 1.9871572271899896e-07, 1.0595200143943266e-06, 5.0423148877264742e-06, 2.1459377904439359e-05, 8.1811800690556602e-05, 2.7983364446273394e-04, 8.5995448443042602e-04, 2.3773109222215024e-03, 5.9185523609855805e-03, 1.3282862169963864e-02, 2.6896050260216100e-02, 4.9173217905643024e-02, 8.1224149327040002e-02, 1.2127838443962285e-01, 1.6375781072963536e-01, 2.0002035034474053e-01, 2.2104883827723254e-01, 2.2104883827723254e-01, 2.0002035034474053e-01, 1.6375781072963536e-01, 1.2127838443962285e-01, 8.1224149327040002e-02, 4.9173217905643024e-02, 2.6896050260216100e-02, 1.3282862169963864e-02, 5.9185523609855805e-03, 2.3773109222215024e-03, 8.5995448443042602e-04, 2.7983364446273394e-04, 8.1811800690556602e-05, 2.1459377904439359e-05, 5.0423148877264742e-06, 1.0595200143943266e-06, 1.9871572271899896e-07, 3.3196572232173258e-08, 4.9282840753506927e-09, 6.4855152005816811e-10, 7.5445969018975008e-11, 7.7347769030963229e-12, 6.9650658814205409e-13, 5.4886703549372233e-14, 3.7697131696054083e-15, 2.2464616952811288e-16, 1.1557955215269003e-17, 5.1057396537975428e-19, 1.9247067870562822e-20, 6.1491894101104838e-22, 1.6522412624655730e-23, 3.7013456293648089e-25, 6.8454256421150675e-27, 1.0335182999889521e-28, 1.2575027798926635e-30, 1.2147369169275739e-32, 9.1548141716730934e-35, 5.2728051887223330e-37, 2.2642373940609524e-39, 7.0346474438870195e-42, 1.5235549200899557e-44, 2.1945724897613748e-47, 1.9777901946758928e-50, 1.0271804264134620e-53, 2.7383297861245024e-57, 3.1505048454950654e-61, 1.1767736856636937e-65, 8.3020782212471425e-71, 2.7904525118679737e-77}, + {4.0613138578260408e-78, 1.2803753168202646e-71, 1.9059379634157273e-66, 5.3348322229477923e-62, 4.8344851717020582e-58, 1.8871785659984032e-54, 3.7761789448607101e-51, 4.3499235924727088e-48, 3.1326162048099509e-45, 1.4994923130410846e-42, 5.0011700959096005e-40, 1.2063719426097628e-37, 2.1689987827926264e-35, 2.9797144315839396e-33, 3.1931805290733206e-31, 2.7165497805935431e-29, 1.8623802130980743e-27, 1.0423117478273709e-25, 4.8161473163605573e-24, 1.8555204994489541e-22, 6.0128622969968872e-21, 1.6515980171005252e-19, 3.8719360930637078e-18, 7.7952821069111630e-17, 1.3552585228326797e-15, 2.0448819688025393e-14, 2.6898645575023506e-13, 3.0973073233390342e-12, 3.1335844312742886e-11, 2.7949011969950757e-10, 2.2044098210910168e-09, 1.5418168139637173e-08, 9.5872357774191023e-08, 5.3122836336339743e-07, 2.6285303500427774e-06, 1.1636493707975660e-05, 4.6170574104968263e-05, 1.6444759671629532e-04, 5.2653510513586970e-04, 1.5174715210062894e-03, 3.9409789851024037e-03, 9.2324971205438137e-03, 1.9527821414966836e-02, 3.7320312768871315e-02, 6.4488485276268173e-02, 1.0081054546716739e-01, 1.4263049549711082e-01, 1.8270590844100287e-01, 2.1195024923496616e-01, 2.2270019277644792e-01, 2.1195024923496616e-01, 1.8270590844100287e-01, 1.4263049549711082e-01, 1.0081054546716739e-01, 6.4488485276268173e-02, 3.7320312768871315e-02, 1.9527821414966836e-02, 9.2324971205438137e-03, 3.9409789851024037e-03, 1.5174715210062894e-03, 5.2653510513586970e-04, 1.6444759671629532e-04, 4.6170574104968263e-05, 1.1636493707975660e-05, 2.6285303500427774e-06, 5.3122836336339743e-07, 9.5872357774191023e-08, 1.5418168139637173e-08, 2.2044098210910168e-09, 2.7949011969950757e-10, 3.1335844312742886e-11, 3.0973073233390342e-12, 2.6898645575023506e-13, 2.0448819688025393e-14, 1.3552585228326797e-15, 7.7952821069111630e-17, 3.8719360930637078e-18, 1.6515980171005252e-19, 6.0128622969968872e-21, 1.8555204994489541e-22, 4.8161473163605573e-24, 1.0423117478273709e-25, 1.8623802130980743e-27, 2.7165497805935431e-29, 3.1931805290733206e-31, 2.9797144315839396e-33, 2.1689987827926264e-35, 1.2063719426097628e-37, 5.0011700959096005e-40, 1.4994923130410846e-42, 3.1326162048099509e-45, 4.3499235924727088e-48, 3.7761789448607101e-51, 1.8871785659984032e-54, 4.8344851717020582e-58, 5.3348322229477923e-62, 1.9059379634157273e-66, 1.2803753168202646e-71, 4.0613138578260408e-78}, + {5.9080678650312624e-79, 1.9728605748792453e-72, 3.0830289900033436e-67, 9.0192223036937046e-63, 8.5188830817618133e-59, 3.4594779364755318e-55, 7.1915294634635365e-52, 8.5975639548257647e-49, 6.4207252053484628e-46, 3.1852178778360094e-43, 1.1004706827142279e-40, 2.7487848843571218e-38, 5.1162326043852910e-36, 7.2745725968876294e-34, 8.0674342787094055e-32, 7.1018122263849361e-30, 5.0377911662132328e-28, 2.9173500726293596e-26, 1.3948415260687786e-24, 5.5610269616591533e-23, 1.8649976751302685e-21, 5.3023161831319081e-20, 1.2868329211211647e-18, 2.6824921647604057e-17, 4.8298353217030778e-16, 7.5488968779152708e-15, 1.0288749373509957e-13, 1.2278785144101270e-12, 1.2879038257315668e-11, 1.1913006349290762e-10, 9.7479212538717177e-10, 7.0758572838895756e-09, 4.5681275084849536e-08, 2.6290974837537234e-07, 1.3517971591103712e-06, 6.2215248177778678e-06, 2.5676159384549134e-05, 9.5171627785509925e-05, 3.1729197104330006e-04, 9.5269218854862072e-04, 2.5792732600590893e-03, 6.3030002856080628e-03, 1.3915665220231790e-02, 2.7779127385933564e-02, 5.0175812677428613e-02, 8.2051827391224449e-02, 1.2153798684410418e-01, 1.6313003050278282e-01, 1.9846285025418653e-01, 2.1889262958743932e-01, 2.1889262958743932e-01, 1.9846285025418653e-01, 1.6313003050278282e-01, 1.2153798684410418e-01, 8.2051827391224449e-02, 5.0175812677428613e-02, 2.7779127385933564e-02, 1.3915665220231790e-02, 6.3030002856080628e-03, 2.5792732600590893e-03, 9.5269218854862072e-04, 3.1729197104330006e-04, 9.5171627785509925e-05, 2.5676159384549134e-05, 6.2215248177778678e-06, 1.3517971591103712e-06, 2.6290974837537234e-07, 4.5681275084849536e-08, 7.0758572838895756e-09, 9.7479212538717177e-10, 1.1913006349290762e-10, 1.2879038257315668e-11, 1.2278785144101270e-12, 1.0288749373509957e-13, 7.5488968779152708e-15, 4.8298353217030778e-16, 2.6824921647604057e-17, 1.2868329211211647e-18, 5.3023161831319081e-20, 1.8649976751302685e-21, 5.5610269616591533e-23, 1.3948415260687786e-24, 2.9173500726293596e-26, 5.0377911662132328e-28, 7.1018122263849361e-30, 8.0674342787094055e-32, 7.2745725968876294e-34, 5.1162326043852910e-36, 2.7487848843571218e-38, 1.1004706827142279e-40, 3.1852178778360094e-43, 6.4207252053484628e-46, 8.5975639548257647e-49, 7.1915294634635365e-52, 3.4594779364755318e-55, 8.5188830817618133e-59, 9.0192223036937046e-63, 3.0830289900033436e-67, 1.9728605748792453e-72, 5.9080678650312624e-79}, + {8.5904309894818364e-80, 3.0371816846686698e-73, 4.9809124279561082e-68, 1.5224294774877133e-63, 1.4982961830544962e-59, 6.3278572616256388e-56, 1.3661743924144741e-52, 1.6945475116309319e-49, 1.3119398711365523e-46, 6.7430272036894988e-44, 2.4125325785224105e-41, 6.2381218594744620e-39, 1.2015973481338649e-36, 1.7677477939830743e-34, 2.0280915379277212e-32, 1.8467949790116279e-30, 1.3550808933459723e-28, 8.1168066229507355e-27, 4.0142573977672800e-25, 1.6555633107937502e-23, 5.7440707561477782e-22, 1.6897039658922656e-20, 4.2436086794049572e-19, 9.1557867438886624e-18, 1.7065546359370669e-16, 2.7618433228960722e-15, 3.8986379094133088e-14, 4.8201156943039955e-13, 5.2391878407492571e-12, 5.0236198872007664e-11, 4.2625383198445261e-10, 3.2096074629923419e-09, 2.1502703382505708e-08, 1.2847504869574726e-07, 6.8606640833299067e-07, 3.2808733242412502e-06, 1.4075589850899586e-05, 5.4263099453546539e-05, 1.8825409449540776e-04, 5.8852552673756763e-04, 1.6599244925103198e-03, 4.2284362004214454e-03, 9.7376438372710882e-03, 2.0289684052787870e-02, 3.8279047715437671e-02, 6.5430893699439191e-02, 1.0138360090162955e-01, 1.4246231456883673e-01, 1.8160258790817957e-01, 2.1005593297000114e-01, 2.2049524037272045e-01, 2.1005593297000114e-01, 1.8160258790817957e-01, 1.4246231456883673e-01, 1.0138360090162955e-01, 6.5430893699439191e-02, 3.8279047715437671e-02, 2.0289684052787870e-02, 9.7376438372710882e-03, 4.2284362004214454e-03, 1.6599244925103198e-03, 5.8852552673756763e-04, 1.8825409449540776e-04, 5.4263099453546539e-05, 1.4075589850899586e-05, 3.2808733242412502e-06, 6.8606640833299067e-07, 1.2847504869574726e-07, 2.1502703382505708e-08, 3.2096074629923419e-09, 4.2625383198445261e-10, 5.0236198872007664e-11, 5.2391878407492571e-12, 4.8201156943039955e-13, 3.8986379094133088e-14, 2.7618433228960722e-15, 1.7065546359370669e-16, 9.1557867438886624e-18, 4.2436086794049572e-19, 1.6897039658922656e-20, 5.7440707561477782e-22, 1.6555633107937502e-23, 4.0142573977672800e-25, 8.1168066229507355e-27, 1.3550808933459723e-28, 1.8467949790116279e-30, 2.0280915379277212e-32, 1.7677477939830743e-34, 1.2015973481338649e-36, 6.2381218594744620e-39, 2.4125325785224105e-41, 6.7430272036894988e-44, 1.3119398711365523e-46, 1.6945475116309319e-49, 1.3661743924144741e-52, 6.3278572616256388e-56, 1.4982961830544962e-59, 1.5224294774877133e-63, 4.9809124279561082e-68, 3.0371816846686698e-73, 8.5904309894818364e-80}, + {1.2484709934169793e-80, 4.6716134267455262e-74, 8.0373302337190505e-69, 2.5658825214250866e-64, 2.6303256479665557e-60, 1.1549629962198519e-56, 2.5889667003232748e-53, 3.3307225187898004e-50, 2.6725211308631837e-47, 1.4227172891228852e-44, 5.2696956176078606e-42, 1.4101103127648418e-39, 2.8100935042395224e-37, 4.2761357132188511e-35, 5.0736585413756089e-33, 4.7776103023740991e-31, 3.6248608340202214e-29, 2.2451158851842135e-27, 1.1481416337131872e-25, 4.8966201179064703e-24, 1.7569837815084929e-22, 5.3457088341630912e-21, 1.3887935290404047e-19, 3.1001141967930157e-18, 5.9794936879871788e-17, 1.0016087747850758e-15, 1.4637583603666311e-14, 1.8740601774404304e-13, 2.1099943426302045e-12, 2.0963143669741310e-11, 1.8436168972317116e-10, 1.4393514257953216e-09, 1.0001836240436016e-08, 6.2007747893151711e-08, 3.4372586316527799e-07, 1.7070358456037084e-06, 7.6089581259975007e-06, 3.0491388427439179e-05, 1.1001458276280751e-04, 3.5787758856259302e-04, 1.0509023763580526e-03, 2.7887647298672400e-03, 6.6943659482095498e-03, 1.4548976670515633e-02, 2.8649120680685196e-02, 5.1148315515202297e-02, 8.2838910302204208e-02, 1.2176431106358794e-01, 1.6249750087283824e-01, 1.9693934921359804e-01, 2.1679829114353039e-01, 2.1679829114353039e-01, 1.9693934921359804e-01, 1.6249750087283824e-01, 1.2176431106358794e-01, 8.2838910302204208e-02, 5.1148315515202297e-02, 2.8649120680685196e-02, 1.4548976670515633e-02, 6.6943659482095498e-03, 2.7887647298672400e-03, 1.0509023763580526e-03, 3.5787758856259302e-04, 1.1001458276280751e-04, 3.0491388427439179e-05, 7.6089581259975007e-06, 1.7070358456037084e-06, 3.4372586316527799e-07, 6.2007747893151711e-08, 1.0001836240436016e-08, 1.4393514257953216e-09, 1.8436168972317116e-10, 2.0963143669741310e-11, 2.1099943426302045e-12, 1.8740601774404304e-13, 1.4637583603666311e-14, 1.0016087747850758e-15, 5.9794936879871788e-17, 3.1001141967930157e-18, 1.3887935290404047e-19, 5.3457088341630912e-21, 1.7569837815084929e-22, 4.8966201179064703e-24, 1.1481416337131872e-25, 2.2451158851842135e-27, 3.6248608340202214e-29, 4.7776103023740991e-31, 5.0736585413756089e-33, 4.2761357132188511e-35, 2.8100935042395224e-37, 1.4101103127648418e-39, 5.2696956176078606e-42, 1.4227172891228852e-44, 2.6725211308631837e-47, 3.3307225187898004e-50, 2.5889667003232748e-53, 1.1549629962198519e-56, 2.6303256479665557e-60, 2.5658825214250866e-64, 8.0373302337190505e-69, 4.6716134267455262e-74, 1.2484709934169793e-80}, + {1.8135909934565948e-81, 7.1794482518779405e-75, 1.2953741930788741e-69, 4.3179663130756179e-65, 4.6092689309993016e-61, 2.1035897073764635e-57, 4.8944169739176386e-54, 6.5290610509647759e-51, 5.4278702104818919e-48, 2.9919651066058538e-45, 1.1469498354442222e-42, 3.1751925459280292e-40, 6.5444038132328712e-38, 1.0297652702618718e-35, 1.2632131984833186e-33, 1.2296697906080111e-31, 9.6441699135755975e-30, 6.1744578340056585e-28, 3.2639881507273933e-26, 1.4390083206149803e-24, 5.3380455822882838e-23, 1.6792427517695717e-21, 4.5112507797362053e-20, 1.0414929706906582e-18, 2.0779783402868767e-17, 3.6013157967372950e-16, 5.4464951383584157e-15, 7.2181098533397167e-14, 8.4145383929577368e-13, 8.6584557144940455e-12, 7.8890516800983647e-11, 6.3831524130277722e-10, 4.5984942968861874e-09, 2.9567316716160832e-08, 1.7005133441347446e-07, 8.7658428229201604e-07, 4.0574245645905015e-06, 1.6891865749199694e-05, 6.3348592408607267e-05, 2.1430344005210969e-04, 6.5478304395432502e-04, 1.8089687249743006e-03, 4.5234328605134695e-03, 1.0247034345774014e-02, 2.1045743544451385e-02, 3.9216150726808105e-02, 6.6337015149646864e-02, 1.0191809344727074e-01, 1.4227374613665661e-01, 1.8051385843527265e-01, 2.0821116124461711e-01, 2.1835450988366478e-01, 2.0821116124461711e-01, 1.8051385843527265e-01, 1.4227374613665661e-01, 1.0191809344727074e-01, 6.6337015149646864e-02, 3.9216150726808105e-02, 2.1045743544451385e-02, 1.0247034345774014e-02, 4.5234328605134695e-03, 1.8089687249743006e-03, 6.5478304395432502e-04, 2.1430344005210969e-04, 6.3348592408607267e-05, 1.6891865749199694e-05, 4.0574245645905015e-06, 8.7658428229201604e-07, 1.7005133441347446e-07, 2.9567316716160832e-08, 4.5984942968861874e-09, 6.3831524130277722e-10, 7.8890516800983647e-11, 8.6584557144940455e-12, 8.4145383929577368e-13, 7.2181098533397167e-14, 5.4464951383584157e-15, 3.6013157967372950e-16, 2.0779783402868767e-17, 1.0414929706906582e-18, 4.5112507797362053e-20, 1.6792427517695717e-21, 5.3380455822882838e-23, 1.4390083206149803e-24, 3.2639881507273933e-26, 6.1744578340056585e-28, 9.6441699135755975e-30, 1.2296697906080111e-31, 1.2632131984833186e-33, 1.0297652702618718e-35, 6.5444038132328712e-38, 3.1751925459280292e-40, 1.1469498354442222e-42, 2.9919651066058538e-45, 5.4278702104818919e-48, 6.5290610509647759e-51, 4.8944169739176386e-54, 2.1035897073764635e-57, 4.6092689309993016e-61, 4.3179663130756179e-65, 1.2953741930788741e-69, 7.1794482518779405e-75, 1.8135909934565948e-81}, + {2.6333035610382397e-82, 1.1024259296315383e-75, 2.0852967445741233e-70, 7.2556400241843898e-66, 8.0626671773555472e-62, 3.8234147683158063e-58, 9.2309809923115915e-55, 1.2764717039702522e-51, 1.0991625015027042e-48, 6.2718288470036324e-46, 2.4875851238977396e-43, 7.1225496037923785e-41, 1.5178899706379763e-38, 2.4689751624056617e-36, 3.1303492079755755e-34, 3.1491543092696820e-32, 2.5522940793940470e-30, 1.6885482670813982e-28, 9.2239272353929576e-27, 4.2024365472164892e-25, 1.6110964547970300e-23, 5.2383797573874037e-22, 1.4547178325694397e-20, 3.4721710760327322e-19, 7.1634722023972862e-18, 1.2840032078315100e-16, 2.0088075710888178e-15, 2.7546357750311648e-14, 3.3235533916670117e-13, 3.5405078866592410e-12, 3.3406627081403544e-11, 2.8000417787301215e-10, 2.0903260822482034e-09, 1.3932720755460754e-08, 8.3098897726797486e-08, 4.4440079875949290e-07, 2.1349200492771325e-06, 9.2289528191432300e-06, 3.5954963665620299e-05, 1.2641879089097217e-04, 4.0166542717281779e-04, 1.1545621668817155e-03, 3.0055192270927668e-03, 7.0920553324460628e-03, 1.5182046088138676e-02, 2.9505655023499801e-02, 5.2091376675144491e-02, 8.3587237918301055e-02, 1.2195957249370640e-01, 1.6186130554382056e-01, 1.9544872749879730e-01, 2.1476292059027455e-01, 2.1476292059027455e-01, 1.9544872749879730e-01, 1.6186130554382056e-01, 1.2195957249370640e-01, 8.3587237918301055e-02, 5.2091376675144491e-02, 2.9505655023499801e-02, 1.5182046088138676e-02, 7.0920553324460628e-03, 3.0055192270927668e-03, 1.1545621668817155e-03, 4.0166542717281779e-04, 1.2641879089097217e-04, 3.5954963665620299e-05, 9.2289528191432300e-06, 2.1349200492771325e-06, 4.4440079875949290e-07, 8.3098897726797486e-08, 1.3932720755460754e-08, 2.0903260822482034e-09, 2.8000417787301215e-10, 3.3406627081403544e-11, 3.5405078866592410e-12, 3.3235533916670117e-13, 2.7546357750311648e-14, 2.0088075710888178e-15, 1.2840032078315100e-16, 7.1634722023972862e-18, 3.4721710760327322e-19, 1.4547178325694397e-20, 5.2383797573874037e-22, 1.6110964547970300e-23, 4.2024365472164892e-25, 9.2239272353929576e-27, 1.6885482670813982e-28, 2.5522940793940470e-30, 3.1491543092696820e-32, 3.1303492079755755e-34, 2.4689751624056617e-36, 1.5178899706379763e-38, 7.1225496037923785e-41, 2.4875851238977396e-43, 6.2718288470036324e-46, 1.0991625015027042e-48, 1.2764717039702522e-51, 9.2309809923115915e-55, 3.8234147683158063e-58, 8.0626671773555472e-62, 7.2556400241843898e-66, 2.0852967445741233e-70, 1.1024259296315383e-75, 2.6333035610382397e-82}, + {3.8217861138085193e-83, 1.6914062097101716e-76, 3.3530353599320843e-71, 1.2174103962049957e-66, 1.4078704255855603e-62, 6.9351300068921097e-59, 1.7369401373650657e-55, 2.4890859009540812e-52, 2.2194272123488213e-49, 1.3105586296104345e-46, 5.3766702664810952e-44, 1.5917657474423608e-41, 3.5064188455904165e-39, 5.8941611353204651e-37, 7.7216030296457281e-35, 8.0254188497506414e-33, 6.7194313102734894e-31, 4.5922904136653062e-29, 2.5914755539513213e-27, 1.2197280334801351e-25, 4.8310543796668917e-24, 1.6229893391874090e-22, 4.6574324658183078e-21, 1.1488922069252337e-19, 2.4500971300072567e-18, 4.5403372361053743e-17, 7.3453513452694623e-16, 1.0418125668654998e-14, 1.3004299981305270e-13, 1.4335908364459435e-12, 1.4002082648585132e-11, 1.2152299982982779e-10, 9.3968905695997315e-10, 6.4898261604097228e-09, 4.0121667112572270e-08, 2.2249156377389857e-07, 1.1087989233089753e-06, 4.9744232013977632e-06, 2.0121686738026826e-05, 7.3491681493347192e-05, 2.4267655305986469e-04, 7.2534332143885018e-04, 1.9644706290361147e-03, 4.8255384821498035e-03, 1.0759969971184533e-02, 2.1795386765479520e-02, 4.0131719533568026e-02, 6.7208115842432761e-02, 1.0241614803131452e-01, 1.4206655437043109e-01, 1.7943973488563147e-01, 2.0641382873539532e-01, 2.1627494312286819e-01, 2.0641382873539532e-01, 1.7943973488563147e-01, 1.4206655437043109e-01, 1.0241614803131452e-01, 6.7208115842432761e-02, 4.0131719533568026e-02, 2.1795386765479520e-02, 1.0759969971184533e-02, 4.8255384821498035e-03, 1.9644706290361147e-03, 7.2534332143885018e-04, 2.4267655305986469e-04, 7.3491681493347192e-05, 2.0121686738026826e-05, 4.9744232013977632e-06, 1.1087989233089753e-06, 2.2249156377389857e-07, 4.0121667112572270e-08, 6.4898261604097228e-09, 9.3968905695997315e-10, 1.2152299982982779e-10, 1.4002082648585132e-11, 1.4335908364459435e-12, 1.3004299981305270e-13, 1.0418125668654998e-14, 7.3453513452694623e-16, 4.5403372361053743e-17, 2.4500971300072567e-18, 1.1488922069252337e-19, 4.6574324658183078e-21, 1.6229893391874090e-22, 4.8310543796668917e-24, 1.2197280334801351e-25, 2.5914755539513213e-27, 4.5922904136653062e-29, 6.7194313102734894e-31, 8.0254188497506414e-33, 7.7216030296457281e-35, 5.8941611353204651e-37, 3.5064188455904165e-39, 1.5917657474423608e-41, 5.3766702664810952e-44, 1.3105586296104345e-46, 2.2194272123488213e-49, 2.4890859009540812e-52, 1.7369401373650657e-55, 6.9351300068921097e-59, 1.4078704255855603e-62, 1.2174103962049957e-66, 3.3530353599320843e-71, 1.6914062097101716e-76, 3.8217861138085193e-83}, + {5.5441992722068482e-84, 2.5929395481292082e-77, 5.3853541853574509e-72, 2.0397343220146265e-67, 2.4541249535874453e-63, 1.2554100822781216e-59, 3.2608376921091931e-56, 4.8412365544964550e-53, 4.4687726007935870e-50, 2.7300300393618730e-47, 1.1581833176995228e-44, 3.5442966005156755e-42, 8.0681149793680242e-40, 1.4011614007496688e-37, 1.8960834059704929e-35, 2.0353977109818878e-33, 1.7599996574525402e-31, 1.2422004027168656e-29, 7.2392001895975213e-28, 3.5188457649983255e-26, 1.4394549700596331e-24, 4.9949088636257322e-23, 1.4806823585568918e-21, 3.7736012205435806e-20, 8.3155142767475590e-19, 1.5925756694175446e-17, 2.6632797443869722e-16, 3.9055385475699820e-15, 5.0416061378516563e-14, 5.7492300646009343e-13, 5.8103188163962404e-12, 5.2193608370012943e-11, 4.1786070059665728e-10, 2.9889202437814213e-09, 1.9144674266312151e-08, 1.1003547442210821e-07, 5.6858218763614167e-07, 2.6459673129317030e-06, 1.1106993480718368e-05, 4.2117165655971054e-05, 1.4445933891050312e-04, 4.4872081587300148e-04, 1.2636334832367285e-03, 3.2292611575356744e-03, 7.4954912038533066e-03, 1.5814177885623497e-02, 3.0348423943327270e-02, 5.3005665528953826e-02, 8.4298566514348958e-02, 1.2212582857840716e-01, 1.6122241452497918e-01, 1.9398990851223818e-01, 2.1278380261127008e-01, 2.1278380261127008e-01, 1.9398990851223818e-01, 1.6122241452497918e-01, 1.2212582857840716e-01, 8.4298566514348958e-02, 5.3005665528953826e-02, 3.0348423943327270e-02, 1.5814177885623497e-02, 7.4954912038533066e-03, 3.2292611575356744e-03, 1.2636334832367285e-03, 4.4872081587300148e-04, 1.4445933891050312e-04, 4.2117165655971054e-05, 1.1106993480718368e-05, 2.6459673129317030e-06, 5.6858218763614167e-07, 1.1003547442210821e-07, 1.9144674266312151e-08, 2.9889202437814213e-09, 4.1786070059665728e-10, 5.2193608370012943e-11, 5.8103188163962404e-12, 5.7492300646009343e-13, 5.0416061378516563e-14, 3.9055385475699820e-15, 2.6632797443869722e-16, 1.5925756694175446e-17, 8.3155142767475590e-19, 3.7736012205435806e-20, 1.4806823585568918e-21, 4.9949088636257322e-23, 1.4394549700596331e-24, 3.5188457649983255e-26, 7.2392001895975213e-28, 1.2422004027168656e-29, 1.7599996574525402e-31, 2.0353977109818878e-33, 1.8960834059704929e-35, 1.4011614007496688e-37, 8.0681149793680242e-40, 3.5442966005156755e-42, 1.1581833176995228e-44, 2.7300300393618730e-47, 4.4687726007935870e-50, 4.8412365544964550e-53, 3.2608376921091931e-56, 1.2554100822781216e-59, 2.4541249535874453e-63, 2.0397343220146265e-67, 5.3853541853574509e-72, 2.5929395481292082e-77, 5.5441992722068482e-84}, + {8.0393570948066263e-85, 3.9718103441759187e-78, 8.6398120096864360e-73, 3.4126815525065270e-68, 4.2706414980124341e-64, 2.2680834264069969e-60, 6.1079802227760500e-57, 9.3924613692270336e-54, 8.9727413440350903e-51, 5.6695759907967620e-48, 2.4865399657656492e-45, 7.8635083915713631e-43, 1.8492505278934263e-40, 3.3170216420826621e-38, 4.6353055637591542e-36, 5.1377976964188761e-34, 4.5868230110636832e-32, 3.3422916829863083e-30, 2.0109122099933846e-28, 1.0091662170872907e-26, 4.2622901606926843e-25, 1.5271754441949008e-23, 4.6750298903216843e-22, 1.2305362144434042e-20, 2.8009656241231101e-19, 5.5420769366655970e-18, 9.5769111189688996e-17, 1.4514991221804437e-15, 1.9370075854564139e-14, 2.2840535977994185e-13, 2.3875175115445612e-12, 2.2189005868460593e-11, 1.8384761407124325e-10, 1.3614036372254147e-09, 9.0305672540467943e-09, 5.3771344014689486e-08, 2.8795698296534307e-07, 1.3893404522738127e-06, 6.0491308542217258e-06, 2.3802318133010187e-05, 8.4755918374596230e-05, 2.7344820329821672e-04, 8.0022923976588462e-04, 2.1262829728506513e-03, 5.1343246513282466e-03, 1.1275787985601648e-02, 2.2538065887400437e-02, 4.1025901106205930e-02, 6.8045431494172207e-02, 1.0287976270898229e-01, 1.4184235712795296e-01, 1.7838019194959490e-01, 2.0466195210272575e-01, 2.1425368197218711e-01, 2.0466195210272575e-01, 1.7838019194959490e-01, 1.4184235712795296e-01, 1.0287976270898229e-01, 6.8045431494172207e-02, 4.1025901106205930e-02, 2.2538065887400437e-02, 1.1275787985601648e-02, 5.1343246513282466e-03, 2.1262829728506513e-03, 8.0022923976588462e-04, 2.7344820329821672e-04, 8.4755918374596230e-05, 2.3802318133010187e-05, 6.0491308542217258e-06, 1.3893404522738127e-06, 2.8795698296534307e-07, 5.3771344014689486e-08, 9.0305672540467943e-09, 1.3614036372254147e-09, 1.8384761407124325e-10, 2.2189005868460593e-11, 2.3875175115445612e-12, 2.2840535977994185e-13, 1.9370075854564139e-14, 1.4514991221804437e-15, 9.5769111189688996e-17, 5.5420769366655970e-18, 2.8009656241231101e-19, 1.2305362144434042e-20, 4.6750298903216843e-22, 1.5271754441949008e-23, 4.2622901606926843e-25, 1.0091662170872907e-26, 2.0109122099933846e-28, 3.3422916829863083e-30, 4.5868230110636832e-32, 5.1377976964188761e-34, 4.6353055637591542e-36, 3.3170216420826621e-38, 1.8492505278934263e-40, 7.8635083915713631e-43, 2.4865399657656492e-45, 5.6695759907967620e-48, 8.9727413440350903e-51, 9.3924613692270336e-54, 6.1079802227760500e-57, 2.2680834264069969e-60, 4.2706414980124341e-64, 3.4126815525065270e-68, 8.6398120096864360e-73, 3.9718103441759187e-78, 8.0393570948066263e-85}, + {1.1652438369940990e-85, 6.0791348825232945e-79, 1.3845734727539209e-73, 5.7018195541180805e-69, 7.4193203262024338e-65, 4.0896774498494807e-61, 1.1415803801508950e-57, 1.8177229307902597e-54, 1.7966861107994258e-51, 1.1738936354016808e-48, 5.3209955905676318e-46, 1.7384628972964638e-43, 4.2224503669018324e-41, 7.8205013430131660e-39, 1.1282489276123687e-36, 1.2908866148089198e-34, 1.1895168657985647e-32, 8.9460231384332668e-31, 5.5552056820850460e-29, 2.8773904696541066e-27, 1.2543771045577858e-25, 4.6393197457827112e-24, 1.4661278293822309e-22, 3.9843331940864138e-21, 9.3649180986702086e-20, 1.9137000334222806e-18, 3.4159437284687078e-17, 5.3490074750121478e-16, 7.3765684098315642e-15, 8.9908236810354557e-14, 9.7167575155334535e-13, 9.3392850013870488e-12, 8.0050126851044650e-11, 6.1341491782010079e-10, 4.2120058561600563e-09, 2.5970629339726590e-08, 1.4407085283844865e-07, 7.2034690286882965e-07, 3.2515206739898432e-06, 1.3269605500302639e-05, 4.9028384509802042e-05, 1.6420793698012457e-04, 4.9909954967131240e-04, 1.3780641953787555e-03, 3.4597075988944920e-03, 7.9041144380998778e-03, 1.6444728895483641e-02, 3.1177182981317560e-02, 5.3891864826823496e-02, 8.4974571583542949e-02, 1.2226499127815092e-01, 1.6058169612107806e-01, 1.9256185751562635e-01, 2.1085839371676188e-01, 2.1085839371676188e-01, 1.9256185751562635e-01, 1.6058169612107806e-01, 1.2226499127815092e-01, 8.4974571583542949e-02, 5.3891864826823496e-02, 3.1177182981317560e-02, 1.6444728895483641e-02, 7.9041144380998778e-03, 3.4597075988944920e-03, 1.3780641953787555e-03, 4.9909954967131240e-04, 1.6420793698012457e-04, 4.9028384509802042e-05, 1.3269605500302639e-05, 3.2515206739898432e-06, 7.2034690286882965e-07, 1.4407085283844865e-07, 2.5970629339726590e-08, 4.2120058561600563e-09, 6.1341491782010079e-10, 8.0050126851044650e-11, 9.3392850013870488e-12, 9.7167575155334535e-13, 8.9908236810354557e-14, 7.3765684098315642e-15, 5.3490074750121478e-16, 3.4159437284687078e-17, 1.9137000334222806e-18, 9.3649180986702086e-20, 3.9843331940864138e-21, 1.4661278293822309e-22, 4.6393197457827112e-24, 1.2543771045577858e-25, 2.8773904696541066e-27, 5.5552056820850460e-29, 8.9460231384332668e-31, 1.1895168657985647e-32, 1.2908866148089198e-34, 1.1282489276123687e-36, 7.8205013430131660e-39, 4.2224503669018324e-41, 1.7384628972964638e-43, 5.3209955905676318e-46, 1.1738936354016808e-48, 1.7966861107994258e-51, 1.8177229307902597e-54, 1.1415803801508950e-57, 4.0896774498494807e-61, 7.4193203262024338e-65, 5.7018195541180805e-69, 1.3845734727539209e-73, 6.0791348825232945e-79, 1.1652438369940990e-85}, + {1.6882167305707454e-86, 9.2973163909464803e-80, 2.2164453269063499e-74, 9.5134149540243336e-70, 1.2868308966878782e-65, 7.3601988558208524e-62, 2.1289805828564999e-58, 3.5092885496818465e-55, 3.5879758763817130e-52, 2.4233946264708683e-49, 1.1349953099138248e-46, 3.8300452415564833e-44, 9.6052219657335494e-42, 1.8364466079421476e-39, 2.7344551836642605e-37, 3.2286335472886435e-35, 3.0699209573361954e-33, 2.3822649787982913e-31, 1.5263559111336781e-29, 8.1574699196788167e-28, 3.6694695554120368e-26, 1.4004790074896691e-24, 4.5675182897648129e-23, 1.2811473098169559e-21, 3.1084252235905216e-20, 6.5579821121285801e-19, 1.2087664560459120e-17, 1.9548969486564158e-16, 2.7849389834496225e-15, 3.5072844186621564e-14, 3.9175124016391924e-13, 3.8925586774167020e-12, 3.4501563168365539e-11, 2.7347438232977245e-10, 1.9430095134453053e-09, 1.2400464068693708e-08, 7.1228670517261927e-08, 3.6889724023685680e-07, 1.7254610364884881e-06, 7.2997812630457740e-06, 2.7971738168589429e-05, 9.7203453180453000e-05, 3.0668682564469456e-04, 8.7945145983116615e-04, 2.2942465962944290e-03, 5.4493669764638540e-03, 1.1793861247331682e-02, 2.3273293687959880e-02, 4.1898884894253120e-02, 6.8850165394430590e-02, 1.0331081665178690e-01, 1.4160263924602950e-01, 1.7733517017411166e-01, 2.0295366115211383e-01, 2.1228805186235042e-01, 2.0295366115211383e-01, 1.7733517017411166e-01, 1.4160263924602950e-01, 1.0331081665178690e-01, 6.8850165394430590e-02, 4.1898884894253120e-02, 2.3273293687959880e-02, 1.1793861247331682e-02, 5.4493669764638540e-03, 2.2942465962944290e-03, 8.7945145983116615e-04, 3.0668682564469456e-04, 9.7203453180453000e-05, 2.7971738168589429e-05, 7.2997812630457740e-06, 1.7254610364884881e-06, 3.6889724023685680e-07, 7.1228670517261927e-08, 1.2400464068693708e-08, 1.9430095134453053e-09, 2.7347438232977245e-10, 3.4501563168365539e-11, 3.8925586774167020e-12, 3.9175124016391924e-13, 3.5072844186621564e-14, 2.7849389834496225e-15, 1.9548969486564158e-16, 1.2087664560459120e-17, 6.5579821121285801e-19, 3.1084252235905216e-20, 1.2811473098169559e-21, 4.5675182897648129e-23, 1.4004790074896691e-24, 3.6694695554120368e-26, 8.1574699196788167e-28, 1.5263559111336781e-29, 2.3822649787982913e-31, 3.0699209573361954e-33, 3.2286335472886435e-35, 2.7344551836642605e-37, 1.8364466079421476e-39, 9.6052219657335494e-42, 3.8300452415564833e-44, 1.1349953099138248e-46, 2.4233946264708683e-49, 3.5879758763817130e-52, 3.5092885496818465e-55, 2.1289805828564999e-58, 7.3601988558208524e-62, 1.2868308966878782e-65, 9.5134149540243336e-70, 2.2164453269063499e-74, 9.2973163909464803e-80, 1.6882167305707454e-86}, + {2.4448842535551943e-87, 1.4208271558885895e-80, 3.5443349838315051e-75, 1.5851638341206613e-70, 2.2283154783345243e-66, 1.3221294591344122e-62, 3.9619475088358356e-59, 6.7588233504303362e-56, 7.1462236088717712e-53, 4.9883667718148639e-50, 2.4133632044032138e-47, 8.4092583458821788e-45, 2.1769699583039015e-42, 4.2954616661119346e-40, 6.5994654800159303e-38, 8.0390389893761170e-36, 7.8853213936624651e-34, 6.3119668181308563e-32, 4.1716030615092882e-30, 2.2997378701939073e-28, 1.0671290531221681e-26, 4.2015271606281150e-25, 1.4137224274155160e-23, 4.0914965094167889e-22, 1.0244196283925887e-20, 2.2306211570300883e-19, 4.2441255956981095e-18, 7.0866359430444936e-17, 1.0425344386668410e-15, 1.3561256356020877e-14, 1.5649369927618164e-13, 1.6069042876497942e-12, 1.4722456305780643e-11, 1.2066201440627706e-10, 8.8669552925941743e-10, 5.8549609302492589e-09, 3.4807738736531026e-08, 1.8664547970988355e-07, 9.0421645542748592e-07, 3.9637332341743650e-06, 1.5744241598181718e-05, 5.6738856687547051e-05, 1.8573262875095809e-04, 5.5284802877925447e-04, 1.4977892627292288e-03, 3.6965702725171162e-03, 8.3173850369341346e-03, 1.7073105881727814e-02, 3.1991743583371472e-02, 5.4750665778331979e-02, 8.5616850779843184e-02, 1.2237883847025718e-01, 1.5993992755454783e-01, 1.9116358027866243e-01, 2.0898430851629271e-01, 2.0898430851629271e-01, 1.9116358027866243e-01, 1.5993992755454783e-01, 1.2237883847025718e-01, 8.5616850779843184e-02, 5.4750665778331979e-02, 3.1991743583371472e-02, 1.7073105881727814e-02, 8.3173850369341346e-03, 3.6965702725171162e-03, 1.4977892627292288e-03, 5.5284802877925447e-04, 1.8573262875095809e-04, 5.6738856687547051e-05, 1.5744241598181718e-05, 3.9637332341743650e-06, 9.0421645542748592e-07, 1.8664547970988355e-07, 3.4807738736531026e-08, 5.8549609302492589e-09, 8.8669552925941743e-10, 1.2066201440627706e-10, 1.4722456305780643e-11, 1.6069042876497942e-12, 1.5649369927618164e-13, 1.3561256356020877e-14, 1.0425344386668410e-15, 7.0866359430444936e-17, 4.2441255956981095e-18, 2.2306211570300883e-19, 1.0244196283925887e-20, 4.0914965094167889e-22, 1.4137224274155160e-23, 4.2015271606281150e-25, 1.0671290531221681e-26, 2.2997378701939073e-28, 4.1716030615092882e-30, 6.3119668181308563e-32, 7.8853213936624651e-34, 8.0390389893761170e-36, 6.5994654800159303e-38, 4.2954616661119346e-40, 2.1769699583039015e-42, 8.4092583458821788e-45, 2.4133632044032138e-47, 4.9883667718148639e-50, 7.1462236088717712e-53, 6.7588233504303362e-56, 3.9619475088358356e-59, 1.3221294591344122e-62, 2.2283154783345243e-66, 1.5851638341206613e-70, 3.5443349838315051e-75, 1.4208271558885895e-80, 2.4448842535551943e-87}, + {3.5392388249213494e-88, 2.1696906628474067e-81, 5.6618251917679648e-76, 2.6377634936769698e-71, 3.8524845909450548e-67, 2.3705848077171715e-63, 7.3575399530382127e-60, 1.2986758900322505e-56, 1.4196212763395569e-53, 1.0238881258836751e-50, 5.1156622686963731e-48, 1.8401448448645002e-45, 4.9161713392811270e-43, 1.0008264983378071e-40, 1.5861732912787765e-38, 1.9928674928468924e-36, 2.0159688321556722e-34, 1.6641520867485548e-32, 1.1341833636634616e-30, 6.4478013617261386e-29, 3.0854328584335985e-27, 1.2528407416044293e-25, 4.3478662125855451e-24, 1.2979585113660281e-22, 3.3525506308968111e-21, 7.5318707919556725e-20, 1.4788148820660904e-18, 2.5485379935372649e-17, 3.8703599993584500e-16, 5.1983189715882119e-15, 6.1952864130014014e-14, 6.5714753453597697e-13, 6.2212201579575959e-12, 5.2699881035078001e-11, 4.0039253602146504e-10, 2.7342851107604089e-09, 1.6816952694545013e-08, 9.3323608375261539e-08, 4.6806643299789927e-07, 2.1250386338304275e-06, 8.7455216612331247e-06, 3.2668449881324752e-05, 1.1089473739894331e-04, 3.4245439902397305e-04, 9.6300903314221480e-04, 2.4681920354686017e-03, 5.7702467735466509e-03, 1.2313597617381173e-02, 2.4000639085914963e-02, 4.2750896794915914e-02, 6.9623487033404263e-02, 1.0371107766286002e-01, 1.4134876449586573e-01, 1.7630458117164949e-01, 2.0128719075538343e-01, 2.1037554689061755e-01, 2.0128719075538343e-01, 1.7630458117164949e-01, 1.4134876449586573e-01, 1.0371107766286002e-01, 6.9623487033404263e-02, 4.2750896794915914e-02, 2.4000639085914963e-02, 1.2313597617381173e-02, 5.7702467735466509e-03, 2.4681920354686017e-03, 9.6300903314221480e-04, 3.4245439902397305e-04, 1.1089473739894331e-04, 3.2668449881324752e-05, 8.7455216612331247e-06, 2.1250386338304275e-06, 4.6806643299789927e-07, 9.3323608375261539e-08, 1.6816952694545013e-08, 2.7342851107604089e-09, 4.0039253602146504e-10, 5.2699881035078001e-11, 6.2212201579575959e-12, 6.5714753453597697e-13, 6.1952864130014014e-14, 5.1983189715882119e-15, 3.8703599993584500e-16, 2.5485379935372649e-17, 1.4788148820660904e-18, 7.5318707919556725e-20, 3.3525506308968111e-21, 1.2979585113660281e-22, 4.3478662125855451e-24, 1.2528407416044293e-25, 3.0854328584335985e-27, 6.4478013617261386e-29, 1.1341833636634616e-30, 1.6641520867485548e-32, 2.0159688321556722e-34, 1.9928674928468924e-36, 1.5861732912787765e-38, 1.0008264983378071e-40, 4.9161713392811270e-43, 1.8401448448645002e-45, 5.1156622686963731e-48, 1.0238881258836751e-50, 1.4196212763395569e-53, 1.2986758900322505e-56, 7.3575399530382127e-60, 2.3705848077171715e-63, 3.8524845909450548e-67, 2.6377634936769698e-71, 5.6618251917679648e-76, 2.1696906628474067e-81, 3.5392388249213494e-88}, + {5.1213633747657793e-89, 3.3107952448155878e-82, 9.0350209598558634e-77, 4.3835962164609016e-72, 6.6500528211701889e-68, 4.2427446781122925e-64, 1.3635093884813276e-60, 2.4895722182831332e-57, 2.8129093907478575e-54, 2.0956899110692340e-51, 1.0810706995222149e-48, 4.0133902027335798e-46, 1.1062614025677837e-43, 2.3230252252301317e-41, 3.7968846438904689e-39, 4.9189778171570439e-37, 5.1304565438169636e-35, 4.3662939232282773e-33, 3.0678714585911782e-31, 1.7980362370024124e-29, 8.8704657684441925e-28, 3.7135654602235681e-26, 1.3288244259482261e-24, 4.0906197763453875e-23, 1.0896574554298035e-21, 2.5250019651414982e-20, 5.1142598161040868e-19, 9.0937679770517361e-18, 1.4251779817419312e-16, 1.9757601287853092e-15, 2.4309836206138916e-14, 2.6627832873106297e-13, 2.6038192973897978e-12, 2.2788951363311533e-11, 1.7893870863289438e-10, 1.2632724994941663e-09, 8.0347791732044002e-09, 4.6125099246668157e-08, 2.3940078640211405e-07, 1.1251692413517793e-06, 4.7955457442441056e-06, 1.8559162409889888e-05, 6.5298413383660050e-05, 2.0909754829024987e-04, 6.1000345990479894e-04, 1.6227318637929411e-03, 3.9395573314086755e-03, 8.7347828708895063e-03, 1.7698763026162554e-02, 3.2791967492410569e-02, 5.5582763848207158e-02, 8.6226926941764842e-02, 1.2246902437683259e-01, 1.5929780439003277e-01, 1.8979412167575810e-01, 2.0715930730796278e-01, 2.0715930730796278e-01, 1.8979412167575810e-01, 1.5929780439003277e-01, 1.2246902437683259e-01, 8.6226926941764842e-02, 5.5582763848207158e-02, 3.2791967492410569e-02, 1.7698763026162554e-02, 8.7347828708895063e-03, 3.9395573314086755e-03, 1.6227318637929411e-03, 6.1000345990479894e-04, 2.0909754829024987e-04, 6.5298413383660050e-05, 1.8559162409889888e-05, 4.7955457442441056e-06, 1.1251692413517793e-06, 2.3940078640211405e-07, 4.6125099246668157e-08, 8.0347791732044002e-09, 1.2632724994941663e-09, 1.7893870863289438e-10, 2.2788951363311533e-11, 2.6038192973897978e-12, 2.6627832873106297e-13, 2.4309836206138916e-14, 1.9757601287853092e-15, 1.4251779817419312e-16, 9.0937679770517361e-18, 5.1142598161040868e-19, 2.5250019651414982e-20, 1.0896574554298035e-21, 4.0906197763453875e-23, 1.3288244259482261e-24, 3.7135654602235681e-26, 8.8704657684441925e-28, 1.7980362370024124e-29, 3.0678714585911782e-31, 4.3662939232282773e-33, 5.1304565438169636e-35, 4.9189778171570439e-37, 3.7968846438904689e-39, 2.3230252252301317e-41, 1.1062614025677837e-43, 4.0133902027335798e-46, 1.0810706995222149e-48, 2.0956899110692340e-51, 2.8129093907478575e-54, 2.4895722182831332e-57, 1.3635093884813276e-60, 4.2427446781122925e-64, 6.6500528211701889e-68, 4.3835962164609016e-72, 9.0350209598558634e-77, 3.3107952448155878e-82, 5.1213633747657793e-89}, + {7.4077801156809802e-90, 5.0483520825696067e-83, 1.4403225795247276e-77, 7.2755698062212851e-73, 1.1461458182067259e-68, 7.5798509757209669e-65, 2.5217356180713449e-61, 4.7616681817655899e-58, 5.5596107723280791e-55, 4.2776169290546349e-52, 2.2777250019423805e-49, 8.7248851122544073e-47, 2.4806792113142151e-44, 5.3718421575826214e-42, 9.0525141699026487e-40, 1.2089985963915576e-37, 1.2997822407575913e-35, 1.1401487006660065e-33, 8.2566517430946983e-32, 4.9874725361855554e-30, 2.5360177279806859e-28, 1.0943086662261828e-26, 4.0363441926925487e-25, 1.2809131432068308e-23, 3.5178503719335083e-22, 8.4054498872392565e-21, 1.7557265568072654e-19, 3.2200557928719378e-18, 5.2060944517170957e-17, 7.4470753817100703e-16, 9.4565868275202180e-15, 1.0692722214257240e-13, 1.0796165415752499e-12, 9.7589319582302090e-12, 7.9162851028857836e-11, 5.7753749442476326e-10, 3.7971425911450754e-09, 2.2540365079384215e-08, 1.2101463098116854e-07, 5.8853747125042215e-07, 2.5965756360441134e-06, 1.0406346919868978e-05, 3.7931294208686378e-05, 1.2588825538260341e-04, 3.8080638386839771e-04, 1.0508900454889139e-03, 2.6479410521627993e-03, 6.0965525061442453e-03, 1.2834439196438882e-02, 2.4719722908456396e-02, 4.3582193779905874e-02, 7.0366531191907819e-02, 1.0408220923468044e-01, 1.4108198634981012e-01, 1.7528831212387214e-01, 1.9966087345702854e-01, 2.0851381638716077e-01, 1.9966087345702854e-01, 1.7528831212387214e-01, 1.4108198634981012e-01, 1.0408220923468044e-01, 7.0366531191907819e-02, 4.3582193779905874e-02, 2.4719722908456396e-02, 1.2834439196438882e-02, 6.0965525061442453e-03, 2.6479410521627993e-03, 1.0508900454889139e-03, 3.8080638386839771e-04, 1.2588825538260341e-04, 3.7931294208686378e-05, 1.0406346919868978e-05, 2.5965756360441134e-06, 5.8853747125042215e-07, 1.2101463098116854e-07, 2.2540365079384215e-08, 3.7971425911450754e-09, 5.7753749442476326e-10, 7.9162851028857836e-11, 9.7589319582302090e-12, 1.0796165415752499e-12, 1.0692722214257240e-13, 9.4565868275202180e-15, 7.4470753817100703e-16, 5.2060944517170957e-17, 3.2200557928719378e-18, 1.7557265568072654e-19, 8.4054498872392565e-21, 3.5178503719335083e-22, 1.2809131432068308e-23, 4.0363441926925487e-25, 1.0943086662261828e-26, 2.5360177279806859e-28, 4.9874725361855554e-30, 8.2566517430946983e-32, 1.1401487006660065e-33, 1.2997822407575913e-35, 1.2089985963915576e-37, 9.0525141699026487e-40, 5.3718421575826214e-42, 2.4806792113142151e-44, 8.7248851122544073e-47, 2.2777250019423805e-49, 4.2776169290546349e-52, 5.5596107723280791e-55, 4.7616681817655899e-58, 2.5217356180713449e-61, 7.5798509757209669e-65, 1.1461458182067259e-68, 7.2755698062212851e-73, 1.4403225795247276e-77, 5.0483520825696067e-83, 7.4077801156809802e-90}, + {1.0710750710094196e-90, 7.6922700260785516e-84, 2.2937970374962485e-78, 1.2060181138762046e-73, 1.9724028846801179e-69, 1.3517892214658933e-65, 4.6544766331713673e-62, 9.0869836287455904e-59, 1.0961147706353286e-55, 8.7075616610856478e-53, 4.7848109229537450e-50, 1.8906897473607166e-47, 5.5435860303288234e-45, 1.2376390647546546e-42, 2.1498363403641766e-40, 2.9591207501866347e-38, 3.2783946198859832e-36, 2.9632924702764426e-34, 2.2111690104503776e-32, 1.3762537782433349e-30, 7.2106896606964717e-29, 3.2061793655442875e-27, 1.2186704300488311e-25, 3.9856906328389221e-24, 1.1282136742777468e-22, 2.7788009433178836e-21, 5.9840605797879746e-20, 1.1316516319423812e-18, 1.8868897366381483e-17, 2.7841156852775031e-16, 3.6474708837523359e-15, 4.2559572408720686e-14, 4.4353966285433845e-13, 4.1393133324428903e-12, 3.4675788374516700e-11, 2.6132836673568577e-10, 1.7753911292124313e-09, 1.0893439091005499e-08, 6.0471668709771245e-08, 3.0419237917584698e-07, 1.3886494911822552e-06, 5.7606576662754425e-06, 2.1743312833175104e-05, 7.4756242475529144e-05, 2.3436272202084139e-04, 6.7059411024834642e-04, 1.7528045021959946e-03, 4.1883749721869905e-03, 9.1558081843385875e-03, 1.8321199420242032e-02, 3.3577761609077682e-02, 5.6388855176296548e-02, 8.6806251150572486e-02, 1.2253708910746171e-01, 1.5865594890874077e-01, 1.8845256425575369e-01, 2.0538128483764440e-01, 2.0538128483764440e-01, 1.8845256425575369e-01, 1.5865594890874077e-01, 1.2253708910746171e-01, 8.6806251150572486e-02, 5.6388855176296548e-02, 3.3577761609077682e-02, 1.8321199420242032e-02, 9.1558081843385875e-03, 4.1883749721869905e-03, 1.7528045021959946e-03, 6.7059411024834642e-04, 2.3436272202084139e-04, 7.4756242475529144e-05, 2.1743312833175104e-05, 5.7606576662754425e-06, 1.3886494911822552e-06, 3.0419237917584698e-07, 6.0471668709771245e-08, 1.0893439091005499e-08, 1.7753911292124313e-09, 2.6132836673568577e-10, 3.4675788374516700e-11, 4.1393133324428903e-12, 4.4353966285433845e-13, 4.2559572408720686e-14, 3.6474708837523359e-15, 2.7841156852775031e-16, 1.8868897366381483e-17, 1.1316516319423812e-18, 5.9840605797879746e-20, 2.7788009433178836e-21, 1.1282136742777468e-22, 3.9856906328389221e-24, 1.2186704300488311e-25, 3.2061793655442875e-27, 7.2106896606964717e-29, 1.3762537782433349e-30, 2.2111690104503776e-32, 2.9632924702764426e-34, 3.2783946198859832e-36, 2.9591207501866347e-38, 2.1498363403641766e-40, 1.2376390647546546e-42, 5.5435860303288234e-45, 1.8906897473607166e-47, 4.7848109229537450e-50, 8.7075616610856478e-53, 1.0961147706353286e-55, 9.0869836287455904e-59, 4.6544766331713673e-62, 1.3517892214658933e-65, 1.9724028846801179e-69, 1.2060181138762046e-73, 2.2937970374962485e-78, 7.6922700260785516e-84, 1.0710750710094196e-90}, + {1.5480449561254974e-91, 1.1712554562855694e-84, 3.6493992259071536e-79, 1.9966381452254604e-74, 3.3892412733092808e-70, 2.4065988574277261e-66, 8.5740429722944209e-63, 1.7303021840396506e-59, 2.1557967924444521e-56, 1.7677871947095523e-53, 1.0022253044363931e-50, 4.0842818848410062e-48, 1.2346472555075369e-45, 2.8411408701159342e-43, 5.0858613958959180e-41, 7.2130038186701857e-39, 8.2330481300630906e-37, 7.6663204905842568e-35, 5.8928891499709780e-33, 3.7782612371775474e-31, 2.0392097722330042e-29, 9.3406997569354054e-28, 3.6577061009128777e-26, 1.2325099622415151e-24, 3.5948795028461328e-23, 9.1244425221919135e-22, 2.0251548550899527e-20, 3.9477817506225531e-19, 6.7863601469508643e-18, 1.0325389659471167e-16, 1.3951643164647175e-15, 1.6793350772844097e-14, 1.8058345392733700e-13, 1.7393402348430495e-12, 1.5041987406688428e-11, 1.1705945482958366e-10, 8.2144797343634809e-10, 5.2077334277669068e-09, 2.9879393170121428e-08, 1.5539942997674910e-07, 7.3371456445731177e-07, 3.1491925110163785e-06, 1.2303027527173753e-05, 4.3799266325778880e-05, 1.4224028492262314e-04, 4.2179171252798944e-04, 1.1430722829481254e-03, 2.8333080652480614e-03, 6.4278810024544141e-03, 1.3355861419689084e-02, 2.5430213894352387e-02, 4.4393059115154253e-02, 7.1080397415348953e-02, 1.0442577716745464e-01, 1.4080345768904715e-01, 1.7428622967828752e-01, 1.9807313269914872e-01, 2.0670065276640287e-01, 1.9807313269914872e-01, 1.7428622967828752e-01, 1.4080345768904715e-01, 1.0442577716745464e-01, 7.1080397415348953e-02, 4.4393059115154253e-02, 2.5430213894352387e-02, 1.3355861419689084e-02, 6.4278810024544141e-03, 2.8333080652480614e-03, 1.1430722829481254e-03, 4.2179171252798944e-04, 1.4224028492262314e-04, 4.3799266325778880e-05, 1.2303027527173753e-05, 3.1491925110163785e-06, 7.3371456445731177e-07, 1.5539942997674910e-07, 2.9879393170121428e-08, 5.2077334277669068e-09, 8.2144797343634809e-10, 1.1705945482958366e-10, 1.5041987406688428e-11, 1.7393402348430495e-12, 1.8058345392733700e-13, 1.6793350772844097e-14, 1.3951643164647175e-15, 1.0325389659471167e-16, 6.7863601469508643e-18, 3.9477817506225531e-19, 2.0251548550899527e-20, 9.1244425221919135e-22, 3.5948795028461328e-23, 1.2325099622415151e-24, 3.6577061009128777e-26, 9.3406997569354054e-28, 2.0392097722330042e-29, 3.7782612371775474e-31, 5.8928891499709780e-33, 7.6663204905842568e-35, 8.2330481300630906e-37, 7.2130038186701857e-39, 5.0858613958959180e-41, 2.8411408701159342e-43, 1.2346472555075369e-45, 4.0842818848410062e-48, 1.0022253044363931e-50, 1.7677871947095523e-53, 2.1557967924444521e-56, 1.7303021840396506e-59, 8.5740429722944209e-63, 2.4065988574277261e-66, 3.3892412733092808e-70, 1.9966381452254604e-74, 3.6493992259071536e-79, 1.1712554562855694e-84, 1.5480449561254974e-91}, + {2.2365648981246453e-92, 1.7821550800540237e-85, 5.8004986924644819e-80, 3.3015035960765624e-75, 5.8152759548633637e-71, 4.2771691981814217e-67, 1.5763666548556604e-63, 3.2876134769273718e-60, 4.2297673811987948e-57, 3.5794857851611975e-54, 2.0932606053442080e-51, 8.7956536234027020e-49, 2.7406328866050857e-46, 6.4989825715662458e-44, 1.1986003025152256e-41, 1.7511205172582050e-39, 2.0587364582129049e-37, 1.9743896190133811e-35, 1.5630006293499951e-33, 1.0320466636328443e-31, 5.7365178511704523e-30, 2.7061869712127610e-28, 1.0914439534101697e-26, 3.7881611827990218e-25, 1.1381700734483244e-23, 2.9761942889320718e-22, 6.8061278108013458e-21, 1.3672374402361970e-19, 2.4223988311307281e-18, 3.7993465086131341e-17, 5.2930247423722938e-16, 6.5702357143564891e-15, 7.2875563565483730e-14, 7.2418684802603713e-13, 6.4631097928536238e-12, 5.1919141781420298e-11, 3.7618946881237821e-10, 2.4632483182140787e-09, 1.4601515540917063e-08, 7.8484291703314789e-08, 3.8310233242483633e-07, 1.7005728326428347e-06, 6.8734922472265778e-06, 2.5326195751014174e-05, 8.5160665584721077e-05, 2.6158391341408045e-04, 7.3463960542667715e-04, 1.8879100806443562e-03, 4.4427288798279318e-03, 9.5799818951133077e-03, 1.8939956587000626e-02, 3.4349073289602634e-02, 5.7169633542064863e-02, 8.7356205785880797e-02, 1.2258446739609345e-01, 1.5801491756025524e-01, 1.8713802680418945e-01, 2.0364826010006534e-01, 2.0364826010006534e-01, 1.8713802680418945e-01, 1.5801491756025524e-01, 1.2258446739609345e-01, 8.7356205785880797e-02, 5.7169633542064863e-02, 3.4349073289602634e-02, 1.8939956587000626e-02, 9.5799818951133077e-03, 4.4427288798279318e-03, 1.8879100806443562e-03, 7.3463960542667715e-04, 2.6158391341408045e-04, 8.5160665584721077e-05, 2.5326195751014174e-05, 6.8734922472265778e-06, 1.7005728326428347e-06, 3.8310233242483633e-07, 7.8484291703314789e-08, 1.4601515540917063e-08, 2.4632483182140787e-09, 3.7618946881237821e-10, 5.1919141781420298e-11, 6.4631097928536238e-12, 7.2418684802603713e-13, 7.2875563565483730e-14, 6.5702357143564891e-15, 5.2930247423722938e-16, 3.7993465086131341e-17, 2.4223988311307281e-18, 1.3672374402361970e-19, 6.8061278108013458e-21, 2.9761942889320718e-22, 1.1381700734483244e-23, 3.7881611827990218e-25, 1.0914439534101697e-26, 2.7061869712127610e-28, 5.7365178511704523e-30, 1.0320466636328443e-31, 1.5630006293499951e-33, 1.9743896190133811e-35, 2.0587364582129049e-37, 1.7511205172582050e-39, 1.1986003025152256e-41, 6.4989825715662458e-44, 2.7406328866050857e-46, 8.7956536234027020e-49, 2.0932606053442080e-51, 3.5794857851611975e-54, 4.2297673811987948e-57, 3.2876134769273718e-60, 1.5763666548556604e-63, 4.2771691981814217e-67, 5.8152759548633637e-71, 3.3015035960765624e-75, 5.8004986924644819e-80, 1.7821550800540237e-85, 2.2365648981246453e-92}, + {3.2301009543101099e-93, 2.7098206745663592e-86, 9.2107100141581600e-81, 5.4525421540759655e-76, 9.9634282798974572e-72, 7.5888934406190700e-68, 2.8926678180441972e-64, 6.2331956354059190e-61, 8.2793896913033925e-58, 7.2291385544928827e-55, 4.3597174343439006e-52, 1.8884218782951360e-49, 6.0637045694189279e-47, 1.4814159278355307e-44, 2.8142461042205111e-42, 4.2343947760097721e-40, 5.1264009327908215e-38, 5.0622696862483853e-36, 4.1261954854591773e-34, 2.8051622162519962e-32, 1.6053724151348174e-30, 7.7976718238941548e-29, 3.2382364130273421e-27, 1.1573493767550765e-25, 3.5810407352214098e-24, 9.6443805701337253e-23, 2.2718330011553644e-21, 4.7015694865721316e-20, 8.5828869554158906e-19, 1.3872615165495405e-17, 1.9920232649990639e-16, 2.5491665563098012e-15, 2.9155331883629833e-14, 2.9881593623355600e-13, 2.7511620846328702e-12, 2.2805223736764051e-11, 1.7055424914056455e-10, 1.1530186653890739e-09, 7.0587498965529012e-09, 3.9196764143747362e-08, 1.9772532357280954e-07, 9.0734367403526114e-07, 3.7926166158590859e-06, 1.4457032475544561e-05, 5.0311336988073622e-05, 1.6000468687262702e-04, 4.6545282707817341e-04, 1.2395239105761761e-03, 3.0241014828653783e-03, 6.7638384706753211e-03, 1.3877372041544333e-02, 2.6131824932046500e-02, 4.5183798113816530e-02, 7.1766149805041285e-02, 1.0474325576824089e-01, 1.4051423956652490e-01, 1.7329818332155345e-01, 1.9652247660560301e-01, 2.0493398052053613e-01, 1.9652247660560301e-01, 1.7329818332155345e-01, 1.4051423956652490e-01, 1.0474325576824089e-01, 7.1766149805041285e-02, 4.5183798113816530e-02, 2.6131824932046500e-02, 1.3877372041544333e-02, 6.7638384706753211e-03, 3.0241014828653783e-03, 1.2395239105761761e-03, 4.6545282707817341e-04, 1.6000468687262702e-04, 5.0311336988073622e-05, 1.4457032475544561e-05, 3.7926166158590859e-06, 9.0734367403526114e-07, 1.9772532357280954e-07, 3.9196764143747362e-08, 7.0587498965529012e-09, 1.1530186653890739e-09, 1.7055424914056455e-10, 2.2805223736764051e-11, 2.7511620846328702e-12, 2.9881593623355600e-13, 2.9155331883629833e-14, 2.5491665563098012e-15, 1.9920232649990639e-16, 1.3872615165495405e-17, 8.5828869554158906e-19, 4.7015694865721316e-20, 2.2718330011553644e-21, 9.6443805701337253e-23, 3.5810407352214098e-24, 1.1573493767550765e-25, 3.2382364130273421e-27, 7.7976718238941548e-29, 1.6053724151348174e-30, 2.8051622162519962e-32, 4.1261954854591773e-34, 5.0622696862483853e-36, 5.1264009327908215e-38, 4.2343947760097721e-40, 2.8142461042205111e-42, 1.4814159278355307e-44, 6.0637045694189279e-47, 1.8884218782951360e-49, 4.3597174343439006e-52, 7.2291385544928827e-55, 8.2793896913033925e-58, 6.2331956354059190e-61, 2.8926678180441972e-64, 7.5888934406190700e-68, 9.9634282798974572e-72, 5.4525421540759655e-76, 9.2107100141581600e-81, 2.7098206745663592e-86, 3.2301009543101099e-93}, + {4.6632605618348153e-94, 4.1175713624143213e-87, 1.4612038470881841e-81, 8.9943320432041730e-77, 1.7046189545614933e-72, 1.3442523656293476e-68, 5.2981258920312120e-65, 1.1793052736766146e-61, 1.6168482075284075e-58, 1.4562812961539782e-55, 9.0550269871980438e-53, 4.0423080380262144e-50, 1.3372947653240557e-47, 3.3652104040755819e-45, 6.5834566491742290e-43, 1.0199300069374435e-40, 1.2712364015219454e-38, 1.2922794919134986e-36, 1.0842626381128112e-34, 7.5875981466261195e-33, 4.4697458344428785e-31, 2.2348156961076159e-29, 9.5537375722030760e-28, 3.5151519348961093e-26, 1.1197954114046576e-24, 3.1052469143218520e-23, 7.5325222776132763e-22, 1.6054837533511592e-20, 3.0189715471734914e-19, 5.0270892648593941e-18, 7.4380949511123831e-17, 9.8097342377809155e-16, 1.1565317290963977e-14, 1.2221338000525176e-13, 1.1603996128858022e-12, 9.9222265232533288e-12, 7.6565621148965857e-11, 5.3422379271962827e-10, 3.3764133497574799e-09, 1.9362011885244885e-08, 1.0089574633621321e-07, 4.7845042712908339e-07, 2.0673284334051564e-06, 8.1491561908568428e-06, 2.9337744635072858e-05, 9.6558931405380603e-05, 2.9081250785794189e-04, 8.0215126322350460e-04, 2.0279429361286859e-03, 4.7023255147965815e-03, 1.0006845717689308e-02, 1.9554616052364186e-02, 3.5105886050128668e-02, 5.7925787803644498e-02, 8.7878107549790321e-02, 1.2261249660444425e-01, 1.5737520760258733e-01, 1.8584966291329158e-01, 2.0195836706954076e-01, 2.0195836706954076e-01, 1.8584966291329158e-01, 1.5737520760258733e-01, 1.2261249660444425e-01, 8.7878107549790321e-02, 5.7925787803644498e-02, 3.5105886050128668e-02, 1.9554616052364186e-02, 1.0006845717689308e-02, 4.7023255147965815e-03, 2.0279429361286859e-03, 8.0215126322350460e-04, 2.9081250785794189e-04, 9.6558931405380603e-05, 2.9337744635072858e-05, 8.1491561908568428e-06, 2.0673284334051564e-06, 4.7845042712908339e-07, 1.0089574633621321e-07, 1.9362011885244885e-08, 3.3764133497574799e-09, 5.3422379271962827e-10, 7.6565621148965857e-11, 9.9222265232533288e-12, 1.1603996128858022e-12, 1.2221338000525176e-13, 1.1565317290963977e-14, 9.8097342377809155e-16, 7.4380949511123831e-17, 5.0270892648593941e-18, 3.0189715471734914e-19, 1.6054837533511592e-20, 7.5325222776132763e-22, 3.1052469143218520e-23, 1.1197954114046576e-24, 3.5151519348961093e-26, 9.5537375722030760e-28, 2.2348156961076159e-29, 4.4697458344428785e-31, 7.5875981466261195e-33, 1.0842626381128112e-34, 1.2922794919134986e-36, 1.2712364015219454e-38, 1.0199300069374435e-40, 6.5834566491742290e-43, 3.3652104040755819e-45, 1.3372947653240557e-47, 4.0423080380262144e-50, 9.0550269871980438e-53, 1.4562812961539782e-55, 1.6168482075284075e-58, 1.1793052736766146e-61, 5.2981258920312120e-65, 1.3442523656293476e-68, 1.7046189545614933e-72, 8.9943320432041730e-77, 1.4612038470881841e-81, 4.1175713624143213e-87, 4.6632605618348153e-94}, + {6.7298368161176175e-95, 6.2524679295400819e-88, 2.3159244482213129e-82, 1.4819345628019795e-77, 2.9122929849292479e-73, 2.3772467547464570e-69, 9.6859162631794203e-66, 2.2265944526096699e-62, 3.1502482452041196e-59, 2.9262669926463904e-56, 1.8755830649756743e-53, 8.6273958082206037e-51, 2.9399528685004811e-48, 7.6185958106575033e-46, 1.5345315352659727e-43, 2.4472631035773749e-41, 3.1395792592468297e-39, 3.2847155364958309e-37, 2.8362637361915701e-35, 2.0425551530268673e-33, 1.2382461823632275e-31, 6.3712964630586884e-30, 2.8030942195831802e-28, 1.0614795301061955e-26, 3.4805041051243282e-25, 9.9351833121692472e-24, 2.4810981347002888e-22, 5.4448704650642035e-21, 1.0543376862850843e-19, 1.8081886383358570e-18, 2.7559344338025971e-17, 3.7447612695692442e-16, 4.5495653050067822e-15, 4.9552804559564594e-14, 4.8505588604403995e-13, 4.2769240959330674e-12, 3.4041116737305440e-11, 2.4505079134311513e-10, 1.5983528945271918e-09, 9.4619152361816427e-09, 5.0915075227638090e-08, 2.4939923966935258e-07, 1.1135208095853982e-06, 4.5371664146194656e-06, 1.6890448115948282e-05, 5.7506280394736890e-05, 1.7923272339346707e-04, 5.1182575908404512e-04, 1.3402041554580024e-03, 3.2201249358166924e-03, 7.1040413328426078e-03, 1.4398510037728523e-02, 2.6824309528990144e-02, 4.5954734368354178e-02, 7.2424817070363218e-02, 1.0503603365193327e-01, 1.4021530912606431e-01, 1.7232400830089628e-01, 1.9500749227238295e-01, 2.0321184623044758e-01, 1.9500749227238295e-01, 1.7232400830089628e-01, 1.4021530912606431e-01, 1.0503603365193327e-01, 7.2424817070363218e-02, 4.5954734368354178e-02, 2.6824309528990144e-02, 1.4398510037728523e-02, 7.1040413328426078e-03, 3.2201249358166924e-03, 1.3402041554580024e-03, 5.1182575908404512e-04, 1.7923272339346707e-04, 5.7506280394736890e-05, 1.6890448115948282e-05, 4.5371664146194656e-06, 1.1135208095853982e-06, 2.4939923966935258e-07, 5.0915075227638090e-08, 9.4619152361816427e-09, 1.5983528945271918e-09, 2.4505079134311513e-10, 3.4041116737305440e-11, 4.2769240959330674e-12, 4.8505588604403995e-13, 4.9552804559564594e-14, 4.5495653050067822e-15, 3.7447612695692442e-16, 2.7559344338025971e-17, 1.8081886383358570e-18, 1.0543376862850843e-19, 5.4448704650642035e-21, 2.4810981347002888e-22, 9.9351833121692472e-24, 3.4805041051243282e-25, 1.0614795301061955e-26, 2.8030942195831802e-28, 6.3712964630586884e-30, 1.2382461823632275e-31, 2.0425551530268673e-33, 2.8362637361915701e-35, 3.2847155364958309e-37, 3.1395792592468297e-39, 2.4472631035773749e-41, 1.5345315352659727e-43, 7.6185958106575033e-46, 2.9399528685004811e-48, 8.6273958082206037e-51, 1.8755830649756743e-53, 2.9262669926463904e-56, 3.1502482452041196e-59, 2.2265944526096699e-62, 9.6859162631794203e-66, 2.3772467547464570e-69, 2.9122929849292479e-73, 1.4819345628019795e-77, 2.3159244482213129e-82, 6.2524679295400819e-88, 6.7298368161176175e-95}, + {9.7087403173561320e-96, 9.4880223969421335e-89, 3.6672428899258345e-83, 2.4388595277598848e-78, 4.9686800178709975e-74, 4.1972934212808472e-70, 1.7675264508544507e-66, 4.1953576796012743e-63, 6.1240687137526128e-60, 5.8655575443381544e-57, 3.8745058915294428e-54, 1.8359883902918249e-51, 6.4431660432386704e-49, 1.7190498209667764e-46, 3.5641227393846403e-44, 5.8499085615955162e-42, 7.7228330960795927e-40, 8.3138040908205878e-38, 7.3861592386371398e-36, 5.4726905931533611e-34, 3.4133817510443908e-32, 1.8070157219004075e-30, 8.1797979499699255e-29, 3.1872062136052619e-27, 1.0753877987999934e-25, 3.1590858369572161e-24, 8.1196497360506958e-23, 1.8341746417696775e-21, 3.6563781425498920e-20, 6.4565140315879466e-19, 1.0133911369582986e-17, 1.4182835695860085e-16, 1.7750978597330652e-15, 1.9921528797000957e-14, 2.0097524571107850e-13, 1.8267486127018911e-12, 1.4991784686824891e-11, 1.1130625000696823e-10, 7.4897520452156729e-10, 4.5753933756254367e-09, 2.5414386492665182e-08, 1.2854272339650551e-07, 5.9280419576037410e-07, 2.4957777427586521e-06, 9.6033945516455336e-06, 3.3808196410240332e-05, 1.0899702609675318e-04, 3.2209543490435076e-04, 8.7313245576434379e-04, 2.1727898312954579e-03, 4.9668732525919509e-03, 1.0435962135902662e-02, 2.0164796980741757e-02, 3.5848215647758121e-02, 5.8657999750043426e-02, 8.8373210437321048e-02, 1.2262242405763166e-01, 1.5673726302678062e-01, 1.8458665957131964e-01, 2.0030984626187961e-01, 2.0030984626187961e-01, 1.8458665957131964e-01, 1.5673726302678062e-01, 1.2262242405763166e-01, 8.8373210437321048e-02, 5.8657999750043426e-02, 3.5848215647758121e-02, 2.0164796980741757e-02, 1.0435962135902662e-02, 4.9668732525919509e-03, 2.1727898312954579e-03, 8.7313245576434379e-04, 3.2209543490435076e-04, 1.0899702609675318e-04, 3.3808196410240332e-05, 9.6033945516455336e-06, 2.4957777427586521e-06, 5.9280419576037410e-07, 1.2854272339650551e-07, 2.5414386492665182e-08, 4.5753933756254367e-09, 7.4897520452156729e-10, 1.1130625000696823e-10, 1.4991784686824891e-11, 1.8267486127018911e-12, 2.0097524571107850e-13, 1.9921528797000957e-14, 1.7750978597330652e-15, 1.4182835695860085e-16, 1.0133911369582986e-17, 6.4565140315879466e-19, 3.6563781425498920e-20, 1.8341746417696775e-21, 8.1196497360506958e-23, 3.1590858369572161e-24, 1.0753877987999934e-25, 3.1872062136052619e-27, 8.1797979499699255e-29, 1.8070157219004075e-30, 3.4133817510443908e-32, 5.4726905931533611e-34, 7.3861592386371398e-36, 8.3138040908205878e-38, 7.7228330960795927e-40, 5.8499085615955162e-42, 3.5641227393846403e-44, 1.7190498209667764e-46, 6.4431660432386704e-49, 1.8359883902918249e-51, 3.8745058915294428e-54, 5.8655575443381544e-57, 6.1240687137526128e-60, 4.1953576796012743e-63, 1.7675264508544507e-66, 4.1972934212808472e-70, 4.9686800178709975e-74, 2.4388595277598848e-78, 3.6672428899258345e-83, 9.4880223969421335e-89, 9.7087403173561320e-96}, + {1.4001253071178789e-96, 1.4388577548096490e-89, 5.8017947700800046e-84, 4.0091236159545663e-79, 8.4655265882771739e-75, 7.3990554223004025e-71, 3.2196574821489126e-67, 7.8890210982671253e-64, 1.1878725902550843e-60, 1.1728639625604033e-57, 7.9826611475407281e-55, 3.8960048884898755e-52, 1.4077485752140258e-49, 3.8661220025482209e-47, 8.2491446524855651e-45, 1.3931625443392332e-42, 1.8922123418053773e-40, 2.0955223902923607e-38, 1.9150597358365338e-36, 1.4595508732329443e-34, 9.3637976764322119e-33, 5.0989613303209105e-31, 2.3742569610821154e-29, 9.5165969692199733e-28, 3.3033284608828233e-26, 9.9838789745986388e-25, 2.6403982498871405e-23, 6.1378568842560367e-22, 1.2592940912286238e-20, 2.2889503956241953e-19, 3.6986721862085567e-18, 5.3301125275267336e-17, 6.8703687643915730e-16, 7.9423755813393362e-15, 8.2552749332412685e-14, 7.7326044861505372e-13, 6.5412509847214547e-12, 5.0072069799282932e-11, 3.4747667141215967e-10, 2.1897184637878725e-09, 1.2550651872012550e-08, 6.5522732997355584e-08, 3.1199715417437437e-07, 1.3566980827714974e-06, 5.3937313862223019e-06, 1.9625894008346668e-05, 6.5422509840297027e-05, 1.9997290405207970e-04, 5.6094024606844449e-04, 1.4450639870005968e-03, 3.4211784137958604e-03, 7.4481168960531027e-03, 1.4918844448036933e-02, 2.7507458506267436e-02, 4.6706206412519734e-02, 7.3057392793912337e-02, 1.0530541916565815e-01, 1.3990756676688021e-01, 1.7136352815479530e-01, 1.9352684051681762e-01, 2.0153240948474130e-01, 1.9352684051681762e-01, 1.7136352815479530e-01, 1.3990756676688021e-01, 1.0530541916565815e-01, 7.3057392793912337e-02, 4.6706206412519734e-02, 2.7507458506267436e-02, 1.4918844448036933e-02, 7.4481168960531027e-03, 3.4211784137958604e-03, 1.4450639870005968e-03, 5.6094024606844449e-04, 1.9997290405207970e-04, 6.5422509840297027e-05, 1.9625894008346668e-05, 5.3937313862223019e-06, 1.3566980827714974e-06, 3.1199715417437437e-07, 6.5522732997355584e-08, 1.2550651872012550e-08, 2.1897184637878725e-09, 3.4747667141215967e-10, 5.0072069799282932e-11, 6.5412509847214547e-12, 7.7326044861505372e-13, 8.2552749332412685e-14, 7.9423755813393362e-15, 6.8703687643915730e-16, 5.3301125275267336e-17, 3.6986721862085567e-18, 2.2889503956241953e-19, 1.2592940912286238e-20, 6.1378568842560367e-22, 2.6403982498871405e-23, 9.9838789745986388e-25, 3.3033284608828233e-26, 9.5165969692199733e-28, 2.3742569610821154e-29, 5.0989613303209105e-31, 9.3637976764322119e-33, 1.4595508732329443e-34, 1.9150597358365338e-36, 2.0955223902923607e-38, 1.8922123418053773e-40, 1.3931625443392332e-42, 8.2491446524855651e-45, 3.8661220025482209e-47, 1.4077485752140258e-49, 3.8960048884898755e-52, 7.9826611475407281e-55, 1.1728639625604033e-57, 1.1878725902550843e-60, 7.8890210982671253e-64, 3.2196574821489126e-67, 7.3990554223004025e-71, 8.4655265882771739e-75, 4.0091236159545663e-79, 5.8017947700800046e-84, 1.4388577548096490e-89, 1.4001253071178789e-96}, + {2.0184534275095049e-97, 2.1806296158265287e-90, 9.1706055028522197e-85, 6.5830036453656527e-80, 1.4403978976524620e-75, 1.3022823162971665e-71, 5.8544142858486073e-68, 1.4805274033207088e-64, 2.2990511219174665e-61, 2.3396177274687451e-58, 1.6403928051497794e-55, 8.2441788250067191e-53, 3.0664667336421114e-50, 8.6667923231989335e-48, 1.9026918231732264e-45, 3.3057067086043009e-43, 4.6182598989607685e-41, 5.2602254003426042e-39, 4.9438860107310490e-37, 3.8749094400485918e-35, 2.5564844139368277e-33, 1.4316070974387265e-31, 6.8553849798952103e-30, 2.8259664729965746e-28, 1.0088930738432750e-26, 3.1364243262134751e-25, 8.5327296120897214e-24, 2.0406372113926846e-22, 4.3078486936244584e-21, 8.0577481866273284e-20, 1.3400866628758495e-18, 1.9879461273563199e-17, 2.6381930823541892e-16, 3.1406382865933653e-15, 3.3622360761898003e-14, 3.2444814316722348e-13, 2.8281489919728500e-12, 2.2313290142958860e-11, 1.5963585528134907e-10, 1.0373981456665397e-09, 6.1333415530709063e-09, 3.3038743448338228e-08, 1.6237364967913452e-07, 7.2898765543366947e-07, 2.9932498983591025e-06, 1.1252541495603299e-05, 3.8767965827716168e-05, 1.2251950121646584e-04, 3.5547512496610876e-04, 9.4757899341760905e-04, 2.3223308982827312e-03, 5.2360833859067743e-03, 1.0866914248342787e-02, 2.0770153886127483e-02, 3.6576106509803016e-02, 5.9366942312670930e-02, 8.8842708636295842e-02, 1.2261541377174207e-01, 1.5610147984994696e-01, 1.8334823578007414e-01, 1.9870103704081624e-01, 1.9870103704081624e-01, 1.8334823578007414e-01, 1.5610147984994696e-01, 1.2261541377174207e-01, 8.8842708636295842e-02, 5.9366942312670930e-02, 3.6576106509803016e-02, 2.0770153886127483e-02, 1.0866914248342787e-02, 5.2360833859067743e-03, 2.3223308982827312e-03, 9.4757899341760905e-04, 3.5547512496610876e-04, 1.2251950121646584e-04, 3.8767965827716168e-05, 1.1252541495603299e-05, 2.9932498983591025e-06, 7.2898765543366947e-07, 1.6237364967913452e-07, 3.3038743448338228e-08, 6.1333415530709063e-09, 1.0373981456665397e-09, 1.5963585528134907e-10, 2.2313290142958860e-11, 2.8281489919728500e-12, 3.2444814316722348e-13, 3.3622360761898003e-14, 3.1406382865933653e-15, 2.6381930823541892e-16, 1.9879461273563199e-17, 1.3400866628758495e-18, 8.0577481866273284e-20, 4.3078486936244584e-21, 2.0406372113926846e-22, 8.5327296120897214e-24, 3.1364243262134751e-25, 1.0088930738432750e-26, 2.8259664729965746e-28, 6.8553849798952103e-30, 1.4316070974387265e-31, 2.5564844139368277e-33, 3.8749094400485918e-35, 4.9438860107310490e-37, 5.2602254003426042e-39, 4.6182598989607685e-41, 3.3057067086043009e-43, 1.9026918231732264e-45, 8.6667923231989335e-48, 3.0664667336421114e-50, 8.2441788250067191e-53, 1.6403928051497794e-55, 2.3396177274687451e-58, 2.2990511219174665e-61, 1.4805274033207088e-64, 5.8544142858486073e-68, 1.3022823162971665e-71, 1.4403978976524620e-75, 6.5830036453656527e-80, 9.1706055028522197e-85, 2.1806296158265287e-90, 2.0184534275095049e-97}, + {2.9088440757674062e-98, 3.3027195553941757e-91, 1.4482784276490109e-85, 1.0797361898132115e-80, 2.4475687753038470e-76, 2.2885780042663531e-72, 1.0626701542492299e-68, 2.7730751722659017e-65, 4.4400764524986828e-62, 4.6560392499732150e-59, 3.3622797072552750e-56, 1.7396913258105826e-53, 6.6597646076210362e-51, 1.9366833085713306e-48, 4.3737554297590874e-46, 7.8155861441480535e-44, 1.1228680356492188e-41, 1.3151165218678305e-39, 1.2708875196505519e-37, 1.0241410150378061e-35, 6.9469156975836022e-34, 3.9996687161846431e-32, 1.9692128985290527e-30, 8.3465290951830949e-29, 3.0639885163656867e-27, 9.7951708742326283e-26, 2.7405597239380626e-24, 6.7411887298015296e-23, 1.4638683297363268e-21, 2.8169790254203712e-20, 4.8205257099851608e-19, 7.3591325007878809e-18, 1.0052255425278666e-16, 1.2319403285686423e-15, 1.3580008734485746e-14, 1.3496086984992707e-13, 1.2118575324056077e-12, 9.8514672314148016e-12, 7.2637761188053839e-11, 4.8661361388782973e-10, 2.9666085963352118e-09, 1.6482913905846427e-08, 8.3579939555984911e-08, 3.8727287415554441e-07, 1.6416874675897103e-06, 6.3737479499140128e-06, 2.2686436750985634e-05, 7.4097922186640899e-05, 2.2227085873416057e-04, 6.1281987967776825e-04, 1.5540467884754450e-03, 3.6270593070595858e-03, 7.7957038787030220e-03, 1.5437973179493971e-02, 2.8181096910943754e-02, 4.7438564768728979e-02, 7.3664835869183778e-02, 1.0555264545810959e-01, 1.3959184263252383e-01, 1.7041655690534233e-01, 1.9207925104318502e-01, 1.9989393461088162e-01, 1.9207925104318502e-01, 1.7041655690534233e-01, 1.3959184263252383e-01, 1.0555264545810959e-01, 7.3664835869183778e-02, 4.7438564768728979e-02, 2.8181096910943754e-02, 1.5437973179493971e-02, 7.7957038787030220e-03, 3.6270593070595858e-03, 1.5540467884754450e-03, 6.1281987967776825e-04, 2.2227085873416057e-04, 7.4097922186640899e-05, 2.2686436750985634e-05, 6.3737479499140128e-06, 1.6416874675897103e-06, 3.8727287415554441e-07, 8.3579939555984911e-08, 1.6482913905846427e-08, 2.9666085963352118e-09, 4.8661361388782973e-10, 7.2637761188053839e-11, 9.8514672314148016e-12, 1.2118575324056077e-12, 1.3496086984992707e-13, 1.3580008734485746e-14, 1.2319403285686423e-15, 1.0052255425278666e-16, 7.3591325007878809e-18, 4.8205257099851608e-19, 2.8169790254203712e-20, 1.4638683297363268e-21, 6.7411887298015296e-23, 2.7405597239380626e-24, 9.7951708742326283e-26, 3.0639885163656867e-27, 8.3465290951830949e-29, 1.9692128985290527e-30, 3.9996687161846431e-32, 6.9469156975836022e-34, 1.0241410150378061e-35, 1.2708875196505519e-37, 1.3151165218678305e-39, 1.1228680356492188e-41, 7.8155861441480535e-44, 4.3737554297590874e-46, 1.9366833085713306e-48, 6.6597646076210362e-51, 1.7396913258105826e-53, 3.3622797072552750e-56, 4.6560392499732150e-59, 4.4400764524986828e-62, 2.7730751722659017e-65, 1.0626701542492299e-68, 2.2885780042663531e-72, 2.4475687753038470e-76, 1.0797361898132115e-80, 1.4482784276490109e-85, 3.3027195553941757e-91, 2.9088440757674062e-98}, + {4.1905794490628812e-99, 4.9990906972957580e-92, 2.2852295477811565e-86, 1.7690369566797577e-81, 4.1535499466158161e-77, 4.0157584892449402e-73, 1.9255984704437394e-69, 5.1840723409278860e-66, 8.5567547361303599e-63, 9.2443848020406234e-60, 6.8742017262988808e-57, 3.6611032011247543e-54, 1.4421371050636836e-51, 4.3141707603430363e-49, 1.0020507711410342e-46, 1.8412712525866596e-44, 2.7198617815524323e-42, 3.2749113002444449e-40, 3.2533264664077919e-38, 2.6949141835666013e-36, 1.8790207698162015e-34, 1.1120314056802636e-32, 5.6279071396682005e-31, 2.4520940513432773e-29, 9.2537661461189014e-28, 3.0414019572106789e-26, 8.7492009712123219e-25, 2.2129732702532020e-23, 4.9419868423536690e-22, 9.7813379414413797e-21, 1.7218091698469169e-19, 2.7043296085128987e-18, 3.8011128040478799e-17, 4.7943347392243567e-16, 5.4401721259012553e-15, 5.5664982903187763e-14, 5.1473099468312146e-13, 4.3100503800704298e-12, 3.2741601230785952e-11, 2.2604055819337785e-10, 1.4204990214913607e-09, 8.1379035349171669e-09, 4.2560154044109738e-08, 2.0345626953177357e-07, 8.9008863258739004e-07, 3.5675339063854564e-06, 1.3113467580430861e-05, 4.4247522456022853e-05, 1.3716931938884588e-04, 3.9098949747131122e-04, 1.0254795244170039e-03, 2.4764405325003970e-03, 5.5096709995779728e-03, 1.1299305506959472e-02, 2.1370374426895520e-02, 3.7289628484137964e-02, 6.0053278089003327e-02, 8.9287739344200062e-02, 1.2259255262751995e-01, 1.5546821084992313e-01, 1.8213364120711689e-01, 1.9713037059257607e-01, 1.9713037059257607e-01, 1.8213364120711689e-01, 1.5546821084992313e-01, 1.2259255262751995e-01, 8.9287739344200062e-02, 6.0053278089003327e-02, 3.7289628484137964e-02, 2.1370374426895520e-02, 1.1299305506959472e-02, 5.5096709995779728e-03, 2.4764405325003970e-03, 1.0254795244170039e-03, 3.9098949747131122e-04, 1.3716931938884588e-04, 4.4247522456022853e-05, 1.3113467580430861e-05, 3.5675339063854564e-06, 8.9008863258739004e-07, 2.0345626953177357e-07, 4.2560154044109738e-08, 8.1379035349171669e-09, 1.4204990214913607e-09, 2.2604055819337785e-10, 3.2741601230785952e-11, 4.3100503800704298e-12, 5.1473099468312146e-13, 5.5664982903187763e-14, 5.4401721259012553e-15, 4.7943347392243567e-16, 3.8011128040478799e-17, 2.7043296085128987e-18, 1.7218091698469169e-19, 9.7813379414413797e-21, 4.9419868423536690e-22, 2.2129732702532020e-23, 8.7492009712123219e-25, 3.0414019572106789e-26, 9.2537661461189014e-28, 2.4520940513432773e-29, 5.6279071396682005e-31, 1.1120314056802636e-32, 1.8790207698162015e-34, 2.6949141835666013e-36, 3.2533264664077919e-38, 3.2749113002444449e-40, 2.7198617815524323e-42, 1.8412712525866596e-44, 1.0020507711410342e-46, 4.3141707603430363e-49, 1.4421371050636836e-51, 3.6611032011247543e-54, 6.8742017262988808e-57, 9.2443848020406234e-60, 8.5567547361303599e-63, 5.1840723409278860e-66, 1.9255984704437394e-69, 4.0157584892449402e-73, 4.1535499466158161e-77, 1.7690369566797577e-81, 2.2852295477811565e-86, 4.9990906972957580e-92, 4.1905794490628812e-99}, + {6.0350604964534262e-100, 7.5621198682031623e-93, 3.6027698446759891e-87, 2.8952659291406100e-82, 7.0395367135995835e-78, 7.0359072121742493e-74, 3.4833403833073089e-70, 9.6729013253984892e-67, 1.6455761362144333e-63, 1.8312341591411876e-60, 1.4019398864694188e-57, 7.6839475145600301e-55, 3.1138694261390015e-52, 9.5806542034971832e-50, 2.2882121049633724e-47, 4.3227155768633621e-45, 6.5638401618338331e-43, 8.1233879274180601e-41, 8.2938969771250512e-39, 7.0606944403026099e-37, 5.0593403396440372e-35, 3.0770662798790086e-33, 1.6004068212453668e-31, 7.1663558200524862e-30, 2.7795790004930404e-28, 9.3899224442264679e-27, 2.7766379169834465e-25, 7.2198960174204195e-24, 1.6577060031062816e-22, 3.3737146353721905e-21, 6.1074208727145320e-20, 9.8664119741289685e-19, 1.4266141735959953e-17, 1.8513770722928222e-16, 2.1618705462400890e-15, 2.2768505441090677e-14, 2.1674951892336612e-13, 1.8688765345567561e-12, 1.4622404081860438e-11, 1.0399946851470756e-10, 6.7347582712586187e-10, 3.9769084715886220e-09, 2.1444167115213114e-08, 1.0572466663977363e-07, 4.7716606625319424e-07, 1.9736622489528508e-06, 7.4891717673847164e-06, 2.6095502713919602e-05, 8.3569751965942746e-05, 2.4616923611611111e-04, 6.6748228082773623e-04, 1.6670890148279265e-03, 3.8375633568742918e-03, 8.1464528080591927e-03, 1.5955521786480558e-02, 2.8845081137418717e-02, 4.8152169340609514e-02, 7.4248071076568556e-02, 1.0577887521500248e-01, 1.3926890249425167e-01, 1.6948290095730328e-01, 1.9066351798670744e-01, 1.9829478313399460e-01, 1.9066351798670744e-01, 1.6948290095730328e-01, 1.3926890249425167e-01, 1.0577887521500248e-01, 7.4248071076568556e-02, 4.8152169340609514e-02, 2.8845081137418717e-02, 1.5955521786480558e-02, 8.1464528080591927e-03, 3.8375633568742918e-03, 1.6670890148279265e-03, 6.6748228082773623e-04, 2.4616923611611111e-04, 8.3569751965942746e-05, 2.6095502713919602e-05, 7.4891717673847164e-06, 1.9736622489528508e-06, 4.7716606625319424e-07, 1.0572466663977363e-07, 2.1444167115213114e-08, 3.9769084715886220e-09, 6.7347582712586187e-10, 1.0399946851470756e-10, 1.4622404081860438e-11, 1.8688765345567561e-12, 2.1674951892336612e-13, 2.2768505441090677e-14, 2.1618705462400890e-15, 1.8513770722928222e-16, 1.4266141735959953e-17, 9.8664119741289685e-19, 6.1074208727145320e-20, 3.3737146353721905e-21, 1.6577060031062816e-22, 7.2198960174204195e-24, 2.7766379169834465e-25, 9.3899224442264679e-27, 2.7795790004930404e-28, 7.1663558200524862e-30, 1.6004068212453668e-31, 3.0770662798790086e-33, 5.0593403396440372e-35, 7.0606944403026099e-37, 8.2938969771250512e-39, 8.1233879274180601e-41, 6.5638401618338331e-43, 4.3227155768633621e-45, 2.2882121049633724e-47, 9.5806542034971832e-50, 3.1138694261390015e-52, 7.6839475145600301e-55, 1.4019398864694188e-57, 1.8312341591411876e-60, 1.6455761362144333e-63, 9.6729013253984892e-67, 3.4833403833073089e-70, 7.0359072121742493e-74, 7.0395367135995835e-78, 2.8952659291406100e-82, 3.6027698446759891e-87, 7.5621198682031623e-93, 6.0350604964534262e-100}, + {8.6885048841104336e-101, 1.1432282229672125e-93, 5.6751482819801390e-88, 4.7334609039691596e-83, 1.1915620124280458e-78, 1.2309273526337388e-74, 6.2907076772692688e-71, 1.8014846076367508e-67, 3.1581319803836728e-64, 3.6193344722347900e-61, 2.8521414298372380e-58, 1.6084468211903416e-55, 6.7043872367938317e-53, 2.1211541634033625e-50, 5.2082971293259102e-48, 1.0113496653683935e-45, 1.5782902465389378e-43, 2.0072591434893221e-41, 2.1058526230258254e-39, 1.8420302384806772e-37, 1.3561579038335388e-35, 8.4745466577882083e-34, 4.5287460314884707e-32, 2.0836578377129600e-30, 8.3043823092881025e-29, 2.8828182366037129e-27, 8.7606149843747518e-26, 2.3412386562212859e-24, 5.5254399484537480e-23, 1.1560142775887639e-21, 2.1516151218938123e-20, 3.5742061956149856e-19, 5.3150514071326065e-18, 7.0949360015714532e-17, 8.5234045323955501e-16, 9.2369780981720531e-15, 9.0500846874230352e-14, 8.0327883964150772e-13, 6.4713186612400961e-12, 4.7401870432354588e-11, 3.1621598261836951e-10, 1.9240529197354846e-09, 1.0693195796935537e-08, 5.4353072977389075e-08, 2.5298490233788676e-07, 1.0794646043238905e-06, 4.2268677400739964e-06, 1.5203524203072556e-05, 5.0277271260002348e-05, 1.5298771765756425e-04, 4.2867197747952282e-04, 1.1068159448702048e-03, 2.6349882348356921e-03, 5.7873557283189625e-03, 1.1732759367031630e-02, 2.1965177289949588e-02, 3.7988873885061170e-02, 6.0717658137057637e-02, 8.9709385493087268e-02, 1.2255485603934885e-01, 1.5483776980551858e-01, 1.8094215487742904e-01, 1.9559636350108756e-01, 1.9559636350108756e-01, 1.8094215487742904e-01, 1.5483776980551858e-01, 1.2255485603934885e-01, 8.9709385493087268e-02, 6.0717658137057637e-02, 3.7988873885061170e-02, 2.1965177289949588e-02, 1.1732759367031630e-02, 5.7873557283189625e-03, 2.6349882348356921e-03, 1.1068159448702048e-03, 4.2867197747952282e-04, 1.5298771765756425e-04, 5.0277271260002348e-05, 1.5203524203072556e-05, 4.2268677400739964e-06, 1.0794646043238905e-06, 2.5298490233788676e-07, 5.4353072977389075e-08, 1.0693195796935537e-08, 1.9240529197354846e-09, 3.1621598261836951e-10, 4.7401870432354588e-11, 6.4713186612400961e-12, 8.0327883964150772e-13, 9.0500846874230352e-14, 9.2369780981720531e-15, 8.5234045323955501e-16, 7.0949360015714532e-17, 5.3150514071326065e-18, 3.5742061956149856e-19, 2.1516151218938123e-20, 1.1560142775887639e-21, 5.5254399484537480e-23, 2.3412386562212859e-24, 8.7606149843747518e-26, 2.8828182366037129e-27, 8.3043823092881025e-29, 2.0836578377129600e-30, 4.5287460314884707e-32, 8.4745466577882083e-34, 1.3561579038335388e-35, 1.8420302384806772e-37, 2.1058526230258254e-39, 2.0072591434893221e-41, 1.5782902465389378e-43, 1.0113496653683935e-45, 5.2082971293259102e-48, 2.1211541634033625e-50, 6.7043872367938317e-53, 1.6084468211903416e-55, 2.8521414298372380e-58, 3.6193344722347900e-61, 3.1581319803836728e-64, 1.8014846076367508e-67, 6.2907076772692688e-71, 1.2309273526337388e-74, 1.1915620124280458e-78, 4.7334609039691596e-83, 5.6751482819801390e-88, 1.1432282229672125e-93, 8.6885048841104336e-101}, + {1.2504497509175530e-101, 1.7272798059471284e-94, 8.9321681572258524e-89, 7.7306185241136030e-84, 2.0143957652711162e-79, 2.1503714733677984e-75, 1.1341924208630308e-71, 3.3489139011900278e-68, 6.0486548964206330e-65, 7.1375092946576251e-62, 5.7884563375067011e-59, 3.3581166223962448e-56, 1.4394641949298623e-53, 4.6821808383361703e-51, 1.1817054440721172e-48, 2.3581659156082481e-46, 3.7814427940915093e-44, 4.9411031115925398e-42, 5.3255303775590573e-40, 4.7854390680281889e-38, 3.6191883446065631e-36, 2.3232083386416384e-34, 1.2753331411048401e-32, 6.0277753850946330e-31, 2.4679773241853991e-29, 8.8019567691972675e-28, 2.7482489212126092e-26, 7.5468218903320873e-25, 1.8303134636337642e-23, 3.9355990860983814e-22, 7.5293161638815711e-21, 1.2857997786762843e-19, 1.9659326888507207e-18, 2.6986511907298130e-17, 3.3344414303302576e-16, 3.7173303125266623e-15, 3.7473954472956373e-14, 3.4230094493503872e-13, 2.8385303725081926e-12, 2.1406920290521382e-11, 1.4706331273477511e-10, 9.2173940967721533e-10, 5.2781663937137130e-09, 2.7650497045037171e-08, 1.3267855842580783e-07, 5.8380944276295039e-07, 2.3581561724849069e-06, 8.7524468034552877e-06, 2.9876790536001972e-05, 9.3874435720364848e-05, 2.7170762628015821e-04, 7.2493929742724068e-04, 1.7841208326818967e-03, 4.0524855186172149e-03, 8.5000263041808636e-03, 1.6471142241660967e-02, 2.9499296248305443e-02, 4.8847387114452009e-02, 7.4807989768816377e-02, 1.0598520508123921e-01, 1.3893945309094766e-01, 1.6856236074260383e-01, 1.8927849580179334e-01, 1.9673340688884505e-01, 1.8927849580179334e-01, 1.6856236074260383e-01, 1.3893945309094766e-01, 1.0598520508123921e-01, 7.4807989768816377e-02, 4.8847387114452009e-02, 2.9499296248305443e-02, 1.6471142241660967e-02, 8.5000263041808636e-03, 4.0524855186172149e-03, 1.7841208326818967e-03, 7.2493929742724068e-04, 2.7170762628015821e-04, 9.3874435720364848e-05, 2.9876790536001972e-05, 8.7524468034552877e-06, 2.3581561724849069e-06, 5.8380944276295039e-07, 1.3267855842580783e-07, 2.7650497045037171e-08, 5.2781663937137130e-09, 9.2173940967721533e-10, 1.4706331273477511e-10, 2.1406920290521382e-11, 2.8385303725081926e-12, 3.4230094493503872e-13, 3.7473954472956373e-14, 3.7173303125266623e-15, 3.3344414303302576e-16, 2.6986511907298130e-17, 1.9659326888507207e-18, 1.2857997786762843e-19, 7.5293161638815711e-21, 3.9355990860983814e-22, 1.8303134636337642e-23, 7.5468218903320873e-25, 2.7482489212126092e-26, 8.8019567691972675e-28, 2.4679773241853991e-29, 6.0277753850946330e-31, 1.2753331411048401e-32, 2.3232083386416384e-34, 3.6191883446065631e-36, 4.7854390680281889e-38, 5.3255303775590573e-40, 4.9411031115925398e-42, 3.7814427940915093e-44, 2.3581659156082481e-46, 1.1817054440721172e-48, 4.6821808383361703e-51, 1.4394641949298623e-53, 3.3581166223962448e-56, 5.7884563375067011e-59, 7.1375092946576251e-62, 6.0486548964206330e-65, 3.3489139011900278e-68, 1.1341924208630308e-71, 2.1503714733677984e-75, 2.0143957652711162e-79, 7.7306185241136030e-84, 8.9321681572258524e-89, 1.7272798059471284e-94, 1.2504497509175530e-101}, + {1.7990659801093241e-102, 2.6081724024084728e-95, 1.4046897713151180e-89, 1.2612494833385409e-84, 3.4012300869368197e-80, 3.7512158688048432e-76, 2.0415857972441075e-72, 6.2142441618306433e-69, 1.1561551640964042e-65, 1.4044672577405165e-62, 1.1719785012130235e-59, 6.9930729240520693e-57, 3.0820773833392742e-54, 1.0304862520557101e-51, 2.6727437517360924e-49, 5.4802170289787664e-47, 9.0280401387865924e-45, 1.2117795341306277e-42, 1.3414974817643660e-40, 1.2380855579763670e-38, 9.6167080679676503e-37, 6.3399135263665769e-35, 3.5743788958794533e-33, 1.7351030202821157e-31, 7.2965450067684075e-30, 2.6729236200580738e-28, 8.5728304837693986e-27, 2.4184034596476935e-25, 6.0259840320064904e-24, 1.3313678590335932e-22, 2.6174575839348305e-21, 4.5940076773297253e-20, 7.2201073169282769e-19, 1.0189332304232922e-17, 1.2945481593393717e-16, 1.4842238375138792e-15, 1.5390497303535517e-14, 1.4463473211904274e-13, 1.2342144866005691e-12, 9.5803165087358731e-12, 6.7757804877745394e-11, 4.3731866598484108e-10, 2.5793972294264184e-09, 1.3921907152935201e-08, 6.8845811221543303e-08, 3.1228729861789030e-07, 1.3007470032382014e-06, 4.9799245325909927e-06, 1.7540485848093888e-05, 5.6887437600402582e-05, 1.7001408826280900e-04, 4.6855153780841227e-04, 1.1915638144571682e-03, 2.7978394016057863e-03, 6.0688624069258814e-03, 1.2166918864469335e-02, 2.2554310167824408e-02, 3.8673954810636818e-02, 6.1360721004490068e-02, 9.0108678376448870e-02, 1.2250327316413555e-01, 1.5421043529835440e-01, 1.7977308390779931e-01, 1.9409761186408808e-01, 1.9409761186408808e-01, 1.7977308390779931e-01, 1.5421043529835440e-01, 1.2250327316413555e-01, 9.0108678376448870e-02, 6.1360721004490068e-02, 3.8673954810636818e-02, 2.2554310167824408e-02, 1.2166918864469335e-02, 6.0688624069258814e-03, 2.7978394016057863e-03, 1.1915638144571682e-03, 4.6855153780841227e-04, 1.7001408826280900e-04, 5.6887437600402582e-05, 1.7540485848093888e-05, 4.9799245325909927e-06, 1.3007470032382014e-06, 3.1228729861789030e-07, 6.8845811221543303e-08, 1.3921907152935201e-08, 2.5793972294264184e-09, 4.3731866598484108e-10, 6.7757804877745394e-11, 9.5803165087358731e-12, 1.2342144866005691e-12, 1.4463473211904274e-13, 1.5390497303535517e-14, 1.4842238375138792e-15, 1.2945481593393717e-16, 1.0189332304232922e-17, 7.2201073169282769e-19, 4.5940076773297253e-20, 2.6174575839348305e-21, 1.3313678590335932e-22, 6.0259840320064904e-24, 2.4184034596476935e-25, 8.5728304837693986e-27, 2.6729236200580738e-28, 7.2965450067684075e-30, 1.7351030202821157e-31, 3.5743788958794533e-33, 6.3399135263665769e-35, 9.6167080679676503e-37, 1.2380855579763670e-38, 1.3414974817643660e-40, 1.2117795341306277e-42, 9.0280401387865924e-45, 5.4802170289787664e-47, 2.6727437517360924e-49, 1.0304862520557101e-51, 3.0820773833392742e-54, 6.9930729240520693e-57, 1.1719785012130235e-59, 1.4044672577405165e-62, 1.1561551640964042e-65, 6.2142441618306433e-69, 2.0415857972441075e-72, 3.7512158688048432e-76, 3.4012300869368197e-80, 1.2612494833385409e-84, 1.4046897713151180e-89, 2.6081724024084728e-95, 1.7990659801093241e-102}, + {2.5875539364524082e-103, 3.9360184590802221e-96, 2.2072552957748285e-90, 2.0556308729779607e-85, 5.7358476340730861e-81, 6.5345649901409931e-77, 3.6690360645455800e-73, 1.1510510197511481e-69, 2.2055377414515242e-66, 2.7576366331120112e-63, 2.3673174707161052e-60, 1.4525786040323095e-57, 6.5811912152939833e-55, 2.2613773295130902e-52, 6.0264301132977530e-50, 1.2693840763809051e-47, 2.1479177879979361e-45, 2.9609218353788539e-43, 3.3661609053282785e-41, 3.1901478352848241e-39, 2.5443979671277979e-37, 1.7223946532210455e-35, 9.9710553873521448e-34, 4.9700994335207590e-32, 2.1462063060723877e-30, 8.0737792155578718e-29, 2.6593692402816157e-27, 7.7051505318327598e-26, 1.9720496638158951e-24, 4.4757971347544071e-23, 9.0403370335874384e-22, 1.6303640703529370e-20, 2.6332049182645191e-19, 3.8194419802784429e-18, 4.9883327330781313e-17, 5.8802277275507751e-16, 6.2702394771473180e-15, 6.0607257135908391e-14, 5.3204907075388442e-13, 4.2495506587750072e-12, 3.0933020393247358e-11, 2.0552435298786022e-10, 1.2482251818681576e-09, 6.9389671445373625e-09, 3.5351823460523453e-08, 1.6525270457753961e-07, 7.0953503060139187e-07, 2.8010603367707380e-06, 1.0176471541446871e-05, 3.4054184172402124e-05, 1.0504748699764762e-04, 2.9892250594151955e-04, 7.8519722061027154e-04, 1.9050667392793649e-03, 4.2716207417923171e-03, 8.8560992639436561e-03, 1.6984511709158091e-02, 3.0143653484891619e-02, 4.9524590136894565e-02, 7.5345450641660414e-02, 1.0617266978963312e-01, 1.3860414698078849e-01, 1.6765473214361890e-01, 1.8792309546385810e-01, 1.9520834171916421e-01, 1.8792309546385810e-01, 1.6765473214361890e-01, 1.3860414698078849e-01, 1.0617266978963312e-01, 7.5345450641660414e-02, 4.9524590136894565e-02, 3.0143653484891619e-02, 1.6984511709158091e-02, 8.8560992639436561e-03, 4.2716207417923171e-03, 1.9050667392793649e-03, 7.8519722061027154e-04, 2.9892250594151955e-04, 1.0504748699764762e-04, 3.4054184172402124e-05, 1.0176471541446871e-05, 2.8010603367707380e-06, 7.0953503060139187e-07, 1.6525270457753961e-07, 3.5351823460523453e-08, 6.9389671445373625e-09, 1.2482251818681576e-09, 2.0552435298786022e-10, 3.0933020393247358e-11, 4.2495506587750072e-12, 5.3204907075388442e-13, 6.0607257135908391e-14, 6.2702394771473180e-15, 5.8802277275507751e-16, 4.9883327330781313e-17, 3.8194419802784429e-18, 2.6332049182645191e-19, 1.6303640703529370e-20, 9.0403370335874384e-22, 4.4757971347544071e-23, 1.9720496638158951e-24, 7.7051505318327598e-26, 2.6593692402816157e-27, 8.0737792155578718e-29, 2.1462063060723877e-30, 4.9700994335207590e-32, 9.9710553873521448e-34, 1.7223946532210455e-35, 2.5443979671277979e-37, 3.1901478352848241e-39, 3.3661609053282785e-41, 2.9609218353788539e-43, 2.1479177879979361e-45, 1.2693840763809051e-47, 6.0264301132977530e-50, 2.2613773295130902e-52, 6.5811912152939833e-55, 1.4525786040323095e-57, 2.3673174707161052e-60, 2.7576366331120112e-63, 2.2055377414515242e-66, 1.1510510197511481e-69, 3.6690360645455800e-73, 6.5345649901409931e-77, 5.7358476340730861e-81, 2.0556308729779607e-85, 2.2072552957748285e-90, 3.9360184590802221e-96, 2.5875539364524082e-103}, + {3.7204460108518457e-104, 5.9364731594787663e-97, 3.4655965116643281e-91, 3.3469757581791224e-86, 9.6613261772636215e-82, 1.1367258528662723e-77, 6.5833865033387550e-74, 2.1283034461639501e-70, 4.1991937638649886e-67, 5.4030149717578019e-64, 4.7707625290237234e-61, 3.0097211186016156e-58, 1.4015247946309535e-55, 4.9483338463613849e-53, 1.3546817753059001e-50, 2.9307665929739616e-48, 5.0927511908300209e-46, 7.2087130229885203e-44, 8.4144007328158726e-42, 8.1870801342500945e-40, 6.7037119216509246e-38, 4.6587143166611642e-36, 2.7687058280430152e-34, 1.4168038025321554e-32, 6.2811433857681812e-31, 2.4259782593432643e-29, 8.2046076950332880e-28, 2.4409654886964413e-26, 6.4156025663739209e-25, 1.4954510277528916e-23, 3.1025363444064255e-22, 5.7477855676921120e-21, 9.5376732466503112e-20, 1.4215508257408722e-18, 1.9080516525917262e-17, 2.3119223992445814e-16, 2.5344536275316043e-15, 2.5189945152766989e-14, 2.2742721378405763e-13, 1.8685821935956322e-12, 1.3994739517759176e-11, 9.5692629429270517e-11, 5.9825297159286590e-10, 3.4243028086561824e-09, 1.7967512803433057e-08, 8.6525026250843954e-08, 3.8283102346903316e-07, 1.5578439536677208e-06, 5.8357960655860304e-06, 2.0142490747188856e-05, 6.4107957353545819e-05, 1.8828587640798520e-04, 5.1065276380199355e-04, 1.2796927737216395e-03, 2.9648560622765260e-03, 6.3539216222626869e-03, 1.2601446134450314e-02, 2.3137547830647125e-02, 3.9345000709058629e-02, 6.1983091960651798e-02, 9.0486600174251544e-02, 1.2243869169055180e-01, 1.5358645412541436e-01, 1.7862576228606980e-01, 1.9263278589714239e-01, 1.9263278589714239e-01, 1.7862576228606980e-01, 1.5358645412541436e-01, 1.2243869169055180e-01, 9.0486600174251544e-02, 6.1983091960651798e-02, 3.9345000709058629e-02, 2.3137547830647125e-02, 1.2601446134450314e-02, 6.3539216222626869e-03, 2.9648560622765260e-03, 1.2796927737216395e-03, 5.1065276380199355e-04, 1.8828587640798520e-04, 6.4107957353545819e-05, 2.0142490747188856e-05, 5.8357960655860304e-06, 1.5578439536677208e-06, 3.8283102346903316e-07, 8.6525026250843954e-08, 1.7967512803433057e-08, 3.4243028086561824e-09, 5.9825297159286590e-10, 9.5692629429270517e-11, 1.3994739517759176e-11, 1.8685821935956322e-12, 2.2742721378405763e-13, 2.5189945152766989e-14, 2.5344536275316043e-15, 2.3119223992445814e-16, 1.9080516525917262e-17, 1.4215508257408722e-18, 9.5376732466503112e-20, 5.7477855676921120e-21, 3.1025363444064255e-22, 1.4954510277528916e-23, 6.4156025663739209e-25, 2.4409654886964413e-26, 8.2046076950332880e-28, 2.4259782593432643e-29, 6.2811433857681812e-31, 1.4168038025321554e-32, 2.7687058280430152e-34, 4.6587143166611642e-36, 6.7037119216509246e-38, 8.1870801342500945e-40, 8.4144007328158726e-42, 7.2087130229885203e-44, 5.0927511908300209e-46, 2.9307665929739616e-48, 1.3546817753059001e-50, 4.9483338463613849e-53, 1.4015247946309535e-55, 3.0097211186016156e-58, 4.7707625290237234e-61, 5.4030149717578019e-64, 4.1991937638649886e-67, 2.1283034461639501e-70, 6.5833865033387550e-74, 1.1367258528662723e-77, 9.6613261772636215e-82, 3.3469757581791224e-86, 3.4655965116643281e-91, 5.9364731594787663e-97, 3.7204460108518457e-104}, + {5.3476826111026365e-105, 8.9485710679509321e-98, 5.4370243471100807e-92, 5.4441378603550616e-87, 1.6254006780310087e-82, 1.9746831356131776e-78, 1.1794217215696164e-74, 3.9284007348254153e-71, 7.9796183204186807e-68, 1.0563843092209409e-64, 9.5924087114315112e-62, 6.2207574186530967e-59, 2.9767954168841160e-56, 1.0797369730934170e-53, 3.0360436451965334e-51, 6.7450137912280108e-49, 1.2034270735300903e-46, 1.7487964745761127e-44, 2.0954606929273772e-42, 2.0928182450743565e-40, 1.7589155981687000e-38, 1.2546216106083190e-36, 7.6531182757967849e-35, 4.0196809205772165e-33, 1.8291657781800354e-31, 7.2519108515928950e-30, 2.5176731485459177e-28, 7.6897052483356061e-27, 2.0750476694679341e-25, 4.9664572942742541e-24, 1.0580876836793333e-22, 2.0131999550178635e-21, 3.4313613065500532e-20, 5.2539364144662411e-19, 7.2456324501572317e-18, 9.0217967422636200e-17, 1.0165109952415262e-15, 1.0385841011593362e-14, 9.6411044899350535e-14, 8.1461816331285264e-13, 6.2756146921948126e-12, 4.4148505508362490e-11, 2.8403341656010478e-10, 1.6734368028761769e-09, 9.0404035956869064e-09, 4.4835197499650446e-08, 2.0435322677073055e-07, 8.5687946165889204e-07, 3.3086178947400949e-06, 1.1774562755908359e-05, 3.8651667203812415e-05, 1.1712338225370822e-04, 3.2784720468186990e-04, 8.4825701574449603e-04, 2.0298461578116241e-03, 4.4947646714684642e-03, 9.2143589576985860e-03, 1.7495331329372001e-02, 3.0778087957022211e-02, 5.0184153739443245e-02, 7.5861280569172768e-02, 1.0634224601517195e-01, 1.3826358695373833e-01, 1.6675980772407939e-01, 1.8659628095711822e-01, 1.9371820170604062e-01, 1.8659628095711822e-01, 1.6675980772407939e-01, 1.3826358695373833e-01, 1.0634224601517195e-01, 7.5861280569172768e-02, 5.0184153739443245e-02, 3.0778087957022211e-02, 1.7495331329372001e-02, 9.2143589576985860e-03, 4.4947646714684642e-03, 2.0298461578116241e-03, 8.4825701574449603e-04, 3.2784720468186990e-04, 1.1712338225370822e-04, 3.8651667203812415e-05, 1.1774562755908359e-05, 3.3086178947400949e-06, 8.5687946165889204e-07, 2.0435322677073055e-07, 4.4835197499650446e-08, 9.0404035956869064e-09, 1.6734368028761769e-09, 2.8403341656010478e-10, 4.4148505508362490e-11, 6.2756146921948126e-12, 8.1461816331285264e-13, 9.6411044899350535e-14, 1.0385841011593362e-14, 1.0165109952415262e-15, 9.0217967422636200e-17, 7.2456324501572317e-18, 5.2539364144662411e-19, 3.4313613065500532e-20, 2.0131999550178635e-21, 1.0580876836793333e-22, 4.9664572942742541e-24, 2.0750476694679341e-25, 7.6897052483356061e-27, 2.5176731485459177e-28, 7.2519108515928950e-30, 1.8291657781800354e-31, 4.0196809205772165e-33, 7.6531182757967849e-35, 1.2546216106083190e-36, 1.7589155981687000e-38, 2.0928182450743565e-40, 2.0954606929273772e-42, 1.7487964745761127e-44, 1.2034270735300903e-46, 6.7450137912280108e-49, 3.0360436451965334e-51, 1.0797369730934170e-53, 2.9767954168841160e-56, 6.2207574186530967e-59, 9.5924087114315112e-62, 1.0563843092209409e-64, 7.9796183204186807e-68, 3.9284007348254153e-71, 1.1794217215696164e-74, 1.9746831356131776e-78, 1.6254006780310087e-82, 5.4441378603550616e-87, 5.4370243471100807e-92, 8.9485710679509321e-98, 5.3476826111026365e-105}, + {7.6842766516367719e-106, 1.3481426814084330e-98, 8.5232824201455338e-93, 8.8466828631703380e-88, 2.7313386049487823e-83, 3.4257032455364114e-79, 2.1096988030040495e-75, 7.2385503439630423e-72, 1.5134726683009566e-68, 2.0611376551597914e-65, 1.9243761113547505e-62, 1.2826427266230406e-59, 6.3061655444515630e-57, 2.3494568244414183e-54, 6.7840814198640183e-52, 1.5474546466895863e-49, 2.8342684935250220e-47, 4.2276037377430170e-45, 5.1990976532787586e-43, 5.3289760352121873e-41, 4.5962221753185640e-39, 3.3643504079348503e-37, 2.1059885157863759e-35, 1.1351213650894055e-33, 5.3008778122412928e-32, 2.1567929048213211e-30, 7.6849291812936124e-29, 2.4091492702687982e-27, 6.6731359742375955e-26, 1.6395930158211436e-24, 3.5862705417926132e-23, 7.0063164858326786e-22, 1.2263229445163221e-20, 1.9284904334361852e-19, 2.7319104369658748e-18, 3.4946872798000184e-17, 4.0459872349113726e-16, 4.2484216574797647e-15, 4.0538431929767204e-14, 3.5215468617192942e-13, 2.7897431630242835e-12, 2.0185811443148509e-11, 1.3360415395259884e-10, 8.0999556201008525e-10, 4.5039223844610038e-09, 2.2996588427898263e-08, 1.0794018969942840e-07, 4.6622930297370394e-07, 1.8549414274389103e-06, 6.8039737747046242e-06, 2.3027980530130599e-05, 7.1968372723672767e-05, 2.0783849443716974e-04, 5.5499593798384811e-04, 1.3711669594184176e-03, 3.1358975655376973e-03, 6.6422701758844281e-03, 1.3036021883614270e-02, 2.3714690293508239e-02, 4.0002156173129341e-02, 6.2585382403901088e-02, 9.0844086374182967e-02, 1.2236194224535350e-01, 1.5296604436543901e-01, 1.7749954969646717e-01, 1.9120062497846860e-01, 1.9120062497846860e-01, 1.7749954969646717e-01, 1.5296604436543901e-01, 1.2236194224535350e-01, 9.0844086374182967e-02, 6.2585382403901088e-02, 4.0002156173129341e-02, 2.3714690293508239e-02, 1.3036021883614270e-02, 6.6422701758844281e-03, 3.1358975655376973e-03, 1.3711669594184176e-03, 5.5499593798384811e-04, 2.0783849443716974e-04, 7.1968372723672767e-05, 2.3027980530130599e-05, 6.8039737747046242e-06, 1.8549414274389103e-06, 4.6622930297370394e-07, 1.0794018969942840e-07, 2.2996588427898263e-08, 4.5039223844610038e-09, 8.0999556201008525e-10, 1.3360415395259884e-10, 2.0185811443148509e-11, 2.7897431630242835e-12, 3.5215468617192942e-13, 4.0538431929767204e-14, 4.2484216574797647e-15, 4.0459872349113726e-16, 3.4946872798000184e-17, 2.7319104369658748e-18, 1.9284904334361852e-19, 1.2263229445163221e-20, 7.0063164858326786e-22, 3.5862705417926132e-23, 1.6395930158211436e-24, 6.6731359742375955e-26, 2.4091492702687982e-27, 7.6849291812936124e-29, 2.1567929048213211e-30, 5.3008778122412928e-32, 1.1351213650894055e-33, 2.1059885157863759e-35, 3.3643504079348503e-37, 4.5962221753185640e-39, 5.3289760352121873e-41, 5.1990976532787586e-43, 4.2276037377430170e-45, 2.8342684935250220e-47, 1.5474546466895863e-49, 6.7840814198640183e-52, 2.3494568244414183e-54, 6.3061655444515630e-57, 1.2826427266230406e-59, 1.9243761113547505e-62, 2.0611376551597914e-65, 1.5134726683009566e-68, 7.2385503439630423e-72, 2.1096988030040495e-75, 3.4257032455364114e-79, 2.7313386049487823e-83, 8.8466828631703380e-88, 8.5232824201455338e-93, 1.3481426814084330e-98, 7.6842766516367719e-106}, + {1.1038467599988350e-106, 2.0299162819709644e-99, 1.3351165545454540e-93, 1.4361908901012819e-88, 4.5844662610976337e-84, 5.9349976525016213e-80, 3.7680124485137400e-76, 1.3315304198313815e-72, 2.8651973069480425e-69, 4.0133192434618745e-66, 3.8520167842143179e-63, 2.6383248122689808e-60, 1.3324956798179218e-57, 5.0982905111217610e-55, 1.5114881547668727e-52, 3.5392080595751209e-50, 6.6532981134843764e-48, 1.0184623032786348e-45, 1.2852633429954566e-43, 1.3517324859318610e-41, 1.1962163965744953e-39, 8.9837835745312106e-38, 5.7697747333366196e-36, 3.1907496278196311e-34, 1.5288163843577720e-32, 6.3824723629696159e-31, 2.3335393536670584e-29, 7.5069091034254989e-28, 2.1339408990452690e-26, 5.3812272933845995e-25, 1.2081587782243251e-23, 2.4230032186653206e-22, 4.3541619756512954e-21, 7.0308758150274706e-20, 1.0228495371481795e-18, 1.3439170617083339e-17, 1.5983699268748500e-16, 1.7244201781932836e-15, 1.6909213145415565e-14, 1.5097790665682497e-13, 1.2295731019067163e-12, 9.1482393782595353e-12, 6.2274132191241200e-11, 3.8838846452764459e-10, 2.2221554698762070e-09, 1.1677641217752186e-08, 5.6428156340858430e-08, 2.5098662449728381e-07, 1.0285882365095455e-06, 3.8874166532037593e-06, 1.3560417245137210e-05, 4.3693239040909913e-05, 1.3013545776424483e-04, 3.5851189054336881e-04, 9.1411456482270634e-04, 2.1583740072268734e-03, 4.7217142757868197e-03, 9.5745050499428906e-03, 1.8003325023065602e-02, 3.1402556502212124e-02, 5.0826454983412143e-02, 7.6356275486723038e-02, 1.0649485597288683e-01, 1.3791833004859055e-01, 1.6587737779249406e-01, 1.8529706602349078e-01, 1.9226167387366441e-01, 1.8529706602349078e-01, 1.6587737779249406e-01, 1.3791833004859055e-01, 1.0649485597288683e-01, 7.6356275486723038e-02, 5.0826454983412143e-02, 3.1402556502212124e-02, 1.8003325023065602e-02, 9.5745050499428906e-03, 4.7217142757868197e-03, 2.1583740072268734e-03, 9.1411456482270634e-04, 3.5851189054336881e-04, 1.3013545776424483e-04, 4.3693239040909913e-05, 1.3560417245137210e-05, 3.8874166532037593e-06, 1.0285882365095455e-06, 2.5098662449728381e-07, 5.6428156340858430e-08, 1.1677641217752186e-08, 2.2221554698762070e-09, 3.8838846452764459e-10, 6.2274132191241200e-11, 9.1482393782595353e-12, 1.2295731019067163e-12, 1.5097790665682497e-13, 1.6909213145415565e-14, 1.7244201781932836e-15, 1.5983699268748500e-16, 1.3439170617083339e-17, 1.0228495371481795e-18, 7.0308758150274706e-20, 4.3541619756512954e-21, 2.4230032186653206e-22, 1.2081587782243251e-23, 5.3812272933845995e-25, 2.1339408990452690e-26, 7.5069091034254989e-28, 2.3335393536670584e-29, 6.3824723629696159e-31, 1.5288163843577720e-32, 3.1907496278196311e-34, 5.7697747333366196e-36, 8.9837835745312106e-38, 1.1962163965744953e-39, 1.3517324859318610e-41, 1.2852633429954566e-43, 1.0184623032786348e-45, 6.6532981134843764e-48, 3.5392080595751209e-50, 1.5114881547668727e-52, 5.0982905111217610e-55, 1.3324956798179218e-57, 2.6383248122689808e-60, 3.8520167842143179e-63, 4.0133192434618745e-66, 2.8651973069480425e-69, 1.3315304198313815e-72, 3.7680124485137400e-76, 5.9349976525016213e-80, 4.5844662610976337e-84, 1.4361908901012819e-88, 1.3351165545454540e-93, 2.0299162819709644e-99, 1.1038467599988350e-106}, + {1.5852022154122762e-107, 3.0548054158892936e-100, 2.0897891620152027e-94, 2.3293228753706694e-89, 7.6861123200181953e-85, 1.0268748980780725e-80, 6.7197562830108496e-77, 2.4452549463378667e-73, 5.4141833815112683e-70, 7.7987351892856256e-67, 7.6937052841722558e-64, 5.4140880882527221e-61, 2.8084445413684342e-58, 1.1033315179441334e-55, 3.3578943438527196e-53, 8.0698691825802516e-51, 1.5567833435482675e-48, 2.4451923543925048e-46, 3.1658838545522830e-44, 3.4158346081733210e-42, 3.1009657171113824e-40, 2.3889887847651522e-38, 1.5738945493185839e-36, 8.9283867523289446e-35, 4.3884114191019410e-33, 1.8794344951812523e-31, 7.0495273821073143e-30, 2.3266903412110293e-28, 6.7861521642478146e-27, 1.7559922329924036e-25, 4.0458189399870260e-24, 8.3276681875539800e-23, 1.5360712580259943e-21, 2.5462929950511611e-20, 3.8033125448314512e-19, 5.1314188262140908e-18, 6.2679375130394878e-17, 6.9461573699177854e-16, 6.9976953274028973e-15, 6.4202984348233192e-14, 5.3739121421360399e-13, 4.1101386023109489e-12, 2.8767484176405797e-11, 1.8451534167067902e-10, 1.0859592046532814e-09, 5.8718148797495608e-09, 2.9201210196159125e-08, 1.3370799258052363e-07, 5.6424627677752911e-07, 2.1965028260725411e-06, 7.8943275081059988e-06, 2.6215639412143949e-05, 8.0497734201318759e-05, 2.2870525172954362e-04, 6.0159714197281571e-04, 1.4659454148941060e-03, 3.3108212147861167e-03, 6.9336514656727563e-03, 1.3470344826444706e-02, 2.4285561078700165e-02, 4.0645578943455961e-02, 6.3168189419948478e-02, 9.1182028088582376e-02, 1.2227380245007502e-01, 1.5234939813711931e-01, 1.7639383039152406e-01, 1.8979993309264909e-01, 1.8979993309264909e-01, 1.7639383039152406e-01, 1.5234939813711931e-01, 1.2227380245007502e-01, 9.1182028088582376e-02, 6.3168189419948478e-02, 4.0645578943455961e-02, 2.4285561078700165e-02, 1.3470344826444706e-02, 6.9336514656727563e-03, 3.3108212147861167e-03, 1.4659454148941060e-03, 6.0159714197281571e-04, 2.2870525172954362e-04, 8.0497734201318759e-05, 2.6215639412143949e-05, 7.8943275081059988e-06, 2.1965028260725411e-06, 5.6424627677752911e-07, 1.3370799258052363e-07, 2.9201210196159125e-08, 5.8718148797495608e-09, 1.0859592046532814e-09, 1.8451534167067902e-10, 2.8767484176405797e-11, 4.1101386023109489e-12, 5.3739121421360399e-13, 6.4202984348233192e-14, 6.9976953274028973e-15, 6.9461573699177854e-16, 6.2679375130394878e-17, 5.1314188262140908e-18, 3.8033125448314512e-19, 2.5462929950511611e-20, 1.5360712580259943e-21, 8.3276681875539800e-23, 4.0458189399870260e-24, 1.7559922329924036e-25, 6.7861521642478146e-27, 2.3266903412110293e-28, 7.0495273821073143e-30, 1.8794344951812523e-31, 4.3884114191019410e-33, 8.9283867523289446e-35, 1.5738945493185839e-36, 2.3889887847651522e-38, 3.1009657171113824e-40, 3.4158346081733210e-42, 3.1658838545522830e-44, 2.4451923543925048e-46, 1.5567833435482675e-48, 8.0698691825802516e-51, 3.3578943438527196e-53, 1.1033315179441334e-55, 2.8084445413684342e-58, 5.4140880882527221e-61, 7.6937052841722558e-64, 7.7987351892856256e-67, 5.4141833815112683e-70, 2.4452549463378667e-73, 6.7197562830108496e-77, 1.0268748980780725e-80, 7.6861123200181953e-85, 2.3293228753706694e-89, 2.0897891620152027e-94, 3.0548054158892936e-100, 1.5852022154122762e-107}, + {2.2757903447048717e-108, 4.5946784737513260e-101, 3.2685938252533535e-95, 3.7743169785683037e-90, 1.2871697383667851e-85, 1.7743864842451219e-81, 1.1966100169534770e-77, 4.4831207104684604e-74, 1.0212230702897007e-70, 1.5124472591580667e-67, 1.5333631698716670e-64, 1.1084367892237507e-61, 5.9044668946443965e-59, 2.3813770140907575e-56, 7.4386721348341212e-54, 1.8345006104189449e-51, 3.6310691969704462e-49, 5.8508598523019220e-47, 7.7706802795811407e-45, 8.5997500074472335e-43, 8.0073315846684445e-41, 6.3269186795493014e-39, 4.2749818807535224e-37, 2.4872103396508171e-35, 1.2538186619197742e-33, 5.5075144968159152e-32, 2.1188905321706446e-30, 7.1735092247885270e-29, 2.1463025081080465e-27, 5.6976909711813352e-26, 1.3468870756541617e-24, 2.8447276912580344e-23, 5.3848024996122255e-22, 9.1613793530553680e-21, 1.4046424779365027e-19, 1.9456017248888693e-18, 2.4401660157799310e-17, 2.7770723790106855e-16, 2.8735526657240152e-15, 2.7084363045358423e-14, 2.3293514464982674e-13, 1.8309133143528682e-12, 1.3172552368556761e-11, 8.6866283016645484e-11, 5.2575217351973056e-10, 2.9240918874514531e-09, 1.4961568756142573e-08, 7.0502109098437831e-08, 3.0626482923803324e-07, 1.2276189268114097e-06, 4.5443796787236290e-06, 1.5548071919772645e-05, 4.9202833580003181e-05, 1.4411581751672914e-04, 3.9094357332687408e-04, 9.8276091717415027e-04, 2.2905612451458858e-03, 4.9522684042317359e-03, 9.9362495542868867e-03, 1.8508238320820009e-02, 3.2017035703904927e-02, 5.1451871301553709e-02, 7.6831201307210703e-02, 1.0663137077642493e-01, 1.3756889121351917e-01, 1.6500723131965989e-01, 1.8402451115016699e-01, 1.9083751332645207e-01, 1.8402451115016699e-01, 1.6500723131965989e-01, 1.3756889121351917e-01, 1.0663137077642493e-01, 7.6831201307210703e-02, 5.1451871301553709e-02, 3.2017035703904927e-02, 1.8508238320820009e-02, 9.9362495542868867e-03, 4.9522684042317359e-03, 2.2905612451458858e-03, 9.8276091717415027e-04, 3.9094357332687408e-04, 1.4411581751672914e-04, 4.9202833580003181e-05, 1.5548071919772645e-05, 4.5443796787236290e-06, 1.2276189268114097e-06, 3.0626482923803324e-07, 7.0502109098437831e-08, 1.4961568756142573e-08, 2.9240918874514531e-09, 5.2575217351973056e-10, 8.6866283016645484e-11, 1.3172552368556761e-11, 1.8309133143528682e-12, 2.3293514464982674e-13, 2.7084363045358423e-14, 2.8735526657240152e-15, 2.7770723790106855e-16, 2.4401660157799310e-17, 1.9456017248888693e-18, 1.4046424779365027e-19, 9.1613793530553680e-21, 5.3848024996122255e-22, 2.8447276912580344e-23, 1.3468870756541617e-24, 5.6976909711813352e-26, 2.1463025081080465e-27, 7.1735092247885270e-29, 2.1188905321706446e-30, 5.5075144968159152e-32, 1.2538186619197742e-33, 2.4872103396508171e-35, 4.2749818807535224e-37, 6.3269186795493014e-39, 8.0073315846684445e-41, 8.5997500074472335e-43, 7.7706802795811407e-45, 5.8508598523019220e-47, 3.6310691969704462e-49, 1.8345006104189449e-51, 7.4386721348341212e-54, 2.3813770140907575e-56, 5.9044668946443965e-59, 1.1084367892237507e-61, 1.5333631698716670e-64, 1.5124472591580667e-67, 1.0212230702897007e-70, 4.4831207104684604e-74, 1.1966100169534770e-77, 1.7743864842451219e-81, 1.2871697383667851e-85, 3.7743169785683037e-90, 3.2685938252533535e-95, 4.5946784737513260e-101, 2.2757903447048717e-108}, + {3.2662778348790219e-109, 6.9071006009219448e-102, 5.1085629363787234e-96, 6.1100313027084669e-91, 2.1531900867437274e-86, 3.0621042209000059e-82, 2.1277376772398947e-78, 8.2059605065764682e-75, 1.9227730563170089e-71, 2.9274096096614171e-68, 3.0495045268798647e-65, 2.2641169845080718e-62, 1.2382980686348502e-59, 5.1263348642622049e-57, 1.6432629457353511e-54, 4.1579427709675079e-52, 8.4425869514003785e-50, 1.3953581486228228e-47, 1.9006681419175218e-45, 2.1571532321739302e-43, 2.0597137897723631e-41, 1.6688589526897371e-39, 1.1562775861404743e-37, 6.8982672254135044e-36, 3.5658879405329104e-34, 1.6062235506206207e-32, 6.3371488059404152e-31, 2.2002659780562692e-29, 6.7518197536098842e-28, 1.8384352926742758e-26, 4.4579796693281321e-25, 9.6593405936315995e-24, 1.8759587883105718e-22, 3.2750072247643929e-21, 5.1531219168800766e-20, 7.3260730719021186e-19, 9.4321973070076218e-18, 1.1021086847913827e-16, 1.1710396791414340e-15, 1.1336050130083279e-14, 1.0014937399406310e-13, 8.0878754293572482e-13, 5.9796723109076469e-12, 4.0531324359847441e-11, 2.5220174708373236e-10, 1.4423973477091834e-09, 7.5910433713044797e-09, 3.6801425167297173e-08, 1.6451664884983423e-07, 6.7880160807256645e-07, 2.5872670138074200e-06, 9.1170822839813128e-06, 2.9724333423383228e-05, 8.9724509010453385e-05, 2.5091729952798149e-04, 6.5046837318858926e-04, 1.5639824929501397e-03, 3.4894828544320858e-03, 7.2278157943492030e-03, 1.3904131095041473e-02, 2.4850005571417737e-02, 4.1275438102408031e-02, 6.3732095470061270e-02, 9.1501274267677846e-02, 1.2217500065832824e-01, 1.5173668408251911e-01, 1.7530801211052990e-01, 1.8842957463583779e-01, 1.8842957463583779e-01, 1.7530801211052990e-01, 1.5173668408251911e-01, 1.2217500065832824e-01, 9.1501274267677846e-02, 6.3732095470061270e-02, 4.1275438102408031e-02, 2.4850005571417737e-02, 1.3904131095041473e-02, 7.2278157943492030e-03, 3.4894828544320858e-03, 1.5639824929501397e-03, 6.5046837318858926e-04, 2.5091729952798149e-04, 8.9724509010453385e-05, 2.9724333423383228e-05, 9.1170822839813128e-06, 2.5872670138074200e-06, 6.7880160807256645e-07, 1.6451664884983423e-07, 3.6801425167297173e-08, 7.5910433713044797e-09, 1.4423973477091834e-09, 2.5220174708373236e-10, 4.0531324359847441e-11, 5.9796723109076469e-12, 8.0878754293572482e-13, 1.0014937399406310e-13, 1.1336050130083279e-14, 1.1710396791414340e-15, 1.1021086847913827e-16, 9.4321973070076218e-18, 7.3260730719021186e-19, 5.1531219168800766e-20, 3.2750072247643929e-21, 1.8759587883105718e-22, 9.6593405936315995e-24, 4.4579796693281321e-25, 1.8384352926742758e-26, 6.7518197536098842e-28, 2.2002659780562692e-29, 6.3371488059404152e-31, 1.6062235506206207e-32, 3.5658879405329104e-34, 6.8982672254135044e-36, 1.1562775861404743e-37, 1.6688589526897371e-39, 2.0597137897723631e-41, 2.1571532321739302e-43, 1.9006681419175218e-45, 1.3953581486228228e-47, 8.4425869514003785e-50, 4.1579427709675079e-52, 1.6432629457353511e-54, 5.1263348642622049e-57, 1.2382980686348502e-59, 2.2641169845080718e-62, 3.0495045268798647e-65, 2.9274096096614171e-68, 1.9227730563170089e-71, 8.2059605065764682e-75, 2.1277376772398947e-78, 3.0621042209000059e-82, 2.1531900867437274e-86, 6.1100313027084669e-91, 5.1085629363787234e-96, 6.9071006009219448e-102, 3.2662778348790219e-109}, + {4.6865023080529104e-110, 1.0377874004830612e-102, 7.9784749096307812e-97, 9.8821174227967692e-92, 3.5979287498244655e-87, 5.2776428357398472e-83, 3.7779666227111211e-79, 1.4996171154683470e-75, 3.6138115204304974e-72, 5.6551650475163530e-69, 6.0520249291763858e-66, 4.6142654439156290e-63, 2.5906808193011388e-60, 1.1006724998865391e-57, 3.6200846949796910e-55, 9.3965049756134747e-53, 1.9569075431422824e-50, 3.3168917267338703e-48, 4.6329566465533973e-46, 5.3914438385767737e-44, 5.2781068509974114e-42, 4.3845152623372787e-40, 3.1144817985274696e-38, 1.9049498787300406e-36, 1.0095682854224567e-34, 4.6623959142602483e-33, 1.8860299651335772e-31, 6.7143368715209606e-30, 2.1127537039024262e-28, 5.8994042231272372e-27, 1.4671212494779564e-25, 3.2605011152464131e-24, 6.4955255161731863e-23, 1.1633403477038459e-21, 1.8781142293296228e-20, 2.7399173517222677e-19, 3.6203893599581944e-18, 4.3421867882952047e-17, 4.7366003944880216e-16, 4.7080515903807368e-15, 4.2715858467937535e-14, 3.5433804833163948e-13, 2.6914605808295047e-12, 1.8746383733203776e-11, 1.1989016690827638e-10, 7.0489725875624514e-10, 3.8145955545353021e-09, 1.9020527069551235e-08, 8.7475726975743740e-08, 3.7140992001185702e-07, 1.4571432947497977e-06, 5.2867540339888927e-06, 1.7751862632560425e-05, 5.5204240789547246e-05, 1.5909525194144218e-04, 4.2516612395155680e-04, 1.0541825457525329e-03, 2.4263153829887293e-03, 5.1862282813377051e-03, 1.0299316731984193e-02, 1.9009837222668049e-02, 3.2621520059018146e-02, 5.2060779315091815e-02, 7.7286794858634558e-02, 1.0675261357345991e-01, 1.3721574664493244e-01, 1.6414915672894112e-01, 1.8277772077559612e-01, 1.8944453877662401e-01, 1.8277772077559612e-01, 1.6414915672894112e-01, 1.3721574664493244e-01, 1.0675261357345991e-01, 7.7286794858634558e-02, 5.2060779315091815e-02, 3.2621520059018146e-02, 1.9009837222668049e-02, 1.0299316731984193e-02, 5.1862282813377051e-03, 2.4263153829887293e-03, 1.0541825457525329e-03, 4.2516612395155680e-04, 1.5909525194144218e-04, 5.5204240789547246e-05, 1.7751862632560425e-05, 5.2867540339888927e-06, 1.4571432947497977e-06, 3.7140992001185702e-07, 8.7475726975743740e-08, 1.9020527069551235e-08, 3.8145955545353021e-09, 7.0489725875624514e-10, 1.1989016690827638e-10, 1.8746383733203776e-11, 2.6914605808295047e-12, 3.5433804833163948e-13, 4.2715858467937535e-14, 4.7080515903807368e-15, 4.7366003944880216e-16, 4.3421867882952047e-17, 3.6203893599581944e-18, 2.7399173517222677e-19, 1.8781142293296228e-20, 1.1633403477038459e-21, 6.4955255161731863e-23, 3.2605011152464131e-24, 1.4671212494779564e-25, 5.8994042231272372e-27, 2.1127537039024262e-28, 6.7143368715209606e-30, 1.8860299651335772e-31, 4.6623959142602483e-33, 1.0095682854224567e-34, 1.9049498787300406e-36, 3.1144817985274696e-38, 4.3845152623372787e-40, 5.2781068509974114e-42, 5.3914438385767737e-44, 4.6329566465533973e-46, 3.3168917267338703e-48, 1.9569075431422824e-50, 9.3965049756134747e-53, 3.6200846949796910e-55, 1.1006724998865391e-57, 2.5906808193011388e-60, 4.6142654439156290e-63, 6.0520249291763858e-66, 5.6551650475163530e-69, 3.6138115204304974e-72, 1.4996171154683470e-75, 3.7779666227111211e-79, 5.2776428357398472e-83, 3.5979287498244655e-87, 9.8821174227967692e-92, 7.9784749096307812e-97, 1.0377874004830612e-102, 4.6865023080529104e-110}, + {6.7223469064836171e-111, 1.5584604318709814e-103, 1.2451690475064742e-97, 1.5968463027613036e-92, 6.0055451530824495e-88, 9.0848000543271587e-84, 6.6985500695669678e-80, 2.7361658102621640e-76, 6.7802095889475983e-73, 1.0903770909317098e-69, 1.1985921850382964e-66, 9.3828601952142795e-64, 5.4070585225542087e-61, 2.3572025385780174e-58, 7.9532902157128368e-56, 2.1173804777066541e-53, 4.5220720973223149e-51, 7.8591635665593126e-49, 1.1254750686853198e-46, 1.3427041430602204e-44, 1.3474889050314146e-42, 1.1474212047422846e-40, 8.3547107388260308e-39, 5.2380609435106477e-37, 2.8455586990614318e-35, 1.3470860626931207e-33, 5.5860425698193572e-32, 2.0386781124262974e-30, 6.5767258559351848e-29, 1.8828451569167714e-27, 4.8012341582972026e-26, 1.0941854437188646e-24, 2.2355486477720061e-23, 4.1066490153458769e-22, 6.8008865930090286e-21, 1.0178867789337611e-19, 1.3800519281469149e-18, 1.6985968059071478e-17, 1.9017680123139647e-16, 1.9404932122013048e-15, 1.8076531130346059e-14, 1.5398466784483034e-13, 1.2013344715990716e-12, 8.5959906732140100e-12, 5.6487797699597178e-11, 3.4133713929443775e-10, 1.8988505331522261e-09, 9.7353434088062900e-09, 4.6047775382709491e-08, 2.0113005931537178e-07, 8.1197441052941798e-07, 3.0322448415500775e-06, 1.0482793298607957e-05, 3.3573050144199230e-05, 9.9676496285740638e-05, 2.7450358985306201e-04, 7.0161767403489428e-04, 1.6652282490644866e-03, 3.6717374087279781e-03, 7.5245206122160650e-03, 1.4337113630217399e-02, 2.5407889466847185e-02, 4.1891912442268933e-02, 6.4277668190634463e-02, 9.1802633810630571e-02, 1.2206621940114575e-01, 1.5112804960523191e-01, 1.7424152504403007e-01, 1.8708847054904945e-01, 1.8708847054904945e-01, 1.7424152504403007e-01, 1.5112804960523191e-01, 1.2206621940114575e-01, 9.1802633810630571e-02, 6.4277668190634463e-02, 4.1891912442268933e-02, 2.5407889466847185e-02, 1.4337113630217399e-02, 7.5245206122160650e-03, 3.6717374087279781e-03, 1.6652282490644866e-03, 7.0161767403489428e-04, 2.7450358985306201e-04, 9.9676496285740638e-05, 3.3573050144199230e-05, 1.0482793298607957e-05, 3.0322448415500775e-06, 8.1197441052941798e-07, 2.0113005931537178e-07, 4.6047775382709491e-08, 9.7353434088062900e-09, 1.8988505331522261e-09, 3.4133713929443775e-10, 5.6487797699597178e-11, 8.5959906732140100e-12, 1.2013344715990716e-12, 1.5398466784483034e-13, 1.8076531130346059e-14, 1.9404932122013048e-15, 1.9017680123139647e-16, 1.6985968059071478e-17, 1.3800519281469149e-18, 1.0178867789337611e-19, 6.8008865930090286e-21, 4.1066490153458769e-22, 2.2355486477720061e-23, 1.0941854437188646e-24, 4.8012341582972026e-26, 1.8828451569167714e-27, 6.5767258559351848e-29, 2.0386781124262974e-30, 5.5860425698193572e-32, 1.3470860626931207e-33, 2.8455586990614318e-35, 5.2380609435106477e-37, 8.3547107388260308e-39, 1.1474212047422846e-40, 1.3474889050314146e-42, 1.3427041430602204e-44, 1.1254750686853198e-46, 7.8591635665593126e-49, 4.5220720973223149e-51, 2.1173804777066541e-53, 7.9532902157128368e-56, 2.3572025385780174e-58, 5.4070585225542087e-61, 9.3828601952142795e-64, 1.1985921850382964e-66, 1.0903770909317098e-69, 6.7802095889475983e-73, 2.7361658102621640e-76, 6.6985500695669678e-80, 9.0848000543271587e-84, 6.0055451530824495e-88, 1.5968463027613036e-92, 1.2451690475064742e-97, 1.5584604318709814e-103, 6.7223469064836171e-111}, + {9.6398630558977581e-112, 2.3391641752283700e-104, 1.9419047430148712e-98, 2.5780282869707508e-93, 1.0013546946979084e-88, 1.5618992863642802e-84, 1.1860256149765069e-80, 4.9845319901386102e-77, 1.2699036539452659e-73, 2.0984019099670130e-70, 2.3689362034001624e-67, 1.9037493843202249e-64, 1.1258502033609599e-61, 5.0354502440866812e-59, 1.7426389319046294e-56, 4.7576590995159999e-54, 1.0418263136743596e-51, 1.8562658771588515e-49, 2.7249577678833700e-47, 3.3321800978024594e-45, 3.4274481444478336e-43, 2.9912154191216358e-41, 2.2321555171303588e-39, 1.4342596614707723e-37, 7.9853025164866527e-36, 3.8743074669761106e-34, 1.6466139693318358e-32, 6.1594817750585881e-31, 2.0367481580156025e-29, 5.9772735819833118e-28, 1.5625565508848433e-26, 3.6509499167114885e-25, 7.6484446772058021e-24, 1.4407768646001281e-22, 2.4470614433838565e-21, 3.7566695291667047e-20, 5.2249355965739373e-19, 6.5981079437776417e-18, 7.5804607661939761e-17, 7.9383130347919212e-16, 7.5907028620400909e-15, 6.6385260183760165e-14, 5.3182112719426004e-13, 3.9083095195736355e-12, 2.6383151459347353e-11, 1.6380456665860958e-10, 9.3648087516475362e-10, 4.9354207551905105e-09, 2.4002106969319454e-08, 1.0781831043581527e-07, 4.4775845772911881e-07, 1.7205483203483572e-06, 6.1220977817639379e-06, 2.0186382119025494e-05, 6.1721031633452369e-05, 1.7510316724439029e-04, 4.6120030826672870e-04, 1.1283616065624156e-03, 2.5655409728187234e-03, 5.4233979404253157e-03, 1.0663442942343464e-02, 1.9507907091601058e-02, 3.3216020285214413e-02, 5.2653553807060320e-02, 7.7723764833089265e-02, 1.0685936247311774e-01, 1.3685933683570478e-01, 1.6330294257556086e-01, 1.8155584069555794e-01, 1.8808162842571305e-01, 1.8155584069555794e-01, 1.6330294257556086e-01, 1.3685933683570478e-01, 1.0685936247311774e-01, 7.7723764833089265e-02, 5.2653553807060320e-02, 3.3216020285214413e-02, 1.9507907091601058e-02, 1.0663442942343464e-02, 5.4233979404253157e-03, 2.5655409728187234e-03, 1.1283616065624156e-03, 4.6120030826672870e-04, 1.7510316724439029e-04, 6.1721031633452369e-05, 2.0186382119025494e-05, 6.1220977817639379e-06, 1.7205483203483572e-06, 4.4775845772911881e-07, 1.0781831043581527e-07, 2.4002106969319454e-08, 4.9354207551905105e-09, 9.3648087516475362e-10, 1.6380456665860958e-10, 2.6383151459347353e-11, 3.9083095195736355e-12, 5.3182112719426004e-13, 6.6385260183760165e-14, 7.5907028620400909e-15, 7.9383130347919212e-16, 7.5804607661939761e-17, 6.5981079437776417e-18, 5.2249355965739373e-19, 3.7566695291667047e-20, 2.4470614433838565e-21, 1.4407768646001281e-22, 7.6484446772058021e-24, 3.6509499167114885e-25, 1.5625565508848433e-26, 5.9772735819833118e-28, 2.0367481580156025e-29, 6.1594817750585881e-31, 1.6466139693318358e-32, 3.8743074669761106e-34, 7.9853025164866527e-36, 1.4342596614707723e-37, 2.2321555171303588e-39, 2.9912154191216358e-41, 3.4274481444478336e-43, 3.3321800978024594e-45, 2.7249577678833700e-47, 1.8562658771588515e-49, 1.0418263136743596e-51, 4.7576590995159999e-54, 1.7426389319046294e-56, 5.0354502440866812e-59, 1.1258502033609599e-61, 1.9037493843202249e-64, 2.3689362034001624e-67, 2.0984019099670130e-70, 1.2699036539452659e-73, 4.9845319901386102e-77, 1.1860256149765069e-80, 1.5618992863642802e-84, 1.0013546946979084e-88, 2.5780282869707508e-93, 1.9419047430148712e-98, 2.3391641752283700e-104, 9.6398630558977581e-112}, + {1.3819748652176074e-112, 3.5091818441132373e-105, 3.0263733342631031e-99, 4.1584216000446123e-94, 1.6678802978259982e-89, 2.6820059816501053e-85, 2.0970348613054561e-81, 9.0664032095201726e-78, 2.3744232682771987e-74, 4.0308051146214329e-71, 4.6725947222676983e-68, 3.8542403780632908e-65, 2.3387627697862867e-62, 1.0729932979377662e-59, 3.8081687860913558e-57, 1.0660224990923822e-54, 2.3931046396310541e-52, 4.3706076964057967e-50, 6.5758217028615195e-48, 8.2408262629145279e-46, 8.6863577038588966e-44, 7.7681876124982396e-42, 5.9400458445057631e-40, 3.9109426504580767e-38, 2.2311802993712928e-36, 1.1092621876592673e-34, 4.8310493095269011e-33, 1.8519160989732117e-31, 6.2757371777744156e-30, 1.8875929093999227e-28, 5.0576726716251256e-27, 1.2113423787195963e-25, 2.6014811007021294e-24, 5.0242965481154138e-23, 8.7498945768853231e-22, 1.3775031653677140e-20, 1.9649805509896429e-19, 2.5453305256296733e-18, 3.0000691187992888e-17, 3.2236051617172698e-16, 3.1633284490034087e-15, 2.8395986506952882e-14, 2.3353492711597277e-13, 1.7622103628998908e-12, 1.2216962997815707e-11, 7.7914682997538544e-11, 4.5765854976073951e-10, 2.4786353105487376e-09, 1.2390357485809571e-08, 5.7223858055497259e-08, 2.4439179961675454e-07, 9.6600646013167157e-07, 3.5367142158469601e-06, 1.2002319438047467e-05, 3.7780839366269368e-05, 1.1038074912944360e-04, 2.9949084760834345e-04, 7.5504927141389195e-04, 1.7696288232331070e-03, 3.8574393750280067e-03, 7.8235307009575233e-03, 1.4769041560724656e-02, 2.5959097306055404e-02, 4.2495188992312062e-02, 6.4805460287971808e-02, 9.2086877576565612e-02, 1.2194809856528342e-01, 1.5052362288934179e-01, 1.7319382084353874e-01, 1.8577559474964558e-01, 1.8577559474964558e-01, 1.7319382084353874e-01, 1.5052362288934179e-01, 1.2194809856528342e-01, 9.2086877576565612e-02, 6.4805460287971808e-02, 4.2495188992312062e-02, 2.5959097306055404e-02, 1.4769041560724656e-02, 7.8235307009575233e-03, 3.8574393750280067e-03, 1.7696288232331070e-03, 7.5504927141389195e-04, 2.9949084760834345e-04, 1.1038074912944360e-04, 3.7780839366269368e-05, 1.2002319438047467e-05, 3.5367142158469601e-06, 9.6600646013167157e-07, 2.4439179961675454e-07, 5.7223858055497259e-08, 1.2390357485809571e-08, 2.4786353105487376e-09, 4.5765854976073951e-10, 7.7914682997538544e-11, 1.2216962997815707e-11, 1.7622103628998908e-12, 2.3353492711597277e-13, 2.8395986506952882e-14, 3.1633284490034087e-15, 3.2236051617172698e-16, 3.0000691187992888e-17, 2.5453305256296733e-18, 1.9649805509896429e-19, 1.3775031653677140e-20, 8.7498945768853231e-22, 5.0242965481154138e-23, 2.6014811007021294e-24, 1.2113423787195963e-25, 5.0576726716251256e-27, 1.8875929093999227e-28, 6.2757371777744156e-30, 1.8519160989732117e-31, 4.8310493095269011e-33, 1.1092621876592673e-34, 2.2311802993712928e-36, 3.9109426504580767e-38, 5.9400458445057631e-40, 7.7681876124982396e-42, 8.6863577038588966e-44, 8.2408262629145279e-46, 6.5758217028615195e-48, 4.3706076964057967e-50, 2.3931046396310541e-52, 1.0660224990923822e-54, 3.8081687860913558e-57, 1.0729932979377662e-59, 2.3387627697862867e-62, 3.8542403780632908e-65, 4.6725947222676983e-68, 4.0308051146214329e-71, 2.3744232682771987e-74, 9.0664032095201726e-78, 2.0970348613054561e-81, 2.6820059816501053e-85, 1.6678802978259982e-89, 4.1584216000446123e-94, 3.0263733342631031e-99, 3.5091818441132373e-105, 1.3819748652176074e-112}, + {1.9806611743021416e-113, 5.2617952692292333e-106, 4.7131990325935266e-100, 6.7017830703194019e-95, 2.7751659416516980e-90, 4.5998341384092458e-86, 3.7027394072850406e-82, 1.6465801492558192e-78, 4.4321525706156201e-75, 7.7285235953959866e-72, 9.1980779235827154e-69, 7.7863635474467061e-66, 4.8472018976182706e-63, 2.2808008160100623e-60, 8.3001996570148669e-58, 2.3819600570060440e-55, 5.4809275321322830e-53, 1.0258876994968507e-50, 1.5817079781846762e-48, 2.0310845466149993e-46, 2.1935503204230003e-44, 2.0098426331457899e-42, 1.5745331638769155e-40, 1.0620797611432563e-38, 6.2076082159887624e-37, 3.1618692048946272e-35, 1.4108563317113768e-33, 5.5412911024876112e-32, 1.9240852596678829e-30, 5.9301271167711558e-29, 1.6282950449666844e-27, 3.9967858207858083e-26, 8.7976197776883766e-25, 1.7416595619626179e-23, 3.1094324529576228e-22, 5.0189377569399244e-21, 7.3412947992638873e-20, 9.7524056424221390e-19, 1.1789993455088293e-17, 1.2995830094215584e-16, 1.3084437330245737e-15, 1.2052816831862512e-14, 1.0173726615206055e-13, 7.8806482946078899e-13, 5.6095283428337204e-12, 3.6739040139866195e-11, 2.2165913480620041e-10, 1.2333492148378478e-09, 6.3355479710981103e-09, 3.0075005874343488e-08, 1.3205310627276386e-07, 5.3676540058539977e-07, 2.0214361392302868e-06, 7.0582654033955854e-06, 2.2866437400066508e-05, 6.8776486666748005e-05, 1.9216752502494505e-04, 4.9906383375612176e-04, 1.2052761990741546e-03, 2.7081400657517538e-03, 5.6635846018365278e-03, 1.1028376452466447e-02, 2.0002251583713944e-02, 3.3800561758698749e-02, 5.3230566834836512e-02, 7.8142792739003333e-02, 1.0695235327964076e-01, 1.3650006936059866e-01, 1.6246837812900003e-01, 1.8035805565273866e-01, 1.8674771616737459e-01, 1.8035805565273866e-01, 1.6246837812900003e-01, 1.3650006936059866e-01, 1.0695235327964076e-01, 7.8142792739003333e-02, 5.3230566834836512e-02, 3.3800561758698749e-02, 2.0002251583713944e-02, 1.1028376452466447e-02, 5.6635846018365278e-03, 2.7081400657517538e-03, 1.2052761990741546e-03, 4.9906383375612176e-04, 1.9216752502494505e-04, 6.8776486666748005e-05, 2.2866437400066508e-05, 7.0582654033955854e-06, 2.0214361392302868e-06, 5.3676540058539977e-07, 1.3205310627276386e-07, 3.0075005874343488e-08, 6.3355479710981103e-09, 1.2333492148378478e-09, 2.2165913480620041e-10, 3.6739040139866195e-11, 5.6095283428337204e-12, 7.8806482946078899e-13, 1.0173726615206055e-13, 1.2052816831862512e-14, 1.3084437330245737e-15, 1.2995830094215584e-16, 1.1789993455088293e-17, 9.7524056424221390e-19, 7.3412947992638873e-20, 5.0189377569399244e-21, 3.1094324529576228e-22, 1.7416595619626179e-23, 8.7976197776883766e-25, 3.9967858207858083e-26, 1.6282950449666844e-27, 5.9301271167711558e-29, 1.9240852596678829e-30, 5.5412911024876112e-32, 1.4108563317113768e-33, 3.1618692048946272e-35, 6.2076082159887624e-37, 1.0620797611432563e-38, 1.5745331638769155e-40, 2.0098426331457899e-42, 2.1935503204230003e-44, 2.0310845466149993e-46, 1.5817079781846762e-48, 1.0258876994968507e-50, 5.4809275321322830e-53, 2.3819600570060440e-55, 8.3001996570148669e-58, 2.2808008160100623e-60, 4.8472018976182706e-63, 7.7863635474467061e-66, 9.1980779235827154e-69, 7.7285235953959866e-72, 4.4321525706156201e-75, 1.6465801492558192e-78, 3.7027394072850406e-82, 4.5998341384092458e-86, 2.7751659416516980e-90, 6.7017830703194019e-95, 4.7131990325935266e-100, 5.2617952692292333e-106, 1.9806611743021416e-113}, + {2.8379348362554196e-114, 7.8858321167381958e-107, 7.3351907294176643e-101, 1.0791401722330717e-95, 4.6128120689561502e-91, 7.8796483529297319e-87, 6.5291103196563761e-83, 2.9859071017101074e-79, 8.2594238150373050e-76, 1.4791530184295327e-72, 1.8070968918430098e-69, 1.5696742395566467e-66, 1.0023248619238131e-63, 4.8364134393087594e-61, 1.8044278404363096e-58, 5.3077896463877236e-56, 1.2516691340073944e-53, 2.4006692740362835e-51, 3.7923450617699092e-49, 4.9890808610628276e-47, 5.5197834921993867e-45, 5.1808064286331934e-43, 4.1575196368970433e-41, 2.8726311560209485e-39, 1.7198340431536187e-37, 8.9732693547519472e-36, 4.1015179356507749e-34, 1.6502257188992863e-32, 5.8701285325766118e-31, 1.8535450041434515e-29, 5.2145562564115323e-28, 1.3115164390064590e-26, 2.9583134344508206e-25, 6.0020532911752611e-24, 1.0982988908956421e-22, 1.8172013379429154e-21, 2.7250115798124682e-20, 3.7116593876307894e-19, 4.6014038935013638e-18, 5.2019302408782819e-17, 5.3723712748625257e-16, 5.0771526984812688e-15, 4.3975029340499356e-14, 3.4959048726655372e-13, 2.5543256450392521e-12, 1.7175688761100677e-11, 1.0641335972971535e-10, 6.0815188314211019e-10, 3.2093758879421831e-09, 1.5654930566151192e-08, 7.0648903615829459e-08, 2.9522889815634413e-07, 1.1433046682221214e-06, 4.1062137791532273e-06, 1.3686795544658825e-05, 4.2366755055396916e-05, 1.2186350361528871e-04, 3.2590355495495157e-04, 8.1076372459361551e-04, 1.8771268090367514e-03, 4.0464432735401257e-03, 8.1246183048277309e-03, 1.5199679576417248e-02, 2.6503531097710236e-02, 4.3085461690763743e-02, 6.5316009514185674e-02, 9.2354740298272661e-02, 1.2182123832712786e-01, 1.4992351472225099e-01, 1.7216437167539980e-01, 1.8448997083421120e-01, 1.8448997083421120e-01, 1.7216437167539980e-01, 1.4992351472225099e-01, 1.2182123832712786e-01, 9.2354740298272661e-02, 6.5316009514185674e-02, 4.3085461690763743e-02, 2.6503531097710236e-02, 1.5199679576417248e-02, 8.1246183048277309e-03, 4.0464432735401257e-03, 1.8771268090367514e-03, 8.1076372459361551e-04, 3.2590355495495157e-04, 1.2186350361528871e-04, 4.2366755055396916e-05, 1.3686795544658825e-05, 4.1062137791532273e-06, 1.1433046682221214e-06, 2.9522889815634413e-07, 7.0648903615829459e-08, 1.5654930566151192e-08, 3.2093758879421831e-09, 6.0815188314211019e-10, 1.0641335972971535e-10, 1.7175688761100677e-11, 2.5543256450392521e-12, 3.4959048726655372e-13, 4.3975029340499356e-14, 5.0771526984812688e-15, 5.3723712748625257e-16, 5.2019302408782819e-17, 4.6014038935013638e-18, 3.7116593876307894e-19, 2.7250115798124682e-20, 1.8172013379429154e-21, 1.0982988908956421e-22, 6.0020532911752611e-24, 2.9583134344508206e-25, 1.3115164390064590e-26, 5.2145562564115323e-28, 1.8535450041434515e-29, 5.8701285325766118e-31, 1.6502257188992863e-32, 4.1015179356507749e-34, 8.9732693547519472e-36, 1.7198340431536187e-37, 2.8726311560209485e-39, 4.1575196368970433e-41, 5.1808064286331934e-43, 5.5197834921993867e-45, 4.9890808610628276e-47, 3.7923450617699092e-49, 2.4006692740362835e-51, 1.2516691340073944e-53, 5.3077896463877236e-56, 1.8044278404363096e-58, 4.8364134393087594e-61, 1.0023248619238131e-63, 1.5696742395566467e-66, 1.8070968918430098e-69, 1.4791530184295327e-72, 8.2594238150373050e-76, 2.9859071017101074e-79, 6.5291103196563761e-83, 7.8796483529297319e-87, 4.6128120689561502e-91, 1.0791401722330717e-95, 7.3351907294176643e-101, 7.8858321167381958e-107, 2.8379348362554196e-114}, + {4.0651653045385065e-115, 1.1812699945481087e-107, 1.1408091037467098e-101, 1.7361831916251206e-96, 7.6595061701919539e-92, 1.3482180200386414e-87, 1.1497555722475321e-83, 5.4065905193630812e-80, 1.5366409186618650e-76, 2.8258657002435720e-73, 3.5434157687072630e-70, 3.1577316852342737e-67, 2.0680029879339054e-64, 1.0231020536481417e-61, 3.9127659587819162e-59, 1.1795593319147925e-56, 2.8502626581292134e-54, 5.6008912228881934e-52, 9.0638661704615042e-50, 1.2214291755276681e-47, 1.3841464531877442e-45, 1.3306007915064349e-43, 1.0936052280580312e-41, 7.7388088770231391e-40, 4.7451186753733802e-38, 2.5356047070173512e-36, 1.1870121009809329e-34, 4.8915667031805749e-33, 1.7822371990214424e-31, 5.7644513660319519e-30, 1.6612582615477246e-28, 4.2804618347791540e-27, 9.8922322140449142e-26, 2.0564738212957134e-24, 3.8562115828650105e-23, 6.5389458924467930e-22, 1.0050517825377878e-20, 1.4033245536407663e-19, 1.7836445099325982e-18, 2.0676254282785005e-17, 2.1899168813282935e-16, 2.1227770911527276e-15, 1.8861860904057362e-14, 1.5385347856793465e-13, 1.1536439246054796e-12, 7.9623160515403962e-12, 5.0644993569234348e-11, 2.9720520664121096e-10, 1.6108731738857700e-09, 8.0720587699486656e-09, 3.7430932220185756e-08, 1.6076054796089227e-07, 6.4000756781336375e-07, 2.3636229043243477e-06, 8.1033917859954005e-06, 2.5807006976135383e-05, 7.6393528572820399e-05, 2.1031479179566012e-04, 5.3877140763670364e-04, 1.2849006257472789e-03, 2.8540126420656033e-03, 5.9065989999834033e-03, 1.1393877212953164e-02, 2.0492691616955331e-02, 3.4375183073736520e-02, 5.3792186966533914e-02, 7.8544533849893697e-02, 1.0703228204562122e-01, 1.3613832142377319e-01, 1.6164525387078738e-01, 1.7918358709477061e-01, 1.8544178808228795e-01, 1.7918358709477061e-01, 1.6164525387078738e-01, 1.3613832142377319e-01, 1.0703228204562122e-01, 7.8544533849893697e-02, 5.3792186966533914e-02, 3.4375183073736520e-02, 2.0492691616955331e-02, 1.1393877212953164e-02, 5.9065989999834033e-03, 2.8540126420656033e-03, 1.2849006257472789e-03, 5.3877140763670364e-04, 2.1031479179566012e-04, 7.6393528572820399e-05, 2.5807006976135383e-05, 8.1033917859954005e-06, 2.3636229043243477e-06, 6.4000756781336375e-07, 1.6076054796089227e-07, 3.7430932220185756e-08, 8.0720587699486656e-09, 1.6108731738857700e-09, 2.9720520664121096e-10, 5.0644993569234348e-11, 7.9623160515403962e-12, 1.1536439246054796e-12, 1.5385347856793465e-13, 1.8861860904057362e-14, 2.1227770911527276e-15, 2.1899168813282935e-16, 2.0676254282785005e-17, 1.7836445099325982e-18, 1.4033245536407663e-19, 1.0050517825377878e-20, 6.5389458924467930e-22, 3.8562115828650105e-23, 2.0564738212957134e-24, 9.8922322140449142e-26, 4.2804618347791540e-27, 1.6612582615477246e-28, 5.7644513660319519e-30, 1.7822371990214424e-31, 4.8915667031805749e-33, 1.1870121009809329e-34, 2.5356047070173512e-36, 4.7451186753733802e-38, 7.7388088770231391e-40, 1.0936052280580312e-41, 1.3306007915064349e-43, 1.3841464531877442e-45, 1.2214291755276681e-47, 9.0638661704615042e-50, 5.6008912228881934e-52, 2.8502626581292134e-54, 1.1795593319147925e-56, 3.9127659587819162e-59, 1.0231020536481417e-61, 2.0680029879339054e-64, 3.1577316852342737e-67, 3.5434157687072630e-70, 2.8258657002435720e-73, 1.5366409186618650e-76, 5.4065905193630812e-80, 1.1497555722475321e-83, 1.3482180200386414e-87, 7.6595061701919539e-92, 1.7361831916251206e-96, 1.1408091037467098e-101, 1.1812699945481087e-107, 4.0651653045385065e-115}, + {5.8215540266145185e-116, 1.7686479321265132e-108, 1.7730623068856681e-102, 2.7909232189455364e-97, 1.2705722231489315e-92, 2.3041370774073117e-88, 2.0220172247445533e-84, 9.7753535494291230e-81, 2.8542469937135876e-77, 5.3891664187060082e-74, 6.9347342664174447e-71, 6.3393303649456501e-68, 4.2572743226051364e-65, 2.1591730776951801e-62, 8.4632278622572117e-60, 2.6143765867593842e-57, 6.4722677680216748e-55, 1.3028416632725528e-52, 2.1595419825453231e-50, 2.9805109745607960e-48, 3.4589808905752308e-46, 3.4051398010375247e-44, 2.8658496493850430e-42, 2.0766525261834300e-40, 1.3038602059242759e-38, 7.1344872719593792e-37, 3.4201248592076866e-35, 1.4432903376167608e-33, 5.3852783517497647e-32, 1.7838570362707828e-30, 5.2653274547677795e-29, 1.3896193908215000e-27, 3.2896623243386845e-26, 7.0060070837042623e-25, 1.3459870964148325e-23, 2.3386559482775554e-22, 3.6836215601895347e-21, 5.2713950568645777e-20, 6.8677255495973648e-19, 8.1615638298029365e-18, 8.8631701623207850e-17, 8.8103300045560730e-16, 8.0291277303592449e-15, 6.7183131113433536e-14, 5.1685673461842002e-13, 3.6606905840155156e-12, 2.3898379902347417e-11, 1.4397371489675669e-10, 8.0125910717950545e-10, 4.1235783120777111e-09, 1.9642460747885040e-08, 8.6680352990322611e-08, 3.5465537239549829e-07, 1.3464428002356888e-06, 4.7465352780258519e-06, 1.5547603684619328e-05, 4.7349798947666790e-05, 1.3415011473384580e-04, 3.5376394702118597e-04, 8.6875807961727194e-04, 1.9876616088445901e-03, 4.2386040557315851e-03, 8.4275632150598145e-03, 1.5628807300276451e-02, 2.7041109022394049e-02, 4.3662930188759774e-02, 6.5809838711917215e-02, 9.2606922401635969e-02, 1.2168620186278144e-01, 1.4932782014181728e-01, 1.7115266931753381e-01, 1.8323066902877375e-01, 1.8323066902877375e-01, 1.7115266931753381e-01, 1.4932782014181728e-01, 1.2168620186278144e-01, 9.2606922401635969e-02, 6.5809838711917215e-02, 4.3662930188759774e-02, 2.7041109022394049e-02, 1.5628807300276451e-02, 8.4275632150598145e-03, 4.2386040557315851e-03, 1.9876616088445901e-03, 8.6875807961727194e-04, 3.5376394702118597e-04, 1.3415011473384580e-04, 4.7349798947666790e-05, 1.5547603684619328e-05, 4.7465352780258519e-06, 1.3464428002356888e-06, 3.5465537239549829e-07, 8.6680352990322611e-08, 1.9642460747885040e-08, 4.1235783120777111e-09, 8.0125910717950545e-10, 1.4397371489675669e-10, 2.3898379902347417e-11, 3.6606905840155156e-12, 5.1685673461842002e-13, 6.7183131113433536e-14, 8.0291277303592449e-15, 8.8103300045560730e-16, 8.8631701623207850e-17, 8.1615638298029365e-18, 6.8677255495973648e-19, 5.2713950568645777e-20, 3.6836215601895347e-21, 2.3386559482775554e-22, 1.3459870964148325e-23, 7.0060070837042623e-25, 3.2896623243386845e-26, 1.3896193908215000e-27, 5.2653274547677795e-29, 1.7838570362707828e-30, 5.3852783517497647e-32, 1.4432903376167608e-33, 3.4201248592076866e-35, 7.1344872719593792e-37, 1.3038602059242759e-38, 2.0766525261834300e-40, 2.8658496493850430e-42, 3.4051398010375247e-44, 3.4589808905752308e-46, 2.9805109745607960e-48, 2.1595419825453231e-50, 1.3028416632725528e-52, 6.4722677680216748e-55, 2.6143765867593842e-57, 8.4632278622572117e-60, 2.1591730776951801e-62, 4.2572743226051364e-65, 6.3393303649456501e-68, 6.9347342664174447e-71, 5.3891664187060082e-74, 2.8542469937135876e-77, 9.7753535494291230e-81, 2.0220172247445533e-84, 2.3041370774073117e-88, 1.2705722231489315e-92, 2.7909232189455364e-97, 1.7730623068856681e-102, 1.7686479321265132e-108, 5.8215540266145185e-116}, + {8.3346219931731252e-117, 2.6468336179684675e-109, 2.7538984203799183e-103, 4.4826957080916534e-98, 2.1055559670183425e-93, 3.9333042153463284e-89, 3.5513952096001502e-85, 1.7648636462384819e-81, 5.2931716200065506e-78, 1.0259659682881671e-74, 1.3546124768341285e-71, 1.2700634063455813e-68, 8.7450484044987438e-66, 4.5461329246587614e-63, 1.8260394178147789e-60, 5.7792816013390868e-58, 1.4656166079834788e-55, 3.0217106412347761e-53, 5.1294451668154943e-51, 7.2494810877533628e-49, 8.6147071643386152e-47, 8.6832052790729524e-45, 7.4822992810294955e-43, 5.5510153038363309e-41, 3.5683132140145833e-39, 1.9990336800405551e-37, 9.8114235481332920e-36, 4.2392471038699379e-34, 1.6195898700068922e-32, 5.4933861932302487e-31, 1.6604056318842839e-29, 4.4876913417614677e-28, 1.0880533660044361e-26, 2.3734409390889848e-25, 4.6708788240159748e-24, 8.3141586271431848e-23, 1.3417423881673005e-21, 1.9674928839115667e-20, 2.6269310713002712e-19, 3.1997441855901569e-18, 3.5620366003569210e-17, 3.6302240823037884e-16, 3.3924183801506980e-15, 2.9112006503092275e-14, 2.2973505987627707e-13, 1.6693328537504025e-12, 1.1182840247910251e-11, 6.9144057864820654e-11, 3.9502105053420148e-10, 2.0873156939372195e-09, 1.0211061576622443e-08, 4.6286545842406255e-08, 1.9458139349161944e-07, 7.5918662435991949e-07, 2.7511365949804849e-06, 9.2658749369498393e-06, 2.9023198119388909e-05, 8.4594658849625380e-05, 2.2956989796967087e-04, 5.8033480492528523e-04, 1.3672056490331354e-03, 3.0030570133818706e-03, 6.1522556633449429e-03, 1.1759716605478240e-02, 2.0979064379787655e-02, 3.4939934715514299e-02, 5.4338778627529040e-02, 7.8929618144152600e-02, 1.0709980745724954e-01, 1.3577444219071524e-01, 1.6083336191837752e-01, 1.7803169108709616e-01, 1.8416287919896177e-01, 1.7803169108709616e-01, 1.6083336191837752e-01, 1.3577444219071524e-01, 1.0709980745724954e-01, 7.8929618144152600e-02, 5.4338778627529040e-02, 3.4939934715514299e-02, 2.0979064379787655e-02, 1.1759716605478240e-02, 6.1522556633449429e-03, 3.0030570133818706e-03, 1.3672056490331354e-03, 5.8033480492528523e-04, 2.2956989796967087e-04, 8.4594658849625380e-05, 2.9023198119388909e-05, 9.2658749369498393e-06, 2.7511365949804849e-06, 7.5918662435991949e-07, 1.9458139349161944e-07, 4.6286545842406255e-08, 1.0211061576622443e-08, 2.0873156939372195e-09, 3.9502105053420148e-10, 6.9144057864820654e-11, 1.1182840247910251e-11, 1.6693328537504025e-12, 2.2973505987627707e-13, 2.9112006503092275e-14, 3.3924183801506980e-15, 3.6302240823037884e-16, 3.5620366003569210e-17, 3.1997441855901569e-18, 2.6269310713002712e-19, 1.9674928839115667e-20, 1.3417423881673005e-21, 8.3141586271431848e-23, 4.6708788240159748e-24, 2.3734409390889848e-25, 1.0880533660044361e-26, 4.4876913417614677e-28, 1.6604056318842839e-29, 5.4933861932302487e-31, 1.6195898700068922e-32, 4.2392471038699379e-34, 9.8114235481332920e-36, 1.9990336800405551e-37, 3.5683132140145833e-39, 5.5510153038363309e-41, 7.4822992810294955e-43, 8.6832052790729524e-45, 8.6147071643386152e-47, 7.2494810877533628e-49, 5.1294451668154943e-51, 3.0217106412347761e-53, 1.4656166079834788e-55, 5.7792816013390868e-58, 1.8260394178147789e-60, 4.5461329246587614e-63, 8.7450484044987438e-66, 1.2700634063455813e-68, 1.3546124768341285e-71, 1.0259659682881671e-74, 5.2931716200065506e-78, 1.7648636462384819e-81, 3.5513952096001502e-85, 3.9333042153463284e-89, 2.1055559670183425e-93, 4.4826957080916534e-98, 2.7538984203799183e-103, 2.6468336179684675e-109, 8.3346219931731252e-117}, + {1.1929450990497388e-117, 3.9591990974598804e-110, 4.2745275541790886e-104, 7.1940582732963705e-99, 3.4858463341267156e-94, 6.7067764488470954e-90, 6.2295239916515678e-86, 3.1817588164569700e-82, 9.8006355361055656e-79, 1.9498222863573950e-75, 2.6411200905371024e-72, 2.5394077671157272e-69, 1.7924826309087973e-66, 9.5498361457830398e-64, 3.9302490205746199e-61, 1.2742413782141750e-58, 3.3097280501169341e-56, 6.9880745770528625e-54, 1.2146673922184433e-51, 1.7576627452371236e-49, 2.1383500879761454e-47, 2.2064997583491492e-45, 1.9463790072121561e-43, 1.4781646220486795e-41, 9.7267315160133413e-40, 5.5780033470752983e-38, 2.8025392714968451e-36, 1.2395973767055291e-34, 4.8482501635459064e-33, 1.6835590125100971e-31, 5.2099674531110126e-30, 1.4417990594032542e-28, 3.5795224098780112e-27, 7.9961758900246410e-26, 1.6116510554151974e-24, 2.9383411496603336e-23, 4.8574792709615864e-22, 7.2973076814277955e-21, 9.9829502923346154e-20, 1.2460703643781112e-18, 1.4216815546927034e-17, 1.4851721687462022e-16, 1.4228468795430129e-15, 1.2519744100239038e-14, 1.0132054243548976e-13, 7.5515422033135666e-13, 5.1897461393175068e-12, 3.2925485308161026e-11, 1.9304840630938534e-10, 1.0471078941135214e-09, 5.2592465173501358e-09, 2.4482298403820274e-08, 1.0571641536621842e-07, 4.2377549476354214e-07, 1.5781624324532756e-06, 5.4637147044287493e-06, 1.7596343655070067e-05, 5.2748866067347142e-05, 1.4726499921039843e-04, 3.8309201801330436e-04, 9.2902602860733265e-04, 2.1011697743361312e-03, 4.4337774736073364e-03, 8.7321528128579372e-03, 1.6056218663448245e-02, 2.7571764216085648e-02, 4.4227798774476149e-02, 6.6287455917162549e-02, 9.2844091734104794e-02, 1.2154351785304160e-01, 1.4873661992593393e-01, 1.7015822429768401e-01, 1.8199680336473223e-01, 1.8199680336473223e-01, 1.7015822429768401e-01, 1.4873661992593393e-01, 1.2154351785304160e-01, 9.2844091734104794e-02, 6.6287455917162549e-02, 4.4227798774476149e-02, 2.7571764216085648e-02, 1.6056218663448245e-02, 8.7321528128579372e-03, 4.4337774736073364e-03, 2.1011697743361312e-03, 9.2902602860733265e-04, 3.8309201801330436e-04, 1.4726499921039843e-04, 5.2748866067347142e-05, 1.7596343655070067e-05, 5.4637147044287493e-06, 1.5781624324532756e-06, 4.2377549476354214e-07, 1.0571641536621842e-07, 2.4482298403820274e-08, 5.2592465173501358e-09, 1.0471078941135214e-09, 1.9304840630938534e-10, 3.2925485308161026e-11, 5.1897461393175068e-12, 7.5515422033135666e-13, 1.0132054243548976e-13, 1.2519744100239038e-14, 1.4228468795430129e-15, 1.4851721687462022e-16, 1.4216815546927034e-17, 1.2460703643781112e-18, 9.9829502923346154e-20, 7.2973076814277955e-21, 4.8574792709615864e-22, 2.9383411496603336e-23, 1.6116510554151974e-24, 7.9961758900246410e-26, 3.5795224098780112e-27, 1.4417990594032542e-28, 5.2099674531110126e-30, 1.6835590125100971e-31, 4.8482501635459064e-33, 1.2395973767055291e-34, 2.8025392714968451e-36, 5.5780033470752983e-38, 9.7267315160133413e-40, 1.4781646220486795e-41, 1.9463790072121561e-43, 2.2064997583491492e-45, 2.1383500879761454e-47, 1.7576627452371236e-49, 1.2146673922184433e-51, 6.9880745770528625e-54, 3.3097280501169341e-56, 1.2742413782141750e-58, 3.9302490205746199e-61, 9.5498361457830398e-64, 1.7924826309087973e-66, 2.5394077671157272e-69, 2.6411200905371024e-72, 1.9498222863573950e-75, 9.8006355361055656e-79, 3.1817588164569700e-82, 6.2295239916515678e-86, 6.7067764488470954e-90, 3.4858463341267156e-94, 7.1940582732963705e-99, 4.2745275541790886e-104, 3.9591990974598804e-110, 1.1929450990497388e-117}, + {1.7070406181366590e-118, 5.9195113844414591e-111, 6.6305252022274385e-105, 1.1536024679706741e-99, 5.7653910975637400e-95, 1.1423077010030593e-90, 1.0913377348991997e-86, 5.7280704066660911e-83, 1.8118187632234171e-79, 3.6992788142779886e-76, 5.1399529790115008e-73, 5.0672863794680850e-70, 3.6662464654865143e-67, 2.0015272638354942e-64, 8.4387742209978957e-62, 2.8023099391369100e-59, 7.4539706347406648e-57, 1.6114689883841890e-54, 2.8677408135139503e-52, 4.2481015098521193e-50, 5.2903245181279725e-48, 5.5876178971908134e-46, 5.0448907217391667e-44, 3.9213661446271294e-42, 2.6409880203075402e-40, 1.5501131114814050e-38, 7.9712569158416828e-37, 3.6087469701637568e-35, 1.4446952835847923e-33, 5.1351616577255980e-32, 1.6267414726790182e-30, 4.6086441078964235e-29, 1.1714111882873408e-27, 2.6792736258069186e-26, 5.5296079664300731e-25, 1.0324183959837516e-23, 1.7479927721363103e-22, 2.6897676451867309e-21, 3.7695192606286801e-20, 4.8205800888162673e-19, 5.6356840948811206e-18, 6.0335058787737898e-17, 5.9246665636288388e-16, 5.3441830122937569e-15, 4.4343905593075405e-14, 3.3891924837505246e-13, 2.3889528428660744e-12, 1.5547996800001229e-11, 9.3534621545646173e-11, 5.2065241132424465e-10, 2.6842310976125569e-09, 1.2828665113850952e-08, 5.6885421998531753e-08, 2.3421973604647242e-07, 8.9613156437377830e-07, 3.1882138059205163e-06, 1.0554357586582146e-05, 3.2530204545596872e-05, 9.3401898795249160e-05, 2.4995620584101932e-04, 6.2376294512410423e-04, 1.4521587444586976e-03, 3.1551701974875863e-03, 6.4003731513496125e-03, 1.2125677167472506e-02, 2.1461222380505476e-02, 3.5494877838398289e-02, 5.4870701544829148e-02, 7.9298651231443446e-02, 1.0715555306319222e-01, 1.3540875492462576e-01, 1.6003249638444184e-01, 1.7690165636825916e-01, 1.8291007049692826e-01, 1.7690165636825916e-01, 1.6003249638444184e-01, 1.3540875492462576e-01, 1.0715555306319222e-01, 7.9298651231443446e-02, 5.4870701544829148e-02, 3.5494877838398289e-02, 2.1461222380505476e-02, 1.2125677167472506e-02, 6.4003731513496125e-03, 3.1551701974875863e-03, 1.4521587444586976e-03, 6.2376294512410423e-04, 2.4995620584101932e-04, 9.3401898795249160e-05, 3.2530204545596872e-05, 1.0554357586582146e-05, 3.1882138059205163e-06, 8.9613156437377830e-07, 2.3421973604647242e-07, 5.6885421998531753e-08, 1.2828665113850952e-08, 2.6842310976125569e-09, 5.2065241132424465e-10, 9.3534621545646173e-11, 1.5547996800001229e-11, 2.3889528428660744e-12, 3.3891924837505246e-13, 4.4343905593075405e-14, 5.3441830122937569e-15, 5.9246665636288388e-16, 6.0335058787737898e-17, 5.6356840948811206e-18, 4.8205800888162673e-19, 3.7695192606286801e-20, 2.6897676451867309e-21, 1.7479927721363103e-22, 1.0324183959837516e-23, 5.5296079664300731e-25, 2.6792736258069186e-26, 1.1714111882873408e-27, 4.6086441078964235e-29, 1.6267414726790182e-30, 5.1351616577255980e-32, 1.4446952835847923e-33, 3.6087469701637568e-35, 7.9712569158416828e-37, 1.5501131114814050e-38, 2.6409880203075402e-40, 3.9213661446271294e-42, 5.0448907217391667e-44, 5.5876178971908134e-46, 5.2903245181279725e-48, 4.2481015098521193e-50, 2.8677408135139503e-52, 1.6114689883841890e-54, 7.4539706347406648e-57, 2.8023099391369100e-59, 8.4387742209978957e-62, 2.0015272638354942e-64, 3.6662464654865143e-67, 5.0672863794680850e-70, 5.1399529790115008e-73, 3.6992788142779886e-76, 1.8118187632234171e-79, 5.7280704066660911e-83, 1.0913377348991997e-86, 1.1423077010030593e-90, 5.7653910975637400e-95, 1.1536024679706741e-99, 6.6305252022274385e-105, 5.9195113844414591e-111, 1.7070406181366590e-118}, + {2.4420658728359029e-119, 8.8463582669186499e-112, 1.0278520435124409e-105, 1.8483749220636043e-100, 9.5264999562099965e-96, 1.9434401044261462e-91, 1.9094951070499896e-87, 1.0297738588062730e-83, 3.3443041190506409e-80, 7.0066129472632568e-77, 9.9847674734222346e-74, 1.0091718959432019e-70, 7.4829681064377069e-68, 4.1855384000761587e-65, 1.8075959008515128e-62, 6.1472579038779528e-60, 1.6742548573659892e-57, 3.7056307854458431e-55, 6.7504839696392484e-53, 1.0235353311199910e-50, 1.3045775870281223e-48, 1.4101600092151863e-46, 1.3029538434289154e-44, 1.0364256329737640e-42, 7.1430632340356861e-41, 4.2904029597408759e-39, 2.2577848908542067e-37, 1.0460259894518416e-35, 4.2855476518701719e-34, 1.5590004744721381e-32, 5.0546933927274757e-31, 1.4657489608244835e-29, 3.8136046756805110e-28, 8.9292832689033937e-27, 1.8867047659679220e-25, 3.6067468226756066e-24, 6.2530721763179845e-23, 9.8539255836953708e-22, 1.4143965820612745e-20, 1.8527994733871280e-19, 2.2190951508494865e-18, 2.4342129329346826e-17, 2.4494846944487187e-16, 2.2645381737872469e-15, 1.9261422339406544e-14, 1.5093097961491213e-13, 1.0909182729913857e-12, 7.2818111329385306e-12, 4.4936440478669596e-11, 2.5663720011644112e-10, 1.3577644240845783e-09, 6.6605391288638309e-09, 3.0321186483039541e-08, 1.2819858780710668e-07, 5.0378676249733306e-07, 1.8413731465659074e-06, 6.2640223021607951e-06, 1.9844802959774770e-05, 5.8582692413005888e-05, 1.6123158507144338e-04, 4.1390553680515079e-04, 9.9155807247580142e-04, 2.2175853317597280e-03, 4.6318204121044990e-03, 9.0381820758826531e-03, 1.6481721286763326e-02, 2.8095443629279886e-02, 4.4780275406602559e-02, 6.6749354510874270e-02, 9.3066885205695463e-02, 1.2139368280029710e-01, 1.4814998194065979e-01, 1.6918056507168472e-01, 1.8078752906102052e-01, 1.8078752906102052e-01, 1.6918056507168472e-01, 1.4814998194065979e-01, 1.2139368280029710e-01, 9.3066885205695463e-02, 6.6749354510874270e-02, 4.4780275406602559e-02, 2.8095443629279886e-02, 1.6481721286763326e-02, 9.0381820758826531e-03, 4.6318204121044990e-03, 2.2175853317597280e-03, 9.9155807247580142e-04, 4.1390553680515079e-04, 1.6123158507144338e-04, 5.8582692413005888e-05, 1.9844802959774770e-05, 6.2640223021607951e-06, 1.8413731465659074e-06, 5.0378676249733306e-07, 1.2819858780710668e-07, 3.0321186483039541e-08, 6.6605391288638309e-09, 1.3577644240845783e-09, 2.5663720011644112e-10, 4.4936440478669596e-11, 7.2818111329385306e-12, 1.0909182729913857e-12, 1.5093097961491213e-13, 1.9261422339406544e-14, 2.2645381737872469e-15, 2.4494846944487187e-16, 2.4342129329346826e-17, 2.2190951508494865e-18, 1.8527994733871280e-19, 1.4143965820612745e-20, 9.8539255836953708e-22, 6.2530721763179845e-23, 3.6067468226756066e-24, 1.8867047659679220e-25, 8.9292832689033937e-27, 3.8136046756805110e-28, 1.4657489608244835e-29, 5.0546933927274757e-31, 1.5590004744721381e-32, 4.2855476518701719e-34, 1.0460259894518416e-35, 2.2577848908542067e-37, 4.2904029597408759e-39, 7.1430632340356861e-41, 1.0364256329737640e-42, 1.3029538434289154e-44, 1.4101600092151863e-46, 1.3045775870281223e-48, 1.0235353311199910e-50, 6.7504839696392484e-53, 3.7056307854458431e-55, 1.6742548573659892e-57, 6.1472579038779528e-60, 1.8075959008515128e-62, 4.1855384000761587e-65, 7.4829681064377069e-68, 1.0091718959432019e-70, 9.9847674734222346e-74, 7.0066129472632568e-77, 3.3443041190506409e-80, 1.0297738588062730e-83, 1.9094951070499896e-87, 1.9434401044261462e-91, 9.5264999562099965e-96, 1.8483749220636043e-100, 1.0278520435124409e-105, 8.8463582669186499e-112, 2.4420658728359029e-119}, + {3.4927077138614495e-120, 1.3214344265685972e-112, 1.5923529644019419e-106, 2.9592365392916602e-101, 1.5726312834383212e-96, 3.3028107528503361e-92, 3.3368715475506461e-88, 1.8487368270391726e-84, 6.1636129673212566e-81, 1.3248817176167857e-77, 1.9361289427704634e-74, 2.0059128285660820e-71, 1.5241335107478225e-68, 8.7332836494574003e-66, 3.8627717414010648e-63, 1.3451211690839924e-60, 3.7506692343030420e-58, 8.4975513070583486e-56, 1.5843787624675853e-53, 2.4585380900294205e-51, 3.2067130430374953e-49, 3.5468958347722111e-47, 3.3533561409072355e-45, 2.7292702435888796e-43, 1.9246140375840066e-41, 1.1827867549833032e-39, 6.3685955808210726e-38, 3.0190103270136603e-36, 1.2656167558393507e-34, 4.7112145637232019e-33, 1.5631232313432506e-31, 4.6386822641081590e-30, 1.2351960569462707e-28, 2.9601529366809405e-27, 6.4022761029959671e-26, 1.2529044419038621e-24, 2.2238719447561208e-23, 3.5882695810709981e-22, 5.2741804743987912e-21, 7.0757399180811555e-20, 8.6802800075429983e-19, 9.7541289549630027e-18, 1.0056284258182538e-16, 9.5266259491509481e-16, 8.3044572801891268e-15, 6.6701332750751410e-14, 4.9425874408492004e-13, 3.3828553008734636e-12, 2.1409348303068694e-11, 1.2542010220460425e-10, 6.8076912279459116e-10, 3.4268964379715692e-09, 1.6011995715635929e-08, 6.9500026302554605e-08, 2.8044586426011501e-07, 1.0528006766858483e-06, 3.6792955563634022e-06, 1.1977707839841136e-05, 3.6343264722217326e-05, 1.0283673489115176e-04, 2.7149548605395329e-04, 6.6906197625873226e-04, 1.5397243486054463e-03, 3.3102482665201089e-03, 6.6507742518744171e-03, 1.2491552298533356e-02, 2.1939032537498546e-02, 3.6040083142086628e-02, 5.5388310278285176e-02, 7.9652215262150924e-02, 1.0720010935792797e-01, 1.3504155894527325e-01, 1.5924245367972575e-01, 1.7579280253635429e-01, 1.8168248613117691e-01, 1.7579280253635429e-01, 1.5924245367972575e-01, 1.3504155894527325e-01, 1.0720010935792797e-01, 7.9652215262150924e-02, 5.5388310278285176e-02, 3.6040083142086628e-02, 2.1939032537498546e-02, 1.2491552298533356e-02, 6.6507742518744171e-03, 3.3102482665201089e-03, 1.5397243486054463e-03, 6.6906197625873226e-04, 2.7149548605395329e-04, 1.0283673489115176e-04, 3.6343264722217326e-05, 1.1977707839841136e-05, 3.6792955563634022e-06, 1.0528006766858483e-06, 2.8044586426011501e-07, 6.9500026302554605e-08, 1.6011995715635929e-08, 3.4268964379715692e-09, 6.8076912279459116e-10, 1.2542010220460425e-10, 2.1409348303068694e-11, 3.3828553008734636e-12, 4.9425874408492004e-13, 6.6701332750751410e-14, 8.3044572801891268e-15, 9.5266259491509481e-16, 1.0056284258182538e-16, 9.7541289549630027e-18, 8.6802800075429983e-19, 7.0757399180811555e-20, 5.2741804743987912e-21, 3.5882695810709981e-22, 2.2238719447561208e-23, 1.2529044419038621e-24, 6.4022761029959671e-26, 2.9601529366809405e-27, 1.2351960569462707e-28, 4.6386822641081590e-30, 1.5631232313432506e-31, 4.7112145637232019e-33, 1.2656167558393507e-34, 3.0190103270136603e-36, 6.3685955808210726e-38, 1.1827867549833032e-39, 1.9246140375840066e-41, 2.7292702435888796e-43, 3.3533561409072355e-45, 3.5468958347722111e-47, 3.2067130430374953e-49, 2.4585380900294205e-51, 1.5843787624675853e-53, 8.4975513070583486e-56, 3.7506692343030420e-58, 1.3451211690839924e-60, 3.8627717414010648e-63, 8.7332836494574003e-66, 1.5241335107478225e-68, 2.0059128285660820e-71, 1.9361289427704634e-74, 1.3248817176167857e-77, 6.1636129673212566e-81, 1.8487368270391726e-84, 3.3368715475506461e-88, 3.3028107528503361e-92, 1.5726312834383212e-96, 2.9592365392916602e-101, 1.5923529644019419e-106, 1.3214344265685972e-112, 3.4927077138614495e-120}, + {4.9941282442606218e-121, 1.9730195235183967e-113, 2.4653426103610859e-107, 4.7340081105291807e-102, 2.5936668261705122e-97, 5.6069447675960520e-93, 5.8240937771374570e-89, 3.3144783626996768e-85, 1.1342570222437056e-81, 2.5011096149430186e-78, 3.7476379174495528e-75, 3.9794814788876447e-72, 3.0979908735545725e-69, 1.8182439901095753e-66, 8.2354102738652040e-64, 2.9360923690156291e-61, 8.3803809757287599e-59, 1.9432660775004502e-56, 3.7079038793856585e-54, 5.8875467910577051e-52, 7.8572573935602256e-50, 8.8917221680510199e-48, 8.6005009516161168e-46, 7.1611639319733097e-44, 5.1661373788013124e-42, 3.2479669251550536e-40, 1.7890987177636214e-38, 8.6765699223362474e-37, 3.7212625316226216e-35, 1.4172340427766930e-33, 4.8110787981190828e-32, 1.4608586938294995e-30, 3.9805330733973355e-29, 9.7620761562971344e-28, 2.1608244949042565e-26, 4.3281046749583524e-25, 7.8636681438025253e-24, 1.2989130984240299e-22, 1.9546850118180088e-21, 2.6851626691585123e-20, 3.3733593511587544e-19, 3.8824303202657657e-18, 4.1001349905289425e-17, 3.9793051828221563e-16, 3.5542824359476288e-15, 2.9256051436471688e-14, 2.2220151125790449e-13, 1.5590549255574669e-12, 1.0116812009960419e-11, 6.0778437594159535e-11, 3.3838207012562939e-10, 1.7475098827142176e-09, 8.3784654573163473e-09, 3.7324734098992270e-08, 1.5461411843105312e-07, 5.9598254897039207e-07, 2.1391519688131322e-06, 7.1539515355890577e-06, 2.2304926470707147e-05, 6.4869805018180065e-05, 1.7607226778935711e-04, 4.4622007110453903e-04, 1.0563416857043819e-03, 2.3368400915518292e-03, 4.8325911868397145e-03, 9.3454535527143379e-03, 1.6905135871613127e-02, 2.8612106958160764e-02, 4.5320570847252710e-02, 6.7196013411209815e-02, 9.3275910346104995e-02, 1.2123716317285059e-01, 1.4756796236123393e-01, 1.6821923724022270e-01, 1.7960204009494329e-01, 1.7960204009494329e-01, 1.6821923724022270e-01, 1.4756796236123393e-01, 1.2123716317285059e-01, 9.3275910346104995e-02, 6.7196013411209815e-02, 4.5320570847252710e-02, 2.8612106958160764e-02, 1.6905135871613127e-02, 9.3454535527143379e-03, 4.8325911868397145e-03, 2.3368400915518292e-03, 1.0563416857043819e-03, 4.4622007110453903e-04, 1.7607226778935711e-04, 6.4869805018180065e-05, 2.2304926470707147e-05, 7.1539515355890577e-06, 2.1391519688131322e-06, 5.9598254897039207e-07, 1.5461411843105312e-07, 3.7324734098992270e-08, 8.3784654573163473e-09, 1.7475098827142176e-09, 3.3838207012562939e-10, 6.0778437594159535e-11, 1.0116812009960419e-11, 1.5590549255574669e-12, 2.2220151125790449e-13, 2.9256051436471688e-14, 3.5542824359476288e-15, 3.9793051828221563e-16, 4.1001349905289425e-17, 3.8824303202657657e-18, 3.3733593511587544e-19, 2.6851626691585123e-20, 1.9546850118180088e-21, 1.2989130984240299e-22, 7.8636681438025253e-24, 4.3281046749583524e-25, 2.1608244949042565e-26, 9.7620761562971344e-28, 3.9805330733973355e-29, 1.4608586938294995e-30, 4.8110787981190828e-32, 1.4172340427766930e-33, 3.7212625316226216e-35, 8.6765699223362474e-37, 1.7890987177636214e-38, 3.2479669251550536e-40, 5.1661373788013124e-42, 7.1611639319733097e-44, 8.6005009516161168e-46, 8.8917221680510199e-48, 7.8572573935602256e-50, 5.8875467910577051e-52, 3.7079038793856585e-54, 1.9432660775004502e-56, 8.3803809757287599e-59, 2.9360923690156291e-61, 8.2354102738652040e-64, 1.8182439901095753e-66, 3.0979908735545725e-69, 3.9794814788876447e-72, 3.7476379174495528e-75, 2.5011096149430186e-78, 1.1342570222437056e-81, 3.3144783626996768e-85, 5.8240937771374570e-89, 5.6069447675960520e-93, 2.5936668261705122e-97, 4.7340081105291807e-102, 2.4653426103610859e-107, 1.9730195235183967e-113, 4.9941282442606218e-121}, + {7.1392222017713907e-122, 2.9445845110667619e-114, 3.8145868837135596e-108, 7.5673169898909099e-103, 4.2736593644380303e-98, 9.5083335143727237e-94, 1.0152930470452851e-89, 5.9342954899998552e-86, 2.0842120266141319e-82, 4.7139344340961388e-79, 7.2413131304484502e-76, 7.8798610228883591e-73, 6.2842892805603737e-70, 3.7773465198180638e-67, 1.7517513408453002e-64, 6.3932209199477197e-62, 1.8676726441679446e-59, 4.4319273103122463e-57, 8.6528507374176976e-55, 1.4056977850593077e-52, 1.9192002948401386e-50, 2.2217716370141584e-48, 2.1982691386986115e-46, 1.8722764372760468e-44, 1.3815703248778117e-42, 8.8845643289761640e-41, 5.0058533566520875e-39, 2.4832338706643681e-37, 1.0894227474485724e-35, 4.2442335712525587e-34, 1.4739090369348960e-32, 4.5785676785685073e-31, 1.2763864929327656e-29, 3.2028196423033392e-28, 7.2542458795704827e-27, 1.4869262820581125e-25, 2.7648741131715751e-24, 4.6744604380487021e-23, 7.2007069149677438e-22, 1.0126623472614820e-20, 1.3025790505179032e-19, 1.5351372541981349e-18, 1.6603563330241997e-17, 1.6505566788948694e-16, 1.5102835946897961e-15, 1.2737138463928603e-14, 9.9133825544714478e-14, 7.1289732797212971e-13, 4.7421458438831827e-12, 2.9209512270101235e-11, 1.6676562560887225e-10, 8.8333847125166249e-10, 4.3447745740955300e-09, 1.9860254178505552e-08, 8.4433687619112637e-08, 3.3409895046160263e-07, 1.2312829806627210e-06, 4.2290221665164350e-06, 1.3544999036061644e-05, 4.0477621043373221e-05, 1.1292006863438276e-04, 2.9420790203745482e-04, 7.1623536508659178e-04, 1.6298641009901027e-03, 3.4681866693627482e-03, 6.9032861428781267e-03, 1.2857145952636101e-02, 2.2412375310366960e-02, 3.6575629838591243e-02, 5.5891953828813568e-02, 7.9990869817108165e-02, 1.0723403572962083e-01, 1.3467313142650547e-01, 1.5846303276659124e-01, 1.7470447835636663e-01, 1.8047929085878514e-01, 1.7470447835636663e-01, 1.5846303276659124e-01, 1.3467313142650547e-01, 1.0723403572962083e-01, 7.9990869817108165e-02, 5.5891953828813568e-02, 3.6575629838591243e-02, 2.2412375310366960e-02, 1.2857145952636101e-02, 6.9032861428781267e-03, 3.4681866693627482e-03, 1.6298641009901027e-03, 7.1623536508659178e-04, 2.9420790203745482e-04, 1.1292006863438276e-04, 4.0477621043373221e-05, 1.3544999036061644e-05, 4.2290221665164350e-06, 1.2312829806627210e-06, 3.3409895046160263e-07, 8.4433687619112637e-08, 1.9860254178505552e-08, 4.3447745740955300e-09, 8.8333847125166249e-10, 1.6676562560887225e-10, 2.9209512270101235e-11, 4.7421458438831827e-12, 7.1289732797212971e-13, 9.9133825544714478e-14, 1.2737138463928603e-14, 1.5102835946897961e-15, 1.6505566788948694e-16, 1.6603563330241997e-17, 1.5351372541981349e-18, 1.3025790505179032e-19, 1.0126623472614820e-20, 7.2007069149677438e-22, 4.6744604380487021e-23, 2.7648741131715751e-24, 1.4869262820581125e-25, 7.2542458795704827e-27, 3.2028196423033392e-28, 1.2763864929327656e-29, 4.5785676785685073e-31, 1.4739090369348960e-32, 4.2442335712525587e-34, 1.0894227474485724e-35, 2.4832338706643681e-37, 5.0058533566520875e-39, 8.8845643289761640e-41, 1.3815703248778117e-42, 1.8722764372760468e-44, 2.1982691386986115e-46, 2.2217716370141584e-48, 1.9192002948401386e-50, 1.4056977850593077e-52, 8.6528507374176976e-55, 4.4319273103122463e-57, 1.8676726441679446e-59, 6.3932209199477197e-62, 1.7517513408453002e-64, 3.7773465198180638e-67, 6.2842892805603737e-70, 7.8798610228883591e-73, 7.2413131304484502e-76, 4.7139344340961388e-79, 2.0842120266141319e-82, 5.9342954899998552e-86, 1.0152930470452851e-89, 9.5083335143727237e-94, 4.2736593644380303e-98, 7.5673169898909099e-103, 3.8145868837135596e-108, 2.9445845110667619e-114, 7.1392222017713907e-122}, + {1.0203215419405115e-122, 4.3926409088220260e-115, 5.8986558173681245e-109, 1.2087105293093391e-103, 7.0353980850250737e-99, 1.6107326288260005e-94, 1.7678067289525790e-90, 1.0610697100358954e-86, 3.8241442068780522e-83, 8.8702923923721366e-80, 1.3967624162820115e-76, 1.5573928888055416e-73, 1.2722188115916827e-70, 7.8305641247237068e-68, 3.7176883954596755e-65, 1.3887513560879043e-62, 4.1517737028880682e-60, 1.0080675510766497e-57, 2.0135706193376487e-55, 3.3463102229914590e-53, 4.6733192109921242e-51, 5.5335945022909141e-49, 5.5997707655432161e-47, 4.8778201649868724e-45, 3.6811705155316592e-43, 2.4210413787496984e-41, 1.3950773628177882e-39, 7.0777866064732306e-38, 3.1757468989046869e-36, 1.2654132053176338e-34, 4.4947480753641788e-33, 1.4281952005441561e-31, 4.0727582182469552e-30, 1.0454808582283026e-28, 2.4226185736538330e-27, 5.0807355599009919e-26, 9.6670785467690252e-25, 1.6725361565602745e-23, 2.6368638947823986e-22, 3.7957111549106315e-21, 4.9980289800251531e-20, 6.0306098179642906e-19, 6.6786804983364280e-18, 6.7991402460144679e-17, 6.3720317811650348e-16, 5.5049284400726915e-15, 4.3896449685818035e-14, 3.2346882306340970e-13, 2.2052168865195276e-12, 1.3923473891503035e-11, 8.1499619365601122e-11, 4.4267370542157585e-10, 2.2331409933577818e-09, 1.0471618689062924e-08, 4.5678915072122709e-08, 1.8549839541616252e-07, 7.0175441742037147e-07, 2.4747420668926454e-06, 8.1402071214919003e-06, 2.4988785980142873e-05, 7.1628474554958981e-05, 1.9180837279585649e-04, 4.8004901932197877e-04, 1.1233614820028411e-03, 2.4588639421196687e-03, 5.0359498094177816e-03, 9.6537773093780983e-03, 1.7326295602536231e-02, 2.9121725644242560e-02, 4.5848897885251948e-02, 6.7627897299374851e-02, 9.3471746781564918e-02, 1.2107439739077461e-01, 1.4699060677873937e-01, 1.6727380280253201e-01, 1.7843956694581845e-01, 1.7843956694581845e-01, 1.6727380280253201e-01, 1.4699060677873937e-01, 1.2107439739077461e-01, 9.3471746781564918e-02, 6.7627897299374851e-02, 4.5848897885251948e-02, 2.9121725644242560e-02, 1.7326295602536231e-02, 9.6537773093780983e-03, 5.0359498094177816e-03, 2.4588639421196687e-03, 1.1233614820028411e-03, 4.8004901932197877e-04, 1.9180837279585649e-04, 7.1628474554958981e-05, 2.4988785980142873e-05, 8.1402071214919003e-06, 2.4747420668926454e-06, 7.0175441742037147e-07, 1.8549839541616252e-07, 4.5678915072122709e-08, 1.0471618689062924e-08, 2.2331409933577818e-09, 4.4267370542157585e-10, 8.1499619365601122e-11, 1.3923473891503035e-11, 2.2052168865195276e-12, 3.2346882306340970e-13, 4.3896449685818035e-14, 5.5049284400726915e-15, 6.3720317811650348e-16, 6.7991402460144679e-17, 6.6786804983364280e-18, 6.0306098179642906e-19, 4.9980289800251531e-20, 3.7957111549106315e-21, 2.6368638947823986e-22, 1.6725361565602745e-23, 9.6670785467690252e-25, 5.0807355599009919e-26, 2.4226185736538330e-27, 1.0454808582283026e-28, 4.0727582182469552e-30, 1.4281952005441561e-31, 4.4947480753641788e-33, 1.2654132053176338e-34, 3.1757468989046869e-36, 7.0777866064732306e-38, 1.3950773628177882e-39, 2.4210413787496984e-41, 3.6811705155316592e-43, 4.8778201649868724e-45, 5.5997707655432161e-47, 5.5335945022909141e-49, 4.6733192109921242e-51, 3.3463102229914590e-53, 2.0135706193376487e-55, 1.0080675510766497e-57, 4.1517737028880682e-60, 1.3887513560879043e-62, 3.7176883954596755e-65, 7.8305641247237068e-68, 1.2722188115916827e-70, 1.5573928888055416e-73, 1.3967624162820115e-76, 8.8702923923721366e-80, 3.8241442068780522e-83, 1.0610697100358954e-86, 1.7678067289525790e-90, 1.6107326288260005e-94, 7.0353980850250737e-99, 1.2087105293093391e-103, 5.8986558173681245e-109, 4.3926409088220260e-115, 1.0203215419405115e-122}, + {1.4578716888574380e-123, 6.5499584195542182e-116, 9.1158441302395916e-110, 1.9291851130201365e-104, 1.1571376888010415e-99, 2.7257668732866951e-95, 3.0744291780743119e-91, 1.8947250431186403e-87, 7.0064183028413687e-84, 1.6664955389849393e-80, 2.6895662316444978e-77, 3.0723812680200150e-74, 2.5704405332276809e-71, 1.6198772061572697e-68, 7.8722498229365745e-66, 3.0095177392268181e-63, 9.2061099904566106e-61, 2.2868504296047653e-58, 4.6726874994563693e-56, 7.9427931843455534e-54, 1.1344972574084324e-51, 1.3738127684763008e-49, 1.4217090927665081e-47, 1.2663997582044745e-45, 9.7729455955061106e-44, 6.5725138972034875e-42, 3.8727324373725659e-40, 2.0091450762048232e-38, 9.2185663859103873e-37, 3.7563551936945986e-35, 1.3644995796552897e-33, 4.4341465741479497e-32, 1.2932715429724819e-30, 3.3956536214966241e-29, 8.0487680064663208e-28, 1.7268001245109222e-26, 3.3613905413108243e-25, 5.9504202589874584e-24, 9.5995603721747768e-23, 1.4141461815469168e-21, 1.9058394524305284e-20, 2.3538938440623925e-19, 2.6687563232163005e-18, 2.7817760484437033e-17, 2.6696608032295694e-16, 2.3621238776008329e-15, 1.9293848215014542e-14, 1.4565613270987712e-13, 1.0174797099588637e-12, 6.5837630407380247e-12, 3.9501281887181556e-11, 2.1996223199610065e-10, 1.1378158851290800e-09, 5.4720083734809282e-09, 2.4485807329829557e-08, 1.0202255589712521e-07, 3.9608954710479925e-07, 1.4337991258427923e-06, 4.8422272544211524e-06, 1.5265488972373680e-05, 4.4948480076886716e-05, 1.2367217082799177e-04, 3.1811200186972611e-04, 7.6528399238001590e-04, 1.7225370790285232e-03, 3.6288805291928589e-03, 7.1577405214717574e-03, 1.3222272319718250e-02, 2.2881143871485050e-02, 3.7101604703410701e-02, 5.6381975314828768e-02, 8.0315152775434245e-02, 1.0725786228191081e-01, 1.3430372904700771e-01, 1.5769403536946561e-01, 1.7363606017905039e-01, 1.7929968765055787e-01, 1.7363606017905039e-01, 1.5769403536946561e-01, 1.3430372904700771e-01, 1.0725786228191081e-01, 8.0315152775434245e-02, 5.6381975314828768e-02, 3.7101604703410701e-02, 2.2881143871485050e-02, 1.3222272319718250e-02, 7.1577405214717574e-03, 3.6288805291928589e-03, 1.7225370790285232e-03, 7.6528399238001590e-04, 3.1811200186972611e-04, 1.2367217082799177e-04, 4.4948480076886716e-05, 1.5265488972373680e-05, 4.8422272544211524e-06, 1.4337991258427923e-06, 3.9608954710479925e-07, 1.0202255589712521e-07, 2.4485807329829557e-08, 5.4720083734809282e-09, 1.1378158851290800e-09, 2.1996223199610065e-10, 3.9501281887181556e-11, 6.5837630407380247e-12, 1.0174797099588637e-12, 1.4565613270987712e-13, 1.9293848215014542e-14, 2.3621238776008329e-15, 2.6696608032295694e-16, 2.7817760484437033e-17, 2.6687563232163005e-18, 2.3538938440623925e-19, 1.9058394524305284e-20, 1.4141461815469168e-21, 9.5995603721747768e-23, 5.9504202589874584e-24, 3.3613905413108243e-25, 1.7268001245109222e-26, 8.0487680064663208e-28, 3.3956536214966241e-29, 1.2932715429724819e-30, 4.4341465741479497e-32, 1.3644995796552897e-33, 3.7563551936945986e-35, 9.2185663859103873e-37, 2.0091450762048232e-38, 3.8727324373725659e-40, 6.5725138972034875e-42, 9.7729455955061106e-44, 1.2663997582044745e-45, 1.4217090927665081e-47, 1.3738127684763008e-49, 1.1344972574084324e-51, 7.9427931843455534e-54, 4.6726874994563693e-56, 2.2868504296047653e-58, 9.2061099904566106e-61, 3.0095177392268181e-63, 7.8722498229365745e-66, 1.6198772061572697e-68, 2.5704405332276809e-71, 3.0723812680200150e-74, 2.6895662316444978e-77, 1.6664955389849393e-80, 7.0064183028413687e-84, 1.8947250431186403e-87, 3.0744291780743119e-91, 2.7257668732866951e-95, 1.1571376888010415e-99, 1.9291851130201365e-104, 9.1158441302395916e-110, 6.5499584195542182e-116, 1.4578716888574380e-123}, + {2.0825660478904760e-124, 9.7625806330567035e-117, 1.4079328290981535e-110, 3.0768081483238432e-105, 1.9014873630323964e-100, 4.6079244634146070e-96, 5.3405557808694215e-92, 3.3789567793532434e-88, 1.2818424753415062e-84, 3.1260093916222602e-81, 5.1701750558611924e-78, 6.0500487002887184e-75, 5.1832685019930213e-72, 3.3439902942647502e-69, 1.6632668027272507e-66, 6.5065315377220389e-64, 2.0362992343457651e-61, 5.1742950935108869e-59, 1.0813687999683845e-56, 1.8798749780879993e-54, 2.7458133331828386e-52, 3.3999899766205468e-50, 3.5976656083923711e-48, 3.2766076271604045e-46, 2.5853058405449532e-44, 1.7776460048844266e-42, 1.0709222498944708e-40, 5.6804446369555694e-39, 2.6648525467274738e-37, 1.1102669670225965e-35, 4.1238340545301011e-34, 1.3703279298000201e-32, 4.0870885738671846e-31, 1.0974483844909332e-29, 2.6604572771951219e-28, 5.8380527272929378e-27, 1.1624651194307257e-25, 2.1051475426760218e-24, 3.4745776974200654e-23, 5.2372761374065798e-22, 7.2227982269547378e-21, 9.1298647949536611e-20, 1.0594921794825161e-18, 1.1305197522298609e-17, 1.1108048214201895e-16, 1.0064014746615927e-15, 8.4185702868695228e-15, 6.5097729971311742e-14, 4.6585402153758067e-13, 3.0885703725214258e-12, 1.8990163158421596e-11, 1.0838710379194289e-10, 5.7477002127859619e-10, 2.8342947222693205e-09, 1.3006943860141712e-08, 5.5591582741553296e-08, 2.2143724484223221e-07, 8.2259408138485364e-07, 2.8515507236878458e-06, 9.2296922270054013e-06, 2.7908549833980887e-05, 7.8876670613220481e-05, 2.0846012412302649e-04, 5.1540364930051158e-04, 1.1925993797900470e-03, 2.5835851277422653e-03, 5.2417582224628060e-03, 9.9629708516368199e-03, 1.7745045563417383e-02, 2.9624281938924940e-02, 4.6365470641524055e-02, 6.8045456872924986e-02, 9.3654947635056565e-02, 1.2090579766618584e-01, 1.4641795120378570e-01, 1.6634383944546130e-01, 1.7729937449709982e-01, 1.7729937449709982e-01, 1.6634383944546130e-01, 1.4641795120378570e-01, 1.2090579766618584e-01, 9.3654947635056565e-02, 6.8045456872924986e-02, 4.6365470641524055e-02, 2.9624281938924940e-02, 1.7745045563417383e-02, 9.9629708516368199e-03, 5.2417582224628060e-03, 2.5835851277422653e-03, 1.1925993797900470e-03, 5.1540364930051158e-04, 2.0846012412302649e-04, 7.8876670613220481e-05, 2.7908549833980887e-05, 9.2296922270054013e-06, 2.8515507236878458e-06, 8.2259408138485364e-07, 2.2143724484223221e-07, 5.5591582741553296e-08, 1.3006943860141712e-08, 2.8342947222693205e-09, 5.7477002127859619e-10, 1.0838710379194289e-10, 1.8990163158421596e-11, 3.0885703725214258e-12, 4.6585402153758067e-13, 6.5097729971311742e-14, 8.4185702868695228e-15, 1.0064014746615927e-15, 1.1108048214201895e-16, 1.1305197522298609e-17, 1.0594921794825161e-18, 9.1298647949536611e-20, 7.2227982269547378e-21, 5.2372761374065798e-22, 3.4745776974200654e-23, 2.1051475426760218e-24, 1.1624651194307257e-25, 5.8380527272929378e-27, 2.6604572771951219e-28, 1.0974483844909332e-29, 4.0870885738671846e-31, 1.3703279298000201e-32, 4.1238340545301011e-34, 1.1102669670225965e-35, 2.6648525467274738e-37, 5.6804446369555694e-39, 1.0709222498944708e-40, 1.7776460048844266e-42, 2.5853058405449532e-44, 3.2766076271604045e-46, 3.5976656083923711e-48, 3.3999899766205468e-50, 2.7458133331828386e-52, 1.8798749780879993e-54, 1.0813687999683845e-56, 5.1742950935108869e-59, 2.0362992343457651e-61, 6.5065315377220389e-64, 1.6632668027272507e-66, 3.3439902942647502e-69, 5.1832685019930213e-72, 6.0500487002887184e-75, 5.1701750558611924e-78, 3.1260093916222602e-81, 1.2818424753415062e-84, 3.3789567793532434e-88, 5.3405557808694215e-92, 4.6079244634146070e-96, 1.9014873630323964e-100, 3.0768081483238432e-105, 1.4079328290981535e-110, 9.7625806330567035e-117, 2.0825660478904760e-124}, + {2.9742440544925765e-125, 1.4544742104415291e-117, 2.1732568643306002e-111, 4.9034921609592363e-106, 3.1218947762576099e-101, 7.7817715084363300e-97, 9.2663025096531715e-93, 6.0181049060844634e-89, 2.3418402716705127e-85, 5.8546944803309517e-82, 9.9220223776303372e-79, 1.1892107956658327e-75, 1.0431826368600407e-72, 6.8889436382474771e-70, 3.5064990884120332e-67, 1.4034428812712122e-64, 4.4930692768932806e-62, 1.1677337858216425e-59, 2.4957603118464674e-57, 4.4365856613493741e-55, 6.6258941032515879e-53, 8.3883165922512944e-51, 9.0744120512086595e-49, 8.4490059406933366e-47, 6.8149889325650219e-45, 4.7903177946790465e-43, 2.9501316492565748e-41, 1.5996806743635201e-39, 7.6718304654322104e-38, 3.2676791768964119e-36, 1.2408362449919783e-34, 4.2155847725706856e-33, 1.2855517878737815e-31, 3.5296150194332557e-30, 8.7497557637466758e-29, 1.9635223775022683e-27, 3.9986259229284162e-26, 7.4065187877720327e-25, 1.2504748686909515e-23, 1.9282493305400296e-22, 2.7207846792186873e-21, 3.5191108460642354e-20, 4.1792457685713468e-19, 4.5641951147736119e-18, 4.5905709762107554e-17, 4.2579719891425731e-16, 3.6469920289222789e-15, 2.8879673414801644e-14, 2.1167713706852141e-13, 1.4376384719405419e-12, 9.0565354971087218e-12, 5.2969771654748994e-11, 2.8789912587990587e-10, 1.4553534068219742e-09, 6.8479451315824872e-09, 3.0015309064632456e-08, 1.2263753200782247e-07, 4.6740187357094381e-07, 1.6627017535681513e-06, 5.5239309109102710e-06, 1.7148598641483128e-05, 4.9770974063404784e-05, 1.3511264030161956e-04, 3.4322471703307256e-04, 8.1620625227316382e-04, 1.8177000254213835e-03, 3.7922249171946417e-03, 7.4139737035166485e-03, 1.3586755499761058e-02, 2.3345243317359717e-02, 3.7618101204680170e-02, 5.6858711709023881e-02, 8.0625581158863605e-02, 1.0727209153833471e-01, 1.3393358950744624e-01, 1.5693526614765907e-01, 1.7258695046281516e-01, 1.7814291547216715e-01, 1.7258695046281516e-01, 1.5693526614765907e-01, 1.3393358950744624e-01, 1.0727209153833471e-01, 8.0625581158863605e-02, 5.6858711709023881e-02, 3.7618101204680170e-02, 2.3345243317359717e-02, 1.3586755499761058e-02, 7.4139737035166485e-03, 3.7922249171946417e-03, 1.8177000254213835e-03, 8.1620625227316382e-04, 3.4322471703307256e-04, 1.3511264030161956e-04, 4.9770974063404784e-05, 1.7148598641483128e-05, 5.5239309109102710e-06, 1.6627017535681513e-06, 4.6740187357094381e-07, 1.2263753200782247e-07, 3.0015309064632456e-08, 6.8479451315824872e-09, 1.4553534068219742e-09, 2.8789912587990587e-10, 5.2969771654748994e-11, 9.0565354971087218e-12, 1.4376384719405419e-12, 2.1167713706852141e-13, 2.8879673414801644e-14, 3.6469920289222789e-15, 4.2579719891425731e-16, 4.5905709762107554e-17, 4.5641951147736119e-18, 4.1792457685713468e-19, 3.5191108460642354e-20, 2.7207846792186873e-21, 1.9282493305400296e-22, 1.2504748686909515e-23, 7.4065187877720327e-25, 3.9986259229284162e-26, 1.9635223775022683e-27, 8.7497557637466758e-29, 3.5296150194332557e-30, 1.2855517878737815e-31, 4.2155847725706856e-33, 1.2408362449919783e-34, 3.2676791768964119e-36, 7.6718304654322104e-38, 1.5996806743635201e-39, 2.9501316492565748e-41, 4.7903177946790465e-43, 6.8149889325650219e-45, 8.4490059406933366e-47, 9.0744120512086595e-49, 8.3883165922512944e-51, 6.6258941032515879e-53, 4.4365856613493741e-55, 2.4957603118464674e-57, 1.1677337858216425e-59, 4.4930692768932806e-62, 1.4034428812712122e-64, 3.5064990884120332e-67, 6.8889436382474771e-70, 1.0431826368600407e-72, 1.1892107956658327e-75, 9.9220223776303372e-79, 5.8546944803309517e-82, 2.3418402716705127e-85, 6.0181049060844634e-89, 9.2663025096531715e-93, 7.7817715084363300e-97, 3.1218947762576099e-101, 4.9034921609592363e-106, 2.1732568643306002e-111, 1.4544742104415291e-117, 2.9742440544925765e-125}, + {4.2467223153569913e-126, 2.1660313165253327e-118, 3.3526412389934468e-112, 7.8089506311734750e-107, 5.1211062371557049e-102, 1.3128438701986923e-97, 1.6059434510399780e-93, 1.0704932710164072e-89, 4.2723909537910979e-86, 1.0948479687576274e-82, 1.9009714466058216e-79, 2.3333732870895970e-76, 2.0954987289754821e-73, 1.4163011238027347e-70, 7.3764205708401192e-68, 3.0202620912677113e-65, 9.8899383346021114e-63, 2.6286294129074487e-60, 5.7447123101943819e-58, 1.0441146661857655e-55, 1.5941894796140349e-53, 2.0631744724119192e-51, 2.2815057723526744e-49, 2.1713655679015281e-47, 1.7902127496153674e-45, 1.2862015727088547e-43, 8.0963481474532886e-42, 4.4873140335977730e-40, 2.1997031006119584e-38, 9.5769420875142906e-37, 3.7173934630972095e-35, 1.2910298923887236e-33, 4.0247941719917949e-32, 1.1297479501227750e-30, 2.8633730681601511e-29, 6.5701662464695220e-28, 1.3681807173905664e-26, 2.5916454156396681e-25, 4.4751190749666469e-24, 7.0583497822483184e-23, 1.0188011695097018e-21, 1.3481278810188344e-20, 1.6381331947152628e-19, 1.8307185107770479e-18, 1.8844546640240470e-17, 1.7891286411123497e-16, 1.5687514682212088e-15, 1.2719076381502738e-14, 9.5465675547568851e-14, 6.6405134257786806e-13, 4.2851307836098596e-12, 2.5677582201989908e-11, 1.4301024597508902e-10, 7.4092720692344339e-10, 3.5737970851749710e-09, 1.6060537813990750e-08, 6.7293992111962037e-08, 2.6306912128825106e-07, 9.6009499955544809e-07, 3.2731466120984474e-06, 1.0429494937549579e-05, 3.1076452822469759e-05, 8.6632019755194801e-05, 2.2604661890533189e-04, 5.5229314310309603e-04, 1.2640347665701273e-03, 2.7109305106750477e-03, 5.4498805064709423e-03, 1.0272859026411405e-02, 1.8161242168807858e-02, 3.0119768029475406e-02, 4.6870503949025956e-02, 6.8449129121212759e-02, 9.3826040853472042e-02, 1.2073175170965833e-01, 1.4585002297738520e-01, 1.6542893986636190e-01, 1.7618076008397315e-01, 1.7618076008397315e-01, 1.6542893986636190e-01, 1.4585002297738520e-01, 1.2073175170965833e-01, 9.3826040853472042e-02, 6.8449129121212759e-02, 4.6870503949025956e-02, 3.0119768029475406e-02, 1.8161242168807858e-02, 1.0272859026411405e-02, 5.4498805064709423e-03, 2.7109305106750477e-03, 1.2640347665701273e-03, 5.5229314310309603e-04, 2.2604661890533189e-04, 8.6632019755194801e-05, 3.1076452822469759e-05, 1.0429494937549579e-05, 3.2731466120984474e-06, 9.6009499955544809e-07, 2.6306912128825106e-07, 6.7293992111962037e-08, 1.6060537813990750e-08, 3.5737970851749710e-09, 7.4092720692344339e-10, 1.4301024597508902e-10, 2.5677582201989908e-11, 4.2851307836098596e-12, 6.6405134257786806e-13, 9.5465675547568851e-14, 1.2719076381502738e-14, 1.5687514682212088e-15, 1.7891286411123497e-16, 1.8844546640240470e-17, 1.8307185107770479e-18, 1.6381331947152628e-19, 1.3481278810188344e-20, 1.0188011695097018e-21, 7.0583497822483184e-23, 4.4751190749666469e-24, 2.5916454156396681e-25, 1.3681807173905664e-26, 6.5701662464695220e-28, 2.8633730681601511e-29, 1.1297479501227750e-30, 4.0247941719917949e-32, 1.2910298923887236e-33, 3.7173934630972095e-35, 9.5769420875142906e-37, 2.1997031006119584e-38, 4.4873140335977730e-40, 8.0963481474532886e-42, 1.2862015727088547e-43, 1.7902127496153674e-45, 2.1713655679015281e-47, 2.2815057723526744e-49, 2.0631744724119192e-51, 1.5941894796140349e-53, 1.0441146661857655e-55, 5.7447123101943819e-58, 2.6286294129074487e-60, 9.8899383346021114e-63, 3.0202620912677113e-65, 7.3764205708401192e-68, 1.4163011238027347e-70, 2.0954987289754821e-73, 2.3333732870895970e-76, 1.9009714466058216e-79, 1.0948479687576274e-82, 4.2723909537910979e-86, 1.0704932710164072e-89, 1.6059434510399780e-93, 1.3128438701986923e-97, 5.1211062371557049e-102, 7.8089506311734750e-107, 3.3526412389934468e-112, 2.1660313165253327e-118, 4.2467223153569913e-126}, + {6.0622191716662980e-127, 3.2243541187800939e-119, 5.1690742816237208e-113, 1.2426977160105404e-107, 8.3933287533777738e-103, 2.2126569238728289e-98, 2.7801189404282378e-94, 1.9017852686354782e-90, 7.7836404960844694e-87, 2.0443095742420186e-83, 3.6361329490246816e-80, 4.5702928776404487e-77, 4.2014053957085256e-74, 2.9059246516402931e-71, 1.5484204394570369e-68, 6.4850166385488236e-66, 2.1717290123179292e-63, 5.9022979463583546e-61, 1.3188160319392796e-58, 2.4504276066974761e-56, 3.8244861009984640e-54, 5.0591506359259702e-52, 5.7180427835175108e-50, 5.5619189779622956e-48, 4.6865094097082296e-46, 3.4411166261243821e-44, 2.2137173158797545e-42, 1.2539021346574782e-40, 6.2819019919798964e-39, 2.7952039819044771e-37, 1.1089145782361913e-35, 3.9362772026982286e-34, 1.2543049763002862e-32, 3.5989403271252947e-31, 9.3246229360624703e-30, 2.1873567871874991e-28, 4.6570323992852519e-27, 9.0198508148124766e-26, 1.5926655666987673e-24, 2.5689779244357800e-23, 3.7925166697437060e-22, 5.1332963733171119e-21, 6.3810270087780860e-20, 7.2960970893548457e-19, 7.6848696141461809e-18, 7.4667368566800348e-17, 6.7010236404093807e-16, 5.5616305380816712e-15, 4.2738351786402332e-14, 3.0441295544509839e-13, 2.0118060311112926e-12, 1.2348350013212526e-11, 7.0457887005315459e-11, 3.7404445985544352e-10, 1.8490262742729560e-09, 8.5176899942265963e-09, 3.6590845237002989e-08, 1.4668615688059134e-07, 5.4909587760916178e-07, 1.9204753233550013e-06, 6.2793321142086111e-06, 1.9203890628511156e-05, 5.4960123823238632e-05, 1.4726036700166861e-04, 3.6956136752144001e-04, 8.6899815474605370e-04, 1.9153075674406669e-03, 3.9581151034971717e-03, 7.6718266966305298e-03, 1.3950429172087464e-02, 2.3804589918929770e-02, 3.8125218704480275e-02, 5.7322493628469834e-02, 8.0922651951388633e-02, 1.0727720003748800e-01, 1.3356293292585539e-01, 1.5618653283532280e-01, 1.7155657639082103e-01, 1.7700824722075201e-01, 1.7155657639082103e-01, 1.5618653283532280e-01, 1.3356293292585539e-01, 1.0727720003748800e-01, 8.0922651951388633e-02, 5.7322493628469834e-02, 3.8125218704480275e-02, 2.3804589918929770e-02, 1.3950429172087464e-02, 7.6718266966305298e-03, 3.9581151034971717e-03, 1.9153075674406669e-03, 8.6899815474605370e-04, 3.6956136752144001e-04, 1.4726036700166861e-04, 5.4960123823238632e-05, 1.9203890628511156e-05, 6.2793321142086111e-06, 1.9204753233550013e-06, 5.4909587760916178e-07, 1.4668615688059134e-07, 3.6590845237002989e-08, 8.5176899942265963e-09, 1.8490262742729560e-09, 3.7404445985544352e-10, 7.0457887005315459e-11, 1.2348350013212526e-11, 2.0118060311112926e-12, 3.0441295544509839e-13, 4.2738351786402332e-14, 5.5616305380816712e-15, 6.7010236404093807e-16, 7.4667368566800348e-17, 7.6848696141461809e-18, 7.2960970893548457e-19, 6.3810270087780860e-20, 5.1332963733171119e-21, 3.7925166697437060e-22, 2.5689779244357800e-23, 1.5926655666987673e-24, 9.0198508148124766e-26, 4.6570323992852519e-27, 2.1873567871874991e-28, 9.3246229360624703e-30, 3.5989403271252947e-31, 1.2543049763002862e-32, 3.9362772026982286e-34, 1.1089145782361913e-35, 2.7952039819044771e-37, 6.2819019919798964e-39, 1.2539021346574782e-40, 2.2137173158797545e-42, 3.4411166261243821e-44, 4.6865094097082296e-46, 5.5619189779622956e-48, 5.7180427835175108e-50, 5.0591506359259702e-52, 3.8244861009984640e-54, 2.4504276066974761e-56, 1.3188160319392796e-58, 5.9022979463583546e-61, 2.1717290123179292e-63, 6.4850166385488236e-66, 1.5484204394570369e-68, 2.9059246516402931e-71, 4.2014053957085256e-74, 4.5702928776404487e-77, 3.6361329490246816e-80, 2.0443095742420186e-83, 7.7836404960844694e-87, 1.9017852686354782e-90, 2.7801189404282378e-94, 2.2126569238728289e-98, 8.3933287533777738e-103, 1.2426977160105404e-107, 5.1690742816237208e-113, 3.2243541187800939e-119, 6.0622191716662980e-127}, + {8.6518898286288247e-128, 4.7977981754547922e-120, 7.9650930361988897e-114, 1.9761840987326553e-108, 1.3744652069324438e-103, 3.7255148645554058e-99, 4.8074121331969427e-95, 3.3744153060134342e-91, 1.4161180265335159e-87, 3.8114504571794760e-84, 6.9438585136020447e-81, 8.9360817516471687e-78, 8.4079759000226087e-75, 5.9504405763416772e-72, 3.2435033695316742e-69, 1.3893312175841125e-66, 4.7576408366455308e-64, 1.3220024862368775e-61, 3.0197052622687561e-59, 5.7351470833255443e-57, 9.1486995119191431e-55, 1.2368470663040083e-52, 1.4286078076592960e-50, 1.4200335880405776e-48, 1.2226957787809403e-46, 9.1739205502621965e-45, 6.0306042099204429e-43, 3.4904884601063066e-41, 1.7869095381531890e-39, 8.1249855483381444e-38, 3.2939528684311649e-36, 1.1948989473488384e-34, 3.8912956469188826e-33, 1.1411267330350244e-31, 3.0219294698888464e-30, 7.2459465976943397e-29, 1.5770256477583313e-27, 3.1226061139317796e-26, 5.6372579181684656e-25, 9.2975592528325581e-24, 1.4036014280320261e-22, 1.9429670019227641e-21, 2.4703591186430466e-20, 2.8894203773544814e-19, 3.1135796480328694e-18, 3.0953725694775336e-17, 2.8427562189767261e-16, 2.4147784190996735e-15, 1.8994699453982887e-14, 1.3851048606782092e-13, 9.3729953674226721e-13, 5.8917523372705995e-12, 3.4433525991626855e-11, 1.8726953725774312e-10, 9.4854377303416358e-10, 4.4780357696096071e-09, 1.9718477984120434e-08, 8.1042320257489110e-08, 3.1108717616071734e-07, 1.1159535961120921e-06, 3.7432563998726419e-06, 1.1746874098316171e-05, 3.4504766489542566e-05, 9.4911766414585672e-05, 2.4458580745649063e-04, 5.9072464709476020e-04, 1.3376446613946990e-03, 2.8408258176521148e-03, 5.6601830605110866e-03, 1.0583273905359803e-02, 1.8574752611538813e-02, 3.0608185223036027e-02, 4.7364212800332400e-02, 6.8839337618374755e-02, 9.3985530465238165e-02, 1.2055262431349997e-01, 1.4528684159808489e-01, 1.6452871112826625e-01, 1.7508305167467292e-01, 1.7508305167467292e-01, 1.6452871112826625e-01, 1.4528684159808489e-01, 1.2055262431349997e-01, 9.3985530465238165e-02, 6.8839337618374755e-02, 4.7364212800332400e-02, 3.0608185223036027e-02, 1.8574752611538813e-02, 1.0583273905359803e-02, 5.6601830605110866e-03, 2.8408258176521148e-03, 1.3376446613946990e-03, 5.9072464709476020e-04, 2.4458580745649063e-04, 9.4911766414585672e-05, 3.4504766489542566e-05, 1.1746874098316171e-05, 3.7432563998726419e-06, 1.1159535961120921e-06, 3.1108717616071734e-07, 8.1042320257489110e-08, 1.9718477984120434e-08, 4.4780357696096071e-09, 9.4854377303416358e-10, 1.8726953725774312e-10, 3.4433525991626855e-11, 5.8917523372705995e-12, 9.3729953674226721e-13, 1.3851048606782092e-13, 1.8994699453982887e-14, 2.4147784190996735e-15, 2.8427562189767261e-16, 3.0953725694775336e-17, 3.1135796480328694e-18, 2.8894203773544814e-19, 2.4703591186430466e-20, 1.9429670019227641e-21, 1.4036014280320261e-22, 9.2975592528325581e-24, 5.6372579181684656e-25, 3.1226061139317796e-26, 1.5770256477583313e-27, 7.2459465976943397e-29, 3.0219294698888464e-30, 1.1411267330350244e-31, 3.8912956469188826e-33, 1.1948989473488384e-34, 3.2939528684311649e-36, 8.1249855483381444e-38, 1.7869095381531890e-39, 3.4904884601063066e-41, 6.0306042099204429e-43, 9.1739205502621965e-45, 1.2226957787809403e-46, 1.4200335880405776e-48, 1.4286078076592960e-50, 1.2368470663040083e-52, 9.1486995119191431e-55, 5.7351470833255443e-57, 3.0197052622687561e-59, 1.3220024862368775e-61, 4.7576408366455308e-64, 1.3893312175841125e-66, 3.2435033695316742e-69, 5.9504405763416772e-72, 8.4079759000226087e-75, 8.9360817516471687e-78, 6.9438585136020447e-81, 3.8114504571794760e-84, 1.4161180265335159e-87, 3.3744153060134342e-91, 4.8074121331969427e-95, 3.7255148645554058e-99, 1.3744652069324438e-103, 1.9761840987326553e-108, 7.9650930361988897e-114, 4.7977981754547922e-120, 8.6518898286288247e-128}, + {1.2345052237856376e-128, 7.1361565819334150e-121, 1.2266594150983389e-114, 3.1403768309606574e-109, 2.2488806415651994e-104, 6.2666361422341182e-100, 8.3038517132199445e-96, 5.9799996465821154e-92, 2.5729286682716097e-88, 7.0956475615088519e-85, 1.3239358802678529e-81, 1.7442238644011473e-78, 1.6795285148575302e-75, 1.2160739161745740e-72, 6.7800483155694390e-70, 2.9698887117979696e-67, 1.0398334915263462e-64, 2.9537631885955336e-62, 6.8964075076110458e-60, 1.3386610121664405e-57, 2.1822972256453033e-55, 3.0148592722499396e-53, 3.5582391595026354e-51, 3.6138684655576511e-49, 3.1792871272966973e-47, 2.4372213779029665e-45, 1.6369116080171861e-43, 9.6799943605644117e-42, 5.0631425091072337e-40, 2.3522144528005868e-38, 9.7436152093981038e-37, 3.6115822674301904e-35, 1.2018288490038798e-33, 3.6015212879811887e-32, 9.7468625406557925e-31, 2.3885355396506504e-29, 5.3132702519188496e-28, 1.0753756973350715e-26, 1.9845716557598769e-25, 3.3462806594548906e-24, 5.1650319326919827e-23, 7.3109577835953338e-22, 9.5059376788875581e-21, 1.1371572178214573e-19, 1.2534183670047640e-18, 1.2747621562807485e-17, 1.1978221703435283e-16, 1.0411788127158037e-15, 8.3817954183785831e-15, 6.2561571481732302e-14, 4.3340112417705868e-13, 2.7894047381925510e-12, 1.6694572089431568e-11, 9.2995420785846948e-11, 4.8253510985881196e-10, 2.3340778029825478e-09, 1.0532686874011172e-08, 4.4371096492273068e-08, 1.7461444759106688e-07, 6.4230905783791856e-07, 2.2097354109635801e-06, 7.1138004485475131e-06, 2.1441047304603760e-05, 6.0530803203101914e-05, 1.6013349936228681e-04, 3.9713567276994117e-04, 9.2365343040052964e-04, 2.0153124277213861e-03, 4.1264467864295497e-03, 7.9311452492789869e-03, 1.4313136262234679e-02, 2.4259110409796711e-02, 3.8623061726879737e-02, 5.7773645171755317e-02, 8.1206842893413358e-02, 1.0727363982645181e-01, 1.3319196312197995e-01, 1.5544764635273797e-01, 1.7054438857615731e-01, 1.7589498780426926e-01, 1.7054438857615731e-01, 1.5544764635273797e-01, 1.3319196312197995e-01, 1.0727363982645181e-01, 8.1206842893413358e-02, 5.7773645171755317e-02, 3.8623061726879737e-02, 2.4259110409796711e-02, 1.4313136262234679e-02, 7.9311452492789869e-03, 4.1264467864295497e-03, 2.0153124277213861e-03, 9.2365343040052964e-04, 3.9713567276994117e-04, 1.6013349936228681e-04, 6.0530803203101914e-05, 2.1441047304603760e-05, 7.1138004485475131e-06, 2.2097354109635801e-06, 6.4230905783791856e-07, 1.7461444759106688e-07, 4.4371096492273068e-08, 1.0532686874011172e-08, 2.3340778029825478e-09, 4.8253510985881196e-10, 9.2995420785846948e-11, 1.6694572089431568e-11, 2.7894047381925510e-12, 4.3340112417705868e-13, 6.2561571481732302e-14, 8.3817954183785831e-15, 1.0411788127158037e-15, 1.1978221703435283e-16, 1.2747621562807485e-17, 1.2534183670047640e-18, 1.1371572178214573e-19, 9.5059376788875581e-21, 7.3109577835953338e-22, 5.1650319326919827e-23, 3.3462806594548906e-24, 1.9845716557598769e-25, 1.0753756973350715e-26, 5.3132702519188496e-28, 2.3885355396506504e-29, 9.7468625406557925e-31, 3.6015212879811887e-32, 1.2018288490038798e-33, 3.6115822674301904e-35, 9.7436152093981038e-37, 2.3522144528005868e-38, 5.0631425091072337e-40, 9.6799943605644117e-42, 1.6369116080171861e-43, 2.4372213779029665e-45, 3.1792871272966973e-47, 3.6138684655576511e-49, 3.5582391595026354e-51, 3.0148592722499396e-53, 2.1822972256453033e-55, 1.3386610121664405e-57, 6.8964075076110458e-60, 2.9537631885955336e-62, 1.0398334915263462e-64, 2.9698887117979696e-67, 6.7800483155694390e-70, 1.2160739161745740e-72, 1.6795285148575302e-75, 1.7442238644011473e-78, 1.3239358802678529e-81, 7.0956475615088519e-85, 2.5729286682716097e-88, 5.9799996465821154e-92, 8.3038517132199445e-96, 6.2666361422341182e-100, 2.2488806415651994e-104, 3.1403768309606574e-109, 1.2266594150983389e-114, 7.1361565819334150e-121, 1.2345052237856376e-128}, + {1.7610777213868225e-129, 1.0609912453053086e-121, 1.8880558326632475e-115, 4.9869144791066677e-110, 3.6765138012657772e-105, 1.0530846293412266e-100, 1.4327597465974048e-96, 1.0584620865577655e-92, 4.6684664948676272e-89, 1.3190436630179440e-85, 2.5202632570592097e-82, 3.3987392362121908e-79, 3.3488181154099359e-76, 2.4804288326920011e-73, 1.4143430079239634e-70, 6.3346915410241234e-68, 2.2674306256941818e-65, 6.5836081498721399e-63, 1.5709872468845785e-60, 3.1162632356321267e-58, 5.1910061298697851e-56, 7.3273399650957289e-54, 8.8354796635334199e-52, 9.1677552430019203e-50, 8.2395121572045278e-48, 6.4526516804970545e-46, 4.4272600478065905e-44, 2.6745508857556167e-42, 1.4291089046778579e-40, 6.7826401946708970e-39, 2.8703150932676095e-37, 1.0869482703973487e-35, 3.6955025716069553e-34, 1.1315067191371783e-32, 3.1289601063429292e-31, 7.8353356972027161e-30, 1.7811808982463465e-28, 3.6843324819342597e-27, 6.9494876383385912e-26, 1.1977696964648504e-24, 1.8899444794564548e-23, 2.7350044749786203e-22, 3.6360647433609545e-21, 4.4479270726420680e-20, 5.0139935781581053e-19, 5.2157884028434802e-18, 5.0135017597656447e-17, 4.4585078370462008e-16, 3.6726238537048878e-15, 2.8053332193363147e-14, 1.9891563745557595e-13, 1.3105682814703333e-12, 8.0308637715632703e-12, 4.5809917511320124e-11, 2.4345153103464099e-10, 1.2063179828327093e-09, 5.5773560719102751e-09, 2.4077676519331747e-08, 9.7119175861531978e-08, 3.6624118990378204e-07, 1.2919701008614705e-06, 4.2657607173255093e-06, 1.3189244631563864e-05, 3.8205770006826046e-05, 1.0373273668170783e-04, 2.6409447862081663e-04, 6.3070332659971552e-04, 1.4134038747122414e-03, 2.9731958710714898e-03, 5.8725347587191210e-03, 1.0894054653347555e-02, 1.8985454327504647e-02, 3.1089543185356148e-02, 4.7846811856586229e-02, 6.9216492829879864e-02, 9.4133897771831843e-02, 1.2036875882166113e-01, 1.4472841947349580e-01, 1.6364277404586250e-01, 1.7400560617482017e-01, 1.7400560617482017e-01, 1.6364277404586250e-01, 1.4472841947349580e-01, 1.2036875882166113e-01, 9.4133897771831843e-02, 6.9216492829879864e-02, 4.7846811856586229e-02, 3.1089543185356148e-02, 1.8985454327504647e-02, 1.0894054653347555e-02, 5.8725347587191210e-03, 2.9731958710714898e-03, 1.4134038747122414e-03, 6.3070332659971552e-04, 2.6409447862081663e-04, 1.0373273668170783e-04, 3.8205770006826046e-05, 1.3189244631563864e-05, 4.2657607173255093e-06, 1.2919701008614705e-06, 3.6624118990378204e-07, 9.7119175861531978e-08, 2.4077676519331747e-08, 5.5773560719102751e-09, 1.2063179828327093e-09, 2.4345153103464099e-10, 4.5809917511320124e-11, 8.0308637715632703e-12, 1.3105682814703333e-12, 1.9891563745557595e-13, 2.8053332193363147e-14, 3.6726238537048878e-15, 4.4585078370462008e-16, 5.0135017597656447e-17, 5.2157884028434802e-18, 5.0139935781581053e-19, 4.4479270726420680e-20, 3.6360647433609545e-21, 2.7350044749786203e-22, 1.8899444794564548e-23, 1.1977696964648504e-24, 6.9494876383385912e-26, 3.6843324819342597e-27, 1.7811808982463465e-28, 7.8353356972027161e-30, 3.1289601063429292e-31, 1.1315067191371783e-32, 3.6955025716069553e-34, 1.0869482703973487e-35, 2.8703150932676095e-37, 6.7826401946708970e-39, 1.4291089046778579e-40, 2.6745508857556167e-42, 4.4272600478065905e-44, 6.4526516804970545e-46, 8.2395121572045278e-48, 9.1677552430019203e-50, 8.8354796635334199e-52, 7.3273399650957289e-54, 5.1910061298697851e-56, 3.1162632356321267e-58, 1.5709872468845785e-60, 6.5836081498721399e-63, 2.2674306256941818e-65, 6.3346915410241234e-68, 1.4143430079239634e-70, 2.4804288326920011e-73, 3.3488181154099359e-76, 3.3987392362121908e-79, 2.5202632570592097e-82, 1.3190436630179440e-85, 4.6684664948676272e-89, 1.0584620865577655e-92, 1.4327597465974048e-96, 1.0530846293412266e-100, 3.6765138012657772e-105, 4.9869144791066677e-110, 1.8880558326632475e-115, 1.0609912453053086e-121, 1.7610777213868225e-129}, + {2.5117056700120872e-130, 1.5768344953215994e-122, 2.9044636530400262e-116, 7.9137283674998714e-111, 6.0054708822621273e-106, 1.7679796472043246e-101, 2.4694368635244847e-97, 1.8712284923478763e-93, 8.4595142859097527e-90, 2.4484925972797376e-86, 4.7901098788291739e-83, 6.6115362451933797e-80, 6.6651975922997095e-77, 5.0496259060528478e-74, 2.9443577961646315e-71, 1.3482570840246656e-68, 4.9330325826042063e-66, 1.4638938206976037e-63, 3.5696603658904023e-61, 7.2351735603462302e-59, 1.2313651255661928e-56, 1.7756983991411928e-54, 2.1873288432589287e-52, 2.3183952076674861e-50, 2.1283904185528713e-48, 1.7025628600075561e-46, 1.1931897574643388e-44, 7.3626408195179616e-43, 4.0184547253394729e-41, 1.9480947197049647e-39, 8.4210939788616602e-38, 3.2575341809749061e-36, 1.1313879341749972e-34, 3.5389381244383855e-33, 9.9980778309899927e-32, 2.5579997011243763e-30, 5.9416331503292959e-29, 1.2558645009560268e-27, 2.4207882624773725e-26, 4.2641635772547449e-25, 6.8770962222233684e-24, 1.0173048420715203e-22, 1.3826289575432440e-21, 1.7292550621372860e-20, 1.9932479444365377e-19, 2.1204345027937428e-18, 2.0846204533947437e-17, 1.8963226940193161e-16, 1.5980648038540025e-15, 1.2489882385266198e-14, 9.0627897868794926e-14, 6.1113514542896781e-13, 3.8334734795673616e-12, 2.2387867842316195e-11, 1.2183208011102774e-10, 6.1827585936607041e-10, 2.9281826160122555e-09, 1.2951325071150348e-08, 5.3532512893353530e-08, 2.0690866853712093e-07, 7.4825803592771974e-07, 2.5332274890078433e-06, 8.0328671931181133e-06, 2.3869848947287937e-05, 6.6497705172595715e-05, 1.7374941584438457e-04, 4.2595976788697434e-04, 9.8016363676181151e-04, 2.1176656262735217e-03, 4.2971163011999540e-03, 8.1917798784339399e-03, 1.4674728608435711e-02, 2.4708741311255288e-02, 3.9111739287652818e-02, 5.8212483797557772e-02, 8.1478613249930595e-02, 1.0726183985947185e-01, 1.3282086880025051e-01, 1.5471842089261012e-01, 1.6954985984858575e-01, 1.7480247235206883e-01, 1.6954985984858575e-01, 1.5471842089261012e-01, 1.3282086880025051e-01, 1.0726183985947185e-01, 8.1478613249930595e-02, 5.8212483797557772e-02, 3.9111739287652818e-02, 2.4708741311255288e-02, 1.4674728608435711e-02, 8.1917798784339399e-03, 4.2971163011999540e-03, 2.1176656262735217e-03, 9.8016363676181151e-04, 4.2595976788697434e-04, 1.7374941584438457e-04, 6.6497705172595715e-05, 2.3869848947287937e-05, 8.0328671931181133e-06, 2.5332274890078433e-06, 7.4825803592771974e-07, 2.0690866853712093e-07, 5.3532512893353530e-08, 1.2951325071150348e-08, 2.9281826160122555e-09, 6.1827585936607041e-10, 1.2183208011102774e-10, 2.2387867842316195e-11, 3.8334734795673616e-12, 6.1113514542896781e-13, 9.0627897868794926e-14, 1.2489882385266198e-14, 1.5980648038540025e-15, 1.8963226940193161e-16, 2.0846204533947437e-17, 2.1204345027937428e-18, 1.9932479444365377e-19, 1.7292550621372860e-20, 1.3826289575432440e-21, 1.0173048420715203e-22, 6.8770962222233684e-24, 4.2641635772547449e-25, 2.4207882624773725e-26, 1.2558645009560268e-27, 5.9416331503292959e-29, 2.5579997011243763e-30, 9.9980778309899927e-32, 3.5389381244383855e-33, 1.1313879341749972e-34, 3.2575341809749061e-36, 8.4210939788616602e-38, 1.9480947197049647e-39, 4.0184547253394729e-41, 7.3626408195179616e-43, 1.1931897574643388e-44, 1.7025628600075561e-46, 2.1283904185528713e-48, 2.3183952076674861e-50, 2.1873288432589287e-52, 1.7756983991411928e-54, 1.2313651255661928e-56, 7.2351735603462302e-59, 3.5696603658904023e-61, 1.4638938206976037e-63, 4.9330325826042063e-66, 1.3482570840246656e-68, 2.9443577961646315e-71, 5.0496259060528478e-74, 6.6651975922997095e-77, 6.6115362451933797e-80, 4.7901098788291739e-83, 2.4484925972797376e-86, 8.4595142859097527e-90, 1.8712284923478763e-93, 2.4694368635244847e-97, 1.7679796472043246e-101, 6.0054708822621273e-106, 7.9137283674998714e-111, 2.9044636530400262e-116, 1.5768344953215994e-122, 2.5117056700120872e-130}, + {3.5814970887800193e-131, 2.3425513711144864e-123, 4.4656005878580503e-117, 1.2549679546936818e-111, 9.8017329285864726e-107, 2.9653839872557489e-102, 4.2516584957198355e-98, 3.3041628702723710e-94, 1.5309029297604490e-90, 4.5385580031078324e-87, 9.0901963341946014e-84, 1.2839971949179289e-80, 1.3242215741981033e-77, 1.0260459032147593e-74, 6.1171687686353920e-72, 2.8634705175373264e-69, 1.0708169155525760e-66, 3.2473167974844921e-64, 8.0909309792517176e-62, 1.6754390708913517e-59, 2.9129572580930014e-57, 4.2909222783948995e-55, 5.3988684348783699e-53, 5.8447003073435629e-51, 5.4802004204685326e-49, 4.4772141969183521e-47, 3.2045539320239441e-45, 2.0194963974060789e-43, 1.1256982521722169e-41, 5.5735541782797091e-40, 2.4607034140503088e-38, 9.7221219580876439e-37, 3.4489022958731964e-35, 1.1019416508568278e-33, 3.1800971964673699e-32, 8.3116537305566989e-31, 1.9723475111279380e-29, 4.2593300365187824e-28, 8.3889785533018652e-27, 1.5099943444312937e-25, 2.4887063965856610e-24, 3.7625921372478096e-23, 5.2269932699489526e-22, 6.6828358472667806e-21, 7.8752810946470447e-20, 8.5660876502561181e-19, 8.6117182742222153e-18, 8.0118871420831184e-17, 6.9061126848313650e-16, 5.5217099395406411e-15, 4.0993475210626060e-14, 2.8287311125546069e-13, 1.8159956877481757e-12, 1.0856048964794633e-11, 6.0482344698906487e-11, 3.1429016861706717e-10, 1.5244189642430853e-09, 6.9064794339712537e-09, 2.9246755983618971e-08, 1.1583508882541563e-07, 4.2933935551544649e-07, 1.4900490066410718e-06, 4.8446895241968929e-06, 1.4764162429716271e-05, 4.2191721743284952e-05, 1.1311130499099743e-04, 2.8458825008902025e-04, 6.7223242445783719e-04, 1.4912851650067261e-03, 3.1079648052231286e-03, 6.0868070844442837e-03, 1.1205047384266207e-02, 1.9393234478244935e-02, 3.1563859231069517e-02, 4.8318515012084520e-02, 6.9580992429206442e-02, 9.4271602476518737e-02, 1.2018047849522055e-01, 1.4417476260347803e-01, 1.6277076260081147e-01, 1.7294780784506847e-01, 1.7294780784506847e-01, 1.6277076260081147e-01, 1.4417476260347803e-01, 1.2018047849522055e-01, 9.4271602476518737e-02, 6.9580992429206442e-02, 4.8318515012084520e-02, 3.1563859231069517e-02, 1.9393234478244935e-02, 1.1205047384266207e-02, 6.0868070844442837e-03, 3.1079648052231286e-03, 1.4912851650067261e-03, 6.7223242445783719e-04, 2.8458825008902025e-04, 1.1311130499099743e-04, 4.2191721743284952e-05, 1.4764162429716271e-05, 4.8446895241968929e-06, 1.4900490066410718e-06, 4.2933935551544649e-07, 1.1583508882541563e-07, 2.9246755983618971e-08, 6.9064794339712537e-09, 1.5244189642430853e-09, 3.1429016861706717e-10, 6.0482344698906487e-11, 1.0856048964794633e-11, 1.8159956877481757e-12, 2.8287311125546069e-13, 4.0993475210626060e-14, 5.5217099395406411e-15, 6.9061126848313650e-16, 8.0118871420831184e-17, 8.6117182742222153e-18, 8.5660876502561181e-19, 7.8752810946470447e-20, 6.6828358472667806e-21, 5.2269932699489526e-22, 3.7625921372478096e-23, 2.4887063965856610e-24, 1.5099943444312937e-25, 8.3889785533018652e-27, 4.2593300365187824e-28, 1.9723475111279380e-29, 8.3116537305566989e-31, 3.1800971964673699e-32, 1.1019416508568278e-33, 3.4489022958731964e-35, 9.7221219580876439e-37, 2.4607034140503088e-38, 5.5735541782797091e-40, 1.1256982521722169e-41, 2.0194963974060789e-43, 3.2045539320239441e-45, 4.4772141969183521e-47, 5.4802004204685326e-49, 5.8447003073435629e-51, 5.3988684348783699e-53, 4.2909222783948995e-55, 2.9129572580930014e-57, 1.6754390708913517e-59, 8.0909309792517176e-62, 3.2473167974844921e-64, 1.0708169155525760e-66, 2.8634705175373264e-69, 6.1171687686353920e-72, 1.0260459032147593e-74, 1.3242215741981033e-77, 1.2839971949179289e-80, 9.0901963341946014e-84, 4.5385580031078324e-87, 1.5309029297604490e-90, 3.3041628702723710e-94, 4.2516584957198355e-98, 2.9653839872557489e-102, 9.8017329285864726e-107, 1.2549679546936818e-111, 4.4656005878580503e-117, 2.3425513711144864e-123, 3.5814970887800193e-131}, + {5.1058382388659269e-132, 3.4787452134261360e-124, 6.8621328476606254e-118, 1.9887929527241800e-112, 1.5984806988768767e-107, 4.9691113060541562e-103, 7.3123967185564915e-99, 5.8275341127995904e-95, 2.7668599413210135e-91, 8.4008516795919007e-88, 1.7224108182682644e-84, 2.4894935837631581e-81, 2.6262929329466987e-78, 2.0809367058140554e-75, 1.2683653376027615e-72, 6.0687062439892660e-70, 2.3192577160038707e-67, 7.1865618890614741e-65, 1.8293638224274986e-62, 3.8697820973543049e-60, 6.8723829518191775e-58, 1.0339639913382959e-55, 1.3286530592326351e-53, 1.4689382904493016e-51, 1.4065458992870208e-49, 1.1734649400073276e-47, 8.5768492248869891e-46, 5.5194857702963127e-44, 3.1417689022491827e-42, 1.5884965434373284e-40, 7.1618254982458697e-39, 2.8896676701682861e-37, 1.0469000850542053e-35, 3.4161633966903074e-34, 1.0069252468038614e-32, 2.6880974156578509e-31, 6.5158094363462302e-30, 1.4374174204375062e-28, 2.8922727144899803e-27, 5.3189806528533866e-26, 8.9574942952228153e-25, 1.3838820621840956e-23, 1.9647377828565719e-22, 2.5674274750397857e-21, 3.0926768131345034e-20, 3.4389885933401063e-19, 3.5348317750763591e-18, 3.3627744521880394e-17, 2.9643952991648909e-16, 2.4242278762902340e-15, 1.8410778220221309e-14, 1.2997777867558265e-13, 8.5384118147611980e-13, 5.2237944008745323e-12, 2.9789583264039043e-11, 1.5847474437596250e-10, 7.8704836352169759e-10, 3.6517281221510981e-09, 1.5839569546032163e-08, 6.4270494029387501e-08, 2.4409702642671850e-07, 8.6823986929119786e-07, 2.8938252044645185e-06, 9.0422158488303162e-06, 2.6500151909252169e-05, 7.2875309659252541e-05, 1.8812470050977485e-04, 4.5604422468456632e-04, 1.0385182654144745e-03, 2.2223166735266457e-03, 4.4700208091087738e-03, 8.4535858780912364e-03, 1.5035066629455310e-02, 2.5153428292907908e-02, 3.9591364280961522e-02, 5.8639320239639699e-02, 8.1738404552485058e-02, 1.0724220730838535e-01, 1.3244982464015054e-01, 1.5399867398459949e-01, 1.6857248411687309e-01, 1.7373006454622800e-01, 1.6857248411687309e-01, 1.5399867398459949e-01, 1.3244982464015054e-01, 1.0724220730838535e-01, 8.1738404552485058e-02, 5.8639320239639699e-02, 3.9591364280961522e-02, 2.5153428292907908e-02, 1.5035066629455310e-02, 8.4535858780912364e-03, 4.4700208091087738e-03, 2.2223166735266457e-03, 1.0385182654144745e-03, 4.5604422468456632e-04, 1.8812470050977485e-04, 7.2875309659252541e-05, 2.6500151909252169e-05, 9.0422158488303162e-06, 2.8938252044645185e-06, 8.6823986929119786e-07, 2.4409702642671850e-07, 6.4270494029387501e-08, 1.5839569546032163e-08, 3.6517281221510981e-09, 7.8704836352169759e-10, 1.5847474437596250e-10, 2.9789583264039043e-11, 5.2237944008745323e-12, 8.5384118147611980e-13, 1.2997777867558265e-13, 1.8410778220221309e-14, 2.4242278762902340e-15, 2.9643952991648909e-16, 3.3627744521880394e-17, 3.5348317750763591e-18, 3.4389885933401063e-19, 3.0926768131345034e-20, 2.5674274750397857e-21, 1.9647377828565719e-22, 1.3838820621840956e-23, 8.9574942952228153e-25, 5.3189806528533866e-26, 2.8922727144899803e-27, 1.4374174204375062e-28, 6.5158094363462302e-30, 2.6880974156578509e-31, 1.0069252468038614e-32, 3.4161633966903074e-34, 1.0469000850542053e-35, 2.8896676701682861e-37, 7.1618254982458697e-39, 1.5884965434373284e-40, 3.1417689022491827e-42, 5.5194857702963127e-44, 8.5768492248869891e-46, 1.1734649400073276e-47, 1.4065458992870208e-49, 1.4689382904493016e-51, 1.3286530592326351e-53, 1.0339639913382959e-55, 6.8723829518191775e-58, 3.8697820973543049e-60, 1.8293638224274986e-62, 7.1865618890614741e-65, 2.3192577160038707e-67, 6.0687062439892660e-70, 1.2683653376027615e-72, 2.0809367058140554e-75, 2.6262929329466987e-78, 2.4894935837631581e-81, 1.7224108182682644e-84, 8.4008516795919007e-88, 2.7668599413210135e-91, 5.8275341127995904e-95, 7.3123967185564915e-99, 4.9691113060541562e-103, 1.5984806988768767e-107, 1.9887929527241800e-112, 6.8621328476606254e-118, 3.4787452134261360e-124, 5.1058382388659269e-132}, + {7.2774136808374355e-133, 5.1640253363781065e-125, 1.0539163395229755e-118, 3.1495974864069521e-113, 2.6047400909049849e-108, 8.3190735956096083e-104, 1.2563394260844383e-99, 1.0266029334944310e-95, 4.9942483588606006e-92, 1.5528225080749898e-88, 3.2586916028699435e-85, 4.8189357949651464e-82, 5.1995900683110418e-79, 4.2125456733725475e-76, 2.6247146396219082e-73, 1.2834925357232391e-70, 5.0121772980919659e-68, 1.5867585378958465e-65, 4.1261409970889649e-63, 8.9152934736506373e-61, 1.6170383864591641e-58, 2.4845512749608618e-56, 3.2602867516914131e-54, 3.6806734534292869e-52, 3.5986560950072034e-50, 3.0655422197589668e-48, 2.2877484525825812e-46, 1.5032084002307616e-44, 8.7364621051992394e-43, 4.5101690564191873e-41, 2.0762677615749785e-39, 8.5540504547638604e-38, 3.1645195547118431e-36, 1.0544772050999357e-34, 3.1740376151073218e-33, 8.6536469704170907e-32, 2.1423361912655937e-30, 4.8272033657573108e-29, 9.9214758418835271e-28, 1.8639024742210292e-26, 3.2068221113110570e-25, 5.0619653821736361e-24, 7.3433969692709968e-23, 9.8063138469438635e-22, 1.2072647224673922e-20, 1.3721655943148051e-19, 1.4417902155501092e-18, 1.4022988180739114e-17, 1.2639871956315117e-16, 1.0570613866427036e-15, 8.2106561126223668e-15, 5.9294550957769600e-14, 3.9849788475246675e-13, 2.4946167855672290e-12, 1.4558577681248529e-11, 7.9272325104664409e-11, 4.0303485756427884e-10, 1.9146717079546461e-09, 8.5049436556100333e-09, 3.5346942618254887e-08, 1.3752997102467001e-07, 5.0124990214178011e-07, 1.7121991444326337e-06, 5.4842169146680313e-06, 1.6479308921225968e-05, 4.6474831646589210e-05, 1.2306336370474281e-04, 3.0608156336295680e-04, 7.1531332284984861e-04, 1.5712593917201550e-03, 3.2450562679797843e-03, 6.3028742438160333e-03, 1.1516105006399560e-02, 1.9797989451736150e-02, 3.2031157662458190e-02, 4.8779535009276516e-02, 6.9933221621689870e-02, 9.4399083753525778e-02, 1.1998808778160919e-01, 1.4362587120152381e-01, 1.6191232338499803e-01, 1.7190906682322146e-01, 1.7190906682322146e-01, 1.6191232338499803e-01, 1.4362587120152381e-01, 1.1998808778160919e-01, 9.4399083753525778e-02, 6.9933221621689870e-02, 4.8779535009276516e-02, 3.2031157662458190e-02, 1.9797989451736150e-02, 1.1516105006399560e-02, 6.3028742438160333e-03, 3.2450562679797843e-03, 1.5712593917201550e-03, 7.1531332284984861e-04, 3.0608156336295680e-04, 1.2306336370474281e-04, 4.6474831646589210e-05, 1.6479308921225968e-05, 5.4842169146680313e-06, 1.7121991444326337e-06, 5.0124990214178011e-07, 1.3752997102467001e-07, 3.5346942618254887e-08, 8.5049436556100333e-09, 1.9146717079546461e-09, 4.0303485756427884e-10, 7.9272325104664409e-11, 1.4558577681248529e-11, 2.4946167855672290e-12, 3.9849788475246675e-13, 5.9294550957769600e-14, 8.2106561126223668e-15, 1.0570613866427036e-15, 1.2639871956315117e-16, 1.4022988180739114e-17, 1.4417902155501092e-18, 1.3721655943148051e-19, 1.2072647224673922e-20, 9.8063138469438635e-22, 7.3433969692709968e-23, 5.0619653821736361e-24, 3.2068221113110570e-25, 1.8639024742210292e-26, 9.9214758418835271e-28, 4.8272033657573108e-29, 2.1423361912655937e-30, 8.6536469704170907e-32, 3.1740376151073218e-33, 1.0544772050999357e-34, 3.1645195547118431e-36, 8.5540504547638604e-38, 2.0762677615749785e-39, 4.5101690564191873e-41, 8.7364621051992394e-43, 1.5032084002307616e-44, 2.2877484525825812e-46, 3.0655422197589668e-48, 3.5986560950072034e-50, 3.6806734534292869e-52, 3.2602867516914131e-54, 2.4845512749608618e-56, 1.6170383864591641e-58, 8.9152934736506373e-61, 4.1261409970889649e-63, 1.5867585378958465e-65, 5.0121772980919659e-68, 1.2834925357232391e-70, 2.6247146396219082e-73, 4.2125456733725475e-76, 5.1995900683110418e-79, 4.8189357949651464e-82, 3.2586916028699435e-85, 1.5528225080749898e-88, 4.9942483588606006e-92, 1.0266029334944310e-95, 1.2563394260844383e-99, 8.3190735956096083e-104, 2.6047400909049849e-108, 3.1495974864069521e-113, 1.0539163395229755e-118, 5.1640253363781065e-125, 7.2774136808374355e-133}, + {1.0370401330404128e-133, 7.6628104007938171e-126, 1.6177944458582779e-119, 4.9846209741944082e-114, 4.2410903981966999e-109, 1.3914702767711137e-104, 2.1562790735643016e-100, 1.8064249655941844e-96, 9.0033176079341812e-93, 2.8662892545517945e-89, 6.1560200907369249e-86, 9.3130571849846176e-83, 1.0276539331534194e-79, 8.5120283276029899e-77, 5.4209234698248101e-74, 2.7089105182625548e-71, 1.0808323828410104e-68, 3.4954669585711314e-66, 9.2841597125229309e-64, 2.0487495492161133e-61, 3.7947795686740356e-59, 5.9537760035157825e-57, 7.9771959541897771e-55, 9.1949435242106659e-53, 9.1785078949346243e-51, 7.9824553719798949e-49, 6.0817267689790556e-47, 4.0796548388663509e-45, 2.4206136388252030e-43, 1.2757690988603576e-41, 5.9959663570350600e-40, 2.5220557090360086e-38, 9.5260156082741867e-37, 3.2409917090630152e-35, 9.9611495020508274e-34, 2.7731632192036800e-32, 7.0108006530723495e-31, 1.6132689567876035e-29, 3.3864807517869285e-28, 6.4981402796424245e-27, 1.1420079983768409e-25, 1.8415308229503966e-24, 2.7293664944237734e-23, 3.7240665643118182e-22, 4.6849502295754945e-21, 5.4418440370928148e-20, 5.8442290512558873e-19, 5.8103464142089000e-18, 5.3541848627525126e-17, 4.5782053131046985e-16, 3.6364250808804760e-15, 2.6857950742667181e-14, 1.8463211087063347e-13, 1.1824213225107695e-12, 7.0605885367663953e-12, 3.9342842554083200e-11, 2.0472924906259976e-10, 9.9563021167170463e-10, 4.5281139927096718e-09, 1.9271612548094547e-08, 7.6800568196628212e-08, 2.8675127848315921e-07, 1.0036330972927129e-06, 3.2945281705899829e-06, 1.0147672170741122e-05, 2.9341866948530294e-05, 7.9677853191228106e-05, 2.0327512248096151e-04, 4.8739807702018396e-04, 1.0987048493532403e-03, 2.3292137543048106e-03, 4.6450584683976901e-03, 8.7164233107623907e-03, 1.5394018995268760e-02, 2.5593125567577809e-02, 4.0062052918626051e-02, 5.9054458453798808e-02, 8.1986641314913386e-02, 1.0721512879081883e-01, 1.3207899230191014e-01, 1.5328822654091181e-01, 1.6761177530123578e-01, 1.7267715506412973e-01, 1.6761177530123578e-01, 1.5328822654091181e-01, 1.3207899230191014e-01, 1.0721512879081883e-01, 8.1986641314913386e-02, 5.9054458453798808e-02, 4.0062052918626051e-02, 2.5593125567577809e-02, 1.5394018995268760e-02, 8.7164233107623907e-03, 4.6450584683976901e-03, 2.3292137543048106e-03, 1.0987048493532403e-03, 4.8739807702018396e-04, 2.0327512248096151e-04, 7.9677853191228106e-05, 2.9341866948530294e-05, 1.0147672170741122e-05, 3.2945281705899829e-06, 1.0036330972927129e-06, 2.8675127848315921e-07, 7.6800568196628212e-08, 1.9271612548094547e-08, 4.5281139927096718e-09, 9.9563021167170463e-10, 2.0472924906259976e-10, 3.9342842554083200e-11, 7.0605885367663953e-12, 1.1824213225107695e-12, 1.8463211087063347e-13, 2.6857950742667181e-14, 3.6364250808804760e-15, 4.5782053131046985e-16, 5.3541848627525126e-17, 5.8103464142089000e-18, 5.8442290512558873e-19, 5.4418440370928148e-20, 4.6849502295754945e-21, 3.7240665643118182e-22, 2.7293664944237734e-23, 1.8415308229503966e-24, 1.1420079983768409e-25, 6.4981402796424245e-27, 3.3864807517869285e-28, 1.6132689567876035e-29, 7.0108006530723495e-31, 2.7731632192036800e-32, 9.9611495020508274e-34, 3.2409917090630152e-35, 9.5260156082741867e-37, 2.5220557090360086e-38, 5.9959663570350600e-40, 1.2757690988603576e-41, 2.4206136388252030e-43, 4.0796548388663509e-45, 6.0817267689790556e-47, 7.9824553719798949e-49, 9.1785078949346243e-51, 9.1949435242106659e-53, 7.9771959541897771e-55, 5.9537760035157825e-57, 3.7947795686740356e-59, 2.0487495492161133e-61, 9.2841597125229309e-64, 3.4954669585711314e-66, 1.0808323828410104e-68, 2.7089105182625548e-71, 5.4209234698248101e-74, 8.5120283276029899e-77, 1.0276539331534194e-79, 9.3130571849846176e-83, 6.1560200907369249e-86, 2.8662892545517945e-89, 9.0033176079341812e-93, 1.8064249655941844e-96, 2.1562790735643016e-100, 1.3914702767711137e-104, 4.2410903981966999e-109, 4.9846209741944082e-114, 1.6177944458582779e-119, 7.6628104007938171e-126, 1.0370401330404128e-133}, + {1.4774864044730919e-134, 1.1366413967312580e-126, 2.4820647345980668e-120, 7.8835864352328026e-115, 6.9000209771443205e-110, 2.3253044708336631e-105, 3.6970767260897540e-101, 3.1749907175216285e-97, 1.6210276225797838e-93, 5.2835329659655297e-90, 1.1612190047837748e-86, 1.7969751555347008e-83, 2.0276116391228268e-80, 1.7168527133451101e-77, 1.1174481216103580e-74, 5.7057155838516782e-72, 2.3257094876339456e-69, 7.6827297329990042e-67, 2.0840476902701378e-64, 4.6963320200403117e-62, 8.8821741614196649e-60, 1.4228297251266947e-57, 1.9462991520350709e-55, 2.2902568991273256e-53, 2.3338081888304624e-51, 2.0719270806826472e-49, 1.6113919045974023e-47, 1.1033912986165171e-45, 6.6828682986466127e-44, 3.5953723054115794e-42, 1.7249314720204933e-40, 7.4065841467302406e-39, 2.8558675123113318e-37, 9.9193674854686742e-36, 3.1125293650397015e-34, 8.8470553643068575e-33, 2.2836747845517017e-31, 5.3659089984759047e-30, 1.1502283587852324e-28, 2.2540053407015112e-27, 4.0457517920854419e-26, 6.6636084030909077e-25, 1.0088605806727544e-23, 1.4062620052335121e-22, 1.8074912939358217e-21, 2.1452843610753105e-20, 2.3544032965183590e-19, 2.3923239898564218e-18, 2.2533431601785240e-17, 1.9696954324441430e-16, 1.5995738956856818e-15, 1.2080546491164034e-14, 8.4930831160690606e-14, 5.5633632513833882e-13, 3.3984267451196722e-12, 1.9374997522123724e-11, 1.0317252591614767e-10, 5.1352562907714339e-10, 2.3907560585436029e-09, 1.0417563656335543e-08, 4.2512972951519652e-08, 1.6257453952247463e-07, 5.8290254892118051e-07, 1.9605333794325452e-06, 6.1886554017466215e-06, 1.8342475402473601e-05, 5.1067234537777706e-05, 1.3360429556693264e-04, 3.2858768305186580e-04, 7.5994560780524184e-04, 1.6532956640381497e-03, 3.3843936084184865e-03, 6.5206132604078895e-03, 1.1827087059306185e-02, 2.0199624381625723e-02, 3.2491469153777909e-02, 4.9230083099421298e-02, 7.0273553473008815e-02, 9.4516761260745735e-02, 1.1979187349505478e-01, 1.4308174026017673e-01, 1.6106711507035643e-01, 1.7088881774276651e-01, 1.7088881774276651e-01, 1.6106711507035643e-01, 1.4308174026017673e-01, 1.1979187349505478e-01, 9.4516761260745735e-02, 7.0273553473008815e-02, 4.9230083099421298e-02, 3.2491469153777909e-02, 2.0199624381625723e-02, 1.1827087059306185e-02, 6.5206132604078895e-03, 3.3843936084184865e-03, 1.6532956640381497e-03, 7.5994560780524184e-04, 3.2858768305186580e-04, 1.3360429556693264e-04, 5.1067234537777706e-05, 1.8342475402473601e-05, 6.1886554017466215e-06, 1.9605333794325452e-06, 5.8290254892118051e-07, 1.6257453952247463e-07, 4.2512972951519652e-08, 1.0417563656335543e-08, 2.3907560585436029e-09, 5.1352562907714339e-10, 1.0317252591614767e-10, 1.9374997522123724e-11, 3.3984267451196722e-12, 5.5633632513833882e-13, 8.4930831160690606e-14, 1.2080546491164034e-14, 1.5995738956856818e-15, 1.9696954324441430e-16, 2.2533431601785240e-17, 2.3923239898564218e-18, 2.3544032965183590e-19, 2.1452843610753105e-20, 1.8074912939358217e-21, 1.4062620052335121e-22, 1.0088605806727544e-23, 6.6636084030909077e-25, 4.0457517920854419e-26, 2.2540053407015112e-27, 1.1502283587852324e-28, 5.3659089984759047e-30, 2.2836747845517017e-31, 8.8470553643068575e-33, 3.1125293650397015e-34, 9.9193674854686742e-36, 2.8558675123113318e-37, 7.4065841467302406e-39, 1.7249314720204933e-40, 3.5953723054115794e-42, 6.6828682986466127e-44, 1.1033912986165171e-45, 1.6113919045974023e-47, 2.0719270806826472e-49, 2.3338081888304624e-51, 2.2902568991273256e-53, 1.9462991520350709e-55, 1.4228297251266947e-57, 8.8821741614196649e-60, 4.6963320200403117e-62, 2.0840476902701378e-64, 7.6827297329990042e-67, 2.3257094876339456e-69, 5.7057155838516782e-72, 1.1174481216103580e-74, 1.7168527133451101e-77, 2.0276116391228268e-80, 1.7969751555347008e-83, 1.1612190047837748e-86, 5.2835329659655297e-90, 1.6210276225797838e-93, 3.1749907175216285e-97, 3.6970767260897540e-101, 2.3253044708336631e-105, 6.9000209771443205e-110, 7.8835864352328026e-115, 2.4820647345980668e-120, 1.1366413967312580e-126, 1.4774864044730919e-134}, + {2.1045621159574830e-135, 1.6853736680140806e-127, 3.8060787191717414e-121, 1.2460431717780355e-115, 1.1217254900384875e-110, 3.8823686733906794e-106, 6.3324559268876792e-102, 5.5741078533835752e-98, 2.9150063258205350e-94, 9.7261605479925101e-91, 2.1872204017818973e-87, 3.4618487459964773e-84, 3.9938420292542256e-81, 3.4566329048643892e-78, 2.2990777865226915e-75, 1.1993601521489046e-72, 4.9937669382694245e-70, 1.6848180938195073e-67, 4.6671413158696264e-65, 1.0738850147584223e-62, 2.0736313112573398e-60, 3.3911184321991622e-58, 4.7353070830108189e-56, 5.6878446259603137e-54, 5.9160971507025675e-52, 5.3608992748856614e-50, 4.2554770940703958e-48, 2.9740995846398285e-46, 1.8385123238649587e-44, 1.0095495376276113e-42, 4.9435800520554766e-41, 2.1666198058800618e-39, 8.5272688786829149e-38, 3.0232780766836873e-36, 9.6838410701764544e-35, 2.8099176317436489e-33, 7.4047930191407272e-32, 1.7763620673555590e-30, 3.8878538387006395e-29, 7.7794521016127823e-28, 1.4259174843705503e-26, 2.3985064022625709e-25, 3.7088241471290263e-24, 5.2806166677136793e-23, 6.9334558099800012e-22, 8.4073193071442628e-21, 9.4275495388536763e-20, 9.7888471796527459e-19, 9.4228636835633407e-18, 8.4188202692459649e-17, 6.9888828000995662e-16, 5.3963258195263796e-15, 3.8792170840235010e-14, 2.5986297789613529e-13, 1.6235905955395716e-12, 9.4688541385973895e-12, 5.1587531828242437e-11, 2.6274698033796913e-10, 1.2519243488472937e-09, 5.5840692373466946e-09, 2.3330544086080361e-08, 9.1359564208430839e-08, 3.3548824403388151e-07, 1.1558985161302230e-06, 3.7384592935259604e-06, 1.1355193773739383e-05, 3.2404937824118138e-05, 8.6919300398468442e-05, 2.1921561912382546e-04, 5.2002884998328185e-04, 1.1607090699966350e-03, 2.4383039027033393e-03, 4.8221285878206101e-03, 8.9801569838840641e-03, 1.5751462301844443e-02, 2.6027795319202608e-02, 4.0523924217918790e-02, 5.9458195592787075e-02, 8.2223731723011229e-02, 1.0718097152174927e-01, 1.3170852135471239e-01, 1.5258690288545360e-01, 1.6666726633087006e-01, 1.7164316012362582e-01, 1.6666726633087006e-01, 1.5258690288545360e-01, 1.3170852135471239e-01, 1.0718097152174927e-01, 8.2223731723011229e-02, 5.9458195592787075e-02, 4.0523924217918790e-02, 2.6027795319202608e-02, 1.5751462301844443e-02, 8.9801569838840641e-03, 4.8221285878206101e-03, 2.4383039027033393e-03, 1.1607090699966350e-03, 5.2002884998328185e-04, 2.1921561912382546e-04, 8.6919300398468442e-05, 3.2404937824118138e-05, 1.1355193773739383e-05, 3.7384592935259604e-06, 1.1558985161302230e-06, 3.3548824403388151e-07, 9.1359564208430839e-08, 2.3330544086080361e-08, 5.5840692373466946e-09, 1.2519243488472937e-09, 2.6274698033796913e-10, 5.1587531828242437e-11, 9.4688541385973895e-12, 1.6235905955395716e-12, 2.5986297789613529e-13, 3.8792170840235010e-14, 5.3963258195263796e-15, 6.9888828000995662e-16, 8.4188202692459649e-17, 9.4228636835633407e-18, 9.7888471796527459e-19, 9.4275495388536763e-20, 8.4073193071442628e-21, 6.9334558099800012e-22, 5.2806166677136793e-23, 3.7088241471290263e-24, 2.3985064022625709e-25, 1.4259174843705503e-26, 7.7794521016127823e-28, 3.8878538387006395e-29, 1.7763620673555590e-30, 7.4047930191407272e-32, 2.8099176317436489e-33, 9.6838410701764544e-35, 3.0232780766836873e-36, 8.5272688786829149e-38, 2.1666198058800618e-39, 4.9435800520554766e-41, 1.0095495376276113e-42, 1.8385123238649587e-44, 2.9740995846398285e-46, 4.2554770940703958e-48, 5.3608992748856614e-50, 5.9160971507025675e-52, 5.6878446259603137e-54, 4.7353070830108189e-56, 3.3911184321991622e-58, 2.0736313112573398e-60, 1.0738850147584223e-62, 4.6671413158696264e-65, 1.6848180938195073e-67, 4.9937669382694245e-70, 1.1993601521489046e-72, 2.2990777865226915e-75, 3.4566329048643892e-78, 3.9938420292542256e-81, 3.4618487459964773e-84, 2.1872204017818973e-87, 9.7261605479925101e-91, 2.9150063258205350e-94, 5.5741078533835752e-98, 6.3324559268876792e-102, 3.8823686733906794e-106, 1.1217254900384875e-110, 1.2460431717780355e-115, 3.8060787191717414e-121, 1.6853736680140806e-127, 2.1045621159574830e-135}, + {2.9971690491012730e-136, 2.4980891398206762e-128, 5.8333713614299987e-122, 1.9681709423933214e-116, 1.8221727762675135e-111, 6.4763280099261484e-107, 1.0835544161526790e-102, 9.7751589620462579e-99, 5.2354686514639054e-95, 1.7880404661796150e-91, 4.1137899834361915e-88, 6.6588269447352457e-85, 7.8536797447719853e-82, 6.9470795412027442e-79, 4.7212966724403236e-76, 2.5160708333635340e-73, 1.0700081200070465e-70, 3.6866210764241453e-68, 1.0427591853094809e-65, 2.4496158809944983e-63, 4.8287654459243867e-61, 8.0607602578177551e-59, 1.1488941335553380e-56, 1.4084920383852964e-54, 1.4951953571335084e-52, 1.3827452604659908e-50, 1.1201727218381219e-48, 7.9894861866156147e-47, 5.0402806679659781e-45, 2.8245056542381498e-43, 1.4115238161648369e-41, 6.3134908835445427e-40, 2.5359952829354267e-38, 9.1766156441607901e-37, 3.0000961317861622e-35, 8.8855426938068462e-34, 2.3901684056219713e-32, 5.8532507898005387e-31, 1.3078348727191383e-29, 2.6717694287109624e-28, 5.0001529132188371e-27, 8.5882149512444349e-26, 1.3561502945339099e-24, 1.9719885628376035e-23, 2.6445905466631306e-22, 3.2756544281813711e-21, 3.7524614126630812e-20, 3.9808239456321635e-19, 3.9155933049886526e-18, 3.5751188594220651e-17, 3.0333673764885698e-16, 2.3941367575799993e-15, 1.7594869510962716e-14, 1.2051394761470136e-13, 7.6998498930386894e-13, 4.5928264710545402e-12, 2.5595903423630225e-11, 1.3337516615570700e-10, 6.5027567060176707e-10, 2.9684197043117582e-09, 1.2694911467897228e-08, 5.0894009383117858e-08, 1.9137169385842292e-07, 6.7528978068278956e-07, 2.2372679339319808e-06, 6.9624497238718160e-06, 2.0361547224732169e-05, 5.5980964406792492e-05, 1.4474894898356766e-04, 3.5211870018385556e-04, 8.0612713585123284e-04, 1.7373614851938118e-03, 3.5259000508765289e-03, 6.7399040525805923e-03, 1.2137859543972172e-02, 2.0598052684982535e-02, 3.2944830178350461e-02, 4.9670368744572549e-02, 7.0602349240131604e-02, 9.4625036098936688e-02, 1.1959210591508003e-01, 1.4254236006576013e-01, 1.6023480790396424e-01, 1.6988651844048314e-01, 1.6988651844048314e-01, 1.6023480790396424e-01, 1.4254236006576013e-01, 1.1959210591508003e-01, 9.4625036098936688e-02, 7.0602349240131604e-02, 4.9670368744572549e-02, 3.2944830178350461e-02, 2.0598052684982535e-02, 1.2137859543972172e-02, 6.7399040525805923e-03, 3.5259000508765289e-03, 1.7373614851938118e-03, 8.0612713585123284e-04, 3.5211870018385556e-04, 1.4474894898356766e-04, 5.5980964406792492e-05, 2.0361547224732169e-05, 6.9624497238718160e-06, 2.2372679339319808e-06, 6.7528978068278956e-07, 1.9137169385842292e-07, 5.0894009383117858e-08, 1.2694911467897228e-08, 2.9684197043117582e-09, 6.5027567060176707e-10, 1.3337516615570700e-10, 2.5595903423630225e-11, 4.5928264710545402e-12, 7.6998498930386894e-13, 1.2051394761470136e-13, 1.7594869510962716e-14, 2.3941367575799993e-15, 3.0333673764885698e-16, 3.5751188594220651e-17, 3.9155933049886526e-18, 3.9808239456321635e-19, 3.7524614126630812e-20, 3.2756544281813711e-21, 2.6445905466631306e-22, 1.9719885628376035e-23, 1.3561502945339099e-24, 8.5882149512444349e-26, 5.0001529132188371e-27, 2.6717694287109624e-28, 1.3078348727191383e-29, 5.8532507898005387e-31, 2.3901684056219713e-32, 8.8855426938068462e-34, 3.0000961317861622e-35, 9.1766156441607901e-37, 2.5359952829354267e-38, 6.3134908835445427e-40, 1.4115238161648369e-41, 2.8245056542381498e-43, 5.0402806679659781e-45, 7.9894861866156147e-47, 1.1201727218381219e-48, 1.3827452604659908e-50, 1.4951953571335084e-52, 1.4084920383852964e-54, 1.1488941335553380e-56, 8.0607602578177551e-59, 4.8287654459243867e-61, 2.4496158809944983e-63, 1.0427591853094809e-65, 3.6866210764241453e-68, 1.0700081200070465e-70, 2.5160708333635340e-73, 4.7212966724403236e-76, 6.9470795412027442e-79, 7.8536797447719853e-82, 6.6588269447352457e-85, 4.1137899834361915e-88, 1.7880404661796150e-91, 5.2354686514639054e-95, 9.7751589620462579e-99, 1.0835544161526790e-102, 6.4763280099261484e-107, 1.8221727762675135e-111, 1.9681709423933214e-116, 5.8333713614299987e-122, 2.4980891398206762e-128, 2.9971690491012730e-136}, + {4.2674931553342203e-137, 3.7013509844210040e-129, 8.9359543576021383e-123, 3.1068184196664260e-117, 2.9577586950025811e-112, 1.0793940202510381e-107, 1.8522459789363982e-103, 1.7123515642355668e-99, 9.3917005928096861e-96, 3.2827539517233995e-92, 7.7262644929909970e-89, 1.2788460726412831e-85, 1.5418407850274678e-82, 1.3937615371156682e-79, 9.6774116872500576e-77, 5.2679228724311439e-74, 2.2879261623118261e-71, 8.0492001695776603e-69, 2.3244392181338319e-66, 5.5743129455028007e-64, 1.1216194835766520e-61, 1.9110201175931197e-59, 2.7798349876894280e-57, 3.4779129275742834e-55, 3.7676299883874885e-53, 3.5555263388415704e-51, 2.9391917507565755e-49, 2.1391283000208420e-47, 1.3770363396814081e-45, 7.8742105891358037e-44, 4.0154223770167576e-42, 1.8327311167318893e-40, 7.5123280800309780e-39, 2.7740812006389936e-37, 9.2554744703184908e-36, 2.7976499634157274e-34, 7.6807810254033586e-33, 1.9198421026192681e-31, 4.3786397679911876e-30, 9.1312863995714357e-29, 1.7445924812851179e-27, 3.0593178878006020e-26, 4.9326008142373812e-25, 7.3241393698795336e-24, 1.0030774102469258e-22, 1.2689360428385754e-21, 1.4847983173617774e-20, 1.6090879587826797e-19, 1.6169926387796005e-18, 1.5085327113052835e-17, 1.3079623075775175e-16, 1.0550654299237249e-15, 7.9256160807813284e-15, 5.5495687412198589e-14, 3.6252638108375508e-13, 2.2112377011770522e-12, 1.2603426258460018e-11, 6.7177337738006964e-11, 3.3507655233538448e-10, 1.5650990540810345e-09, 6.8499863308168436e-09, 2.8109038530404097e-08, 1.0820676942101237e-07, 3.9097121047484011e-07, 1.3265796796150300e-06, 4.2288616562734994e-06, 1.2670859378200327e-05, 3.5699320251985919e-05, 9.4613317406319364e-05, 2.3596028278015030e-04, 5.5394259248142631e-04, 1.2245148633746915e-03, 2.5495331679026910e-03, 5.0011317639987000e-03, 9.2446564129297221e-03, 1.6107280751087583e-02, 2.6457407162359760e-02, 4.0977099534106338e-02, 5.9850822005640535e-02, 8.2450068298432835e-02, 1.0714008439362262e-01, 1.3133855013394508e-01, 1.5189453076872492e-01, 1.6573850820195182e-01, 1.7062752012289428e-01, 1.6573850820195182e-01, 1.5189453076872492e-01, 1.3133855013394508e-01, 1.0714008439362262e-01, 8.2450068298432835e-02, 5.9850822005640535e-02, 4.0977099534106338e-02, 2.6457407162359760e-02, 1.6107280751087583e-02, 9.2446564129297221e-03, 5.0011317639987000e-03, 2.5495331679026910e-03, 1.2245148633746915e-03, 5.5394259248142631e-04, 2.3596028278015030e-04, 9.4613317406319364e-05, 3.5699320251985919e-05, 1.2670859378200327e-05, 4.2288616562734994e-06, 1.3265796796150300e-06, 3.9097121047484011e-07, 1.0820676942101237e-07, 2.8109038530404097e-08, 6.8499863308168436e-09, 1.5650990540810345e-09, 3.3507655233538448e-10, 6.7177337738006964e-11, 1.2603426258460018e-11, 2.2112377011770522e-12, 3.6252638108375508e-13, 5.5495687412198589e-14, 7.9256160807813284e-15, 1.0550654299237249e-15, 1.3079623075775175e-16, 1.5085327113052835e-17, 1.6169926387796005e-18, 1.6090879587826797e-19, 1.4847983173617774e-20, 1.2689360428385754e-21, 1.0030774102469258e-22, 7.3241393698795336e-24, 4.9326008142373812e-25, 3.0593178878006020e-26, 1.7445924812851179e-27, 9.1312863995714357e-29, 4.3786397679911876e-30, 1.9198421026192681e-31, 7.6807810254033586e-33, 2.7976499634157274e-34, 9.2554744703184908e-36, 2.7740812006389936e-37, 7.5123280800309780e-39, 1.8327311167318893e-40, 4.0154223770167576e-42, 7.8742105891358037e-44, 1.3770363396814081e-45, 2.1391283000208420e-47, 2.9391917507565755e-49, 3.5555263388415704e-51, 3.7676299883874885e-53, 3.4779129275742834e-55, 2.7798349876894280e-57, 1.9110201175931197e-59, 1.1216194835766520e-61, 5.5743129455028007e-64, 2.3244392181338319e-66, 8.0492001695776603e-69, 2.2879261623118261e-71, 5.2679228724311439e-74, 9.6774116872500576e-77, 1.3937615371156682e-79, 1.5418407850274678e-82, 1.2788460726412831e-85, 7.7262644929909970e-89, 3.2827539517233995e-92, 9.3917005928096861e-96, 1.7123515642355668e-99, 1.8522459789363982e-103, 1.0793940202510381e-107, 2.9577586950025811e-112, 3.1068184196664260e-117, 8.9359543576021383e-123, 3.7013509844210040e-129, 4.2674931553342203e-137}, + {6.0750158130606195e-138, 5.4821992024733287e-130, 1.3681822165982846e-123, 4.9011169950359405e-118, 4.7974396933811439e-113, 1.7974392277078273e-108, 3.1631548152333414e-104, 2.9963165563522804e-100, 1.6827169561417482e-96, 6.0190850814126162e-93, 1.4490438595507066e-89, 2.4523185664718153e-86, 3.0220219471047618e-83, 2.7913874973199548e-80, 1.9799592744971097e-77, 1.1008005267477927e-74, 4.8820589020655159e-72, 1.7536229837285863e-69, 5.1696909850843693e-67, 1.2654633658209892e-64, 2.5987959219621812e-62, 4.5188057419567269e-60, 6.7077790006444227e-58, 8.5635704641083388e-56, 9.4658821709007862e-54, 9.1146156997272630e-52, 7.6876441303763667e-50, 5.7085575439180572e-48, 3.7493520841061347e-46, 2.1874580274727376e-44, 1.1381244408182845e-42, 5.3001743821412355e-41, 2.2167101442428974e-39, 8.3523638615101674e-38, 2.8435471995138850e-36, 8.7709151746020293e-35, 2.4573526663074424e-33, 6.2684680341301147e-32, 1.4591317861612538e-30, 3.1058077266730593e-29, 6.0569508661768345e-28, 1.0842625724312578e-26, 1.7847202502838671e-25, 2.7056507791212747e-24, 3.7836354660151275e-23, 4.8878185643771254e-22, 5.8409861850177518e-21, 6.4652715404585129e-20, 6.6366701688022747e-19, 6.3252994285961157e-18, 5.6034658987730242e-17, 4.6187988803389262e-16, 3.5458950811944735e-15, 2.5377705512106429e-14, 1.6946972716989475e-13, 1.0568382827043380e-12, 6.1595020440963285e-12, 3.3576005591117169e-11, 1.7130382466099029e-10, 8.1856149500888656e-10, 3.6657050674739318e-09, 1.5393813958417279e-08, 6.0654560255829627e-08, 2.2435783940914669e-07, 7.7946793854749263e-07, 2.5447213452537048e-06, 7.8101702177205490e-06, 2.2544487920551540e-05, 6.1227929783044720e-05, 1.5651161607055494e-04, 3.7668553922014524e-04, 8.5385410230442147e-04, 1.8234228920144958e-03, 3.6694988559735154e-03, 6.9606294949961902e-03, 1.2448294747794275e-02, 2.0993195618512490e-02, 3.3391282475767885e-02, 5.0100599356951693e-02, 7.0919958702876942e-02, 9.4724291720265918e-02, 1.1938903980933140e-01, 1.4200771666714165e-01, 1.5941508322714990e-01, 1.6890164874640598e-01, 1.6890164874640598e-01, 1.5941508322714990e-01, 1.4200771666714165e-01, 1.1938903980933140e-01, 9.4724291720265918e-02, 7.0919958702876942e-02, 5.0100599356951693e-02, 3.3391282475767885e-02, 2.0993195618512490e-02, 1.2448294747794275e-02, 6.9606294949961902e-03, 3.6694988559735154e-03, 1.8234228920144958e-03, 8.5385410230442147e-04, 3.7668553922014524e-04, 1.5651161607055494e-04, 6.1227929783044720e-05, 2.2544487920551540e-05, 7.8101702177205490e-06, 2.5447213452537048e-06, 7.7946793854749263e-07, 2.2435783940914669e-07, 6.0654560255829627e-08, 1.5393813958417279e-08, 3.6657050674739318e-09, 8.1856149500888656e-10, 1.7130382466099029e-10, 3.3576005591117169e-11, 6.1595020440963285e-12, 1.0568382827043380e-12, 1.6946972716989475e-13, 2.5377705512106429e-14, 3.5458950811944735e-15, 4.6187988803389262e-16, 5.6034658987730242e-17, 6.3252994285961157e-18, 6.6366701688022747e-19, 6.4652715404585129e-20, 5.8409861850177518e-21, 4.8878185643771254e-22, 3.7836354660151275e-23, 2.7056507791212747e-24, 1.7847202502838671e-25, 1.0842625724312578e-26, 6.0569508661768345e-28, 3.1058077266730593e-29, 1.4591317861612538e-30, 6.2684680341301147e-32, 2.4573526663074424e-33, 8.7709151746020293e-35, 2.8435471995138850e-36, 8.3523638615101674e-38, 2.2167101442428974e-39, 5.3001743821412355e-41, 1.1381244408182845e-42, 2.1874580274727376e-44, 3.7493520841061347e-46, 5.7085575439180572e-48, 7.6876441303763667e-50, 9.1146156997272630e-52, 9.4658821709007862e-54, 8.5635704641083388e-56, 6.7077790006444227e-58, 4.5188057419567269e-60, 2.5987959219621812e-62, 1.2654633658209892e-64, 5.1696909850843693e-67, 1.7536229837285863e-69, 4.8820589020655159e-72, 1.1008005267477927e-74, 1.9799592744971097e-77, 2.7913874973199548e-80, 3.0220219471047618e-83, 2.4523185664718153e-86, 1.4490438595507066e-89, 6.0190850814126162e-93, 1.6827169561417482e-96, 2.9963165563522804e-100, 3.1631548152333414e-104, 1.7974392277078273e-108, 4.7974396933811439e-113, 4.9011169950359405e-118, 1.3681822165982846e-123, 5.4821992024733287e-130, 6.0750158130606195e-138}, + {8.6464098495106045e-139, 8.1169547967150641e-131, 2.0937788694250258e-124, 7.7268624062801043e-119, 7.7755878030242305e-114, 2.9905793066209871e-109, 5.3966031917331080e-105, 5.2373672835160608e-101, 3.0113519152678094e-97, 1.1021983838887256e-93, 2.7138416423119788e-90, 4.6954865769208796e-87, 5.9136418179343394e-84, 5.5809142352163536e-81, 4.0435337904295643e-78, 2.2958300915077279e-75, 1.0396325878228644e-72, 3.8123200620819477e-70, 1.1471867481155006e-67, 2.8660528596806035e-65, 6.0065917977528455e-63, 1.0657711610182893e-60, 1.6142564784909037e-58, 2.1026978884308611e-56, 2.3713251069838819e-54, 2.3294898984397351e-52, 2.0044580918502007e-50, 1.5184626573152095e-48, 1.0174299157427975e-46, 6.0556195147012746e-45, 3.2142710908365357e-43, 1.5270851777984907e-41, 6.5158604619910054e-40, 2.5048070243067333e-38, 8.7004606571271586e-37, 2.7381749245865647e-35, 7.8277738587896100e-34, 2.0375540992709603e-32, 4.8399847326203970e-31, 1.0513633818680897e-29, 2.0926202706959383e-28, 3.8234939104131151e-27, 6.4242027780709820e-26, 9.9421354277925673e-25, 1.4194294864852321e-23, 1.8722162613285435e-22, 2.2845745768934510e-21, 2.5824265914439110e-20, 2.7074430614342264e-19, 2.6357601492491789e-18, 2.3853221384019439e-17, 2.0087998156976881e-16, 1.5758126400353855e-15, 1.1525451076836792e-14, 7.8665152475648879e-14, 5.0146808941799565e-13, 2.9880423319270495e-12, 1.6654840593814865e-11, 8.6899012302376471e-11, 4.2472082249711324e-10, 1.9457386067825712e-09, 8.3602716973645751e-09, 3.3710054470838133e-08, 1.2762506765080952e-07, 4.5391122547936338e-07, 1.5173031250618367e-06, 4.7690949847434419e-06, 1.4100857760918970e-05, 3.9234961307384339e-05, 1.0277324714018339e-04, 2.5352235086933272e-04, 5.8914391280362889e-04, 1.2901045250613646e-03, 2.6628467710093206e-03, 5.1819700035925865e-03, 9.5097957728564348e-03, 1.6461365836824633e-02, 2.6881937632071830e-02, 4.1421702134247403e-02, 6.0232621258249110e-02, 8.2666028537237118e-02, 1.0709279898985245e-01, 1.3096920653341185e-01, 1.5121094137038713e-01, 1.6482506909185640e-01, 1.6962969836778974e-01, 1.6482506909185640e-01, 1.5121094137038713e-01, 1.3096920653341185e-01, 1.0709279898985245e-01, 8.2666028537237118e-02, 6.0232621258249110e-02, 4.1421702134247403e-02, 2.6881937632071830e-02, 1.6461365836824633e-02, 9.5097957728564348e-03, 5.1819700035925865e-03, 2.6628467710093206e-03, 1.2901045250613646e-03, 5.8914391280362889e-04, 2.5352235086933272e-04, 1.0277324714018339e-04, 3.9234961307384339e-05, 1.4100857760918970e-05, 4.7690949847434419e-06, 1.5173031250618367e-06, 4.5391122547936338e-07, 1.2762506765080952e-07, 3.3710054470838133e-08, 8.3602716973645751e-09, 1.9457386067825712e-09, 4.2472082249711324e-10, 8.6899012302376471e-11, 1.6654840593814865e-11, 2.9880423319270495e-12, 5.0146808941799565e-13, 7.8665152475648879e-14, 1.1525451076836792e-14, 1.5758126400353855e-15, 2.0087998156976881e-16, 2.3853221384019439e-17, 2.6357601492491789e-18, 2.7074430614342264e-19, 2.5824265914439110e-20, 2.2845745768934510e-21, 1.8722162613285435e-22, 1.4194294864852321e-23, 9.9421354277925673e-25, 6.4242027780709820e-26, 3.8234939104131151e-27, 2.0926202706959383e-28, 1.0513633818680897e-29, 4.8399847326203970e-31, 2.0375540992709603e-32, 7.8277738587896100e-34, 2.7381749245865647e-35, 8.7004606571271586e-37, 2.5048070243067333e-38, 6.5158604619910054e-40, 1.5270851777984907e-41, 3.2142710908365357e-43, 6.0556195147012746e-45, 1.0174299157427975e-46, 1.5184626573152095e-48, 2.0044580918502007e-50, 2.3294898984397351e-52, 2.3713251069838819e-54, 2.1026978884308611e-56, 1.6142564784909037e-58, 1.0657711610182893e-60, 6.0065917977528455e-63, 2.8660528596806035e-65, 1.1471867481155006e-67, 3.8123200620819477e-70, 1.0396325878228644e-72, 2.2958300915077279e-75, 4.0435337904295643e-78, 5.5809142352163536e-81, 5.9136418179343394e-84, 4.6954865769208796e-87, 2.7138416423119788e-90, 1.1021983838887256e-93, 3.0113519152678094e-97, 5.2373672835160608e-101, 5.3966031917331080e-105, 2.9905793066209871e-109, 7.7755878030242305e-114, 7.7268624062801043e-119, 2.0937788694250258e-124, 8.1169547967150641e-131, 8.6464098495106045e-139}, + {1.2303789814620092e-139, 1.2013699333289992e-131, 3.2026074548384006e-125, 1.2174269794916373e-119, 1.2593229738553804e-114, 4.9714964520806193e-110, 9.1982052962411378e-106, 9.1447911140134055e-102, 5.3827092462530275e-98, 2.0157286790487118e-94, 5.0755707227503414e-91, 8.9771058574961900e-88, 1.1553649373808784e-84, 1.1139151556417037e-81, 8.2429409894791420e-79, 4.7790526311204645e-76, 2.2094400576899919e-73, 8.2703192545553517e-71, 2.5400223834270154e-68, 6.4759951809357819e-66, 1.3849218619189611e-63, 2.5072557278333359e-61, 3.8744806525565368e-59, 5.1487100357555966e-57, 5.9234211353878837e-55, 5.9358962183919884e-53, 5.2102035909462387e-51, 4.0261165631274628e-49, 2.7517389408826910e-47, 1.6706338169898752e-45, 9.0454023907569489e-44, 4.3836632815273276e-42, 1.9080203924026029e-40, 7.4822875434667983e-39, 2.6513404940738975e-37, 8.5126426420369604e-36, 2.4827942651601884e-34, 6.5937510349118087e-33, 1.5981308016388612e-31, 3.5423572866413238e-30, 7.1949797524882649e-29, 1.3416207816913450e-27, 2.3006552131922817e-26, 3.6342070015972533e-25, 5.2963698057770957e-24, 7.1317120414745996e-23, 8.8849961119116762e-22, 1.0255026540751254e-20, 1.0979177006155230e-19, 1.0916029509464340e-18, 1.0090271979231116e-17, 8.6804078056359369e-17, 6.9567797833146074e-16, 5.1989584985238723e-15, 3.6262025536343989e-14, 2.3625593061240154e-13, 1.4389854608144821e-12, 8.1997932243736651e-12, 4.3745620487604465e-11, 2.1864887185791365e-10, 1.0245209689572339e-09, 4.5031898910426613e-09, 1.8577866622072818e-08, 7.1975399855994780e-08, 2.6200414925731448e-07, 8.9655811991941417e-07, 2.8853130691641410e-06, 8.7365058018499081e-06, 2.4899323348910079e-05, 6.6819890242436042e-05, 1.6890601339725517e-04, 4.0229796846567709e-04, 9.0312111074868030e-04, 1.9114445894976445e-03, 3.8151134691487313e-03, 7.1826754657021994e-03, 1.2758271065775782e-02, 2.1384981853074116e-02, 3.3830872556682462e-02, 5.0520980072118506e-02, 7.1226720494510898e-02, 9.4814894788900164e-02, 1.1918291538647637e-01, 1.4147779230279267e-01, 1.5860763301741698e-01, 1.6793370935002905e-01, 1.6793370935002905e-01, 1.5860763301741698e-01, 1.4147779230279267e-01, 1.1918291538647637e-01, 9.4814894788900164e-02, 7.1226720494510898e-02, 5.0520980072118506e-02, 3.3830872556682462e-02, 2.1384981853074116e-02, 1.2758271065775782e-02, 7.1826754657021994e-03, 3.8151134691487313e-03, 1.9114445894976445e-03, 9.0312111074868030e-04, 4.0229796846567709e-04, 1.6890601339725517e-04, 6.6819890242436042e-05, 2.4899323348910079e-05, 8.7365058018499081e-06, 2.8853130691641410e-06, 8.9655811991941417e-07, 2.6200414925731448e-07, 7.1975399855994780e-08, 1.8577866622072818e-08, 4.5031898910426613e-09, 1.0245209689572339e-09, 2.1864887185791365e-10, 4.3745620487604465e-11, 8.1997932243736651e-12, 1.4389854608144821e-12, 2.3625593061240154e-13, 3.6262025536343989e-14, 5.1989584985238723e-15, 6.9567797833146074e-16, 8.6804078056359369e-17, 1.0090271979231116e-17, 1.0916029509464340e-18, 1.0979177006155230e-19, 1.0255026540751254e-20, 8.8849961119116762e-22, 7.1317120414745996e-23, 5.2963698057770957e-24, 3.6342070015972533e-25, 2.3006552131922817e-26, 1.3416207816913450e-27, 7.1949797524882649e-29, 3.5423572866413238e-30, 1.5981308016388612e-31, 6.5937510349118087e-33, 2.4827942651601884e-34, 8.5126426420369604e-36, 2.6513404940738975e-37, 7.4822875434667983e-39, 1.9080203924026029e-40, 4.3836632815273276e-42, 9.0454023907569489e-44, 1.6706338169898752e-45, 2.7517389408826910e-47, 4.0261165631274628e-49, 5.2102035909462387e-51, 5.9358962183919884e-53, 5.9234211353878837e-55, 5.1487100357555966e-57, 3.8744806525565368e-59, 2.5072557278333359e-61, 1.3849218619189611e-63, 6.4759951809357819e-66, 2.5400223834270154e-68, 8.2703192545553517e-71, 2.2094400576899919e-73, 4.7790526311204645e-76, 8.2429409894791420e-79, 1.1139151556417037e-81, 1.1553649373808784e-84, 8.9771058574961900e-88, 5.0755707227503414e-91, 2.0157286790487118e-94, 5.3827092462530275e-98, 9.1447911140134055e-102, 9.1982052962411378e-106, 4.9714964520806193e-110, 1.2593229738553804e-114, 1.2174269794916373e-119, 3.2026074548384006e-125, 1.2013699333289992e-131, 1.2303789814620092e-139}, + {1.7504813313443110e-140, 1.7774902414670824e-132, 4.8962631916290320e-126, 1.9169773412509448e-120, 2.0380950317636651e-115, 8.2575913221058373e-111, 1.5662913179616934e-106, 1.5950515939148060e-102, 9.6102475509992629e-99, 3.6817405361106414e-95, 9.4795771929584613e-92, 1.7137636253252277e-88, 2.2537069207131266e-85, 2.2195670363270061e-82, 1.6773665243938764e-79, 9.9294168393320748e-77, 4.6861855398798507e-74, 1.7903790379405142e-71, 5.6115831515377673e-69, 1.4599152900352242e-66, 3.1854832448751424e-64, 5.8835568128153365e-62, 9.2750122555037185e-60, 1.2572829274411131e-57, 1.4754337744917936e-55, 1.5080977336171035e-53, 1.3501492314506362e-51, 1.0641162728147897e-49, 7.4179019446614824e-48, 4.5933036667242678e-46, 2.5365532103719637e-44, 1.2538070457653651e-42, 5.5662423908008861e-41, 2.2264349328620495e-39, 8.0473188469528885e-38, 2.6355807192340085e-36, 7.8414692242533960e-35, 2.1244914229476255e-33, 5.2531973592621732e-32, 1.1880047374923401e-30, 2.4620531629619134e-29, 4.6845665497518896e-28, 8.1977521328279625e-27, 1.3215706261902287e-25, 1.9657684577473083e-24, 2.7018364834425692e-23, 3.4361611658856167e-22, 4.0489821139593706e-21, 4.4260400812843420e-20, 4.4935788616135659e-19, 4.2418977594565075e-18, 3.7271474634420088e-17, 3.0512318816558229e-16, 2.3295237031463167e-15, 1.6601293173811213e-14, 1.1052712006706022e-13, 6.8801511055288008e-13, 4.0073848073937339e-12, 2.1856088643011424e-11, 1.1169403547356809e-10, 5.3519948055672733e-10, 2.4060047025435626e-09, 1.0153711719361421e-08, 4.0247544813147544e-08, 1.4992205080398724e-07, 5.2506826823537642e-07, 1.7297783253854633e-06, 5.3626317222650889e-06, 1.5651476474775071e-05, 4.3021779350373374e-05, 1.1141208654585957e-04, 2.7191419917337988e-04, 6.2563601676209426e-04, 1.3574588134771591e-03, 2.7781892530593399e-03, 5.3645468312921761e-03, 9.7754538393799058e-03, 1.6813616037549516e-02, 2.7301369702544091e-02, 4.1857856809001823e-02, 6.0603870172343872e-02, 8.2871975523587077e-02, 1.0703943053616907e-01, 1.3060060873789656e-01, 1.5053596929119434e-01, 1.6392653352569631e-01, 1.6864917988011466e-01, 1.6392653352569631e-01, 1.5053596929119434e-01, 1.3060060873789656e-01, 1.0703943053616907e-01, 8.2871975523587077e-02, 6.0603870172343872e-02, 4.1857856809001823e-02, 2.7301369702544091e-02, 1.6813616037549516e-02, 9.7754538393799058e-03, 5.3645468312921761e-03, 2.7781892530593399e-03, 1.3574588134771591e-03, 6.2563601676209426e-04, 2.7191419917337988e-04, 1.1141208654585957e-04, 4.3021779350373374e-05, 1.5651476474775071e-05, 5.3626317222650889e-06, 1.7297783253854633e-06, 5.2506826823537642e-07, 1.4992205080398724e-07, 4.0247544813147544e-08, 1.0153711719361421e-08, 2.4060047025435626e-09, 5.3519948055672733e-10, 1.1169403547356809e-10, 2.1856088643011424e-11, 4.0073848073937339e-12, 6.8801511055288008e-13, 1.1052712006706022e-13, 1.6601293173811213e-14, 2.3295237031463167e-15, 3.0512318816558229e-16, 3.7271474634420088e-17, 4.2418977594565075e-18, 4.4935788616135659e-19, 4.4260400812843420e-20, 4.0489821139593706e-21, 3.4361611658856167e-22, 2.7018364834425692e-23, 1.9657684577473083e-24, 1.3215706261902287e-25, 8.1977521328279625e-27, 4.6845665497518896e-28, 2.4620531629619134e-29, 1.1880047374923401e-30, 5.2531973592621732e-32, 2.1244914229476255e-33, 7.8414692242533960e-35, 2.6355807192340085e-36, 8.0473188469528885e-38, 2.2264349328620495e-39, 5.5662423908008861e-41, 1.2538070457653651e-42, 2.5365532103719637e-44, 4.5933036667242678e-46, 7.4179019446614824e-48, 1.0641162728147897e-49, 1.3501492314506362e-51, 1.5080977336171035e-53, 1.4754337744917936e-55, 1.2572829274411131e-57, 9.2750122555037185e-60, 5.8835568128153365e-62, 3.1854832448751424e-64, 1.4599152900352242e-66, 5.6115831515377673e-69, 1.7903790379405142e-71, 4.6861855398798507e-74, 9.9294168393320748e-77, 1.6773665243938764e-79, 2.2195670363270061e-82, 2.2537069207131266e-85, 1.7137636253252277e-88, 9.4795771929584613e-92, 3.6817405361106414e-95, 9.6102475509992629e-99, 1.5950515939148060e-102, 1.5662913179616934e-106, 8.2575913221058373e-111, 2.0380950317636651e-115, 1.9169773412509448e-120, 4.8962631916290320e-126, 1.7774902414670824e-132, 1.7504813313443110e-140}, + {2.4899600964326729e-141, 2.6289723724457029e-133, 7.4819712112270593e-127, 3.0166712841087998e-121, 3.2960842775717504e-116, 1.3704328437984587e-111, 2.6646059822111242e-107, 2.7792048294771247e-103, 1.7138296773072837e-99, 6.7162796391421331e-96, 1.7680841960979503e-92, 3.2668637275061076e-89, 4.3893173430676675e-86, 4.4153132623096831e-83, 3.4072707861884866e-80, 2.0591798858084703e-77, 9.9197548192127678e-75, 3.8678293788234498e-72, 1.2370523208691571e-69, 3.2836627133699974e-67, 7.3095353354239491e-65, 1.3772094187709065e-62, 2.2145636638702121e-60, 3.0619202170369175e-58, 3.6647661995973869e-56, 3.8203649763779160e-54, 3.4881351774083147e-52, 2.8036775536310555e-50, 1.9931613619579773e-48, 1.2586567146117010e-46, 7.0884044215753474e-45, 3.5732404426806206e-43, 1.6178126120857497e-41, 6.5996510428781978e-40, 2.4328759328467202e-38, 8.1267763573550637e-37, 2.4662127220461684e-35, 6.8155261813509929e-34, 1.7191030917484011e-32, 3.9660195668953352e-31, 8.3853154776461475e-30, 1.6278171201629848e-28, 2.9065390998814081e-27, 4.7813433896247487e-26, 7.2578010107444783e-25, 1.0180797851831930e-23, 1.3215548441960911e-22, 1.5895976396503745e-21, 1.7738996763753002e-20, 1.8387513781865510e-19, 1.7723693479759404e-18, 1.5903120371435548e-17, 1.3296671955521453e-16, 1.0369288823537636e-15, 7.5490426637877302e-15, 5.1350286901144194e-14, 3.2662837995375004e-13, 1.9442795471244843e-12, 1.0838609818985724e-11, 5.6623712315092519e-11, 2.7740673531720516e-10, 1.2752593807305187e-09, 5.5042412134787782e-09, 2.2317961616833082e-08, 8.5054483756057923e-08, 3.0481775749836127e-07, 1.0277468837741270e-06, 3.2615617411254204e-06, 9.7462566160282362e-06, 2.7434125933222057e-05, 7.2768434100256330e-05, 1.8194526534270113e-04, 4.2896461357756435e-04, 9.5392124328337667e-04, 2.0013900802573659e-03, 3.9626676572752555e-03, 7.4059308800968815e-03, 1.3067672819155697e-02, 2.1773347066246198e-02, 3.4263651242794235e-02, 5.0931713552683139e-02, 7.1522962430052642e-02, 9.4897195996236208e-02, 1.1897395918444152e-01, 1.4095256578997853e-01, 1.5781215945203400e-01, 1.6698222073712451e-01, 1.6698222073712451e-01, 1.5781215945203400e-01, 1.4095256578997853e-01, 1.1897395918444152e-01, 9.4897195996236208e-02, 7.1522962430052642e-02, 5.0931713552683139e-02, 3.4263651242794235e-02, 2.1773347066246198e-02, 1.3067672819155697e-02, 7.4059308800968815e-03, 3.9626676572752555e-03, 2.0013900802573659e-03, 9.5392124328337667e-04, 4.2896461357756435e-04, 1.8194526534270113e-04, 7.2768434100256330e-05, 2.7434125933222057e-05, 9.7462566160282362e-06, 3.2615617411254204e-06, 1.0277468837741270e-06, 3.0481775749836127e-07, 8.5054483756057923e-08, 2.2317961616833082e-08, 5.5042412134787782e-09, 1.2752593807305187e-09, 2.7740673531720516e-10, 5.6623712315092519e-11, 1.0838609818985724e-11, 1.9442795471244843e-12, 3.2662837995375004e-13, 5.1350286901144194e-14, 7.5490426637877302e-15, 1.0369288823537636e-15, 1.3296671955521453e-16, 1.5903120371435548e-17, 1.7723693479759404e-18, 1.8387513781865510e-19, 1.7738996763753002e-20, 1.5895976396503745e-21, 1.3215548441960911e-22, 1.0180797851831930e-23, 7.2578010107444783e-25, 4.7813433896247487e-26, 2.9065390998814081e-27, 1.6278171201629848e-28, 8.3853154776461475e-30, 3.9660195668953352e-31, 1.7191030917484011e-32, 6.8155261813509929e-34, 2.4662127220461684e-35, 8.1267763573550637e-37, 2.4328759328467202e-38, 6.5996510428781978e-40, 1.6178126120857497e-41, 3.5732404426806206e-43, 7.0884044215753474e-45, 1.2586567146117010e-46, 1.9931613619579773e-48, 2.8036775536310555e-50, 3.4881351774083147e-52, 3.8203649763779160e-54, 3.6647661995973869e-56, 3.0619202170369175e-58, 2.2145636638702121e-60, 1.3772094187709065e-62, 7.3095353354239491e-65, 3.2836627133699974e-67, 1.2370523208691571e-69, 3.8678293788234498e-72, 9.9197548192127678e-75, 2.0591798858084703e-77, 3.4072707861884866e-80, 4.4153132623096831e-83, 4.3893173430676675e-86, 3.2668637275061076e-89, 1.7680841960979503e-92, 6.7162796391421331e-96, 1.7138296773072837e-99, 2.7792048294771247e-103, 2.6646059822111242e-107, 1.3704328437984587e-111, 3.2960842775717504e-116, 3.0166712841087998e-121, 7.4819712112270593e-127, 2.6289723724457029e-133, 2.4899600964326729e-141}, + {3.5411506471568517e-142, 3.8870007298929211e-134, 1.1427720218874746e-127, 4.7443699591186030e-122, 5.3267445942905176e-117, 2.2724999081578913e-112, 4.5288568274049433e-108, 4.8374430266711206e-104, 3.0528486739600850e-100, 1.2236703652880107e-96, 3.2933121419749483e-93, 6.2184654173606399e-90, 8.5354199357192903e-87, 8.7687858501113383e-84, 6.9091769993084969e-81, 4.2624770595798820e-78, 2.0957319191157142e-75, 8.3387106103658512e-73, 2.7211703761612434e-70, 7.3690229255476969e-68, 1.6733234438392451e-65, 3.2158114928338939e-63, 5.2740829263623727e-61, 7.4369351842678165e-59, 9.0774918435864705e-57, 9.6499842697585386e-55, 8.9847110119503318e-53, 7.3640839458387673e-51, 5.3383547450946618e-49, 3.4375135972727117e-47, 1.9740530949677369e-45, 1.0147285474798106e-43, 4.6848975802870826e-42, 1.9488875555428468e-40, 7.3264228854645894e-39, 2.4958088668373114e-37, 7.7243461606513683e-36, 2.1771495752866995e-34, 5.6010600122601367e-33, 1.3180336788235122e-31, 2.8426307813064235e-30, 5.6294266388452469e-29, 1.0254685909108741e-27, 1.7211387969394399e-26, 2.6657834170950206e-25, 3.8158515821307025e-24, 5.0550170089602786e-23, 6.2057205211001172e-22, 7.0687611828654942e-21, 7.4798012691484967e-20, 7.3607060012414608e-19, 6.7436191474716113e-18, 5.7576889770247240e-17, 4.5856377569387674e-16, 3.4098950541891060e-15, 2.3694365058853221e-14, 1.5398051925046748e-13, 9.3656673457701801e-13, 5.3355866239683074e-12, 2.8490354792258560e-11, 1.4268284555926340e-10, 6.7061742381683788e-10, 2.9598086074993327e-09, 1.2273853303242205e-08, 4.7847173987299635e-08, 1.7543109823449902e-07, 6.0525229343483686e-07, 1.9657973702696829e-06, 6.0130527402628209e-06, 1.7329090398329860e-05, 4.7069644542722322e-05, 1.2054246571768105e-04, 2.9114733811626920e-04, 6.6342074803749660e-04, 1.4265570512383724e-03, 2.8955046143597550e-03, 5.5487673845870103e-03, 1.0041513921437970e-02, 1.7163936516514416e-02, 2.7715692333499325e-02, 4.2285689519455438e-02, 6.0964838880386028e-02, 8.3068258519182064e-02, 1.0698027879398084e-01, 1.3023286590097533e-01, 1.4986945253577164e-01, 1.6304250159157527e-01, 1.6768547028079969e-01, 1.6304250159157527e-01, 1.4986945253577164e-01, 1.3023286590097533e-01, 1.0698027879398084e-01, 8.3068258519182064e-02, 6.0964838880386028e-02, 4.2285689519455438e-02, 2.7715692333499325e-02, 1.7163936516514416e-02, 1.0041513921437970e-02, 5.5487673845870103e-03, 2.8955046143597550e-03, 1.4265570512383724e-03, 6.6342074803749660e-04, 2.9114733811626920e-04, 1.2054246571768105e-04, 4.7069644542722322e-05, 1.7329090398329860e-05, 6.0130527402628209e-06, 1.9657973702696829e-06, 6.0525229343483686e-07, 1.7543109823449902e-07, 4.7847173987299635e-08, 1.2273853303242205e-08, 2.9598086074993327e-09, 6.7061742381683788e-10, 1.4268284555926340e-10, 2.8490354792258560e-11, 5.3355866239683074e-12, 9.3656673457701801e-13, 1.5398051925046748e-13, 2.3694365058853221e-14, 3.4098950541891060e-15, 4.5856377569387674e-16, 5.7576889770247240e-17, 6.7436191474716113e-18, 7.3607060012414608e-19, 7.4798012691484967e-20, 7.0687611828654942e-21, 6.2057205211001172e-22, 5.0550170089602786e-23, 3.8158515821307025e-24, 2.6657834170950206e-25, 1.7211387969394399e-26, 1.0254685909108741e-27, 5.6294266388452469e-29, 2.8426307813064235e-30, 1.3180336788235122e-31, 5.6010600122601367e-33, 2.1771495752866995e-34, 7.7243461606513683e-36, 2.4958088668373114e-37, 7.3264228854645894e-39, 1.9488875555428468e-40, 4.6848975802870826e-42, 1.0147285474798106e-43, 1.9740530949677369e-45, 3.4375135972727117e-47, 5.3383547450946618e-49, 7.3640839458387673e-51, 8.9847110119503318e-53, 9.6499842697585386e-55, 9.0774918435864705e-57, 7.4369351842678165e-59, 5.2740829263623727e-61, 3.2158114928338939e-63, 1.6733234438392451e-65, 7.3690229255476969e-68, 2.7211703761612434e-70, 8.3387106103658512e-73, 2.0957319191157142e-75, 4.2624770595798820e-78, 6.9091769993084969e-81, 8.7687858501113383e-84, 8.5354199357192903e-87, 6.2184654173606399e-90, 3.2933121419749483e-93, 1.2236703652880107e-96, 3.0528486739600850e-100, 4.8374430266711206e-104, 4.5288568274049433e-108, 2.2724999081578913e-112, 5.3267445942905176e-117, 4.7443699591186030e-122, 1.1427720218874746e-127, 3.8870007298929211e-134, 3.5411506471568517e-142}, + {5.0351722883464185e-143, 5.7450587562745078e-135, 1.7446064596498268e-128, 7.4571213334341600e-123, 8.6023715273839571e-118, 3.7652628313310755e-113, 7.6903016009308287e-109, 8.4113401468636500e-105, 5.4319085709594968e-101, 2.2267204629384821e-97, 6.1261103396048387e-94, 1.1819905626126024e-90, 1.6572504238354695e-87, 1.7386395392283553e-84, 1.3986045504550338e-81, 8.8071523423621673e-79, 4.4190897787947332e-76, 1.7941108043227645e-73, 5.9730812278268291e-71, 1.6500317832456593e-68, 3.8217018216862523e-66, 7.4907171097897077e-64, 1.2528614722567282e-61, 1.8015494058808057e-59, 2.2422904341536794e-57, 2.4305731255545130e-55, 2.3074311289682700e-53, 1.9283073358698602e-51, 1.4252524566058730e-49, 9.3573522665893741e-48, 5.4788838446141128e-46, 2.8715169045497604e-44, 1.3517494625509147e-42, 5.7335891630321996e-41, 2.1977946695381225e-39, 7.6344180491439718e-38, 2.4094190488253342e-36, 6.9253812367067252e-35, 1.8169855856152196e-33, 4.3607057687085942e-32, 9.5923503135464682e-31, 1.9376278309334056e-29, 3.6004726047782310e-28, 6.1647472746508888e-27, 9.7413623207618448e-26, 1.4227116244089339e-24, 1.9231607886931175e-23, 2.4093040723082529e-22, 2.8008499497491982e-21, 3.0250061661788475e-20, 3.0387132211276073e-19, 2.8421271873321773e-18, 2.4775756264214477e-17, 2.0149141590187015e-16, 1.5301273364381654e-15, 1.0859626897815736e-14, 7.2089869379341516e-14, 4.4796392616415365e-13, 2.6076028723419556e-12, 1.4228958097317545e-11, 7.2832614256562299e-11, 3.4992319867238825e-10, 1.5789636824184370e-09, 6.6952823181138107e-09, 2.6692828097969734e-08, 1.0010785492509061e-07, 3.5334287745169781e-07, 1.1742867585331092e-06, 3.6760831094679487e-06, 1.0844326360928105e-05, 3.0156999060878010e-05, 7.9084957328144794e-05, 1.9564188997236542e-04, 4.5669297388226392e-04, 1.0062461311647175e-03, 2.0932217887326024e-03, 4.1120856339170011e-03, 7.6302877130003874e-03, 1.3376390072548504e-02, 2.2158233552618596e-02, 3.4689673239772116e-02, 5.1332999819585050e-02, 7.1809001831171768e-02, 9.4971530833224349e-02, 1.1876238489882553e-01, 1.4043201287954626e-01, 1.5702837449220031e-01, 1.6604672219204664e-01, 1.6604672219204664e-01, 1.5702837449220031e-01, 1.4043201287954626e-01, 1.1876238489882553e-01, 9.4971530833224349e-02, 7.1809001831171768e-02, 5.1332999819585050e-02, 3.4689673239772116e-02, 2.2158233552618596e-02, 1.3376390072548504e-02, 7.6302877130003874e-03, 4.1120856339170011e-03, 2.0932217887326024e-03, 1.0062461311647175e-03, 4.5669297388226392e-04, 1.9564188997236542e-04, 7.9084957328144794e-05, 3.0156999060878010e-05, 1.0844326360928105e-05, 3.6760831094679487e-06, 1.1742867585331092e-06, 3.5334287745169781e-07, 1.0010785492509061e-07, 2.6692828097969734e-08, 6.6952823181138107e-09, 1.5789636824184370e-09, 3.4992319867238825e-10, 7.2832614256562299e-11, 1.4228958097317545e-11, 2.6076028723419556e-12, 4.4796392616415365e-13, 7.2089869379341516e-14, 1.0859626897815736e-14, 1.5301273364381654e-15, 2.0149141590187015e-16, 2.4775756264214477e-17, 2.8421271873321773e-18, 3.0387132211276073e-19, 3.0250061661788475e-20, 2.8008499497491982e-21, 2.4093040723082529e-22, 1.9231607886931175e-23, 1.4227116244089339e-24, 9.7413623207618448e-26, 6.1647472746508888e-27, 3.6004726047782310e-28, 1.9376278309334056e-29, 9.5923503135464682e-31, 4.3607057687085942e-32, 1.8169855856152196e-33, 6.9253812367067252e-35, 2.4094190488253342e-36, 7.6344180491439718e-38, 2.1977946695381225e-39, 5.7335891630321996e-41, 1.3517494625509147e-42, 2.8715169045497604e-44, 5.4788838446141128e-46, 9.3573522665893741e-48, 1.4252524566058730e-49, 1.9283073358698602e-51, 2.3074311289682700e-53, 2.4305731255545130e-55, 2.2422904341536794e-57, 1.8015494058808057e-59, 1.2528614722567282e-61, 7.4907171097897077e-64, 3.8217018216862523e-66, 1.6500317832456593e-68, 5.9730812278268291e-71, 1.7941108043227645e-73, 4.4190897787947332e-76, 8.8071523423621673e-79, 1.3986045504550338e-81, 1.7386395392283553e-84, 1.6572504238354695e-87, 1.1819905626126024e-90, 6.1261103396048387e-94, 2.2267204629384821e-97, 5.4319085709594968e-101, 8.4113401468636500e-105, 7.6903016009308287e-109, 3.7652628313310755e-113, 8.6023715273839571e-118, 7.4571213334341600e-123, 1.7446064596498268e-128, 5.7450587562745078e-135, 5.0351722883464185e-143}, + {7.1581854941568756e-144, 8.4884228757564859e-136, 2.6621446843016668e-129, 1.1714088250630149e-123, 1.3882583385637704e-118, 6.2335512554508696e-114, 1.3046719672955675e-109, 1.4610767163662094e-105, 9.6541517663049285e-102, 4.0470443036783296e-98, 1.1380585129708444e-94, 2.2435189643567695e-91, 3.2128730776926215e-88, 3.4417484237908715e-85, 2.8263134922810747e-82, 1.8164480123517544e-79, 9.3003877258546557e-77, 3.8523675927861067e-74, 1.3083561453477787e-71, 3.6865159997894300e-69, 8.7082600252251548e-67, 1.7406436581415539e-64, 2.9687147399709626e-62, 4.3527424404558593e-60, 5.5237929617045550e-58, 6.1047069753060061e-56, 5.9085581038387938e-54, 5.0340269517910206e-52, 3.7932466358096469e-50, 2.5389205160417814e-48, 1.5155318342592620e-46, 8.0977464419800098e-45, 3.8862848936787104e-43, 1.6805797332715199e-41, 6.5678744364293848e-40, 2.3261212178440308e-38, 7.4851978878895327e-37, 2.1937508830604144e-35, 5.8690540840121578e-34, 1.4363784560339465e-32, 3.2222344142269078e-31, 6.6381799678904965e-30, 1.2580944858403407e-28, 2.1972252658847511e-27, 3.5417421260548565e-26, 5.2769903994937601e-25, 7.2776858868650826e-24, 9.3028399771791796e-23, 1.1035696761428192e-21, 1.2163644574829813e-20, 1.2470907989461904e-19, 1.1906056130964038e-18, 1.0595326417660698e-17, 8.7974278780040251e-17, 6.8216435985574468e-16, 4.9441425800883030e-15, 3.3521165632319237e-14, 2.1277112806959519e-13, 1.2653006101080342e-12, 7.0545233223348931e-12, 3.6899828977436854e-11, 1.8119180456089166e-10, 8.3573910554417999e-10, 3.6229939665804831e-09, 1.4769397910223943e-08, 5.6647039057714555e-08, 2.0451241808924649e-07, 6.9532414269249713e-07, 2.2272343809174102e-06, 6.7240427138149140e-06, 1.9140150173987354e-05, 5.1388360015799239e-05, 1.3017662891537081e-04, 3.1123241184750341e-04, 7.0249863037702334e-04, 1.4973772242764213e-03, 3.0147364453737358e-03, 5.7345384962421463e-03, 1.0307863786080675e-02, 1.7512238829626020e-02, 2.8124900042797892e-02, 4.2705327076181680e-02, 6.1315790894116422e-02, 8.3255213529058528e-02, 1.0691562889960281e-01, 1.2986607877253428e-01, 1.4921123248756085e-01, 1.6217258820124303e-01, 1.6673809474249007e-01, 1.6217258820124303e-01, 1.4921123248756085e-01, 1.2986607877253428e-01, 1.0691562889960281e-01, 8.3255213529058528e-02, 6.1315790894116422e-02, 4.2705327076181680e-02, 2.8124900042797892e-02, 1.7512238829626020e-02, 1.0307863786080675e-02, 5.7345384962421463e-03, 3.0147364453737358e-03, 1.4973772242764213e-03, 7.0249863037702334e-04, 3.1123241184750341e-04, 1.3017662891537081e-04, 5.1388360015799239e-05, 1.9140150173987354e-05, 6.7240427138149140e-06, 2.2272343809174102e-06, 6.9532414269249713e-07, 2.0451241808924649e-07, 5.6647039057714555e-08, 1.4769397910223943e-08, 3.6229939665804831e-09, 8.3573910554417999e-10, 1.8119180456089166e-10, 3.6899828977436854e-11, 7.0545233223348931e-12, 1.2653006101080342e-12, 2.1277112806959519e-13, 3.3521165632319237e-14, 4.9441425800883030e-15, 6.8216435985574468e-16, 8.7974278780040251e-17, 1.0595326417660698e-17, 1.1906056130964038e-18, 1.2470907989461904e-19, 1.2163644574829813e-20, 1.1035696761428192e-21, 9.3028399771791796e-23, 7.2776858868650826e-24, 5.2769903994937601e-25, 3.5417421260548565e-26, 2.1972252658847511e-27, 1.2580944858403407e-28, 6.6381799678904965e-30, 3.2222344142269078e-31, 1.4363784560339465e-32, 5.8690540840121578e-34, 2.1937508830604144e-35, 7.4851978878895327e-37, 2.3261212178440308e-38, 6.5678744364293848e-40, 1.6805797332715199e-41, 3.8862848936787104e-43, 8.0977464419800098e-45, 1.5155318342592620e-46, 2.5389205160417814e-48, 3.7932466358096469e-50, 5.0340269517910206e-52, 5.9085581038387938e-54, 6.1047069753060061e-56, 5.5237929617045550e-58, 4.3527424404558593e-60, 2.9687147399709626e-62, 1.7406436581415539e-64, 8.7082600252251548e-67, 3.6865159997894300e-69, 1.3083561453477787e-71, 3.8523675927861067e-74, 9.3003877258546557e-77, 1.8164480123517544e-79, 2.8263134922810747e-82, 3.4417484237908715e-85, 3.2128730776926215e-88, 2.2435189643567695e-91, 1.1380585129708444e-94, 4.0470443036783296e-98, 9.6541517663049285e-102, 1.4610767163662094e-105, 1.3046719672955675e-109, 6.2335512554508696e-114, 1.3882583385637704e-118, 1.1714088250630149e-123, 2.6621446843016668e-129, 8.4884228757564859e-136, 7.1581854941568756e-144}, + {1.0174451907169722e-144, 1.2537577338109092e-136, 4.0603558490313254e-130, 1.8390471781108747e-124, 2.2388300710588648e-119, 1.0311647067706544e-114, 2.2113953581884588e-110, 2.5353839157043305e-106, 1.7139381704010506e-102, 7.3466025769339733e-99, 2.1114364896149106e-95, 4.2524253414775605e-92, 6.2193919080044227e-89, 6.8022938891305936e-86, 5.7017766571657716e-83, 3.7396644213938176e-80, 1.9536604993085239e-77, 8.2555014673420022e-75, 2.8598818663126844e-72, 8.2184808615623598e-70, 1.9797683901166225e-67, 4.0351646934878695e-65, 7.0170567960964978e-63, 1.0489546649192595e-60, 1.3571109461554121e-58, 1.5290034639304410e-56, 1.5086081632928153e-54, 1.3102411068553504e-52, 1.0064229300129089e-50, 6.8667092650473948e-49, 4.1782480984927090e-47, 2.2757544084791531e-45, 1.1133537204234619e-43, 4.9079810854674800e-42, 1.9553490062333371e-40, 7.0599294307578851e-39, 2.3160882385061203e-37, 6.9205465629360576e-36, 1.8877397396823247e-34, 4.7107012996283542e-33, 1.0775571184918142e-31, 2.2637292363656048e-30, 4.3753093336081546e-29, 7.7932715085212503e-28, 1.2812781788064907e-26, 1.9472758171895140e-25, 2.7395824646129918e-24, 3.5726754325441841e-23, 4.3241778048815671e-22, 4.8633316486835449e-21, 5.0883502730989637e-20, 4.9579227287808755e-19, 4.5034462009468205e-18, 3.8170938055666007e-17, 3.0217745531718828e-16, 2.2362025898948135e-15, 1.5482439389379285e-14, 1.0036629079256339e-13, 6.0964973515510935e-13, 3.4723560883860410e-12, 1.8557142556642682e-11, 9.3114559517381624e-11, 4.3894092072618305e-10, 1.9450249932898343e-09, 8.1060721426662619e-09, 3.1789582778002615e-08, 1.1737053608502818e-07, 4.0816183881635333e-07, 1.3374965511498204e-06, 4.1315876560548306e-06, 1.2035714382322826e-05, 3.3076061707490808e-05, 8.5780643722862892e-05, 2.1000778733594350e-04, 4.8548944122296688e-04, 1.0600860254999084e-03, 2.1869011800911028e-03, 4.2632921737953853e-03, 7.8556410099729287e-03, 1.3684318450535705e-02, 2.2539589851423701e-02, 3.5108996740976929e-02, 5.1725036108245200e-02, 7.2085145846744095e-02, 9.5038220322125194e-02, 1.1854839415593066e-01, 1.3991610657942335e-01, 1.5625599948674623e-01, 1.6512677086080088e-01, 1.6512677086080088e-01, 1.5625599948674623e-01, 1.3991610657942335e-01, 1.1854839415593066e-01, 9.5038220322125194e-02, 7.2085145846744095e-02, 5.1725036108245200e-02, 3.5108996740976929e-02, 2.2539589851423701e-02, 1.3684318450535705e-02, 7.8556410099729287e-03, 4.2632921737953853e-03, 2.1869011800911028e-03, 1.0600860254999084e-03, 4.8548944122296688e-04, 2.1000778733594350e-04, 8.5780643722862892e-05, 3.3076061707490808e-05, 1.2035714382322826e-05, 4.1315876560548306e-06, 1.3374965511498204e-06, 4.0816183881635333e-07, 1.1737053608502818e-07, 3.1789582778002615e-08, 8.1060721426662619e-09, 1.9450249932898343e-09, 4.3894092072618305e-10, 9.3114559517381624e-11, 1.8557142556642682e-11, 3.4723560883860410e-12, 6.0964973515510935e-13, 1.0036629079256339e-13, 1.5482439389379285e-14, 2.2362025898948135e-15, 3.0217745531718828e-16, 3.8170938055666007e-17, 4.5034462009468205e-18, 4.9579227287808755e-19, 5.0883502730989637e-20, 4.8633316486835449e-21, 4.3241778048815671e-22, 3.5726754325441841e-23, 2.7395824646129918e-24, 1.9472758171895140e-25, 1.2812781788064907e-26, 7.7932715085212503e-28, 4.3753093336081546e-29, 2.2637292363656048e-30, 1.0775571184918142e-31, 4.7107012996283542e-33, 1.8877397396823247e-34, 6.9205465629360576e-36, 2.3160882385061203e-37, 7.0599294307578851e-39, 1.9553490062333371e-40, 4.9079810854674800e-42, 1.1133537204234619e-43, 2.2757544084791531e-45, 4.1782480984927090e-47, 6.8667092650473948e-49, 1.0064229300129089e-50, 1.3102411068553504e-52, 1.5086081632928153e-54, 1.5290034639304410e-56, 1.3571109461554121e-58, 1.0489546649192595e-60, 7.0170567960964978e-63, 4.0351646934878695e-65, 1.9797683901166225e-67, 8.2184808615623598e-70, 2.8598818663126844e-72, 8.2555014673420022e-75, 1.9536604993085239e-77, 3.7396644213938176e-80, 5.7017766571657716e-83, 6.8022938891305936e-86, 6.2193919080044227e-89, 4.2524253414775605e-92, 2.1114364896149106e-95, 7.3466025769339733e-99, 1.7139381704010506e-102, 2.5353839157043305e-106, 2.2113953581884588e-110, 1.0311647067706544e-114, 2.2388300710588648e-119, 1.8390471781108747e-124, 4.0603558490313254e-130, 1.2537577338109092e-136, 1.0174451907169722e-144}, + {1.4459034710264201e-145, 1.8512101069007797e-137, 6.1900866973604703e-131, 2.8855379169821182e-125, 3.6080591054052492e-120, 1.7044183943684018e-115, 3.7449189704395232e-111, 4.3952304904350605e-107, 3.0394872358078098e-103, 1.3320382883615053e-99, 3.9122879439382170e-96, 8.0489834136101609e-93, 1.2021477111483726e-89, 1.3422872316499288e-86, 1.1483443011896613e-83, 7.6855073087396857e-81, 4.0962408560880496e-78, 1.7656535944547459e-75, 6.2384154226153306e-73, 1.8282206685181686e-70, 4.4907236877039048e-68, 9.3322988518723512e-66, 1.6545283606525458e-63, 2.5213872637605977e-61, 3.3253581541518404e-59, 3.8190282366232640e-57, 3.8408503131563961e-55, 3.4001469878023392e-53, 2.6620432033111890e-51, 1.8512591668862315e-49, 1.1481424339931328e-47, 6.3739969672637270e-46, 3.1784051437766470e-44, 1.4281570152975713e-42, 5.7996825799748193e-41, 2.1345161706875471e-39, 7.1381873166360108e-38, 2.1743217660681791e-36, 6.0463752750772134e-35, 1.5382579845230378e-33, 3.5875473238148687e-32, 7.6845885182041777e-31, 1.5145049680016594e-29, 2.7509103704580098e-28, 4.6123845343733745e-27, 7.1493666161606643e-26, 1.0259279798609206e-24, 1.3647547675188007e-23, 1.6851209810753113e-22, 1.9336042594232875e-21, 2.0642309881609900e-20, 2.0524462477993889e-19, 1.9026226109394554e-18, 1.6459732365754106e-17, 1.3300948716108394e-16, 1.0048759007103044e-15, 7.1035141604691271e-15, 4.7022739273699201e-14, 2.9170375040074331e-13, 1.6970108678299655e-12, 9.2646537879215591e-12, 4.7495690973542646e-11, 2.2878306073735174e-10, 1.0360690148079607e-09, 4.4135301064719171e-09, 1.7694607842914065e-08, 6.6798391472451806e-08, 2.3755404518235753e-07, 7.9619631902655087e-07, 2.5160446644029356e-06, 7.4993851915062359e-06, 2.1091170590509833e-05, 5.5987643740857493e-05, 1.4032641744066531e-04, 3.3217919994016825e-04, 7.4286891131823533e-04, 1.5698960784933606e-03, 3.1358280493826080e-03, 5.9217687653631513e-03, 1.0574395576910816e-02, 1.7858440641500769e-02, 2.8528992504062382e-02, 4.3116896847977884e-02, 6.1656983184778281e-02, 8.3433163844430863e-02, 1.0684575215294285e-01, 1.2950034028006346e-01, 1.4856115387707583e-01, 1.6131642239308974e-01, 1.6580659700649841e-01, 1.6131642239308974e-01, 1.4856115387707583e-01, 1.2950034028006346e-01, 1.0684575215294285e-01, 8.3433163844430863e-02, 6.1656983184778281e-02, 4.3116896847977884e-02, 2.8528992504062382e-02, 1.7858440641500769e-02, 1.0574395576910816e-02, 5.9217687653631513e-03, 3.1358280493826080e-03, 1.5698960784933606e-03, 7.4286891131823533e-04, 3.3217919994016825e-04, 1.4032641744066531e-04, 5.5987643740857493e-05, 2.1091170590509833e-05, 7.4993851915062359e-06, 2.5160446644029356e-06, 7.9619631902655087e-07, 2.3755404518235753e-07, 6.6798391472451806e-08, 1.7694607842914065e-08, 4.4135301064719171e-09, 1.0360690148079607e-09, 2.2878306073735174e-10, 4.7495690973542646e-11, 9.2646537879215591e-12, 1.6970108678299655e-12, 2.9170375040074331e-13, 4.7022739273699201e-14, 7.1035141604691271e-15, 1.0048759007103044e-15, 1.3300948716108394e-16, 1.6459732365754106e-17, 1.9026226109394554e-18, 2.0524462477993889e-19, 2.0642309881609900e-20, 1.9336042594232875e-21, 1.6851209810753113e-22, 1.3647547675188007e-23, 1.0259279798609206e-24, 7.1493666161606643e-26, 4.6123845343733745e-27, 2.7509103704580098e-28, 1.5145049680016594e-29, 7.6845885182041777e-31, 3.5875473238148687e-32, 1.5382579845230378e-33, 6.0463752750772134e-35, 2.1743217660681791e-36, 7.1381873166360108e-38, 2.1345161706875471e-39, 5.7996825799748193e-41, 1.4281570152975713e-42, 3.1784051437766470e-44, 6.3739969672637270e-46, 1.1481424339931328e-47, 1.8512591668862315e-49, 2.6620432033111890e-51, 3.4001469878023392e-53, 3.8408503131563961e-55, 3.8190282366232640e-57, 3.3253581541518404e-59, 2.5213872637605977e-61, 1.6545283606525458e-63, 9.3322988518723512e-66, 4.4907236877039048e-68, 1.8282206685181686e-70, 6.2384154226153306e-73, 1.7656535944547459e-75, 4.0962408560880496e-78, 7.6855073087396857e-81, 1.1483443011896613e-83, 1.3422872316499288e-86, 1.2021477111483726e-89, 8.0489834136101609e-93, 3.9122879439382170e-96, 1.3320382883615053e-99, 3.0394872358078098e-103, 4.3952304904350605e-107, 3.7449189704395232e-111, 1.7044183943684018e-115, 3.6080591054052492e-120, 2.8855379169821182e-125, 6.1900866973604703e-131, 1.8512101069007797e-137, 1.4459034710264201e-145}, + {2.0544167081187589e-146, 2.7324651628287789e-138, 9.4326009424734410e-132, 4.5249380509459828e-126, 5.8107301413051742e-121, 2.8150324044562284e-116, 6.3362635154258981e-112, 7.6118645291179184e-108, 5.3843632439536920e-104, 2.4123127079122074e-100, 7.2398333677694101e-97, 1.5214189335297059e-93, 2.3202235060376314e-90, 2.6445775673882037e-87, 2.3089447193822174e-84, 1.5767056174162126e-81, 8.5727195865402764e-79, 3.7689704357176965e-76, 1.3580443028284028e-73, 4.0582349306406949e-71, 1.0163600799789738e-68, 2.1532917098122703e-66, 3.8916837271887350e-64, 6.0453772000204261e-62, 8.1267907500285513e-60, 9.5128584361969727e-58, 9.7509710005032432e-56, 8.7976987433650472e-54, 7.0198773756157181e-52, 4.9753094376640113e-50, 3.1447462107627518e-48, 1.7792627000157171e-46, 9.0423237558527988e-45, 4.1409133307449204e-43, 1.7138906209368488e-41, 6.4290783512879458e-40, 2.1913996777475932e-38, 6.8039020082108794e-37, 1.9286270378988431e-35, 5.0017461082503641e-34, 1.1891915619808499e-32, 2.5969337466904165e-31, 5.2182308893507914e-30, 9.6642798753295627e-29, 1.6523003694364310e-27, 2.6117599911695471e-26, 3.8222432521976105e-25, 5.1859356642906214e-24, 6.5314813585357555e-23, 7.6453095155047312e-22, 8.3267040963735343e-21, 8.4472663315088944e-20, 7.9904365646153140e-19, 7.0543936381041909e-18, 5.8181634606657441e-17, 4.4867423723460479e-16, 3.2378602233952898e-15, 2.1883227889949076e-14, 1.3861757281246388e-13, 8.2354944810071531e-13, 4.5921996541535561e-12, 2.4048711144413950e-11, 1.1835015186215515e-10, 5.4765134657351679e-10, 2.3841694011026308e-09, 9.7699965359482599e-09, 3.7704288545104245e-08, 1.3709740387891837e-07, 4.6989603841203290e-07, 1.5187614573110066e-06, 4.6308779212753262e-06, 1.3325507543076759e-05, 3.6199433343496547e-05, 9.2866446344988979e-05, 2.2505423008074610e-04, 5.1535932107027135e-04, 1.1154298676886345e-03, 2.2823888738018917e-03, 4.4162127170279562e-03, 8.0818888889421375e-03, 1.3991358954534535e-02, 2.2917370391076095e-02, 3.5521683059969993e-02, 5.2108016747135361e-02, 7.2351691768296089e-02, 9.5097571709914869e-02, 1.1833217723448959e-01, 1.3940481744965749e-01, 1.5549476479437641e-01, 1.6422194087055850e-01, 1.6422194087055850e-01, 1.5549476479437641e-01, 1.3940481744965749e-01, 1.1833217723448959e-01, 9.5097571709914869e-02, 7.2351691768296089e-02, 5.2108016747135361e-02, 3.5521683059969993e-02, 2.2917370391076095e-02, 1.3991358954534535e-02, 8.0818888889421375e-03, 4.4162127170279562e-03, 2.2823888738018917e-03, 1.1154298676886345e-03, 5.1535932107027135e-04, 2.2505423008074610e-04, 9.2866446344988979e-05, 3.6199433343496547e-05, 1.3325507543076759e-05, 4.6308779212753262e-06, 1.5187614573110066e-06, 4.6989603841203290e-07, 1.3709740387891837e-07, 3.7704288545104245e-08, 9.7699965359482599e-09, 2.3841694011026308e-09, 5.4765134657351679e-10, 1.1835015186215515e-10, 2.4048711144413950e-11, 4.5921996541535561e-12, 8.2354944810071531e-13, 1.3861757281246388e-13, 2.1883227889949076e-14, 3.2378602233952898e-15, 4.4867423723460479e-16, 5.8181634606657441e-17, 7.0543936381041909e-18, 7.9904365646153140e-19, 8.4472663315088944e-20, 8.3267040963735343e-21, 7.6453095155047312e-22, 6.5314813585357555e-23, 5.1859356642906214e-24, 3.8222432521976105e-25, 2.6117599911695471e-26, 1.6523003694364310e-27, 9.6642798753295627e-29, 5.2182308893507914e-30, 2.5969337466904165e-31, 1.1891915619808499e-32, 5.0017461082503641e-34, 1.9286270378988431e-35, 6.8039020082108794e-37, 2.1913996777475932e-38, 6.4290783512879458e-40, 1.7138906209368488e-41, 4.1409133307449204e-43, 9.0423237558527988e-45, 1.7792627000157171e-46, 3.1447462107627518e-48, 4.9753094376640113e-50, 7.0198773756157181e-52, 8.7976987433650472e-54, 9.7509710005032432e-56, 9.5128584361969727e-58, 8.1267907500285513e-60, 6.0453772000204261e-62, 3.8916837271887350e-64, 2.1532917098122703e-66, 1.0163600799789738e-68, 4.0582349306406949e-71, 1.3580443028284028e-73, 3.7689704357176965e-76, 8.5727195865402764e-79, 1.5767056174162126e-81, 2.3089447193822174e-84, 2.6445775673882037e-87, 2.3202235060376314e-90, 1.5214189335297059e-93, 7.2398333677694101e-97, 2.4123127079122074e-100, 5.3843632439536920e-104, 7.6118645291179184e-108, 6.3362635154258981e-112, 2.8150324044562284e-116, 5.8107301413051742e-121, 4.5249380509459828e-126, 9.4326009424734410e-132, 2.7324651628287789e-138, 2.0544167081187589e-146}, + {2.9184983704075192e-147, 4.0319183713400766e-139, 1.4367134541050939e-132, 7.0917398018507910e-127, 9.3517988737392972e-122, 4.6457185244440549e-117, 1.0711309190325783e-112, 1.3169706905085093e-108, 9.5280026251390744e-105, 4.3635736981957750e-101, 1.3380638102406329e-97, 2.8718782241763001e-94, 4.4716757994553476e-91, 5.2022930902389893e-88, 4.6349150479031114e-85, 3.2290491038758581e-82, 1.7908398704126536e-79, 8.0297842302329272e-77, 2.9503683873426791e-74, 8.9893224354049310e-72, 2.2951885774902920e-69, 4.9569512961693677e-67, 9.1317952402850698e-65, 1.4458391823512865e-62, 1.9809319471106229e-60, 2.3631742826980710e-58, 2.4686029155016893e-56, 2.2697566491840546e-54, 1.8456028929462080e-52, 1.3329759770755586e-50, 8.5857720828783205e-49, 4.9502403838758848e-47, 2.5636716593985549e-45, 1.1964123882499316e-43, 5.0463692733981642e-42, 1.9291541526211061e-40, 6.7015535541500665e-39, 2.1206217889043141e-37, 6.1266403471398839e-36, 1.6195131761876436e-34, 3.9248683542722297e-33, 8.7371187009076405e-32, 1.7897414312928308e-30, 3.3792749075968173e-29, 5.8905961617051956e-28, 9.4940326558644130e-27, 1.4168234014649860e-25, 1.9603740051045881e-24, 2.5181065241794600e-23, 3.0063944491537587e-22, 3.3400431583218902e-21, 3.4567219838648987e-20, 3.3360382939472660e-19, 3.0052255828362505e-18, 2.5293356487116101e-17, 1.9906862214252033e-16, 1.4663260946610058e-15, 1.0116632951507467e-14, 6.5425658781468336e-14, 3.9689851927958321e-13, 2.2600968959480387e-12, 1.2088512678946103e-11, 6.0769364101383090e-11, 2.8728746426712136e-10, 1.2779384152123448e-09, 5.3517155996766336e-09, 2.1109723472766886e-08, 7.8466356162788103e-08, 2.7497279026009702e-07, 9.0883362098124687e-07, 2.8342636150206807e-06, 8.3429573893995674e-06, 2.3188718962635865e-05, 6.0877111145275987e-05, 1.5100325433613592e-04, 3.5399662151566394e-04, 7.8452960713547043e-04, 1.6440892137594167e-03, 3.2587225571780792e-03, 6.1103686178933300e-03, 1.0841005727093818e-02, 1.8202465449941120e-02, 2.8927974168057351e-02, 4.3520526497899684e-02, 6.1988666273243780e-02, 8.3602420563279559e-02, 1.0677090675896843e-01, 1.2913573606742534e-01, 1.4791906474448899e-01, 1.6047364667465450e-01, 1.6489053845950130e-01, 1.6047364667465450e-01, 1.4791906474448899e-01, 1.2913573606742534e-01, 1.0677090675896843e-01, 8.3602420563279559e-02, 6.1988666273243780e-02, 4.3520526497899684e-02, 2.8927974168057351e-02, 1.8202465449941120e-02, 1.0841005727093818e-02, 6.1103686178933300e-03, 3.2587225571780792e-03, 1.6440892137594167e-03, 7.8452960713547043e-04, 3.5399662151566394e-04, 1.5100325433613592e-04, 6.0877111145275987e-05, 2.3188718962635865e-05, 8.3429573893995674e-06, 2.8342636150206807e-06, 9.0883362098124687e-07, 2.7497279026009702e-07, 7.8466356162788103e-08, 2.1109723472766886e-08, 5.3517155996766336e-09, 1.2779384152123448e-09, 2.8728746426712136e-10, 6.0769364101383090e-11, 1.2088512678946103e-11, 2.2600968959480387e-12, 3.9689851927958321e-13, 6.5425658781468336e-14, 1.0116632951507467e-14, 1.4663260946610058e-15, 1.9906862214252033e-16, 2.5293356487116101e-17, 3.0052255828362505e-18, 3.3360382939472660e-19, 3.4567219838648987e-20, 3.3400431583218902e-21, 3.0063944491537587e-22, 2.5181065241794600e-23, 1.9603740051045881e-24, 1.4168234014649860e-25, 9.4940326558644130e-27, 5.8905961617051956e-28, 3.3792749075968173e-29, 1.7897414312928308e-30, 8.7371187009076405e-32, 3.9248683542722297e-33, 1.6195131761876436e-34, 6.1266403471398839e-36, 2.1206217889043141e-37, 6.7015535541500665e-39, 1.9291541526211061e-40, 5.0463692733981642e-42, 1.1964123882499316e-43, 2.5636716593985549e-45, 4.9502403838758848e-47, 8.5857720828783205e-49, 1.3329759770755586e-50, 1.8456028929462080e-52, 2.2697566491840546e-54, 2.4686029155016893e-56, 2.3631742826980710e-58, 1.9809319471106229e-60, 1.4458391823512865e-62, 9.1317952402850698e-65, 4.9569512961693677e-67, 2.2951885774902920e-69, 8.9893224354049310e-72, 2.9503683873426791e-74, 8.0297842302329272e-77, 1.7908398704126536e-79, 3.2290491038758581e-82, 4.6349150479031114e-85, 5.2022930902389893e-88, 4.4716757994553476e-91, 2.8718782241763001e-94, 1.3380638102406329e-97, 4.3635736981957750e-101, 9.5280026251390744e-105, 1.3169706905085093e-108, 1.0711309190325783e-112, 4.6457185244440549e-117, 9.3517988737392972e-122, 7.0917398018507910e-127, 1.4367134541050939e-132, 4.0319183713400766e-139, 2.9184983704075192e-147}, + {4.1452696623483395e-148, 5.9474161464872244e-140, 2.1873318060197500e-133, 1.1108350634945189e-127, 1.5040760324474137e-122, 7.6610437292542439e-118, 1.8091479691129481e-113, 2.2763600768872421e-109, 1.6842534274181958e-105, 7.8840222434465455e-102, 2.4699093339298307e-98, 5.4137540405290719e-95, 8.6056883186768174e-92, 1.0218043358339510e-88, 9.2888951681828944e-86, 6.6016471696136248e-83, 3.7342898142071596e-80, 1.7074874775824880e-77, 6.3969105456232966e-75, 1.9870439601235429e-72, 5.1717638304628555e-70, 1.1385038568984282e-67, 2.1376722221415430e-65, 3.4493784123174178e-63, 4.8161711078239858e-61, 5.8549015274027961e-59, 6.2323324068554731e-57, 5.8390470979220446e-55, 4.8378847700931107e-53, 3.5603170842517748e-51, 2.3366431061277383e-49, 1.3727341637645679e-47, 7.2439067732577147e-46, 3.4446682433867826e-44, 1.4805046972403839e-42, 5.7672996866961233e-41, 2.0415908964489771e-39, 6.5835338360421613e-38, 1.9383756218147382e-36, 5.2220236908204409e-35, 1.2898503021552704e-33, 2.9266129491084507e-32, 6.1107571504811921e-31, 1.1761496941464036e-29, 2.0900714057742614e-28, 3.4343583117038137e-27, 5.2255927032642325e-26, 7.3725440555518383e-25, 9.6570947115181529e-24, 1.1758429681040065e-22, 1.3323707929307384e-21, 1.4065250811244644e-20, 1.3847330443129062e-19, 1.2726463913998945e-18, 1.0928940877684042e-17, 8.7773275665944823e-17, 6.5982162774306465e-16, 4.6464228722152545e-15, 3.0673938466320995e-14, 1.8997359653204635e-13, 1.1045578960219544e-12, 6.0330789028505752e-12, 3.0975214481618230e-11, 1.4957890384694261e-10, 6.7975116544323199e-10, 2.9085970464514601e-09, 1.1724370655087347e-08, 4.4542518892262074e-08, 1.5956404054013332e-07, 5.3920679976732085e-07, 1.7195329738679880e-06, 5.1768455512555845e-06, 1.4718871925099586e-05, 3.9535219175273295e-05, 1.0035307023681430e-04, 2.4079185627092926e-04, 5.4630685564139225e-04, 1.1722653593393563e-03, 2.3796447518820959e-03, 4.5707734636933712e-03, 8.3089325331250057e-03, 1.4297417780659441e-02, 2.3291535150151157e-02, 3.5927796289914674e-02, 5.2482133056536061e-02, 7.2608927339705281e-02, 9.5149879125439124e-02, 1.1811391373984721e-01, 1.3889811387154746e-01, 1.5474440942350939e-01, 1.6333182250163769e-01, 1.6333182250163769e-01, 1.5474440942350939e-01, 1.3889811387154746e-01, 1.1811391373984721e-01, 9.5149879125439124e-02, 7.2608927339705281e-02, 5.2482133056536061e-02, 3.5927796289914674e-02, 2.3291535150151157e-02, 1.4297417780659441e-02, 8.3089325331250057e-03, 4.5707734636933712e-03, 2.3796447518820959e-03, 1.1722653593393563e-03, 5.4630685564139225e-04, 2.4079185627092926e-04, 1.0035307023681430e-04, 3.9535219175273295e-05, 1.4718871925099586e-05, 5.1768455512555845e-06, 1.7195329738679880e-06, 5.3920679976732085e-07, 1.5956404054013332e-07, 4.4542518892262074e-08, 1.1724370655087347e-08, 2.9085970464514601e-09, 6.7975116544323199e-10, 1.4957890384694261e-10, 3.0975214481618230e-11, 6.0330789028505752e-12, 1.1045578960219544e-12, 1.8997359653204635e-13, 3.0673938466320995e-14, 4.6464228722152545e-15, 6.5982162774306465e-16, 8.7773275665944823e-17, 1.0928940877684042e-17, 1.2726463913998945e-18, 1.3847330443129062e-19, 1.4065250811244644e-20, 1.3323707929307384e-21, 1.1758429681040065e-22, 9.6570947115181529e-24, 7.3725440555518383e-25, 5.2255927032642325e-26, 3.4343583117038137e-27, 2.0900714057742614e-28, 1.1761496941464036e-29, 6.1107571504811921e-31, 2.9266129491084507e-32, 1.2898503021552704e-33, 5.2220236908204409e-35, 1.9383756218147382e-36, 6.5835338360421613e-38, 2.0415908964489771e-39, 5.7672996866961233e-41, 1.4805046972403839e-42, 3.4446682433867826e-44, 7.2439067732577147e-46, 1.3727341637645679e-47, 2.3366431061277383e-49, 3.5603170842517748e-51, 4.8378847700931107e-53, 5.8390470979220446e-55, 6.2323324068554731e-57, 5.8549015274027961e-59, 4.8161711078239858e-61, 3.4493784123174178e-63, 2.1376722221415430e-65, 1.1385038568984282e-67, 5.1717638304628555e-70, 1.9870439601235429e-72, 6.3969105456232966e-75, 1.7074874775824880e-77, 3.7342898142071596e-80, 6.6016471696136248e-83, 9.2888951681828944e-86, 1.0218043358339510e-88, 8.6056883186768174e-92, 5.4137540405290719e-95, 2.4699093339298307e-98, 7.8840222434465455e-102, 1.6842534274181958e-105, 2.2763600768872421e-109, 1.8091479691129481e-113, 7.6610437292542439e-118, 1.5040760324474137e-122, 1.1108350634945189e-127, 2.1873318060197500e-133, 5.9474161464872244e-140, 4.1452696623483395e-148}, + {5.8866637956879832e-149, 8.7701238593349446e-141, 3.3286398376690490e-134, 1.7390228685740816e-128, 2.4174491971248305e-123, 1.2623847464849609e-118, 3.0530327446766110e-114, 3.9308789125198654e-110, 2.9740999490947605e-106, 1.4228368487505154e-102, 4.5535119727458115e-99, 1.0191828364399763e-95, 1.6537960518565174e-92, 2.0039262792917714e-89, 1.8586066284522124e-86, 1.3473832322197353e-83, 7.7728521820677718e-81, 3.6240329528761601e-78, 1.3842194496021173e-75, 4.3831680288373217e-73, 1.1628357927637541e-70, 2.6089921702855559e-68, 4.9923292649319471e-66, 8.2091330064948600e-64, 1.1679600204323236e-61, 1.4467547750792869e-59, 1.5691297806630218e-57, 1.4978576876165396e-55, 1.2644313857762022e-53, 9.4805533849020122e-52, 6.3392777437739552e-50, 3.7943396524379168e-48, 2.0399882317508400e-46, 9.8835394906743943e-45, 4.3280559299142535e-43, 1.7178434457904729e-41, 6.1961228512356421e-40, 2.0359401385923293e-38, 6.1082242612809361e-37, 1.6768933675263854e-35, 4.2210054325158127e-34, 9.7605477823793654e-33, 2.0771142264898199e-31, 4.0748381699253249e-30, 7.3810648870417183e-29, 1.2363547377218958e-27, 1.9178022081467005e-26, 2.7586033246049575e-25, 3.6843129796217172e-24, 4.5743951370215857e-23, 5.2859323137468154e-22, 5.6910915175835955e-21, 5.7148760619818976e-20, 5.3577677281181046e-19, 4.6939007358067331e-18, 3.8463054439056453e-17, 2.9504021972772029e-16, 2.1202927606877813e-15, 1.4286304928072976e-14, 9.0316979019406731e-14, 5.3609851542957339e-13, 2.9897229802024487e-12, 1.5674715085860065e-11, 7.7305137154009676e-11, 3.5884068378224706e-10, 1.5685984370316076e-09, 6.4603917825466764e-09, 2.5081389998281072e-08, 9.1830644706366585e-08, 3.1721513586827257e-07, 1.0342536339020313e-06, 3.1840053712593505e-06, 9.2587247391013518e-06, 2.5439403557345701e-05, 6.6066258510845340e-05, 1.6221813086114782e-04, 3.7669274161032700e-04, 8.2747754872833888e-04, 1.7199311750936504e-03, 3.3833630340537615e-03, 6.3002503573431189e-03, 1.1107594867856934e-02, 1.8544242319012489e-02, 2.9321853906612717e-02, 4.3916343744405027e-02, 6.2311084328469719e-02, 8.3763283089409293e-02, 1.0669133852506041e-01, 1.2877234499448006e-01, 1.4728481639742919e-01, 1.5964391640203837e-01, 1.6398949726573361e-01, 1.5964391640203837e-01, 1.4728481639742919e-01, 1.2877234499448006e-01, 1.0669133852506041e-01, 8.3763283089409293e-02, 6.2311084328469719e-02, 4.3916343744405027e-02, 2.9321853906612717e-02, 1.8544242319012489e-02, 1.1107594867856934e-02, 6.3002503573431189e-03, 3.3833630340537615e-03, 1.7199311750936504e-03, 8.2747754872833888e-04, 3.7669274161032700e-04, 1.6221813086114782e-04, 6.6066258510845340e-05, 2.5439403557345701e-05, 9.2587247391013518e-06, 3.1840053712593505e-06, 1.0342536339020313e-06, 3.1721513586827257e-07, 9.1830644706366585e-08, 2.5081389998281072e-08, 6.4603917825466764e-09, 1.5685984370316076e-09, 3.5884068378224706e-10, 7.7305137154009676e-11, 1.5674715085860065e-11, 2.9897229802024487e-12, 5.3609851542957339e-13, 9.0316979019406731e-14, 1.4286304928072976e-14, 2.1202927606877813e-15, 2.9504021972772029e-16, 3.8463054439056453e-17, 4.6939007358067331e-18, 5.3577677281181046e-19, 5.7148760619818976e-20, 5.6910915175835955e-21, 5.2859323137468154e-22, 4.5743951370215857e-23, 3.6843129796217172e-24, 2.7586033246049575e-25, 1.9178022081467005e-26, 1.2363547377218958e-27, 7.3810648870417183e-29, 4.0748381699253249e-30, 2.0771142264898199e-31, 9.7605477823793654e-33, 4.2210054325158127e-34, 1.6768933675263854e-35, 6.1082242612809361e-37, 2.0359401385923293e-38, 6.1961228512356421e-40, 1.7178434457904729e-41, 4.3280559299142535e-43, 9.8835394906743943e-45, 2.0399882317508400e-46, 3.7943396524379168e-48, 6.3392777437739552e-50, 9.4805533849020122e-52, 1.2644313857762022e-53, 1.4978576876165396e-55, 1.5691297806630218e-57, 1.4467547750792869e-59, 1.1679600204323236e-61, 8.2091330064948600e-64, 4.9923292649319471e-66, 2.6089921702855559e-68, 1.1628357927637541e-70, 4.3831680288373217e-73, 1.3842194496021173e-75, 3.6240329528761601e-78, 7.7728521820677718e-81, 1.3473832322197353e-83, 1.8586066284522124e-86, 2.0039262792917714e-89, 1.6537960518565174e-92, 1.0191828364399763e-95, 4.5535119727458115e-99, 1.4228368487505154e-102, 2.9740999490947605e-106, 3.9308789125198654e-110, 3.0530327446766110e-114, 1.2623847464849609e-118, 2.4174491971248305e-123, 1.7390228685740816e-128, 3.3286398376690490e-134, 8.7701238593349446e-141, 5.8866637956879832e-149}, + {8.3581373975539108e-150, 1.2928412877755577e-141, 5.0632382588324120e-135, 2.7209602221952139e-129, 3.8829389622015062e-124, 2.0785832875875387e-119, 5.1477595408996125e-115, 6.7815072200124497e-111, 5.2462701695642363e-107, 2.5648912231375885e-103, 8.3845258592424195e-100, 1.9161630252069163e-96, 3.1736968736455641e-93, 3.9241298067673186e-90, 3.7129493377218318e-87, 2.7453553081368732e-84, 1.6150344379416257e-81, 7.6774327866656284e-79, 2.9894343828423281e-76, 9.6489070550182607e-74, 2.6089586336270140e-71, 5.9654008943367430e-69, 1.1631966527487701e-66, 1.9489490740739864e-64, 2.8252664298663074e-62, 3.5656104439409607e-60, 3.9399315442250632e-58, 3.8315828065199010e-56, 3.2951200002417535e-54, 2.5169328462380233e-52, 1.7144956007470846e-50, 1.0454204091183458e-48, 5.7258874684495484e-47, 2.8261341310391440e-45, 1.2607977361040919e-43, 5.0982121558902017e-42, 1.8734745650648728e-40, 6.2719136180711063e-39, 1.9172254945419127e-37, 5.3629616050774624e-36, 1.3755486543958331e-34, 3.2412811142581749e-33, 7.0292474203881568e-32, 1.4053678782835759e-30, 2.5945192595304142e-29, 4.4296347519346036e-28, 7.0039976811745699e-27, 1.0270246629696484e-25, 1.3983996188477357e-24, 1.7702189074849013e-23, 2.0857890645994067e-22, 2.2900155277371847e-21, 2.3452218050389733e-20, 2.2425235675550114e-19, 2.0040402270860207e-18, 1.6752540366716003e-17, 1.3110796195605400e-16, 9.6139706301947510e-16, 6.6105224464386113e-15, 4.2652608433469510e-14, 2.5842479214605026e-13, 1.4712572098023350e-12, 7.8755658569412608e-12, 3.9661851656268533e-11, 1.8802196827204209e-10, 8.3950345085448172e-10, 3.5321294226177634e-09, 1.4010751708171831e-08, 5.2419925848831286e-08, 1.8506755890537394e-07, 6.1679613744986908e-07, 1.9413286157507076e-06, 5.7724680860172742e-06, 1.6221044402072930e-05, 4.3091495767535577e-05, 1.0825095642068624e-04, 2.5723066429963950e-04, 5.7833524878596126e-04, 1.2305790314187559e-03, 2.4786280618533298e-03, 4.7269014592664482e-03, 8.5366761761569536e-03, 1.4602406139195508e-02, 2.3662049334306538e-02, 3.6327402988086469e-02, 5.2847573265457019e-02, 7.2857131060649991e-02, 9.5195424202311488e-02, 1.1789377323403843e-01, 1.3839596229316664e-01, 1.5400468068882942e-01, 1.6245602140829696e-01, 1.6245602140829696e-01, 1.5400468068882942e-01, 1.3839596229316664e-01, 1.1789377323403843e-01, 9.5195424202311488e-02, 7.2857131060649991e-02, 5.2847573265457019e-02, 3.6327402988086469e-02, 2.3662049334306538e-02, 1.4602406139195508e-02, 8.5366761761569536e-03, 4.7269014592664482e-03, 2.4786280618533298e-03, 1.2305790314187559e-03, 5.7833524878596126e-04, 2.5723066429963950e-04, 1.0825095642068624e-04, 4.3091495767535577e-05, 1.6221044402072930e-05, 5.7724680860172742e-06, 1.9413286157507076e-06, 6.1679613744986908e-07, 1.8506755890537394e-07, 5.2419925848831286e-08, 1.4010751708171831e-08, 3.5321294226177634e-09, 8.3950345085448172e-10, 1.8802196827204209e-10, 3.9661851656268533e-11, 7.8755658569412608e-12, 1.4712572098023350e-12, 2.5842479214605026e-13, 4.2652608433469510e-14, 6.6105224464386113e-15, 9.6139706301947510e-16, 1.3110796195605400e-16, 1.6752540366716003e-17, 2.0040402270860207e-18, 2.2425235675550114e-19, 2.3452218050389733e-20, 2.2900155277371847e-21, 2.0857890645994067e-22, 1.7702189074849013e-23, 1.3983996188477357e-24, 1.0270246629696484e-25, 7.0039976811745699e-27, 4.4296347519346036e-28, 2.5945192595304142e-29, 1.4053678782835759e-30, 7.0292474203881568e-32, 3.2412811142581749e-33, 1.3755486543958331e-34, 5.3629616050774624e-36, 1.9172254945419127e-37, 6.2719136180711063e-39, 1.8734745650648728e-40, 5.0982121558902017e-42, 1.2607977361040919e-43, 2.8261341310391440e-45, 5.7258874684495484e-47, 1.0454204091183458e-48, 1.7144956007470846e-50, 2.5169328462380233e-52, 3.2951200002417535e-54, 3.8315828065199010e-56, 3.9399315442250632e-58, 3.5656104439409607e-60, 2.8252664298663074e-62, 1.9489490740739864e-64, 1.1631966527487701e-66, 5.9654008943367430e-69, 2.6089586336270140e-71, 9.6489070550182607e-74, 2.9894343828423281e-76, 7.6774327866656284e-79, 1.6150344379416257e-81, 2.7453553081368732e-84, 3.7129493377218318e-87, 3.9241298067673186e-90, 3.1736968736455641e-93, 1.9161630252069163e-96, 8.3845258592424195e-100, 2.5648912231375885e-103, 5.2462701695642363e-107, 6.7815072200124497e-111, 5.1477595408996125e-115, 2.0785832875875387e-119, 3.8829389622015062e-124, 2.7209602221952139e-129, 5.0632382588324120e-135, 1.2928412877755577e-141, 8.3581373975539108e-150}, + {1.1865178694667318e-150, 1.9052328091840223e-142, 7.6984112043987381e-136, 4.2550288152769099e-130, 6.2327840907767578e-125, 3.4199371076928271e-120, 8.6723736530813987e-116, 1.1688387166643387e-111, 9.2447904963657574e-108, 4.6184277629201267e-104, 1.5419925530578493e-100, 3.5978676971165183e-97, 6.0819398055170106e-94, 7.6728915952440279e-91, 7.4056905596969795e-88, 5.5844689207576789e-85, 3.3498078614715179e-82, 1.6234441963286573e-79, 6.4436381052523653e-77, 2.1197593898507255e-74, 5.8410998823252364e-72, 1.3609591582325947e-69, 2.7039668570857215e-67, 4.6159532490505087e-65, 6.8172254689772145e-63, 8.7649300109604261e-61, 9.8662587260951024e-59, 9.7741261753796815e-57, 8.5624277958175666e-55, 6.6621826190749697e-53, 4.6227110569813219e-51, 2.8712161421730314e-49, 1.6018948070503715e-47, 8.0538675955345321e-46, 3.6600273200497822e-44, 1.5076237023555035e-42, 5.6437809696463000e-41, 1.9247883296069542e-39, 5.9942100762419949e-38, 1.7082702187606927e-36, 4.4641638317895058e-35, 1.0718010386176091e-33, 2.3684402708428834e-32, 4.8253003329308802e-31, 9.0781689354637632e-30, 1.5795898083977327e-28, 2.5455821620542874e-27, 3.8046791468512480e-26, 5.2807723431418099e-25, 6.8148555847519964e-24, 8.1865279023956756e-23, 9.1644244237263828e-22, 9.5703407786302617e-21, 9.3325018346830289e-20, 8.5060423271066705e-19, 7.2528021781457044e-18, 5.7903374085298744e-17, 4.3318599899726389e-16, 3.0391558780794568e-15, 2.0010535409370048e-14, 1.2373574238435096e-13, 7.1903669458823460e-13, 3.9291706318326725e-12, 2.0202524727399665e-11, 9.7794253591584735e-11, 4.4592266183083370e-10, 1.9163195825780139e-09, 7.7651658482449274e-09, 2.9683092240535501e-08, 1.0708625929490390e-07, 3.6475807440990068e-07, 1.1735270767794228e-06, 3.5674612381232805e-06, 1.0250735219808427e-05, 2.7849862113005195e-05, 7.1564447183165722e-05, 1.7398159469356308e-04, 4.0027477960329739e-04, 8.7170842819435444e-04, 1.7973955409015775e-03, 3.5096925793779445e-03, 6.4913282065116552e-03, 1.1374067733309335e-02, 1.8883705620831706e-02, 2.9710644677922813e-02, 4.4304476145580723e-02, 6.2624475272894761e-02, 8.3916039610710105e-02, 1.0660728151712012e-01, 1.2841023960066572e-01, 1.4665826336478710e-01, 1.5882689919380447e-01, 1.6310306755078369e-01, 1.5882689919380447e-01, 1.4665826336478710e-01, 1.2841023960066572e-01, 1.0660728151712012e-01, 8.3916039610710105e-02, 6.2624475272894761e-02, 4.4304476145580723e-02, 2.9710644677922813e-02, 1.8883705620831706e-02, 1.1374067733309335e-02, 6.4913282065116552e-03, 3.5096925793779445e-03, 1.7973955409015775e-03, 8.7170842819435444e-04, 4.0027477960329739e-04, 1.7398159469356308e-04, 7.1564447183165722e-05, 2.7849862113005195e-05, 1.0250735219808427e-05, 3.5674612381232805e-06, 1.1735270767794228e-06, 3.6475807440990068e-07, 1.0708625929490390e-07, 2.9683092240535501e-08, 7.7651658482449274e-09, 1.9163195825780139e-09, 4.4592266183083370e-10, 9.7794253591584735e-11, 2.0202524727399665e-11, 3.9291706318326725e-12, 7.1903669458823460e-13, 1.2373574238435096e-13, 2.0010535409370048e-14, 3.0391558780794568e-15, 4.3318599899726389e-16, 5.7903374085298744e-17, 7.2528021781457044e-18, 8.5060423271066705e-19, 9.3325018346830289e-20, 9.5703407786302617e-21, 9.1644244237263828e-22, 8.1865279023956756e-23, 6.8148555847519964e-24, 5.2807723431418099e-25, 3.8046791468512480e-26, 2.5455821620542874e-27, 1.5795898083977327e-28, 9.0781689354637632e-30, 4.8253003329308802e-31, 2.3684402708428834e-32, 1.0718010386176091e-33, 4.4641638317895058e-35, 1.7082702187606927e-36, 5.9942100762419949e-38, 1.9247883296069542e-39, 5.6437809696463000e-41, 1.5076237023555035e-42, 3.6600273200497822e-44, 8.0538675955345321e-46, 1.6018948070503715e-47, 2.8712161421730314e-49, 4.6227110569813219e-51, 6.6621826190749697e-53, 8.5624277958175666e-55, 9.7741261753796815e-57, 9.8662587260951024e-59, 8.7649300109604261e-61, 6.8172254689772145e-63, 4.6159532490505087e-65, 2.7039668570857215e-67, 1.3609591582325947e-69, 5.8410998823252364e-72, 2.1197593898507255e-74, 6.4436381052523653e-77, 1.6234441963286573e-79, 3.3498078614715179e-82, 5.5844689207576789e-85, 7.4056905596969795e-88, 7.6728915952440279e-91, 6.0819398055170106e-94, 3.5978676971165183e-97, 1.5419925530578493e-100, 4.6184277629201267e-104, 9.2447904963657574e-108, 1.1688387166643387e-111, 8.6723736530813987e-116, 3.4199371076928271e-120, 6.2327840907767578e-125, 4.2550288152769099e-130, 7.6984112043987381e-136, 1.9052328091840223e-142, 1.1865178694667318e-150}, + {1.6840859823147192e-151, 2.8068259915465668e-143, 1.1700024361722009e-136, 6.6504100620446623e-131, 9.9982626870689096e-126, 5.6227251746796540e-121, 1.4598025546816272e-116, 2.0126980605111617e-112, 1.6274180017356631e-108, 8.3068317564996415e-105, 2.8324541894274240e-101, 6.7467686874093196e-98, 1.1639059887066096e-94, 1.4980806006797597e-91, 1.4748024918249946e-88, 1.1340919960793407e-85, 6.9358925722736469e-83, 3.4266063564656041e-80, 1.3862443412766689e-77, 4.6475320184424221e-75, 1.3049987561313226e-72, 3.0981254141048187e-70, 6.2713089100746324e-68, 1.0906635714604883e-65, 1.6409070764036964e-63, 2.1490689833897993e-61, 2.4641241627782225e-59, 2.4864657741894790e-57, 2.2186336768274302e-55, 1.7582563693437111e-53, 1.2426111111041695e-51, 7.8609642161410873e-50, 4.4670071717223134e-48, 2.2875134062797375e-46, 1.0588298166277823e-44, 4.4424843586907703e-43, 1.6939665809360599e-41, 5.8848055182020130e-40, 1.8668536705967508e-38, 5.4197686272780061e-37, 1.4428750537835282e-35, 3.5292920298964982e-34, 7.9458957717354865e-33, 1.6494369134608046e-31, 3.1620314656015991e-30, 5.6065555004969651e-29, 9.2077125425461603e-28, 1.4025749559057771e-26, 1.9841800348065493e-25, 2.6100548891439468e-24, 3.1962255598539348e-23, 3.6477448742277230e-22, 3.8838880473136030e-21, 3.8618679709476893e-20, 3.5894545533623586e-19, 3.1214143458455917e-18, 2.5417847367765562e-17, 1.9397457159226965e-16, 1.3883744241015343e-15, 9.3270625462533699e-15, 5.8852482736096351e-14, 3.4902504651461380e-13, 1.9466883562172841e-12, 1.0217552929953939e-11, 5.0496076724281894e-11, 2.3510718451740779e-10, 1.0318035977700679e-09, 4.2703647703012249e-09, 1.6675261164947539e-08, 6.1462809064451552e-08, 2.1392739679622303e-07, 7.0340742267172300e-07, 2.1857314406758851e-06, 6.4208055079598766e-06, 1.7837324122194181e-05, 4.6876297088489141e-05, 1.1657026717177768e-04, 2.7438000977925001e-04, 6.1144669240944507e-04, 1.2903563124214057e-03, 2.5792975144676013e-03, 4.8845246714536682e-03, 8.7650270802736002e-03, 1.4906240076216418e-02, 2.4028883068628805e-02, 3.6720571883816493e-02, 5.3204522444878222e-02, 7.3096572483403829e-02, 9.5234476669428525e-02, 1.1767191582495477e-01, 1.3789832745338026e-01, 1.5327533388369177e-01, 1.6159415788497841e-01, 1.6159415788497841e-01, 1.5327533388369177e-01, 1.3789832745338026e-01, 1.1767191582495477e-01, 9.5234476669428525e-02, 7.3096572483403829e-02, 5.3204522444878222e-02, 3.6720571883816493e-02, 2.4028883068628805e-02, 1.4906240076216418e-02, 8.7650270802736002e-03, 4.8845246714536682e-03, 2.5792975144676013e-03, 1.2903563124214057e-03, 6.1144669240944507e-04, 2.7438000977925001e-04, 1.1657026717177768e-04, 4.6876297088489141e-05, 1.7837324122194181e-05, 6.4208055079598766e-06, 2.1857314406758851e-06, 7.0340742267172300e-07, 2.1392739679622303e-07, 6.1462809064451552e-08, 1.6675261164947539e-08, 4.2703647703012249e-09, 1.0318035977700679e-09, 2.3510718451740779e-10, 5.0496076724281894e-11, 1.0217552929953939e-11, 1.9466883562172841e-12, 3.4902504651461380e-13, 5.8852482736096351e-14, 9.3270625462533699e-15, 1.3883744241015343e-15, 1.9397457159226965e-16, 2.5417847367765562e-17, 3.1214143458455917e-18, 3.5894545533623586e-19, 3.8618679709476893e-20, 3.8838880473136030e-21, 3.6477448742277230e-22, 3.1962255598539348e-23, 2.6100548891439468e-24, 1.9841800348065493e-25, 1.4025749559057771e-26, 9.2077125425461603e-28, 5.6065555004969651e-29, 3.1620314656015991e-30, 1.6494369134608046e-31, 7.9458957717354865e-33, 3.5292920298964982e-34, 1.4428750537835282e-35, 5.4197686272780061e-37, 1.8668536705967508e-38, 5.8848055182020130e-40, 1.6939665809360599e-41, 4.4424843586907703e-43, 1.0588298166277823e-44, 2.2875134062797375e-46, 4.4670071717223134e-48, 7.8609642161410873e-50, 1.2426111111041695e-51, 1.7582563693437111e-53, 2.2186336768274302e-55, 2.4864657741894790e-57, 2.4641241627782225e-59, 2.1490689833897993e-61, 1.6409070764036964e-63, 1.0906635714604883e-65, 6.2713089100746324e-68, 3.0981254141048187e-70, 1.3049987561313226e-72, 4.6475320184424221e-75, 1.3862443412766689e-77, 3.4266063564656041e-80, 6.9358925722736469e-83, 1.1340919960793407e-85, 1.4748024918249946e-88, 1.4980806006797597e-91, 1.1639059887066096e-94, 6.7467686874093196e-98, 2.8324541894274240e-101, 8.3068317564996415e-105, 1.6274180017356631e-108, 2.0126980605111617e-112, 1.4598025546816272e-116, 5.6227251746796540e-121, 9.9982626870689096e-126, 6.6504100620446623e-131, 1.1700024361722009e-136, 2.8068259915465668e-143, 1.6840859823147192e-151}, + {2.3899020087783538e-152, 4.1337932844079439e-144, 1.7774077118017352e-137, 1.0388721680141190e-131, 1.6028413383110423e-126, 9.2375467812799180e-122, 2.4552181378752603e-117, 3.4625987620456931e-113, 2.8619431556076958e-109, 1.4924416386535932e-105, 5.1966730435893490e-102, 1.2635422959480214e-98, 2.2243270327788831e-95, 2.9206395863825604e-92, 2.9324498160004818e-89, 2.2993488113263748e-86, 1.4336286376453945e-83, 7.2194564657826763e-81, 2.9766194663244294e-78, 1.0169377873705381e-75, 2.9095299074235018e-73, 7.0373804171328241e-71, 1.4512217440971957e-68, 2.5709836724164109e-66, 3.9400295587538806e-64, 5.2559492672815257e-62, 6.1380579859214437e-60, 6.3081846096424608e-58, 5.7325826101059963e-56, 4.6268156176755226e-54, 3.3301662675561347e-52, 2.1455339764954737e-50, 1.2416693105547687e-48, 6.4756889941564796e-47, 3.0527217350206308e-45, 1.3044685923509235e-43, 5.0660482804550958e-42, 1.7925263383158762e-40, 5.7919770166825449e-39, 1.7127600543267554e-37, 4.6447431828997982e-36, 1.1573309534274821e-34, 2.6544306695450948e-33, 5.6136594541327730e-32, 1.0964361374105204e-30, 1.9808277135032592e-29, 3.3148509472564812e-28, 5.1455269820153546e-27, 7.4183584908683151e-26, 9.9456309833303069e-25, 1.2413968193571878e-23, 1.4441897483451718e-22, 1.5675836145616411e-21, 1.5891496108132932e-20, 1.5060515461273932e-19, 1.3355156911983980e-18, 1.1090885964042391e-17, 8.6327149787564008e-17, 6.3027647004538790e-16, 4.3195605416094461e-15, 2.7808623921464611e-14, 1.6828396856093499e-13, 9.5787095713446750e-13, 5.1314070230067691e-12, 2.5887038946092999e-11, 1.2305056649947358e-10, 5.5140053605655075e-10, 2.3304976685688244e-09, 9.2946430660480328e-09, 3.4995595911608765e-08, 1.2444418429985038e-07, 4.1810988437722446e-07, 1.3277780039510742e-06, 3.9868978854768734e-06, 1.1323113503918158e-05, 3.0426750494245559e-05, 7.7380888614623922e-05, 1.8630373980043952e-04, 4.2474911952990744e-04, 9.1721684584915764e-04, 1.8764550081725386e-03, 3.6376544190370392e-03, 6.6835183409171238e-03, 1.1640333062329629e-02, 1.9220794786116900e-02, 3.0094363212091947e-02, 4.4685050904584946e-02, 6.2929070893539232e-02, 8.4060967557359437e-02, 1.0651895867711307e-01, 1.2804948653534245e-01, 1.4603926334720602e-01, 1.5802227437713226e-01, 1.6223085863339984e-01, 1.5802227437713226e-01, 1.4603926334720602e-01, 1.2804948653534245e-01, 1.0651895867711307e-01, 8.4060967557359437e-02, 6.2929070893539232e-02, 4.4685050904584946e-02, 3.0094363212091947e-02, 1.9220794786116900e-02, 1.1640333062329629e-02, 6.6835183409171238e-03, 3.6376544190370392e-03, 1.8764550081725386e-03, 9.1721684584915764e-04, 4.2474911952990744e-04, 1.8630373980043952e-04, 7.7380888614623922e-05, 3.0426750494245559e-05, 1.1323113503918158e-05, 3.9868978854768734e-06, 1.3277780039510742e-06, 4.1810988437722446e-07, 1.2444418429985038e-07, 3.4995595911608765e-08, 9.2946430660480328e-09, 2.3304976685688244e-09, 5.5140053605655075e-10, 1.2305056649947358e-10, 2.5887038946092999e-11, 5.1314070230067691e-12, 9.5787095713446750e-13, 1.6828396856093499e-13, 2.7808623921464611e-14, 4.3195605416094461e-15, 6.3027647004538790e-16, 8.6327149787564008e-17, 1.1090885964042391e-17, 1.3355156911983980e-18, 1.5060515461273932e-19, 1.5891496108132932e-20, 1.5675836145616411e-21, 1.4441897483451718e-22, 1.2413968193571878e-23, 9.9456309833303069e-25, 7.4183584908683151e-26, 5.1455269820153546e-27, 3.3148509472564812e-28, 1.9808277135032592e-29, 1.0964361374105204e-30, 5.6136594541327730e-32, 2.6544306695450948e-33, 1.1573309534274821e-34, 4.6447431828997982e-36, 1.7127600543267554e-37, 5.7919770166825449e-39, 1.7925263383158762e-40, 5.0660482804550958e-42, 1.3044685923509235e-43, 3.0527217350206308e-45, 6.4756889941564796e-47, 1.2416693105547687e-48, 2.1455339764954737e-50, 3.3301662675561347e-52, 4.6268156176755226e-54, 5.7325826101059963e-56, 6.3081846096424608e-58, 6.1380579859214437e-60, 5.2559492672815257e-62, 3.9400295587538806e-64, 2.5709836724164109e-66, 1.4512217440971957e-68, 7.0373804171328241e-71, 2.9095299074235018e-73, 1.0169377873705381e-75, 2.9766194663244294e-78, 7.2194564657826763e-81, 1.4336286376453945e-83, 2.2993488113263748e-86, 2.9324498160004818e-89, 2.9206395863825604e-92, 2.2243270327788831e-95, 1.2635422959480214e-98, 5.1966730435893490e-102, 1.4924416386535932e-105, 2.8619431556076958e-109, 3.4625987620456931e-113, 2.4552181378752603e-117, 9.2375467812799180e-122, 1.6028413383110423e-126, 1.0388721680141190e-131, 1.7774077118017352e-137, 4.1337932844079439e-144, 2.3899020087783538e-152}, + {3.3909583926202969e-153, 6.0862398111746403e-145, 2.6990049104808299e-138, 1.6219807504695568e-132, 2.5679266269176032e-127, 1.5165281109964923e-122, 4.1260001698114066e-118, 5.9515348152406019e-114, 5.0279031031404388e-110, 2.6784561524395333e-106, 9.5230206639834012e-103, 2.3633738761330501e-99, 4.2451210579798656e-96, 5.6858261506014681e-93, 5.8218672370402156e-90, 4.6543449390713426e-87, 2.9582182277022238e-84, 1.5183294739007438e-81, 6.3795487359338829e-79, 2.2208089866950920e-76, 6.4735410582641528e-74, 1.5951103254298808e-71, 3.3507196700207861e-69, 6.0464069117443835e-67, 9.4376753651859668e-65, 1.2822191213791653e-62, 1.5249989655376484e-60, 1.5960849625455376e-58, 1.4770796663837213e-56, 1.2140312147914462e-54, 8.8982101270994950e-53, 5.8379315269148491e-51, 3.4404622652833074e-49, 1.8272036259234053e-47, 8.7716947482766774e-46, 3.8170926065847122e-44, 1.5096656333028563e-42, 5.4400265472252386e-41, 1.7901934646856910e-39, 5.3916646781027312e-38, 1.4892193296848201e-36, 3.7795868784349260e-35, 8.8301666493717958e-34, 1.9022911023392480e-32, 3.7850530748490676e-31, 6.9665700818714156e-30, 1.1878115612451122e-28, 1.8786842016880562e-27, 2.7599602414845152e-26, 3.7707755724079553e-25, 4.7967389479007740e-24, 5.6876402480164174e-23, 6.2928558569586138e-22, 6.5032337700285951e-21, 6.2833568961437137e-20, 5.6810615766852734e-19, 4.8108093342629945e-18, 3.8186952800271027e-17, 2.8435455634715359e-16, 1.9878218878928244e-15, 1.3054944744238950e-14, 8.0602086244990039e-14, 4.6813428453581271e-13, 2.5592533379055519e-12, 1.3177335517890257e-11, 6.3937241128218932e-11, 2.9249655637661996e-10, 1.2622501489006109e-09, 5.1408413936157202e-09, 1.9768915482746416e-08, 7.1808683672368473e-08, 2.4648607700088249e-07, 7.9982594734022375e-07, 2.4543893859357136e-06, 7.1249965705005385e-06, 1.9573063938461480e-05, 5.0897601014117974e-05, 1.2532087255275024e-04, 2.9224860429386435e-04, 6.4564239421835911e-04, 1.3515815953737001e-03, 2.6816113762841770e-03, 5.0435720589444479e-03, 8.9938955083231700e-03, 1.5208840297800851e-02, 2.4392011104876491e-02, 3.7107373608297196e-02, 5.3553162455639902e-02, 7.3327512502661077e-02, 9.5267294910895362e-02, 1.1744849271751398e-01, 1.3740517258624155e-01, 1.5255613196758108e-01, 1.6074586617490177e-01, 1.6074586617490177e-01, 1.5255613196758108e-01, 1.3740517258624155e-01, 1.1744849271751398e-01, 9.5267294910895362e-02, 7.3327512502661077e-02, 5.3553162455639902e-02, 3.7107373608297196e-02, 2.4392011104876491e-02, 1.5208840297800851e-02, 8.9938955083231700e-03, 5.0435720589444479e-03, 2.6816113762841770e-03, 1.3515815953737001e-03, 6.4564239421835911e-04, 2.9224860429386435e-04, 1.2532087255275024e-04, 5.0897601014117974e-05, 1.9573063938461480e-05, 7.1249965705005385e-06, 2.4543893859357136e-06, 7.9982594734022375e-07, 2.4648607700088249e-07, 7.1808683672368473e-08, 1.9768915482746416e-08, 5.1408413936157202e-09, 1.2622501489006109e-09, 2.9249655637661996e-10, 6.3937241128218932e-11, 1.3177335517890257e-11, 2.5592533379055519e-12, 4.6813428453581271e-13, 8.0602086244990039e-14, 1.3054944744238950e-14, 1.9878218878928244e-15, 2.8435455634715359e-16, 3.8186952800271027e-17, 4.8108093342629945e-18, 5.6810615766852734e-19, 6.2833568961437137e-20, 6.5032337700285951e-21, 6.2928558569586138e-22, 5.6876402480164174e-23, 4.7967389479007740e-24, 3.7707755724079553e-25, 2.7599602414845152e-26, 1.8786842016880562e-27, 1.1878115612451122e-28, 6.9665700818714156e-30, 3.7850530748490676e-31, 1.9022911023392480e-32, 8.8301666493717958e-34, 3.7795868784349260e-35, 1.4892193296848201e-36, 5.3916646781027312e-38, 1.7901934646856910e-39, 5.4400265472252386e-41, 1.5096656333028563e-42, 3.8170926065847122e-44, 8.7716947482766774e-46, 1.8272036259234053e-47, 3.4404622652833074e-49, 5.8379315269148491e-51, 8.8982101270994950e-53, 1.2140312147914462e-54, 1.4770796663837213e-56, 1.5960849625455376e-58, 1.5249989655376484e-60, 1.2822191213791653e-62, 9.4376753651859668e-65, 6.0464069117443835e-67, 3.3507196700207861e-69, 1.5951103254298808e-71, 6.4735410582641528e-74, 2.2208089866950920e-76, 6.3795487359338829e-79, 1.5183294739007438e-81, 2.9582182277022238e-84, 4.6543449390713426e-87, 5.8218672370402156e-90, 5.6858261506014681e-93, 4.2451210579798656e-96, 2.3633738761330501e-99, 9.5230206639834012e-103, 2.6784561524395333e-106, 5.0279031031404388e-110, 5.9515348152406019e-114, 4.1260001698114066e-118, 1.5165281109964923e-122, 2.5679266269176032e-127, 1.6219807504695568e-132, 2.6990049104808299e-138, 6.0862398111746403e-145, 3.3909583926202969e-153}, + {4.8105196926800447e-154, 8.9581349097014215e-146, 4.0967387783316221e-139, 2.5310532151069106e-133, 4.1115283174204790e-128, 2.4878902559132056e-123, 6.9281121543161367e-119, 1.0220279314543827e-114, 8.8243129868960541e-111, 4.8017711254332563e-107, 1.7430737935309201e-103, 4.4149829449283152e-100, 8.0909195748902241e-97, 1.1053200966532163e-93, 1.1540787556182570e-90, 9.4062445961729118e-88, 6.0938287850722912e-85, 3.1875459729105427e-82, 1.3647333597873649e-79, 4.8404013281274901e-77, 1.4373955207015468e-74, 3.6078416607613653e-72, 7.7193542145188385e-70, 1.4187152411878090e-67, 2.2552327816162141e-65, 3.1202888315880434e-63, 3.7791134625824903e-61, 4.0276289664497742e-59, 3.7954127913999138e-57, 3.1764227614962876e-55, 2.3706043434701509e-53, 1.5836556658561472e-51, 9.5030686706332782e-50, 5.1390369637842554e-48, 2.5120644517965854e-46, 1.1131134062886865e-44, 4.4828688752777018e-43, 1.6449624113929946e-41, 5.5124888578291881e-40, 1.6907462404862362e-38, 4.7559672339276421e-37, 1.2293279880804420e-35, 2.9252024556839558e-34, 6.4187377483908620e-33, 1.3009300303447977e-31, 2.4391335868389452e-30, 4.2366796233867587e-29, 6.8268728000449227e-28, 1.0218585868330291e-26, 1.4225584486944289e-25, 1.8440385833763509e-24, 2.2283071036811595e-23, 2.5127294052122314e-22, 2.6467919286881548e-21, 2.6068354747780742e-20, 2.4028313064323887e-19, 2.0745586965632990e-18, 1.6791123823339180e-17, 1.2750493352152407e-16, 9.0906021055959760e-16, 6.0895673953539301e-15, 3.8353345411384518e-14, 2.2726043918949056e-13, 1.2676970629687990e-12, 6.6608945127799692e-12, 3.2985045445873824e-11, 1.5402785642655144e-10, 6.7857514014962344e-10, 2.8217661921664192e-09, 1.1080667611835489e-08, 4.1107393732952725e-08, 1.4413206230487042e-07, 4.7781084115403341e-07, 1.4981838617872995e-06, 4.4446553339045300e-06, 1.2480054945286184e-05, 3.3176731522024002e-05, 8.3524630257267974e-05, 1.9919419791658306e-04, 4.5012132211052618e-04, 9.6399635747843960e-04, 1.9570814745659979e-03, 3.7671919910449735e-03, 6.8767389146135380e-03, 1.1906303498193138e-02, 1.9555454063496128e-02, 3.0473029715843637e-02, 4.5058194694576482e-02, 6.3225096957716942e-02, 8.4198334040706369e-02, 1.0642658240453728e-01, 1.2769014695749564e-01, 1.4542767716486577e-01, 1.5722973246415300e-01, 1.6137249430200609e-01, 1.5722973246415300e-01, 1.4542767716486577e-01, 1.2769014695749564e-01, 1.0642658240453728e-01, 8.4198334040706369e-02, 6.3225096957716942e-02, 4.5058194694576482e-02, 3.0473029715843637e-02, 1.9555454063496128e-02, 1.1906303498193138e-02, 6.8767389146135380e-03, 3.7671919910449735e-03, 1.9570814745659979e-03, 9.6399635747843960e-04, 4.5012132211052618e-04, 1.9919419791658306e-04, 8.3524630257267974e-05, 3.3176731522024002e-05, 1.2480054945286184e-05, 4.4446553339045300e-06, 1.4981838617872995e-06, 4.7781084115403341e-07, 1.4413206230487042e-07, 4.1107393732952725e-08, 1.1080667611835489e-08, 2.8217661921664192e-09, 6.7857514014962344e-10, 1.5402785642655144e-10, 3.2985045445873824e-11, 6.6608945127799692e-12, 1.2676970629687990e-12, 2.2726043918949056e-13, 3.8353345411384518e-14, 6.0895673953539301e-15, 9.0906021055959760e-16, 1.2750493352152407e-16, 1.6791123823339180e-17, 2.0745586965632990e-18, 2.4028313064323887e-19, 2.6068354747780742e-20, 2.6467919286881548e-21, 2.5127294052122314e-22, 2.2283071036811595e-23, 1.8440385833763509e-24, 1.4225584486944289e-25, 1.0218585868330291e-26, 6.8268728000449227e-28, 4.2366796233867587e-29, 2.4391335868389452e-30, 1.3009300303447977e-31, 6.4187377483908620e-33, 2.9252024556839558e-34, 1.2293279880804420e-35, 4.7559672339276421e-37, 1.6907462404862362e-38, 5.5124888578291881e-40, 1.6449624113929946e-41, 4.4828688752777018e-43, 1.1131134062886865e-44, 2.5120644517965854e-46, 5.1390369637842554e-48, 9.5030686706332782e-50, 1.5836556658561472e-51, 2.3706043434701509e-53, 3.1764227614962876e-55, 3.7954127913999138e-57, 4.0276289664497742e-59, 3.7791134625824903e-61, 3.1202888315880434e-63, 2.2552327816162141e-65, 1.4187152411878090e-67, 7.7193542145188385e-70, 3.6078416607613653e-72, 1.4373955207015468e-74, 4.8404013281274901e-77, 1.3647333597873649e-79, 3.1875459729105427e-82, 6.0938287850722912e-85, 9.4062445961729118e-88, 1.1540787556182570e-90, 1.1053200966532163e-93, 8.0909195748902241e-97, 4.4149829449283152e-100, 1.7430737935309201e-103, 4.8017711254332563e-107, 8.8243129868960541e-111, 1.0220279314543827e-114, 6.9281121543161367e-119, 2.4878902559132056e-123, 4.1115283174204790e-128, 2.5310532151069106e-133, 4.0967387783316221e-139, 8.9581349097014215e-146, 4.8105196926800447e-154}, + {6.8232197942250040e-155, 1.3181218114180107e-146, 6.2157350428501506e-140, 3.9475798303387850e-134, 6.5789265659620338e-129, 4.0785124308845132e-124, 1.1623859612267819e-119, 1.7535057075593614e-115, 1.5472021309193150e-111, 8.5990905704820439e-108, 3.1867892204083499e-104, 8.2372979129162400e-101, 1.5400245034982435e-97, 2.1456921017005163e-94, 2.2843171180826872e-91, 1.8979497846368726e-88, 1.2532102545185035e-85, 6.6801061673807505e-83, 2.9141025510545569e-80, 1.0529633740939257e-77, 3.1851858054210446e-75, 8.1431135103329952e-73, 1.7744839092477200e-70, 3.3212610596524388e-68, 5.3763688423964646e-66, 7.5746019148953009e-64, 9.3412200164700803e-62, 1.0136702052099045e-59, 9.7258603579728974e-58, 8.2874406983788114e-56, 6.2972157268746326e-54, 4.2830642136217272e-52, 2.6167460089856425e-50, 1.4407389710981317e-48, 7.1704184113766286e-47, 3.2349665837355912e-45, 1.3265135880257318e-43, 4.9561856762703143e-42, 1.6911721771605448e-40, 5.2817945954838791e-39, 1.5129382111557171e-37, 3.9824232345150253e-36, 9.6505627399970417e-35, 2.1566756583641779e-33, 4.4519543419059356e-32, 8.5019504368590908e-31, 1.5042535921639604e-29, 2.4692068347694563e-28, 3.7652687650201339e-27, 5.3404226168220292e-26, 7.0535560842160286e-25, 8.6851943617712193e-24, 9.9804891048351136e-23, 1.0714309730247980e-21, 1.0755595219737973e-20, 1.0105554063847399e-19, 8.8944609945993243e-19, 7.3396140181061249e-18, 5.6828205180213369e-17, 4.1316021764480691e-16, 2.8225916935311505e-15, 1.8132136826440378e-14, 1.0959822792780298e-13, 6.2370678258135157e-13, 3.3437645093788376e-12, 1.6897122210470246e-11, 8.0527347789629487e-11, 3.6211627179619072e-10, 1.5372205783801174e-09, 6.1632086713433375e-09, 2.3347964326766498e-08, 8.3606844554454458e-08, 2.8310992931625352e-07, 9.0687938435499206e-07, 2.7490144224436228e-06, 7.8882549269903193e-06, 2.1433661822155404e-05, 5.5163316323048505e-05, 1.3451233819198536e-04, 3.1084451589835123e-04, 6.8092260658474482e-04, 1.4142383035108275e-03, 2.7855275571971620e-03, 5.2039736325766575e-03, 9.2231946903286923e-03, 1.5510131997231313e-02, 2.4751412543080331e-02, 3.7487880444774385e-02, 5.3893671909463224e-02, 7.3550203638163128e-02, 9.5294126497036155e-02, 1.1722364672954393e-01, 1.3691645960749019e-01, 1.5184684526785858e-01, 1.5991079381814263e-01, 1.5991079381814263e-01, 1.5184684526785858e-01, 1.3691645960749019e-01, 1.1722364672954393e-01, 9.5294126497036155e-02, 7.3550203638163128e-02, 5.3893671909463224e-02, 3.7487880444774385e-02, 2.4751412543080331e-02, 1.5510131997231313e-02, 9.2231946903286923e-03, 5.2039736325766575e-03, 2.7855275571971620e-03, 1.4142383035108275e-03, 6.8092260658474482e-04, 3.1084451589835123e-04, 1.3451233819198536e-04, 5.5163316323048505e-05, 2.1433661822155404e-05, 7.8882549269903193e-06, 2.7490144224436228e-06, 9.0687938435499206e-07, 2.8310992931625352e-07, 8.3606844554454458e-08, 2.3347964326766498e-08, 6.1632086713433375e-09, 1.5372205783801174e-09, 3.6211627179619072e-10, 8.0527347789629487e-11, 1.6897122210470246e-11, 3.3437645093788376e-12, 6.2370678258135157e-13, 1.0959822792780298e-13, 1.8132136826440378e-14, 2.8225916935311505e-15, 4.1316021764480691e-16, 5.6828205180213369e-17, 7.3396140181061249e-18, 8.8944609945993243e-19, 1.0105554063847399e-19, 1.0755595219737973e-20, 1.0714309730247980e-21, 9.9804891048351136e-23, 8.6851943617712193e-24, 7.0535560842160286e-25, 5.3404226168220292e-26, 3.7652687650201339e-27, 2.4692068347694563e-28, 1.5042535921639604e-29, 8.5019504368590908e-31, 4.4519543419059356e-32, 2.1566756583641779e-33, 9.6505627399970417e-35, 3.9824232345150253e-36, 1.5129382111557171e-37, 5.2817945954838791e-39, 1.6911721771605448e-40, 4.9561856762703143e-42, 1.3265135880257318e-43, 3.2349665837355912e-45, 7.1704184113766286e-47, 1.4407389710981317e-48, 2.6167460089856425e-50, 4.2830642136217272e-52, 6.2972157268746326e-54, 8.2874406983788114e-56, 9.7258603579728974e-58, 1.0136702052099045e-59, 9.3412200164700803e-62, 7.5746019148953009e-64, 5.3763688423964646e-66, 3.3212610596524388e-68, 1.7744839092477200e-70, 8.1431135103329952e-73, 3.1851858054210446e-75, 1.0529633740939257e-77, 2.9141025510545569e-80, 6.6801061673807505e-83, 1.2532102545185035e-85, 1.8979497846368726e-88, 2.2843171180826872e-91, 2.1456921017005163e-94, 1.5400245034982435e-97, 8.2372979129162400e-101, 3.1867892204083499e-104, 8.5990905704820439e-108, 1.5472021309193150e-111, 1.7535057075593614e-115, 1.1623859612267819e-119, 4.0785124308845132e-124, 6.5789265659620338e-129, 3.9475798303387850e-134, 6.2157350428501506e-140, 1.3181218114180107e-146, 6.8232197942250040e-155}, + {9.6764302762857911e-156, 1.9389386338649253e-147, 9.4268794388387584e-141, 6.1537049528839255e-135, 1.0520595245806230e-129, 6.6813621694344271e-125, 1.9486722540934962e-120, 3.0058398378782854e-116, 2.7101250640991562e-112, 1.5383037549430030e-108, 5.8195869131646608e-105, 1.5349872474118010e-101, 2.9274184968148517e-98, 4.1594648723850271e-95, 4.5147260427833628e-92, 3.8235833994762416e-89, 2.5729913678738507e-86, 1.3975076314494611e-83, 6.2111050589991735e-81, 2.2862048443444402e-78, 7.0441083482496365e-76, 1.8341247494924424e-73, 4.0702482203595230e-71, 7.7576584194845979e-69, 1.2786993882275677e-66, 1.8342905501305085e-64, 2.3031479777875351e-62, 2.5445408528816102e-60, 2.4855538228455434e-58, 2.1561995344944781e-56, 1.6679549705866419e-54, 1.1549259780000125e-52, 7.1833013403181687e-51, 4.0263574453603144e-49, 2.0400456628439797e-47, 9.3700002807816908e-46, 3.9116867251382951e-44, 1.4879647423347193e-42, 5.1693708373553046e-41, 1.6438042759677152e-39, 4.7942896465195374e-38, 1.2849980190682212e-36, 3.1708729314553754e-35, 7.2161081218241727e-34, 1.5169921976469880e-32, 2.9504597948207525e-31, 5.3168727228967571e-30, 8.8896336943576362e-29, 1.3808362593425483e-27, 1.9951324606202683e-26, 2.6846378493690218e-25, 3.3679964757574780e-24, 3.9436002250852672e-23, 4.3140992488603084e-22, 4.4134945997917874e-21, 4.2263869813792336e-20, 3.7916648002202093e-19, 3.1895272336827489e-18, 2.5176935915196902e-17, 1.8663270859468551e-16, 1.3001503435609439e-15, 8.5176175587843442e-15, 5.2510379021912937e-14, 3.0482099219006810e-13, 1.6671499873186635e-12, 8.5956677592000092e-12, 4.1801607084826671e-11, 1.9183890700529380e-10, 8.3123118452689150e-10, 3.4021150696080136e-09, 1.3158571431631216e-08, 4.8115154735048105e-08, 1.6639485157072335e-07, 5.4443385920665998e-07, 1.6859754012772494e-06, 4.9431447402619969e-06, 1.3725819438547434e-05, 3.6106464014912190e-05, 9.0004542316217840e-05, 2.1266213156628891e-04, 4.7639613833099480e-04, 1.0120395216254993e-03, 2.0392461173393923e-03, 3.8982490246164416e-03, 7.0709100790306376e-03, 1.2171895486539193e-02, 1.9887632287530231e-02, 3.0846667595353164e-02, 4.5424033501544080e-02, 6.3512773332392206e-02, 8.4328396273560896e-02, 1.0633035510412364e-01, 1.2733227690715612e-01, 1.4482336870308740e-01, 1.5644897465655389e-01, 1.6052761213288572e-01, 1.5644897465655389e-01, 1.4482336870308740e-01, 1.2733227690715612e-01, 1.0633035510412364e-01, 8.4328396273560896e-02, 6.3512773332392206e-02, 4.5424033501544080e-02, 3.0846667595353164e-02, 1.9887632287530231e-02, 1.2171895486539193e-02, 7.0709100790306376e-03, 3.8982490246164416e-03, 2.0392461173393923e-03, 1.0120395216254993e-03, 4.7639613833099480e-04, 2.1266213156628891e-04, 9.0004542316217840e-05, 3.6106464014912190e-05, 1.3725819438547434e-05, 4.9431447402619969e-06, 1.6859754012772494e-06, 5.4443385920665998e-07, 1.6639485157072335e-07, 4.8115154735048105e-08, 1.3158571431631216e-08, 3.4021150696080136e-09, 8.3123118452689150e-10, 1.9183890700529380e-10, 4.1801607084826671e-11, 8.5956677592000092e-12, 1.6671499873186635e-12, 3.0482099219006810e-13, 5.2510379021912937e-14, 8.5176175587843442e-15, 1.3001503435609439e-15, 1.8663270859468551e-16, 2.5176935915196902e-17, 3.1895272336827489e-18, 3.7916648002202093e-19, 4.2263869813792336e-20, 4.4134945997917874e-21, 4.3140992488603084e-22, 3.9436002250852672e-23, 3.3679964757574780e-24, 2.6846378493690218e-25, 1.9951324606202683e-26, 1.3808362593425483e-27, 8.8896336943576362e-29, 5.3168727228967571e-30, 2.9504597948207525e-31, 1.5169921976469880e-32, 7.2161081218241727e-34, 3.1708729314553754e-35, 1.2849980190682212e-36, 4.7942896465195374e-38, 1.6438042759677152e-39, 5.1693708373553046e-41, 1.4879647423347193e-42, 3.9116867251382951e-44, 9.3700002807816908e-46, 2.0400456628439797e-47, 4.0263574453603144e-49, 7.1833013403181687e-51, 1.1549259780000125e-52, 1.6679549705866419e-54, 2.1561995344944781e-56, 2.4855538228455434e-58, 2.5445408528816102e-60, 2.3031479777875351e-62, 1.8342905501305085e-64, 1.2786993882275677e-66, 7.7576584194845979e-69, 4.0702482203595230e-71, 1.8341247494924424e-73, 7.0441083482496365e-76, 2.2862048443444402e-78, 6.2111050589991735e-81, 1.3975076314494611e-83, 2.5729913678738507e-86, 3.8235833994762416e-89, 4.5147260427833628e-92, 4.1594648723850271e-95, 2.9274184968148517e-98, 1.5349872474118010e-101, 5.8195869131646608e-105, 1.5383037549430030e-108, 2.7101250640991562e-112, 3.0058398378782854e-116, 1.9486722540934962e-120, 6.6813621694344271e-125, 1.0520595245806230e-129, 6.1537049528839255e-135, 9.4268794388387584e-141, 1.9389386338649253e-147, 9.6764302762857911e-156}, + {1.3720504154302014e-156, 2.8513090679363871e-148, 1.4291119261031478e-141, 9.5878345367776407e-136, 1.6813631090843168e-130, 1.0937641473652881e-125, 3.2642500496954800e-121, 5.1480442370317754e-117, 4.7425471562207601e-113, 2.7489983469746781e-109, 1.0615412978825736e-105, 2.8568935742124688e-102, 5.5574407262791218e-99, 8.0520048626328837e-96, 8.9097729474744936e-93, 7.6909567014190078e-90, 5.2740027603411657e-87, 2.9186112720938588e-84, 1.3214406564729561e-81, 4.9544462772840985e-79, 1.5547429149839197e-76, 4.1226034386806711e-74, 9.3161574688297957e-72, 1.8079563460381452e-69, 3.0341692292606370e-67, 4.4312923121519367e-65, 5.6644240327335667e-63, 6.3708774357395162e-61, 6.3351435391240280e-59, 5.5944362188420675e-57, 4.4053385520999193e-55, 3.1050807666511750e-53, 1.9659178072617245e-51, 1.1217013968671671e-49, 5.7853802707668581e-48, 2.7049816006551789e-46, 1.1495533915103732e-44, 4.4515141949278675e-43, 1.5743976688633690e-41, 5.0968507385634822e-40, 1.5134439954515047e-38, 4.1300163134837491e-37, 1.0376574212671890e-35, 2.4044973436406753e-34, 5.1472183288770750e-33, 1.0194603568070278e-31, 1.8709115794220601e-30, 3.1858380070837839e-29, 5.0402581729336372e-28, 7.4179265516977060e-27, 1.0167813330369454e-25, 1.2995016885518635e-24, 1.5502266336408172e-23, 1.7279241662380531e-22, 1.8012995272732974e-21, 1.7578400079602021e-20, 1.6072599968378759e-19, 1.3780640314290736e-18, 1.1088556613183840e-17, 8.3797787500377154e-17, 5.9519054533347666e-16, 3.9759844018964598e-15, 2.4996755476537754e-14, 1.4799417664726766e-13, 8.2563190162426826e-13, 4.3426586703108686e-12, 2.1547012918303077e-11, 1.0090299262094598e-10, 4.4618936758916388e-10, 1.8639520759198730e-09, 7.3594054861502447e-09, 2.7474235203608662e-08, 9.7018924643039030e-08, 3.2418977135736030e-07, 1.0254381425692049e-06, 3.0713815320154091e-06, 8.7138650801478641e-06, 2.3424552293210665e-05, 5.9681270208738333e-05, 1.4415391428196787e-04, 3.3017517124886084e-04, 7.1728665634025713e-04, 1.4783089544886255e-03, 2.8910036930282720e-03, 5.3656605093971325e-03, 9.4528407852602792e-03, 1.5810044685497838e-02, 2.5107070566959051e-02, 3.7862166097742164e-02, 5.4226226141723462e-02, 7.3764890309958767e-02, 9.5315208688082131e-02, 1.1699751277485990e-01, 1.3643214928471140e-01, 1.5114725119507466e-01, 1.5908860103657232e-01, 1.5908860103657232e-01, 1.5114725119507466e-01, 1.3643214928471140e-01, 1.1699751277485990e-01, 9.5315208688082131e-02, 7.3764890309958767e-02, 5.4226226141723462e-02, 3.7862166097742164e-02, 2.5107070566959051e-02, 1.5810044685497838e-02, 9.4528407852602792e-03, 5.3656605093971325e-03, 2.8910036930282720e-03, 1.4783089544886255e-03, 7.1728665634025713e-04, 3.3017517124886084e-04, 1.4415391428196787e-04, 5.9681270208738333e-05, 2.3424552293210665e-05, 8.7138650801478641e-06, 3.0713815320154091e-06, 1.0254381425692049e-06, 3.2418977135736030e-07, 9.7018924643039030e-08, 2.7474235203608662e-08, 7.3594054861502447e-09, 1.8639520759198730e-09, 4.4618936758916388e-10, 1.0090299262094598e-10, 2.1547012918303077e-11, 4.3426586703108686e-12, 8.2563190162426826e-13, 1.4799417664726766e-13, 2.4996755476537754e-14, 3.9759844018964598e-15, 5.9519054533347666e-16, 8.3797787500377154e-17, 1.1088556613183840e-17, 1.3780640314290736e-18, 1.6072599968378759e-19, 1.7578400079602021e-20, 1.8012995272732974e-21, 1.7279241662380531e-22, 1.5502266336408172e-23, 1.2995016885518635e-24, 1.0167813330369454e-25, 7.4179265516977060e-27, 5.0402581729336372e-28, 3.1858380070837839e-29, 1.8709115794220601e-30, 1.0194603568070278e-31, 5.1472183288770750e-33, 2.4044973436406753e-34, 1.0376574212671890e-35, 4.1300163134837491e-37, 1.5134439954515047e-38, 5.0968507385634822e-40, 1.5743976688633690e-41, 4.4515141949278675e-43, 1.1495533915103732e-44, 2.7049816006551789e-46, 5.7853802707668581e-48, 1.1217013968671671e-49, 1.9659178072617245e-51, 3.1050807666511750e-53, 4.4053385520999193e-55, 5.5944362188420675e-57, 6.3351435391240280e-59, 6.3708774357395162e-61, 5.6644240327335667e-63, 4.4312923121519367e-65, 3.0341692292606370e-67, 1.8079563460381452e-69, 9.3161574688297957e-72, 4.1226034386806711e-74, 1.5547429149839197e-76, 4.9544462772840985e-79, 1.3214406564729561e-81, 2.9186112720938588e-84, 5.2740027603411657e-87, 7.6909567014190078e-90, 8.9097729474744936e-93, 8.0520048626328837e-96, 5.5574407262791218e-99, 2.8568935742124688e-102, 1.0615412978825736e-105, 2.7489983469746781e-109, 4.7425471562207601e-113, 5.1480442370317754e-117, 3.2642500496954800e-121, 1.0937641473652881e-125, 1.6813631090843168e-130, 9.5878345367776407e-136, 1.4291119261031478e-141, 2.8513090679363871e-148, 1.3720504154302014e-156}, + {1.9451569748580915e-157, 4.1917692496623074e-149, 2.1656533203264049e-142, 1.4930848367233329e-136, 2.6854744034643652e-131, 1.7892892532014627e-126, 5.4637061901241444e-122, 8.8092712504606827e-118, 8.2912095929290215e-114, 4.9074274510768621e-110, 1.9341588617846345e-106, 5.3107713773093621e-103, 1.0536661811562218e-99, 1.5565848726847315e-96, 1.7557722156935769e-93, 1.5446161289516271e-90, 1.0792867414624379e-87, 6.0849467639302215e-85, 2.8063950432169120e-82, 1.0716703469936493e-79, 3.4248444263060510e-77, 9.2475643800642814e-75, 2.1277914455786410e-72, 4.2042110347158325e-70, 7.1831202945319969e-68, 1.0679652291289812e-65, 1.3896846788334397e-63, 1.5910268843395548e-61, 1.6104220743828299e-59, 1.4475542666378789e-57, 1.1602357060613541e-55, 8.3238465917891379e-54, 5.3641275790400676e-52, 3.1152601083577022e-50, 1.6354424962643853e-48, 7.7832174172965086e-47, 3.3668417110773493e-45, 1.3271170300689291e-43, 4.7778763656316077e-42, 1.5745422805731105e-40, 4.7595446906951574e-39, 1.3222509215279862e-37, 3.3821840940140512e-36, 7.9793659216047449e-35, 1.7391569791608673e-33, 3.5073691468931601e-32, 6.5544111912453122e-31, 1.1365779583643404e-29, 1.8312631014871582e-28, 2.7449324565145490e-27, 3.8322872065908508e-26, 4.9890778549827656e-25, 6.0629582449560457e-24, 6.8848488569478251e-23, 7.3125997647970303e-22, 7.2714081831677253e-21, 6.7751229891684194e-20, 5.9201437592343701e-19, 4.8552433914811921e-18, 3.7401100817855975e-17, 2.7081193971598301e-16, 1.8444288831090382e-15, 1.1823696121971421e-14, 7.1386313730701460e-14, 4.0616946929687980e-13, 2.1791052221508088e-12, 1.1029706356088577e-11, 5.2697432068365651e-11, 2.3777643019834690e-10, 1.0136912013567245e-09, 4.0850156582808148e-09, 1.5567430501187781e-08, 5.6124175036636782e-08, 1.9149546201420412e-07, 6.1858506291091545e-07, 1.8924364481789124e-06, 5.4848459956508166e-06, 1.5064725177098550e-05, 3.9222592074287836e-05, 9.6829305369002766e-05, 2.2671622856088540e-04, 5.0357752441741071e-04, 1.0613379467370166e-03, 2.1229194690909154e-03, 4.0307696130016573e-03, 7.2659539954360898e-03, 1.2437029172215985e-02, 2.0217282655364367e-02, 3.1215303196211058e-02, 4.5782692483561545e-02, 6.3792314106331613e-02, 8.4451401972617260e-02, 1.0623046970193420e-01, 1.2697592765070259e-01, 1.4422620485622731e-01, 1.5567971237666092e-01, 1.5969586284722317e-01, 1.5567971237666092e-01, 1.4422620485622731e-01, 1.2697592765070259e-01, 1.0623046970193420e-01, 8.4451401972617260e-02, 6.3792314106331613e-02, 4.5782692483561545e-02, 3.1215303196211058e-02, 2.0217282655364367e-02, 1.2437029172215985e-02, 7.2659539954360898e-03, 4.0307696130016573e-03, 2.1229194690909154e-03, 1.0613379467370166e-03, 5.0357752441741071e-04, 2.2671622856088540e-04, 9.6829305369002766e-05, 3.9222592074287836e-05, 1.5064725177098550e-05, 5.4848459956508166e-06, 1.8924364481789124e-06, 6.1858506291091545e-07, 1.9149546201420412e-07, 5.6124175036636782e-08, 1.5567430501187781e-08, 4.0850156582808148e-09, 1.0136912013567245e-09, 2.3777643019834690e-10, 5.2697432068365651e-11, 1.1029706356088577e-11, 2.1791052221508088e-12, 4.0616946929687980e-13, 7.1386313730701460e-14, 1.1823696121971421e-14, 1.8444288831090382e-15, 2.7081193971598301e-16, 3.7401100817855975e-17, 4.8552433914811921e-18, 5.9201437592343701e-19, 6.7751229891684194e-20, 7.2714081831677253e-21, 7.3125997647970303e-22, 6.8848488569478251e-23, 6.0629582449560457e-24, 4.9890778549827656e-25, 3.8322872065908508e-26, 2.7449324565145490e-27, 1.8312631014871582e-28, 1.1365779583643404e-29, 6.5544111912453122e-31, 3.5073691468931601e-32, 1.7391569791608673e-33, 7.9793659216047449e-35, 3.3821840940140512e-36, 1.3222509215279862e-37, 4.7595446906951574e-39, 1.5745422805731105e-40, 4.7778763656316077e-42, 1.3271170300689291e-43, 3.3668417110773493e-45, 7.7832174172965086e-47, 1.6354424962643853e-48, 3.1152601083577022e-50, 5.3641275790400676e-52, 8.3238465917891379e-54, 1.1602357060613541e-55, 1.4475542666378789e-57, 1.6104220743828299e-59, 1.5910268843395548e-61, 1.3896846788334397e-63, 1.0679652291289812e-65, 7.1831202945319969e-68, 4.2042110347158325e-70, 2.1277914455786410e-72, 9.2475643800642814e-75, 3.4248444263060510e-77, 1.0716703469936493e-79, 2.8063950432169120e-82, 6.0849467639302215e-85, 1.0792867414624379e-87, 1.5446161289516271e-90, 1.7557722156935769e-93, 1.5565848726847315e-96, 1.0536661811562218e-99, 5.3107713773093621e-103, 1.9341588617846345e-106, 4.9074274510768621e-110, 8.2912095929290215e-114, 8.8092712504606827e-118, 5.4637061901241444e-122, 1.7892892532014627e-126, 2.6854744034643652e-131, 1.4930848367233329e-136, 2.1656533203264049e-142, 4.1917692496623074e-149, 1.9451569748580915e-157}, + {2.7572081394930497e-158, 6.1606195891114038e-150, 3.2804813831912987e-143, 2.3239698294632731e-137, 4.2866809471010448e-132, 2.9250839726119467e-127, 9.1380522604480418e-123, 1.5061298645822260e-118, 1.4481443283610901e-114, 8.7515402609102180e-111, 3.5201601974984495e-107, 9.8605307314410817e-104, 1.9951459370163873e-100, 3.0050341197440912e-97, 3.4549517863933081e-94, 3.0974015995404665e-91, 2.2051316618251230e-88, 1.2664932443877347e-85, 5.9494906351077990e-83, 2.3137758798623088e-80, 7.5297591329388192e-78, 2.0701649292513591e-75, 4.8496085133984147e-73, 9.7550576247941725e-71, 1.6966738887834285e-68, 2.5677846130096429e-66, 3.4010587398231950e-64, 3.9632860731065032e-62, 4.0830488118084828e-60, 3.7353956966630745e-58, 3.0471769779359536e-56, 2.2249520894879323e-54, 1.4592805785267631e-52, 8.6253646389571326e-51, 4.6085517173721152e-49, 2.2322309293391554e-47, 9.8278883256522070e-46, 3.9428752392560041e-44, 1.4448263309190163e-42, 4.8464578191552559e-41, 1.4912109536234187e-39, 4.2170331394849629e-38, 1.0980633083650227e-36, 2.6372704388350129e-35, 5.8519678162563370e-34, 1.2015551933775674e-32, 2.2862239823374585e-31, 4.0367549228098398e-30, 6.6230590346823284e-29, 1.0109795409268771e-27, 1.4374775988383664e-26, 1.9060160602736751e-25, 2.3593174689076554e-24, 2.7291375088225280e-23, 2.9530245244292184e-22, 2.9916750627894004e-21, 2.8402168199630962e-20, 2.5289725099536307e-19, 2.1136880764547752e-18, 1.6594882054957410e-17, 1.2247874128456919e-16, 8.5035945941928308e-16, 5.5576041209463139e-15, 3.4212940713768145e-14, 1.9850553217879612e-13, 1.0861345804029464e-12, 5.6073947890454799e-12, 2.7329486591769151e-11, 1.2580856861713816e-10, 5.4727113377318889e-10, 2.2506273484860213e-09, 8.7538457447490308e-09, 3.2215483374955876e-08, 1.1221944492414074e-07, 3.7014154510322367e-07, 1.1564156154340975e-06, 3.4233275145786425e-06, 9.6051781722267405e-06, 2.5551197899130104e-05, 6.4459196331247565e-05, 1.5425452576992943e-04, 3.5024735925131938e-04, 7.5473297532327498e-04, 1.5437752230132358e-03, 2.9979972233121189e-03, 5.5285649600795095e-03, 9.6827528386239439e-03, 1.6108512025371353e-02, 2.5458972192611309e-02, 3.8230305479849361e-02, 5.4550997194724032e-02, 7.3971809106191291e-02, 9.5330768912038982e-02, 1.1677021831583778e-01, 1.3595220139257186e-01, 1.5045713397116045e-01, 1.5827896015320714e-01, 1.5827896015320714e-01, 1.5045713397116045e-01, 1.3595220139257186e-01, 1.1677021831583778e-01, 9.5330768912038982e-02, 7.3971809106191291e-02, 5.4550997194724032e-02, 3.8230305479849361e-02, 2.5458972192611309e-02, 1.6108512025371353e-02, 9.6827528386239439e-03, 5.5285649600795095e-03, 2.9979972233121189e-03, 1.5437752230132358e-03, 7.5473297532327498e-04, 3.5024735925131938e-04, 1.5425452576992943e-04, 6.4459196331247565e-05, 2.5551197899130104e-05, 9.6051781722267405e-06, 3.4233275145786425e-06, 1.1564156154340975e-06, 3.7014154510322367e-07, 1.1221944492414074e-07, 3.2215483374955876e-08, 8.7538457447490308e-09, 2.2506273484860213e-09, 5.4727113377318889e-10, 1.2580856861713816e-10, 2.7329486591769151e-11, 5.6073947890454799e-12, 1.0861345804029464e-12, 1.9850553217879612e-13, 3.4212940713768145e-14, 5.5576041209463139e-15, 8.5035945941928308e-16, 1.2247874128456919e-16, 1.6594882054957410e-17, 2.1136880764547752e-18, 2.5289725099536307e-19, 2.8402168199630962e-20, 2.9916750627894004e-21, 2.9530245244292184e-22, 2.7291375088225280e-23, 2.3593174689076554e-24, 1.9060160602736751e-25, 1.4374775988383664e-26, 1.0109795409268771e-27, 6.6230590346823284e-29, 4.0367549228098398e-30, 2.2862239823374585e-31, 1.2015551933775674e-32, 5.8519678162563370e-34, 2.6372704388350129e-35, 1.0980633083650227e-36, 4.2170331394849629e-38, 1.4912109536234187e-39, 4.8464578191552559e-41, 1.4448263309190163e-42, 3.9428752392560041e-44, 9.8278883256522070e-46, 2.2322309293391554e-47, 4.6085517173721152e-49, 8.6253646389571326e-51, 1.4592805785267631e-52, 2.2249520894879323e-54, 3.0471769779359536e-56, 3.7353956966630745e-58, 4.0830488118084828e-60, 3.9632860731065032e-62, 3.4010587398231950e-64, 2.5677846130096429e-66, 1.6966738887834285e-68, 9.7550576247941725e-71, 4.8496085133984147e-73, 2.0701649292513591e-75, 7.5297591329388192e-78, 2.3137758798623088e-80, 5.9494906351077990e-83, 1.2664932443877347e-85, 2.2051316618251230e-88, 3.0974015995404665e-91, 3.4549517863933081e-94, 3.0050341197440912e-97, 1.9951459370163873e-100, 9.8605307314410817e-104, 3.5201601974984495e-107, 8.7515402609102180e-111, 1.4481443283610901e-114, 1.5061298645822260e-118, 9.1380522604480418e-123, 2.9250839726119467e-127, 4.2866809471010448e-132, 2.3239698294632731e-137, 3.2804813831912987e-143, 6.1606195891114038e-150, 2.7572081394930497e-158}, + {3.9076471690941080e-159, 9.0516231985655450e-151, 4.9672234319145855e-144, 3.6154341661312203e-138, 6.8385535268994495e-133, 4.7785893786651104e-128, 1.5271628772769884e-123, 2.5728411822428113e-119, 2.5269536248805626e-115, 1.5590872025715406e-111, 6.3995909265162004e-108, 1.8286346030132772e-104, 3.7730702714400253e-101, 5.7934780549600130e-98, 6.7888152108219864e-95, 6.2017960981784824e-92, 4.4982131286438984e-89, 2.6316100628013750e-86, 1.2590645102017268e-83, 4.9863539974326119e-81, 1.6522944213413452e-78, 4.6250118175679923e-76, 1.1030078970560833e-73, 2.2585685158900422e-71, 3.9985750751823772e-69, 6.1594934342804038e-67, 8.3034758916801791e-65, 9.8479077342924136e-63, 1.0325295240318946e-60, 9.6133222464273388e-59, 7.9807919503856858e-57, 5.9302840185272367e-55, 3.9582000609173701e-53, 2.3808961922219179e-51, 1.2945943475503535e-49, 6.3814434194007278e-48, 2.8592815645992017e-46, 1.1674410264648282e-44, 4.3538446893851820e-43, 1.4863772701012763e-41, 4.6548397931087811e-40, 1.3398281145584983e-38, 3.5510998957536425e-37, 8.6816489289737604e-36, 1.9610184560405483e-34, 4.0989946034555524e-33, 7.9401630700838486e-32, 1.4273966207691636e-30, 2.3845069143279796e-29, 3.7062734865446578e-28, 5.3663645149930618e-27, 7.2463592171380759e-26, 9.1353566359276092e-25, 1.0763247315298265e-23, 1.1863095918086436e-22, 1.2243177639523886e-21, 1.1841779286732196e-20, 1.0743199749303155e-19, 9.1494332489911347e-19, 7.3203566611052359e-18, 5.5063768554293231e-17, 3.8967149070515473e-16, 2.5960894208342548e-15, 1.6293142388397836e-14, 9.6386743368990212e-14, 5.3778391218729220e-13, 2.8314924455552075e-12, 1.4075632287720228e-11, 6.6097087557103094e-11, 2.9333592912411779e-10, 1.2308733220895705e-09, 4.8855519350876319e-09, 1.8350327790289198e-08, 6.5248828381395632e-08, 2.1971536691628579e-07, 7.0090428369282574e-07, 2.1189035330905069e-06, 6.0723051489799535e-06, 1.6501142336395539e-05, 4.2531734642799478e-05, 1.0400739885143485e-04, 2.4136469790269507e-04, 5.3166865805501619e-04, 1.1118823380073424e-03, 2.2080714903093502e-03, 4.1646982803793314e-03, 7.4617948415810062e-03, 1.2701628295481309e-02, 2.0544362511894173e-02, 3.1578965559564402e-02, 4.6134295845117745e-02, 6.4063927714297891e-02, 8.4567589743710897e-02, 1.0612711013185427e-01, 1.2662114600203433e-01, 1.4363605547026137e-01, 1.5492166682336009e-01, 1.5887690970441684e-01, 1.5492166682336009e-01, 1.4363605547026137e-01, 1.2662114600203433e-01, 1.0612711013185427e-01, 8.4567589743710897e-02, 6.4063927714297891e-02, 4.6134295845117745e-02, 3.1578965559564402e-02, 2.0544362511894173e-02, 1.2701628295481309e-02, 7.4617948415810062e-03, 4.1646982803793314e-03, 2.2080714903093502e-03, 1.1118823380073424e-03, 5.3166865805501619e-04, 2.4136469790269507e-04, 1.0400739885143485e-04, 4.2531734642799478e-05, 1.6501142336395539e-05, 6.0723051489799535e-06, 2.1189035330905069e-06, 7.0090428369282574e-07, 2.1971536691628579e-07, 6.5248828381395632e-08, 1.8350327790289198e-08, 4.8855519350876319e-09, 1.2308733220895705e-09, 2.9333592912411779e-10, 6.6097087557103094e-11, 1.4075632287720228e-11, 2.8314924455552075e-12, 5.3778391218729220e-13, 9.6386743368990212e-14, 1.6293142388397836e-14, 2.5960894208342548e-15, 3.8967149070515473e-16, 5.5063768554293231e-17, 7.3203566611052359e-18, 9.1494332489911347e-19, 1.0743199749303155e-19, 1.1841779286732196e-20, 1.2243177639523886e-21, 1.1863095918086436e-22, 1.0763247315298265e-23, 9.1353566359276092e-25, 7.2463592171380759e-26, 5.3663645149930618e-27, 3.7062734865446578e-28, 2.3845069143279796e-29, 1.4273966207691636e-30, 7.9401630700838486e-32, 4.0989946034555524e-33, 1.9610184560405483e-34, 8.6816489289737604e-36, 3.5510998957536425e-37, 1.3398281145584983e-38, 4.6548397931087811e-40, 1.4863772701012763e-41, 4.3538446893851820e-43, 1.1674410264648282e-44, 2.8592815645992017e-46, 6.3814434194007278e-48, 1.2945943475503535e-49, 2.3808961922219179e-51, 3.9582000609173701e-53, 5.9302840185272367e-55, 7.9807919503856858e-57, 9.6133222464273388e-59, 1.0325295240318946e-60, 9.8479077342924136e-63, 8.3034758916801791e-65, 6.1594934342804038e-67, 3.9985750751823772e-69, 2.2585685158900422e-71, 1.1030078970560833e-73, 4.6250118175679923e-76, 1.6522944213413452e-78, 4.9863539974326119e-81, 1.2590645102017268e-83, 2.6316100628013750e-86, 4.4982131286438984e-89, 6.2017960981784824e-92, 6.7888152108219864e-95, 5.7934780549600130e-98, 3.7730702714400253e-101, 1.8286346030132772e-104, 6.3995909265162004e-108, 1.5590872025715406e-111, 2.5269536248805626e-115, 2.5728411822428113e-119, 1.5271628772769884e-123, 4.7785893786651104e-128, 6.8385535268994495e-133, 3.6154341661312203e-138, 4.9672234319145855e-144, 9.0516231985655450e-151, 3.9076471690941080e-159}, + {5.5372309477634655e-160, 1.3295499920372636e-151, 7.5182851789608105e-145, 5.6218117631932678e-139, 1.0903164404085858e-133, 7.8013060714659609e-129, 2.5502660858886434e-124, 4.3913191972243959e-120, 4.4053240904063359e-116, 2.7746976743925027e-112, 1.1621599260631149e-108, 3.3872112245822123e-105, 7.1263773535131733e-102, 1.1154449265558409e-98, 1.3320789562852151e-95, 1.2398999039839109e-92, 9.1613585633591115e-90, 5.4590825264344227e-87, 2.6598715295190543e-84, 1.0726407876436278e-81, 3.6188278671651930e-79, 1.0312393292677344e-76, 2.5035350436180196e-74, 5.2179989944251382e-72, 9.4025005576362417e-70, 1.4740979038429450e-67, 2.0223861173713801e-65, 2.4409225876304963e-63, 2.6043821060405426e-61, 2.4675003119821257e-59, 2.0845067543701599e-57, 1.5761631000101791e-55, 1.0705056723174281e-53, 6.5523461103489109e-52, 3.6254089691585309e-50, 1.8184989576075493e-48, 8.2913990414809887e-47, 3.4450097830357403e-45, 1.3074430076121838e-43, 4.5423930481987850e-42, 1.4477028628289723e-40, 4.2408968311262046e-39, 1.1439892419798912e-37, 2.8466218480726145e-36, 6.5448147609160573e-35, 1.3925226088255375e-33, 2.7459089931491756e-32, 5.0252446557042918e-31, 8.5465806757782117e-30, 1.3525065257212417e-28, 1.9939689031724527e-27, 2.7417253568038711e-26, 3.5198681528057952e-25, 4.2235075145104786e-24, 4.7412259196608422e-23, 4.9840723225381343e-22, 4.9106724438195655e-21, 4.5386744987288709e-20, 3.9382188462775671e-19, 3.2106160083645321e-18, 2.4610138689948007e-17, 1.7749316371092158e-16, 1.2052626919006545e-15, 7.7106596673007474e-15, 4.6502415038307999e-14, 2.6453661839732785e-13, 1.4202436007691954e-12, 7.2000553706787476e-12, 3.4484441377850428e-11, 1.5611080651132002e-10, 6.6828734274332115e-10, 2.7064654297770221e-09, 1.0373610614267088e-08, 3.7645745874679117e-08, 1.2939635385192320e-07, 4.2140690642224546e-07, 1.3007683229247929e-06, 3.8067496326313364e-06, 1.0565607635971951e-05, 2.7819080771995885e-05, 6.9504723426630250e-05, 1.6482276370905397e-04, 3.7106723611638040e-04, 7.9325913151483628e-04, 1.6106180017909323e-03, 3.1064654644112318e-03, 5.6926204501420372e-03, 9.9128527364234706e-03, 1.6405471669264392e-02, 2.5807108029946707e-02, 3.8592374515300572e-02, 5.4868153810335302e-02, 7.4171189043357108e-02, 9.5341025218153283e-02, 1.1654188378760408e-01, 1.3547657485442111e-01, 1.4977628436985038e-01, 1.5748155504372183e-01, 1.5748155504372183e-01, 1.4977628436985038e-01, 1.3547657485442111e-01, 1.1654188378760408e-01, 9.5341025218153283e-02, 7.4171189043357108e-02, 5.4868153810335302e-02, 3.8592374515300572e-02, 2.5807108029946707e-02, 1.6405471669264392e-02, 9.9128527364234706e-03, 5.6926204501420372e-03, 3.1064654644112318e-03, 1.6106180017909323e-03, 7.9325913151483628e-04, 3.7106723611638040e-04, 1.6482276370905397e-04, 6.9504723426630250e-05, 2.7819080771995885e-05, 1.0565607635971951e-05, 3.8067496326313364e-06, 1.3007683229247929e-06, 4.2140690642224546e-07, 1.2939635385192320e-07, 3.7645745874679117e-08, 1.0373610614267088e-08, 2.7064654297770221e-09, 6.6828734274332115e-10, 1.5611080651132002e-10, 3.4484441377850428e-11, 7.2000553706787476e-12, 1.4202436007691954e-12, 2.6453661839732785e-13, 4.6502415038307999e-14, 7.7106596673007474e-15, 1.2052626919006545e-15, 1.7749316371092158e-16, 2.4610138689948007e-17, 3.2106160083645321e-18, 3.9382188462775671e-19, 4.5386744987288709e-20, 4.9106724438195655e-21, 4.9840723225381343e-22, 4.7412259196608422e-23, 4.2235075145104786e-24, 3.5198681528057952e-25, 2.7417253568038711e-26, 1.9939689031724527e-27, 1.3525065257212417e-28, 8.5465806757782117e-30, 5.0252446557042918e-31, 2.7459089931491756e-32, 1.3925226088255375e-33, 6.5448147609160573e-35, 2.8466218480726145e-36, 1.1439892419798912e-37, 4.2408968311262046e-39, 1.4477028628289723e-40, 4.5423930481987850e-42, 1.3074430076121838e-43, 3.4450097830357403e-45, 8.2913990414809887e-47, 1.8184989576075493e-48, 3.6254089691585309e-50, 6.5523461103489109e-52, 1.0705056723174281e-53, 1.5761631000101791e-55, 2.0845067543701599e-57, 2.4675003119821257e-59, 2.6043821060405426e-61, 2.4409225876304963e-63, 2.0223861173713801e-65, 1.4740979038429450e-67, 9.4025005576362417e-70, 5.2179989944251382e-72, 2.5035350436180196e-74, 1.0312393292677344e-76, 3.6188278671651930e-79, 1.0726407876436278e-81, 2.6598715295190543e-84, 5.4590825264344227e-87, 9.1613585633591115e-90, 1.2398999039839109e-92, 1.3320789562852151e-95, 1.1154449265558409e-98, 7.1263773535131733e-102, 3.3872112245822123e-105, 1.1621599260631149e-108, 2.7746976743925027e-112, 4.4053240904063359e-116, 4.3913191972243959e-120, 2.5502660858886434e-124, 7.8013060714659609e-129, 1.0903164404085858e-133, 5.6218117631932678e-139, 7.5182851789608105e-145, 1.3295499920372636e-151, 5.5372309477634655e-160}, + {7.8451635230016858e-161, 1.9523607750140259e-152, 1.1375077401246616e-145, 8.7373530318096058e-140, 1.7373540565570015e-134, 1.2727518873570116e-129, 4.2555627733290781e-125, 7.4887926040201802e-121, 7.6728599246194710e-117, 4.9331494690374170e-113, 2.1081805704508371e-109, 6.2668746307989698e-106, 1.3443162713188522e-102, 2.1447717307711369e-99, 2.6100910182768806e-96, 2.4752041309788718e-93, 1.8629470575327606e-90, 1.1305871177614866e-87, 5.6095106427386894e-85, 2.3032570747054949e-82, 7.9109829843002634e-80, 2.2948435687570354e-77, 5.6707499982586783e-75, 1.2029596296647568e-72, 2.2060845936398770e-70, 3.5197550034683429e-68, 4.9140189431762165e-66, 6.0352629400444085e-64, 6.5524291595185267e-62, 6.3168313216462770e-60, 5.4297718879402538e-58, 4.1774383436193032e-56, 2.8868574992210366e-54, 1.7978766039740882e-52, 1.0121575932082767e-50, 5.1657784424151435e-49, 2.3965562741555340e-47, 1.0131990990489010e-45, 3.9127390924870208e-44, 1.3832722270346481e-42, 4.4862136218811265e-41, 1.3373657357984576e-39, 3.6713213079441595e-38, 9.2972768440223579e-37, 2.1755444131733555e-35, 4.7112703089400342e-34, 9.4560355326075165e-33, 1.7615330473782583e-31, 3.0497304146140982e-30, 4.9132641478669298e-29, 7.3745987634168783e-28, 1.0324336757120609e-26, 1.3496248520015288e-25, 1.6490733800656049e-24, 1.8852558386853772e-23, 2.0184180321625388e-22, 2.0255846228536046e-21, 1.9070317011573267e-20, 1.6857232563417842e-19, 1.4001409738252677e-18, 1.0935411714915941e-17, 8.0367861053116616e-17, 5.5616740488492008e-16, 3.6264613629986606e-15, 2.2293626576566599e-14, 1.2928616191624445e-13, 7.0768307534960783e-13, 3.6582348996540792e-12, 1.7867762742843070e-11, 8.2498114987726634e-11, 3.6024058170237729e-10, 1.4883529382284672e-09, 5.8205576663344680e-09, 2.1554622191079048e-08, 7.5613014701765766e-08, 2.5135518772343285e-07, 7.9206548159012504e-07, 2.3667653844440894e-06, 6.7081316695963449e-06, 1.8039486708167727e-05, 4.6040475362243668e-05, 1.1154709040626857e-04, 2.5661526702463013e-04, 5.6067195570805187e-04, 1.1636625437784563e-03, 2.2946716387392549e-03, 4.2999800431004790e-03, 7.6583588130546571e-03, 1.2965620087982580e-02, 2.0868833143304531e-02, 3.1937686193532246e-02, 4.6478966725271985e-02, 6.4327817062627538e-02, 8.4677189450608162e-02, 1.0602045179435517e-01, 1.2626797462143288e-01, 1.4305279328441931e-01, 1.5417456855130846e-01, 1.5807042792926745e-01, 1.5417456855130846e-01, 1.4305279328441931e-01, 1.2626797462143288e-01, 1.0602045179435517e-01, 8.4677189450608162e-02, 6.4327817062627538e-02, 4.6478966725271985e-02, 3.1937686193532246e-02, 2.0868833143304531e-02, 1.2965620087982580e-02, 7.6583588130546571e-03, 4.2999800431004790e-03, 2.2946716387392549e-03, 1.1636625437784563e-03, 5.6067195570805187e-04, 2.5661526702463013e-04, 1.1154709040626857e-04, 4.6040475362243668e-05, 1.8039486708167727e-05, 6.7081316695963449e-06, 2.3667653844440894e-06, 7.9206548159012504e-07, 2.5135518772343285e-07, 7.5613014701765766e-08, 2.1554622191079048e-08, 5.8205576663344680e-09, 1.4883529382284672e-09, 3.6024058170237729e-10, 8.2498114987726634e-11, 1.7867762742843070e-11, 3.6582348996540792e-12, 7.0768307534960783e-13, 1.2928616191624445e-13, 2.2293626576566599e-14, 3.6264613629986606e-15, 5.5616740488492008e-16, 8.0367861053116616e-17, 1.0935411714915941e-17, 1.4001409738252677e-18, 1.6857232563417842e-19, 1.9070317011573267e-20, 2.0255846228536046e-21, 2.0184180321625388e-22, 1.8852558386853772e-23, 1.6490733800656049e-24, 1.3496248520015288e-25, 1.0324336757120609e-26, 7.3745987634168783e-28, 4.9132641478669298e-29, 3.0497304146140982e-30, 1.7615330473782583e-31, 9.4560355326075165e-33, 4.7112703089400342e-34, 2.1755444131733555e-35, 9.2972768440223579e-37, 3.6713213079441595e-38, 1.3373657357984576e-39, 4.4862136218811265e-41, 1.3832722270346481e-42, 3.9127390924870208e-44, 1.0131990990489010e-45, 2.3965562741555340e-47, 5.1657784424151435e-49, 1.0121575932082767e-50, 1.7978766039740882e-52, 2.8868574992210366e-54, 4.1774383436193032e-56, 5.4297718879402538e-58, 6.3168313216462770e-60, 6.5524291595185267e-62, 6.0352629400444085e-64, 4.9140189431762165e-66, 3.5197550034683429e-68, 2.2060845936398770e-70, 1.2029596296647568e-72, 5.6707499982586783e-75, 2.2948435687570354e-77, 7.9109829843002634e-80, 2.3032570747054949e-82, 5.6095106427386894e-85, 1.1305871177614866e-87, 1.8629470575327606e-90, 2.4752041309788718e-93, 2.6100910182768806e-96, 2.1447717307711369e-99, 1.3443162713188522e-102, 6.2668746307989698e-106, 2.1081805704508371e-109, 4.9331494690374170e-113, 7.6728599246194710e-117, 7.4887926040201802e-121, 4.2555627733290781e-125, 1.2727518873570116e-129, 1.7373540565570015e-134, 8.7373530318096058e-140, 1.1375077401246616e-145, 1.9523607750140259e-152, 7.8451635230016858e-161}, + {1.1113325242665607e-161, 2.8661157405088651e-153, 1.7203699801925772e-146, 1.3572912678569801e-140, 2.7667745801693423e-135, 2.0750643806729351e-130, 7.0958232027421688e-126, 1.2760468594731325e-121, 1.3351777371855847e-117, 8.7619375020369923e-114, 3.8201658326880149e-110, 1.1581310985408031e-106, 2.5327817240407812e-103, 4.1185419255140006e-100, 5.1071272449783039e-97, 4.9339716820592914e-94, 3.7824070114676548e-91, 2.3376600104580566e-88, 1.1809947785806983e-85, 4.9369057800338342e-83, 1.7261669173831611e-80, 5.0968500275659627e-78, 1.2818807628470368e-75, 2.7674728413631406e-73, 5.1647694116231104e-71, 8.3851919880334988e-69, 1.1912098546399618e-66, 1.4886103795423663e-64, 1.6443955400649481e-62, 1.6129133242366921e-60, 1.4105633288272223e-58, 1.1041151603377387e-56, 7.7628198468094521e-55, 4.9186136364477312e-53, 2.8172193314312900e-51, 1.4628544044995270e-49, 6.9047962388108693e-48, 2.9700444136624115e-46, 1.1669783057995060e-44, 4.1977240232717920e-43, 1.3852328747381678e-41, 4.2018792516358609e-40, 1.1737667874934990e-38, 3.0248112870289189e-37, 7.2029787582674604e-36, 1.5874640120654814e-34, 3.2427846726141820e-33, 6.1484526840191010e-32, 1.0834946554226288e-30, 1.7768523467499803e-29, 2.7149541158618372e-28, 3.8695229489123667e-27, 5.1500223036312467e-26, 6.4071917092815282e-25, 7.4586793696524265e-24, 8.1320524064342075e-23, 8.3113512372523795e-22, 7.9697999021291434e-21, 7.1759828546746257e-20, 6.0717113565204395e-19, 4.8312403419891758e-18, 3.6176893189785955e-17, 2.5510691957075621e-16, 1.6951627656128116e-15, 1.0621010070430722e-14, 6.2782746989491113e-14, 3.5033054765081019e-13, 1.8463363234967078e-12, 9.1951726021293097e-12, 4.3294831001094053e-11, 1.9281472420443613e-10, 8.1257537810009703e-10, 3.2418174605425769e-09, 1.2248647054749650e-08, 4.3845698417608257e-08, 1.4875155394404803e-07, 4.7845376510326057e-07, 1.4594959469005024e-06, 4.2236041008124797e-06, 1.1598624726140732e-05, 3.0233694291010849e-05, 7.4825364488004140e-05, 1.7586687773524874e-04, 3.9264033171199677e-04, 8.3286186061158249e-04, 1.6788174607182051e-03, 3.2163656781061659e-03, 5.8577616753894349e-03, 1.0143065156003795e-02, 1.6700865101051256e-02, 2.6151472056325592e-02, 3.8948449958622955e-02, 5.5177861430971059e-02, 7.4363251819021731e-02, 9.5346186707308309e-02, 1.1631262299580138e-01, 1.3500522787142605e-01, 1.4910449946872065e-01, 1.5669608061804552e-01, 1.5669608061804552e-01, 1.4910449946872065e-01, 1.3500522787142605e-01, 1.1631262299580138e-01, 9.5346186707308309e-02, 7.4363251819021731e-02, 5.5177861430971059e-02, 3.8948449958622955e-02, 2.6151472056325592e-02, 1.6700865101051256e-02, 1.0143065156003795e-02, 5.8577616753894349e-03, 3.2163656781061659e-03, 1.6788174607182051e-03, 8.3286186061158249e-04, 3.9264033171199677e-04, 1.7586687773524874e-04, 7.4825364488004140e-05, 3.0233694291010849e-05, 1.1598624726140732e-05, 4.2236041008124797e-06, 1.4594959469005024e-06, 4.7845376510326057e-07, 1.4875155394404803e-07, 4.3845698417608257e-08, 1.2248647054749650e-08, 3.2418174605425769e-09, 8.1257537810009703e-10, 1.9281472420443613e-10, 4.3294831001094053e-11, 9.1951726021293097e-12, 1.8463363234967078e-12, 3.5033054765081019e-13, 6.2782746989491113e-14, 1.0621010070430722e-14, 1.6951627656128116e-15, 2.5510691957075621e-16, 3.6176893189785955e-17, 4.8312403419891758e-18, 6.0717113565204395e-19, 7.1759828546746257e-20, 7.9697999021291434e-21, 8.3113512372523795e-22, 8.1320524064342075e-23, 7.4586793696524265e-24, 6.4071917092815282e-25, 5.1500223036312467e-26, 3.8695229489123667e-27, 2.7149541158618372e-28, 1.7768523467499803e-29, 1.0834946554226288e-30, 6.1484526840191010e-32, 3.2427846726141820e-33, 1.5874640120654814e-34, 7.2029787582674604e-36, 3.0248112870289189e-37, 1.1737667874934990e-38, 4.2018792516358609e-40, 1.3852328747381678e-41, 4.1977240232717920e-43, 1.1669783057995060e-44, 2.9700444136624115e-46, 6.9047962388108693e-48, 1.4628544044995270e-49, 2.8172193314312900e-51, 4.9186136364477312e-53, 7.7628198468094521e-55, 1.1041151603377387e-56, 1.4105633288272223e-58, 1.6129133242366921e-60, 1.6443955400649481e-62, 1.4886103795423663e-64, 1.1912098546399618e-66, 8.3851919880334988e-69, 5.1647694116231104e-71, 2.7674728413631406e-73, 1.2818807628470368e-75, 5.0968500275659627e-78, 1.7261669173831611e-80, 4.9369057800338342e-83, 1.1809947785806983e-85, 2.3376600104580566e-88, 3.7824070114676548e-91, 4.9339716820592914e-94, 5.1071272449783039e-97, 4.1185419255140006e-100, 2.5327817240407812e-103, 1.1581310985408031e-106, 3.8201658326880149e-110, 8.7619375020369923e-114, 1.3351777371855847e-117, 1.2760468594731325e-121, 7.0958232027421688e-126, 2.0750643806729351e-130, 2.7667745801693423e-135, 1.3572912678569801e-140, 1.7203699801925772e-146, 2.8661157405088651e-153, 1.1113325242665607e-161}, + {1.5740526693584465e-162, 4.2063621518212007e-154, 2.6008944296538456e-147, 2.1074517218240589e-141, 4.4036325515199439e-136, 3.3809077673415763e-131, 1.1822946408488032e-126, 2.1725144459735252e-122, 2.3212763347728001e-118, 1.5547020684816359e-114, 6.9150182989560957e-111, 2.1377995126059837e-107, 4.7660941708469085e-104, 7.8984266909061953e-101, 9.9792660546750878e-98, 9.8208576850538984e-95, 7.6677750665974574e-92, 4.8256764019125120e-89, 2.4821990706514334e-86, 1.0563282231662235e-83, 3.7595217722773437e-81, 1.1298318188883590e-78, 2.8919012660409682e-76, 6.3534513888384988e-74, 1.2065320173749644e-71, 1.9931390693715852e-69, 2.8809012333842463e-67, 3.6628479225209667e-65, 4.1164923961054212e-63, 4.1077464167348542e-61, 3.6546677508675100e-59, 2.9102221244239064e-57, 2.0815358697976881e-55, 1.3417085980893448e-53, 7.8178603818978630e-52, 4.1297412217775072e-50, 1.9830414431093633e-48, 8.6778002491153641e-47, 3.4688352621558211e-45, 1.2694602644562695e-43, 4.2621053825441441e-42, 1.3153901362816908e-40, 3.7386729623017851e-39, 9.8033645273483504e-38, 2.3754629195463299e-36, 5.3274424573468086e-35, 1.1074717912785746e-33, 2.1369895498120545e-32, 3.8327370697542584e-31, 6.3974120073582433e-30, 9.9497591435745215e-29, 1.4435514631174776e-27, 1.9558597204465646e-26, 2.4773098248022596e-25, 2.9362302035583120e-24, 3.2596930342072210e-23, 3.3925841234631972e-22, 3.3130211274194918e-21, 3.0381735933104597e-20, 2.6183914995557019e-19, 2.1223329298239927e-18, 1.6190413502935239e-17, 1.1632214089861438e-16, 7.8760411702639125e-16, 5.0287848550079939e-15, 3.0295892003599562e-14, 1.7231158339195911e-13, 9.2573881503227024e-13, 4.7003287276740161e-12, 2.2565549953554105e-11, 1.0248110528690129e-10, 4.4046822285487214e-10, 1.7924282778278772e-09, 6.9087593674811365e-09, 2.5232222625609405e-08, 8.7350604983433712e-08, 2.8673524946820525e-07, 8.9277708976484127e-07, 2.6374622880097546e-06, 7.3949955626738131e-06, 1.9684213310007427e-05, 4.9755352753869857e-05, 1.1945642608697544e-04, 2.7247518029396975e-04, 5.9058909090482672e-04, 1.2166676013683477e-03, 2.3826889355841037e-03, 4.4365604655715969e-03, 7.8555741198391739e-03, 1.3228935168893997e-02, 2.1190659578816773e-02, 3.2291498859030154e-02, 4.6816827098479806e-02, 6.4584179655610197e-02, 8.4780422567999614e-02, 1.0591066198925958e-01, 1.2591645229378781e-01, 1.4247629387217531e-01, 1.5343815707202285e-01, 1.5727610417082902e-01, 1.5343815707202285e-01, 1.4247629387217531e-01, 1.2591645229378781e-01, 1.0591066198925958e-01, 8.4780422567999614e-02, 6.4584179655610197e-02, 4.6816827098479806e-02, 3.2291498859030154e-02, 2.1190659578816773e-02, 1.3228935168893997e-02, 7.8555741198391739e-03, 4.4365604655715969e-03, 2.3826889355841037e-03, 1.2166676013683477e-03, 5.9058909090482672e-04, 2.7247518029396975e-04, 1.1945642608697544e-04, 4.9755352753869857e-05, 1.9684213310007427e-05, 7.3949955626738131e-06, 2.6374622880097546e-06, 8.9277708976484127e-07, 2.8673524946820525e-07, 8.7350604983433712e-08, 2.5232222625609405e-08, 6.9087593674811365e-09, 1.7924282778278772e-09, 4.4046822285487214e-10, 1.0248110528690129e-10, 2.2565549953554105e-11, 4.7003287276740161e-12, 9.2573881503227024e-13, 1.7231158339195911e-13, 3.0295892003599562e-14, 5.0287848550079939e-15, 7.8760411702639125e-16, 1.1632214089861438e-16, 1.6190413502935239e-17, 2.1223329298239927e-18, 2.6183914995557019e-19, 3.0381735933104597e-20, 3.3130211274194918e-21, 3.3925841234631972e-22, 3.2596930342072210e-23, 2.9362302035583120e-24, 2.4773098248022596e-25, 1.9558597204465646e-26, 1.4435514631174776e-27, 9.9497591435745215e-29, 6.3974120073582433e-30, 3.8327370697542584e-31, 2.1369895498120545e-32, 1.1074717912785746e-33, 5.3274424573468086e-35, 2.3754629195463299e-36, 9.8033645273483504e-38, 3.7386729623017851e-39, 1.3153901362816908e-40, 4.2621053825441441e-42, 1.2694602644562695e-43, 3.4688352621558211e-45, 8.6778002491153641e-47, 1.9830414431093633e-48, 4.1297412217775072e-50, 7.8178603818978630e-52, 1.3417085980893448e-53, 2.0815358697976881e-55, 2.9102221244239064e-57, 3.6546677508675100e-59, 4.1077464167348542e-61, 4.1164923961054212e-63, 3.6628479225209667e-65, 2.8809012333842463e-67, 1.9931390693715852e-69, 1.2065320173749644e-71, 6.3534513888384988e-74, 2.8919012660409682e-76, 1.1298318188883590e-78, 3.7595217722773437e-81, 1.0563282231662235e-83, 2.4821990706514334e-86, 4.8256764019125120e-89, 7.6677750665974574e-92, 9.8208576850538984e-95, 9.9792660546750878e-98, 7.8984266909061953e-101, 4.7660941708469085e-104, 2.1377995126059837e-107, 6.9150182989560957e-111, 1.5547020684816359e-114, 2.3212763347728001e-118, 2.1725144459735252e-122, 1.1822946408488032e-126, 3.3809077673415763e-131, 4.4036325515199439e-136, 2.1074517218240589e-141, 2.6008944296538456e-147, 4.2063621518212007e-154, 1.5740526693584465e-162}, + {2.2290934963031539e-163, 6.1716304223418473e-155, 3.9305958509063355e-148, 3.2706601334834755e-142, 7.0049069648137550e-137, 5.5049260050287900e-132, 1.9684692530020812e-127, 3.6957545112422320e-123, 4.0320327117616306e-119, 2.7559362749699724e-115, 1.2503894738744883e-111, 3.9416969862084461e-108, 8.9577890237321700e-105, 1.5127860735379895e-101, 1.9472732376896783e-98, 1.9519789398323314e-95, 1.5520652579926001e-92, 9.9458309202670908e-90, 5.2083206235820379e-87, 2.2562215375682347e-84, 8.1731118972592471e-82, 2.4997514837476365e-79, 6.5111285362111366e-77, 1.4555888776738779e-74, 2.8125155025369667e-72, 4.7271089337772468e-70, 6.9513137370020262e-68, 8.9912466505154563e-66, 1.0279594830695334e-63, 1.0434894316959833e-61, 9.4440639857201346e-60, 7.6499247670821092e-58, 5.5658406725957325e-56, 3.6493796373809251e-54, 2.1630323514364711e-52, 1.1622901525905010e-50, 5.6773339224732908e-49, 2.5272570465088243e-47, 1.0276815273410889e-45, 3.8259457909463708e-44, 1.3067728287128299e-42, 4.1029828415971428e-41, 1.1864415902523173e-39, 3.1652198121078916e-38, 7.8035886293155777e-37, 1.7807430428966829e-35, 3.7667945725159055e-34, 7.3963969744653024e-33, 1.3499836949356773e-31, 2.2932424003565328e-30, 3.6300293183361797e-29, 5.3605436078106824e-28, 7.3930155412655720e-27, 9.5323773039462743e-26, 1.1502145928125925e-24, 1.3000662757028629e-23, 1.3776941782313042e-22, 1.3699807056265559e-21, 1.2794012136597428e-20, 1.1229742763811151e-19, 9.2710336687274256e-19, 7.2042972150393114e-18, 5.2729781171856177e-17, 3.6375048889083554e-16, 2.3664867578847666e-15, 1.4528301518132017e-14, 8.4213476872404286e-14, 4.6114644502136799e-13, 2.3867692880717110e-12, 1.1681801468249808e-11, 5.4092941845487156e-11, 2.3708105480750139e-10, 9.8392832670094020e-10, 3.8682673753498617e-09, 1.4411972185221586e-08, 5.0903013962041357e-08, 1.7050141340191249e-07, 5.4177677321026202e-07, 1.6336412605871983e-06, 4.6759044289293238e-06, 1.2707753951032874e-05, 3.2800534876023489e-05, 8.0428506528979537e-05, 1.8739476963256670e-04, 4.1497155710923123e-04, 8.7353709789879039e-04, 1.7483531042542699e-03, 3.3276551358222884e-03, 6.0239245919995622e-03, 1.0373317514267365e-02, 1.6994637482018023e-02, 2.6492061401939205e-02, 3.9298609227795579e-02, 5.5480282208033298e-02, 7.4548212057078664e-02, 9.5346453940664169e-02, 1.1608254348974273e-01, 1.3453811804025481e-01, 1.4844158241213595e-01, 1.5592224232989221e-01, 1.5592224232989221e-01, 1.4844158241213595e-01, 1.3453811804025481e-01, 1.1608254348974273e-01, 9.5346453940664169e-02, 7.4548212057078664e-02, 5.5480282208033298e-02, 3.9298609227795579e-02, 2.6492061401939205e-02, 1.6994637482018023e-02, 1.0373317514267365e-02, 6.0239245919995622e-03, 3.3276551358222884e-03, 1.7483531042542699e-03, 8.7353709789879039e-04, 4.1497155710923123e-04, 1.8739476963256670e-04, 8.0428506528979537e-05, 3.2800534876023489e-05, 1.2707753951032874e-05, 4.6759044289293238e-06, 1.6336412605871983e-06, 5.4177677321026202e-07, 1.7050141340191249e-07, 5.0903013962041357e-08, 1.4411972185221586e-08, 3.8682673753498617e-09, 9.8392832670094020e-10, 2.3708105480750139e-10, 5.4092941845487156e-11, 1.1681801468249808e-11, 2.3867692880717110e-12, 4.6114644502136799e-13, 8.4213476872404286e-14, 1.4528301518132017e-14, 2.3664867578847666e-15, 3.6375048889083554e-16, 5.2729781171856177e-17, 7.2042972150393114e-18, 9.2710336687274256e-19, 1.1229742763811151e-19, 1.2794012136597428e-20, 1.3699807056265559e-21, 1.3776941782313042e-22, 1.3000662757028629e-23, 1.1502145928125925e-24, 9.5323773039462743e-26, 7.3930155412655720e-27, 5.3605436078106824e-28, 3.6300293183361797e-29, 2.2932424003565328e-30, 1.3499836949356773e-31, 7.3963969744653024e-33, 3.7667945725159055e-34, 1.7807430428966829e-35, 7.8035886293155777e-37, 3.1652198121078916e-38, 1.1864415902523173e-39, 4.1029828415971428e-41, 1.3067728287128299e-42, 3.8259457909463708e-44, 1.0276815273410889e-45, 2.5272570465088243e-47, 5.6773339224732908e-49, 1.1622901525905010e-50, 2.1630323514364711e-52, 3.6493796373809251e-54, 5.5658406725957325e-56, 7.6499247670821092e-58, 9.4440639857201346e-60, 1.0434894316959833e-61, 1.0279594830695334e-63, 8.9912466505154563e-66, 6.9513137370020262e-68, 4.7271089337772468e-70, 2.8125155025369667e-72, 1.4555888776738779e-74, 6.5111285362111366e-77, 2.4997514837476365e-79, 8.1731118972592471e-82, 2.2562215375682347e-84, 5.2083206235820379e-87, 9.9458309202670908e-90, 1.5520652579926001e-92, 1.9519789398323314e-95, 1.9472732376896783e-98, 1.5127860735379895e-101, 8.9577890237321700e-105, 3.9416969862084461e-108, 1.2503894738744883e-111, 2.7559362749699724e-115, 4.0320327117616306e-119, 3.6957545112422320e-123, 1.9684692530020812e-127, 5.5049260050287900e-132, 7.0049069648137550e-137, 3.2706601334834755e-142, 3.9305958509063355e-148, 6.1716304223418473e-155, 2.2290934963031539e-163}, +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/hermite_test.go b/vendor/gonum.org/v1/gonum/integrate/quad/hermite_test.go new file mode 100644 index 00000000..d74b82dc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/hermite_test.go @@ -0,0 +1,251 @@ +// Copyright ©2016 The gonum 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 quad + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestHermite(t *testing.T) { + for cas, test := range []struct { + n int + f func(float64) float64 + ev float64 + tol float64 + }{ + { + n: 2, + f: func(x float64) float64 { return 1 }, + ev: math.SqrtPi, + tol: 1e-14, + }, + { + n: 4, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-4, + }, + { + n: 9, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-12, + }, + { + n: 10, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-12, + }, + { + n: 15, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-4, + }, + { + n: 22, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-12, + }, + { + n: 21, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-12, + }, + } { + ev := Fixed(test.f, math.Inf(-1), math.Inf(1), test.n, Hermite{}, 0) + if !floats.EqualWithinAbsOrRel(test.ev, ev, test.tol, test.tol) { + t.Errorf("Case %d: expected value mismatch.\nWant %v\ngot %v", cas, test.ev, ev) + } + } +} + +func TestHermiteLocations(t *testing.T) { + // Test the hermite locations and weights against other precomputed table. + // Data from http://dlmf.nist.gov/3.5. + for _, test := range []struct { + n int + x []float64 + w []float64 + }{ + // Evaluated from Chebfun. + { + n: 5, + x: []float64{-0.202018287045609e1, -0.958572464613819, 0, 0.958572464613819, 0.202018287045609e1}, + w: []float64{0.199532420590459e-1, 0.393619323152241, 0.945308720482942, 0.393619323152241, 0.199532420590459e-1}, + }, + { + n: 10, + x: []float64{-0.343615911883773760e1, -0.253273167423278980e1, -0.175668364929988177e1, -0.103661082978951365e1, -0.342901327223704609, 0.342901327223704609, 0.103661082978951365e1, 0.175668364929988177e1, 0.253273167423278980e1, 0.343615911883773760e1}, + w: []float64{0.764043285523262063e-5, 0.134364574678123269e-2, 0.338743944554810631e-1, 0.240138611082314686, 0.610862633735325799, 0.610862633735325799, 0.240138611082314686, 0.338743944554810631e-1, 0.134364574678123269e-2, 0.764043285523262063e-5}, + }, + { + n: 215, + x: []float64{-2.0083110126223993e+01, -1.9573161931385755e+01, -1.9153731166695263e+01, -1.8781558404513735e+01, -1.8440108632764016e+01, -1.8120857960601569e+01, -1.7818692349773503e+01, -1.7530242081974308e+01, -1.7253139752773148e+01, -1.6985642449377284e+01, -1.6726420346886542e+01, -1.6474429782282726e+01, -1.6228832750513551e+01, -1.5988943547145137e+01, -1.5754192102761674e+01, -1.5524098014731747e+01, -1.5298251677453143e+01, -1.5076300264808333e+01, -1.4857937115425768e+01, -1.4642893558208563e+01, -1.4430932522616979e+01, -1.4221843477251845e+01, -1.4015438372554696e+01, -1.3811548353270942e+01, -1.3610021068540190e+01, -1.3410718451340038e+01, -1.3213514870431910e+01, -1.3018295580800100e+01, -1.2824955415404188e+01, -1.2633397673617059e+01, -1.2443533171189967e+01, -1.2255279423804318e+01, -1.2068559941826503e+01, -1.1883303618198463e+01, -1.1699444194777641e+01, -1.1516919795109878e+01, -1.1335672513742256e+01, -1.1155648053883823e+01, -1.0976795406593546e+01, -1.0799066565787168e+01, -1.0622416274262394e+01, -1.0446801796686490e+01, -1.0272182716104577e+01, -1.0098520751035824e+01, -9.9257795906487338e+00, -9.7539247458611111e+00, -9.5829234145081710e+00, -9.4127443589734394e+00, -9.2433577948895387e+00, -9.0747352896969389e+00, -8.9068496700026394e+00, -8.7396749368126798e+00, -8.5731861878255415e+00, -8.4073595460710955e+00, -8.2421720942637187e+00, -8.0776018143113824e+00, -7.9136275314855800e+00, -7.7502288628124383e+00, -7.5873861692931381e+00, -7.4250805116042331e+00, -7.2632936089653120e+00, -7.1020078008938672e+00, -6.9412060115960434e+00, -6.7808717167671544e+00, -6.6209889125982082e+00, -6.4615420868046280e+00, -6.3025161915109100e+00, -6.1438966178406549e+00, -5.9856691720754620e+00, -5.8278200532585673e+00, -5.6703358321303936e+00, -5.5132034312931157e+00, -5.3564101065103049e+00, -5.1999434290559226e+00, -5.0437912690340267e+00, -4.8879417795972326e+00, -4.7323833819978187e+00, -4.5771047514106780e+00, -4.4220948034722349e+00, -4.2673426814837114e+00, -4.1128377442311503e+00, -3.9585695543782120e+00, -3.8045278673909002e+00, -3.6507026209565665e+00, -3.4970839248619634e+00, -3.3436620512978501e+00, -3.1904274255596032e+00, -3.0373706171156218e+00, -2.8844823310168755e+00, -2.7317533996228827e+00, -2.5791747746208049e+00, -2.4267375193157439e+00, -2.2744328011717010e+00, -2.1222518845837395e+00, -1.9701861238629792e+00, -1.8182269564169717e+00, -1.6663658961089640e+00, -1.5145945267802365e+00, -1.3629044959205205e+00, -1.2112875084719879e+00, -1.0597353207530273e+00, -9.0823973448851325e-01, -7.5679259093351370e-01, -6.0538576507805808e-01, -4.5401115992078167e-01, -3.0266070079942864e-01, -1.5132632976672361e-01, 7.9483151672010196e-15, 1.5132632976672361e-01, 3.0266070079942864e-01, 4.5401115992078167e-01, 6.0538576507805808e-01, 7.5679259093351370e-01, 9.0823973448851325e-01, 1.0597353207530273e+00, 1.2112875084719879e+00, 1.3629044959205205e+00, 1.5145945267802365e+00, 1.6663658961089640e+00, 1.8182269564169717e+00, 1.9701861238629792e+00, 2.1222518845837395e+00, 2.2744328011717010e+00, 2.4267375193157439e+00, 2.5791747746208049e+00, 2.7317533996228827e+00, 2.8844823310168755e+00, 3.0373706171156218e+00, 3.1904274255596032e+00, 3.3436620512978501e+00, 3.4970839248619634e+00, 3.6507026209565665e+00, 3.8045278673909002e+00, 3.9585695543782120e+00, 4.1128377442311503e+00, 4.2673426814837114e+00, 4.4220948034722349e+00, 4.5771047514106780e+00, 4.7323833819978187e+00, 4.8879417795972326e+00, 5.0437912690340267e+00, 5.1999434290559226e+00, 5.3564101065103049e+00, 5.5132034312931157e+00, 5.6703358321303936e+00, 5.8278200532585673e+00, 5.9856691720754620e+00, 6.1438966178406549e+00, 6.3025161915109100e+00, 6.4615420868046280e+00, 6.6209889125982082e+00, 6.7808717167671544e+00, 6.9412060115960434e+00, 7.1020078008938672e+00, 7.2632936089653120e+00, 7.4250805116042331e+00, 7.5873861692931381e+00, 7.7502288628124383e+00, 7.9136275314855800e+00, 8.0776018143113824e+00, 8.2421720942637187e+00, 8.4073595460710955e+00, 8.5731861878255415e+00, 8.7396749368126798e+00, 8.9068496700026394e+00, 9.0747352896969389e+00, 9.2433577948895387e+00, 9.4127443589734394e+00, 9.5829234145081710e+00, 9.7539247458611111e+00, 9.9257795906487338e+00, 1.0098520751035824e+01, 1.0272182716104577e+01, 1.0446801796686490e+01, 1.0622416274262394e+01, 1.0799066565787168e+01, 1.0976795406593546e+01, 1.1155648053883823e+01, 1.1335672513742256e+01, 1.1516919795109878e+01, 1.1699444194777641e+01, 1.1883303618198463e+01, 1.2068559941826503e+01, 1.2255279423804318e+01, 1.2443533171189967e+01, 1.2633397673617059e+01, 1.2824955415404188e+01, 1.3018295580800100e+01, 1.3213514870431910e+01, 1.3410718451340038e+01, 1.3610021068540190e+01, 1.3811548353270942e+01, 1.4015438372554696e+01, 1.4221843477251845e+01, 1.4430932522616979e+01, 1.4642893558208563e+01, 1.4857937115425768e+01, 1.5076300264808333e+01, 1.5298251677453143e+01, 1.5524098014731747e+01, 1.5754192102761674e+01, 1.5988943547145137e+01, 1.6228832750513551e+01, 1.6474429782282726e+01, 1.6726420346886542e+01, 1.6985642449377284e+01, 1.7253139752773148e+01, 1.7530242081974308e+01, 1.7818692349773503e+01, 1.8120857960601569e+01, 1.8440108632764016e+01, 1.8781558404513735e+01, 1.9153731166695263e+01, 1.9573161931385755e+01, 2.0083110126223993e+01}, + w: []float64{4.0474005560499094e-176, 1.8797130400856443e-167, 1.8432377040276421e-160, 2.2601442864626069e-154, 6.9363023753259492e-149, 7.6575370428605554e-144, 3.7894855074137878e-139, 9.7310398950542353e-135, 1.4382941114934084e-130, 1.3214094652141891e-126, 8.0053233705919762e-123, 3.3506484324551954e-119, 1.0061133084529732e-115, 2.2355880918528976e-112, 3.7723274691873339e-109, 4.9410774014014167e-106, 5.1189805080467357e-103, 4.2633269887655389e-100, 2.8951564896303124e-97, 1.6231768954981774e-94, 7.5966487579367170e-92, 2.9971587600601123e-89, 1.0056653752640396e-86, 2.8926565116618279e-84, 7.1838069610206879e-82, 1.5504440487214177e-79, 2.9253709118548054e-77, 4.8516529695481360e-75, 7.1080340648382430e-73, 9.2417798747589595e-71, 1.0709039437896534e-68, 1.1102986726619406e-66, 1.0337280935884043e-64, 8.6720569345151135e-63, 6.5759615285599325e-61, 4.5206307708839604e-59, 2.8251413443094276e-57, 1.6091856250751163e-55, 8.3743579179261028e-54, 3.9908716881614503e-52, 1.7453732998154445e-50, 7.0192904730947679e-49, 2.6008368230936308e-47, 8.8947358191690260e-46, 2.8125213532676820e-44, 8.2357837374304705e-43, 2.2368010157343200e-41, 5.6428177886700861e-40, 1.3240736407971940e-38, 2.8936578029605094e-37, 5.8971855560501346e-36, 1.1220768467833071e-34, 1.9956009474900652e-33, 3.3209946083724174e-32, 5.1767166839129889e-31, 7.5658951790722304e-30, 1.0377543674300410e-28, 1.3370496163293642e-27, 1.6195422525877890e-26, 1.8458039741402227e-25, 1.9809275961773415e-24, 2.0034006172471768e-23, 1.9107136033126365e-22, 1.7196934641222891e-21, 1.4615728740382834e-20, 1.1737567188678477e-19, 8.9122322093114715e-19, 6.4017277272147784e-18, 4.3526236743179514e-17, 2.8027154496363443e-16, 1.7100226833829111e-15, 9.8907988394494626e-15, 5.4258798698008971e-14, 2.8243097014577004e-13, 1.3955439320917938e-12, 6.5484943121277863e-12, 2.9192823809511808e-11, 1.2368298646403665e-10, 4.9819378483709125e-10, 1.9084879833147422e-09, 6.9554442384546823e-09, 2.4123461087320678e-08, 7.9645691304111948e-08, 2.5038904484412268e-07, 7.4974774628062337e-07, 2.1388110362272039e-06, 5.8142267442915587e-06, 1.5065139508846480e-05, 3.7214305501073257e-05, 8.7657861198914500e-05, 1.9692436368292282e-04, 4.2200152760283493e-04, 8.6279569789330843e-04, 1.6832545363270029e-03, 3.1340302956109622e-03, 5.5696401904272858e-03, 9.4487851093380676e-03, 1.5303805411902717e-02, 2.3666975130344652e-02, 3.4949960453868167e-02, 4.9288724246681882e-02, 6.6386134961517171e-02, 8.5401153510804823e-02, 1.0493731687783339e-01, 1.2316720474285285e-01, 1.3809371553328023e-01, 1.4790300421921079e-01, 1.5132498974070285e-01, 1.4790300421921079e-01, 1.3809371553328023e-01, 1.2316720474285285e-01, 1.0493731687783339e-01, 8.5401153510804823e-02, 6.6386134961517171e-02, 4.9288724246681882e-02, 3.4949960453868167e-02, 2.3666975130344652e-02, 1.5303805411902717e-02, 9.4487851093380676e-03, 5.5696401904272858e-03, 3.1340302956109622e-03, 1.6832545363270029e-03, 8.6279569789330843e-04, 4.2200152760283493e-04, 1.9692436368292282e-04, 8.7657861198914500e-05, 3.7214305501073257e-05, 1.5065139508846480e-05, 5.8142267442915587e-06, 2.1388110362272039e-06, 7.4974774628062337e-07, 2.5038904484412268e-07, 7.9645691304111948e-08, 2.4123461087320678e-08, 6.9554442384546823e-09, 1.9084879833147422e-09, 4.9819378483709125e-10, 1.2368298646403665e-10, 2.9192823809511808e-11, 6.5484943121277863e-12, 1.3955439320917938e-12, 2.8243097014577004e-13, 5.4258798698008971e-14, 9.8907988394494626e-15, 1.7100226833829111e-15, 2.8027154496363443e-16, 4.3526236743179514e-17, 6.4017277272147784e-18, 8.9122322093114715e-19, 1.1737567188678477e-19, 1.4615728740382834e-20, 1.7196934641222891e-21, 1.9107136033126365e-22, 2.0034006172471768e-23, 1.9809275961773415e-24, 1.8458039741402227e-25, 1.6195422525877890e-26, 1.3370496163293642e-27, 1.0377543674300410e-28, 7.5658951790722304e-30, 5.1767166839129889e-31, 3.3209946083724174e-32, 1.9956009474900652e-33, 1.1220768467833071e-34, 5.8971855560501346e-36, 2.8936578029605094e-37, 1.3240736407971940e-38, 5.6428177886700861e-40, 2.2368010157343200e-41, 8.2357837374304705e-43, 2.8125213532676820e-44, 8.8947358191690260e-46, 2.6008368230936308e-47, 7.0192904730947679e-49, 1.7453732998154445e-50, 3.9908716881614503e-52, 8.3743579179261028e-54, 1.6091856250751163e-55, 2.8251413443094276e-57, 4.5206307708839604e-59, 6.5759615285599325e-61, 8.6720569345151135e-63, 1.0337280935884043e-64, 1.1102986726619406e-66, 1.0709039437896534e-68, 9.2417798747589595e-71, 7.1080340648382430e-73, 4.8516529695481360e-75, 2.9253709118548054e-77, 1.5504440487214177e-79, 7.1838069610206879e-82, 2.8926565116618279e-84, 1.0056653752640396e-86, 2.9971587600601123e-89, 7.5966487579367170e-92, 1.6231768954981774e-94, 2.8951564896303124e-97, 4.2633269887655389e-100, 5.1189805080467357e-103, 4.9410774014014167e-106, 3.7723274691873339e-109, 2.2355880918528976e-112, 1.0061133084529732e-115, 3.3506484324551954e-119, 8.0053233705919762e-123, 1.3214094652141891e-126, 1.4382941114934084e-130, 9.7310398950542353e-135, 3.7894855074137878e-139, 7.6575370428605554e-144, 6.9363023753259492e-149, 2.2601442864626069e-154, 1.8432377040276421e-160, 1.8797130400856443e-167, 4.0474005560499094e-176}, + }, + { + n: 216, + x: []float64{-2.0131752068397390e+01, -1.9622211733828486e+01, -1.9203122650098184e+01, -1.8831257901839155e+01, -1.8490094811217439e+01, -1.8171115805943941e+01, -1.7869210618319627e+01, -1.7581012003064874e+01, -1.7304154286393636e+01, -1.7036895825521608e+01, -1.6777907762072694e+01, -1.6526147190139376e+01, -1.6280776711860355e+01, -1.6041111119395726e+01, -1.5806580756275796e+01, -1.5576705568204593e+01, -1.5351076247103551e+01, -1.5129340223792830e+01, -1.4911191060978103e+01, -1.4696360284715409e+01, -1.4484610999323769e+01, -1.4275732829628778e+01, -1.4069537866591046e+01, -1.3865857382137794e+01, -1.3664539141187824e+01, -1.3465445182689793e+01, -1.3268449972893279e+01, -1.3073438856897617e+01, -1.2880306751340244e+01, -1.2688957033629340e+01, -1.2499300592587632e+01, -1.2311255012587219e+01, -1.2124743868808109e+01, -1.1939696115566026e+01, -1.1756045553033841e+01, -1.1573730360348824e+01, -1.1392692685219812e+01, -1.1212878281848150e+01, -1.1034236190346626e+01, -1.0856718451952171e+01, -1.0680279855235202e+01, -1.0504877709252620e+01, -1.0330471640205081e+01, -1.0157023408668081e+01, -9.9844967448895385e+00, -9.8128572000013108e+00, -9.6420720112891818e+00, -9.4721099799172528e+00, -9.3029413597147883e+00, -9.1345377558145096e+00, -8.9668720320849413e+00, -8.7999182264315081e+00, -8.6336514731539875e+00, -8.4680479316454296e+00, -8.3030847208017082e+00, -8.1387398585838486e+00, -7.9749922062384426e+00, -7.8118214167366684e+00, -7.6492078870405447e+00, -7.4871327138470951e+00, -7.3255776524981444e+00, -7.1645250787759087e+00, -7.0039579533331269e+00, -6.8438597885318986e+00, -6.6842146174875827e+00, -6.5250069651340752e+00, -6.3662218211444577e+00, -6.2078446145563948e+00, -6.0498611899661094e+00, -5.8922577851667635e+00, -5.7350210101185848e+00, -5.5781378271479722e+00, -5.4215955322816969e+00, -5.2653817376305465e+00, -5.1094843547439881e+00, -4.9538915788638089e+00, -4.7985918740108131e+00, -4.6435739588438905e+00, -4.4888267932355790e+00, -4.3343395655126109e+00, -4.1801016803139959e+00, -4.0261027470226392e+00, -3.8723325687298416e+00, -3.7187811316950210e+00, -3.5654385952656149e+00, -3.4122952822245907e+00, -3.2593416695353823e+00, -3.1065683794558021e+00, -2.9539661709946619e+00, -2.8015259316863266e+00, -2.6492386696600243e+00, -2.4970955059821409e+00, -2.3450876672510903e+00, -2.1932064784252856e+00, -2.0414433558661624e+00, -1.8897898005787916e+00, -1.7382373916337388e+00, -1.5867777797546210e+00, -1.4354026810562848e+00, -1.2841038709195900e+00, -1.1328731779888348e+00, -9.8170247827895785e-01, -8.3058368937955573e-01, -6.7950876474356448e-01, -5.2846968804856509e-01, -3.7745846761911317e-01, -2.2646713089859094e-01, -7.5487718959414210e-02, 7.5487718959414210e-02, 2.2646713089859094e-01, 3.7745846761911317e-01, 5.2846968804856509e-01, 6.7950876474356448e-01, 8.3058368937955573e-01, 9.8170247827895785e-01, 1.1328731779888348e+00, 1.2841038709195900e+00, 1.4354026810562848e+00, 1.5867777797546210e+00, 1.7382373916337388e+00, 1.8897898005787916e+00, 2.0414433558661624e+00, 2.1932064784252856e+00, 2.3450876672510903e+00, 2.4970955059821409e+00, 2.6492386696600243e+00, 2.8015259316863266e+00, 2.9539661709946619e+00, 3.1065683794558021e+00, 3.2593416695353823e+00, 3.4122952822245907e+00, 3.5654385952656149e+00, 3.7187811316950210e+00, 3.8723325687298416e+00, 4.0261027470226392e+00, 4.1801016803139959e+00, 4.3343395655126109e+00, 4.4888267932355790e+00, 4.6435739588438905e+00, 4.7985918740108131e+00, 4.9538915788638089e+00, 5.1094843547439881e+00, 5.2653817376305465e+00, 5.4215955322816969e+00, 5.5781378271479722e+00, 5.7350210101185848e+00, 5.8922577851667635e+00, 6.0498611899661094e+00, 6.2078446145563948e+00, 6.3662218211444577e+00, 6.5250069651340752e+00, 6.6842146174875827e+00, 6.8438597885318986e+00, 7.0039579533331269e+00, 7.1645250787759087e+00, 7.3255776524981444e+00, 7.4871327138470951e+00, 7.6492078870405447e+00, 7.8118214167366684e+00, 7.9749922062384426e+00, 8.1387398585838486e+00, 8.3030847208017082e+00, 8.4680479316454296e+00, 8.6336514731539875e+00, 8.7999182264315081e+00, 8.9668720320849413e+00, 9.1345377558145096e+00, 9.3029413597147883e+00, 9.4721099799172528e+00, 9.6420720112891818e+00, 9.8128572000013108e+00, 9.9844967448895385e+00, 1.0157023408668081e+01, 1.0330471640205081e+01, 1.0504877709252620e+01, 1.0680279855235202e+01, 1.0856718451952171e+01, 1.1034236190346626e+01, 1.1212878281848150e+01, 1.1392692685219812e+01, 1.1573730360348824e+01, 1.1756045553033841e+01, 1.1939696115566026e+01, 1.2124743868808109e+01, 1.2311255012587219e+01, 1.2499300592587632e+01, 1.2688957033629340e+01, 1.2880306751340244e+01, 1.3073438856897617e+01, 1.3268449972893279e+01, 1.3465445182689793e+01, 1.3664539141187824e+01, 1.3865857382137794e+01, 1.4069537866591046e+01, 1.4275732829628778e+01, 1.4484610999323769e+01, 1.4696360284715409e+01, 1.4911191060978103e+01, 1.5129340223792830e+01, 1.5351076247103551e+01, 1.5576705568204593e+01, 1.5806580756275796e+01, 1.6041111119395726e+01, 1.6280776711860355e+01, 1.6526147190139376e+01, 1.6777907762072694e+01, 1.7036895825521608e+01, 1.7304154286393636e+01, 1.7581012003064874e+01, 1.7869210618319627e+01, 1.8171115805943941e+01, 1.8490094811217439e+01, 1.8831257901839155e+01, 1.9203122650098184e+01, 1.9622211733828486e+01, 2.0131752068397390e+01}, + w: []float64{5.7186844211118222e-177, 2.7466189949527236e-168, 2.7698274929964049e-161, 3.4828172461418377e-155, 1.0940903755394791e-149, 1.2347606047124676e-144, 6.2404773612052171e-140, 1.6353340891378212e-135, 2.4650950171742754e-131, 2.3085411036710099e-127, 1.4249650100034198e-123, 6.0746030482858092e-120, 1.8572077169453742e-116, 4.2005766103289114e-113, 7.2131362796894811e-110, 9.6125997143450870e-107, 1.0130358260780602e-103, 8.5810245129266594e-101, 5.9257988910096090e-98, 3.3780606107607827e-95, 1.6073077596553874e-92, 6.4463886647737192e-90, 2.1986159587286647e-87, 6.4275556938243753e-85, 1.6222763835321407e-82, 3.5581101139323407e-80, 6.8220148646876484e-78, 1.1496573365594917e-75, 1.7114200608857651e-73, 2.2608688324572314e-71, 2.6617645198762597e-69, 2.8038024736345674e-67, 2.6521234350652613e-65, 2.2603869398967457e-63, 1.7413601437152754e-61, 1.2161701083247541e-59, 7.7214787759599970e-58, 4.4681959655564470e-56, 2.3623580471674404e-54, 1.1437576644069702e-52, 5.0819691921164956e-51, 2.0764486091263794e-49, 7.8168818968667932e-48, 2.7161609526051418e-46, 8.7263192332605962e-45, 2.5963610791198993e-43, 7.1651564650842932e-42, 1.8367370768736730e-40, 4.3795689659428445e-39, 9.7263842188046952e-38, 2.0144288376257676e-36, 3.8953956971431042e-35, 7.0411654624671892e-34, 1.1909731529300876e-32, 1.8870059773886237e-31, 2.8034152482012231e-30, 3.9088957466494064e-29, 5.1199371899987404e-28, 6.3051173258996659e-27, 7.3062988441733997e-26, 7.9729602997232079e-25, 8.1994951837475763e-24, 7.9526775811935095e-23, 7.2794477168595113e-22, 6.2925924422563063e-21, 5.1402243977739270e-20, 3.9702645520078747e-19, 2.9013105636885269e-18, 2.0070043240260125e-17, 1.3149628048888219e-16, 8.1641639956286359e-16, 4.8056898389707300e-15, 2.6831763736632487e-14, 1.4216321504480736e-13, 7.1508314522575616e-13, 3.4161417919950439e-12, 1.5505876032631646e-11, 6.6896188793649314e-11, 2.7441476023994389e-10, 1.0706905991113023e-09, 3.9747846429602356e-09, 1.4044052119190546e-08, 4.7242215798796869e-08, 1.5133894631903387e-07, 4.6181858824280925e-07, 1.3427778873836719e-06, 3.7209613424878082e-06, 9.8293533546629111e-06, 2.4757612288389546e-05, 5.9469805842774389e-05, 1.3626145195379436e-04, 2.9786395909886146e-04, 6.2130683688573309e-04, 1.2368227283931328e-03, 2.3501040099770882e-03, 4.2629032262842719e-03, 7.3827553287034008e-03, 1.2208924001688722e-02, 1.9280976823883154e-02, 2.9081432020399377e-02, 4.1896299298471870e-02, 5.7655710815363609e-02, 7.5795804675644604e-02, 9.5193937891141694e-02, 1.1422353375366404e-01, 1.3094856577352781e-01, 1.4343569727181574e-01, 1.5011822522474477e-01, 1.5011822522474477e-01, 1.4343569727181574e-01, 1.3094856577352781e-01, 1.1422353375366404e-01, 9.5193937891141694e-02, 7.5795804675644604e-02, 5.7655710815363609e-02, 4.1896299298471870e-02, 2.9081432020399377e-02, 1.9280976823883154e-02, 1.2208924001688722e-02, 7.3827553287034008e-03, 4.2629032262842719e-03, 2.3501040099770882e-03, 1.2368227283931328e-03, 6.2130683688573309e-04, 2.9786395909886146e-04, 1.3626145195379436e-04, 5.9469805842774389e-05, 2.4757612288389546e-05, 9.8293533546629111e-06, 3.7209613424878082e-06, 1.3427778873836719e-06, 4.6181858824280925e-07, 1.5133894631903387e-07, 4.7242215798796869e-08, 1.4044052119190546e-08, 3.9747846429602356e-09, 1.0706905991113023e-09, 2.7441476023994389e-10, 6.6896188793649314e-11, 1.5505876032631646e-11, 3.4161417919950439e-12, 7.1508314522575616e-13, 1.4216321504480736e-13, 2.6831763736632487e-14, 4.8056898389707300e-15, 8.1641639956286359e-16, 1.3149628048888219e-16, 2.0070043240260125e-17, 2.9013105636885269e-18, 3.9702645520078747e-19, 5.1402243977739270e-20, 6.2925924422563063e-21, 7.2794477168595113e-22, 7.9526775811935095e-23, 8.1994951837475763e-24, 7.9729602997232079e-25, 7.3062988441733997e-26, 6.3051173258996659e-27, 5.1199371899987404e-28, 3.9088957466494064e-29, 2.8034152482012231e-30, 1.8870059773886237e-31, 1.1909731529300876e-32, 7.0411654624671892e-34, 3.8953956971431042e-35, 2.0144288376257676e-36, 9.7263842188046952e-38, 4.3795689659428445e-39, 1.8367370768736730e-40, 7.1651564650842932e-42, 2.5963610791198993e-43, 8.7263192332605962e-45, 2.7161609526051418e-46, 7.8168818968667932e-48, 2.0764486091263794e-49, 5.0819691921164956e-51, 1.1437576644069702e-52, 2.3623580471674404e-54, 4.4681959655564470e-56, 7.7214787759599970e-58, 1.2161701083247541e-59, 1.7413601437152754e-61, 2.2603869398967457e-63, 2.6521234350652613e-65, 2.8038024736345674e-67, 2.6617645198762597e-69, 2.2608688324572314e-71, 1.7114200608857651e-73, 1.1496573365594917e-75, 6.8220148646876484e-78, 3.5581101139323407e-80, 1.6222763835321407e-82, 6.4275556938243753e-85, 2.1986159587286647e-87, 6.4463886647737192e-90, 1.6073077596553874e-92, 3.3780606107607827e-95, 5.9257988910096090e-98, 8.5810245129266594e-101, 1.0130358260780602e-103, 9.6125997143450870e-107, 7.2131362796894811e-110, 4.2005766103289114e-113, 1.8572077169453742e-116, 6.0746030482858092e-120, 1.4249650100034198e-123, 2.3085411036710099e-127, 2.4650950171742754e-131, 1.6353340891378212e-135, 6.2404773612052171e-140, 1.2347606047124676e-144, 1.0940903755394791e-149, 3.4828172461418377e-155, 2.7698274929964049e-161, 2.7466189949527236e-168, 5.7186844211118222e-177}, + }, + { + n: 217, + x: []float64{-2.0180280152078982e+01, -1.9671145428267970e+01, -1.9252396116029669e+01, -1.8880837640701767e+01, -1.8539959593913657e+01, -1.8221250688860252e+01, -1.7919604408706316e+01, -1.7631655968298805e+01, -1.7355041415469405e+01, -1.7088020370809854e+01, -1.6829264937408070e+01, -1.6577732962488266e+01, -1.6332587652172350e+01, -1.6093144292573264e+01, -1.5858833637952957e+01, -1.5629175980464554e+01, -1.5403762307923412e+01, -1.5182240306661464e+01, -1.4964303762199654e+01, -1.4749684396618285e+01, -1.4538145488075983e+01, -1.4329476816694543e+01, -1.4123490613100632e+01, -1.3920018275613611e+01, -1.3718907684195138e+01, -1.3520020983073742e+01, -1.3323232735334253e+01, -1.3128428375570619e+01, -1.2935502903505391e+01, -1.2744359774012816e+01, -1.2554909948437734e+01, -1.2367071079310476e+01, -1.2180766806106346e+01, -1.1995926144008331e+01, -1.1812482951007951e+01, -1.1630375461345015e+01, -1.1449545875407471e+01, -1.1269939997911081e+01, -1.1091506917547994e+01, -1.0914198722404091e+01, -1.0737970246351363e+01, -1.0562778842365235e+01, -1.0388584179329960e+01, -1.0215348059403579e+01, -1.0043034253437085e+01, -9.8716083522966080e+00, -9.7010376322345699e+00, -9.5312909327068294e+00, -9.3623385452449437e+00, -9.1941521121732386e+00, -9.0267045341142556e+00, -8.8599698853577831e+00, -8.6939233362816957e+00, -8.5285410821102356e+00, -8.3638002773794167e+00, -8.1996789755519419e+00, -8.0361560732874953e+00, -7.8732112589291026e+00, -7.7108249648145373e+00, -7.5489783230637100e+00, -7.3876531245300106e+00, -7.2268317806359086e+00, -7.0664972878418659e+00, -6.9066331945227768e+00, -6.7472235700485381e+00, -6.5882529758852613e+00, -6.4297064385510465e+00, -6.2715694242761426e+00, -6.1138278152311072e+00, -5.9564678871991967e+00, -5.7994762885802258e+00, -5.6428400206233480e+00, -5.4865464187949282e+00, -5.3305831351959538e+00, -5.1749381219506319e+00, -5.0195996154942355e+00, -4.8645561216944264e+00, -4.7097964017452645e+00, -4.5553094587783480e+00, -4.4010845251394572e+00, -4.2471110502834843e+00, -4.0933786892435746e+00, -3.9398772916341032e+00, -3.7865968911497059e+00, -3.6335276955255318e+00, -3.4806600769262501e+00, -3.3279845627335654e+00, -3.1754918267040755e+00, -3.0231726804711898e+00, -2.8710180653663722e+00, -2.7190190445367941e+00, -2.5671667953376018e+00, -2.4154526019785036e+00, -2.2638678484054164e+00, -2.1124040113990956e+00, -1.9610526538735082e+00, -1.8098054183577674e+00, -1.6586540206460576e+00, -1.5075902436008417e+00, -1.3566059310952046e+00, -1.2056929820809235e+00, -1.0548433447690717e+00, -9.0404901091087708e-01, -7.5330201016646747e-01, -6.0259440454997382e-01, -4.5191828293935077e-01, -3.0126575563983427e-01, -1.5062894899007009e-01, 7.9851131193273576e-15, 1.5062894899007009e-01, 3.0126575563983427e-01, 4.5191828293935077e-01, 6.0259440454997382e-01, 7.5330201016646747e-01, 9.0404901091087708e-01, 1.0548433447690717e+00, 1.2056929820809235e+00, 1.3566059310952046e+00, 1.5075902436008417e+00, 1.6586540206460576e+00, 1.8098054183577674e+00, 1.9610526538735082e+00, 2.1124040113990956e+00, 2.2638678484054164e+00, 2.4154526019785036e+00, 2.5671667953376018e+00, 2.7190190445367941e+00, 2.8710180653663722e+00, 3.0231726804711898e+00, 3.1754918267040755e+00, 3.3279845627335654e+00, 3.4806600769262501e+00, 3.6335276955255318e+00, 3.7865968911497059e+00, 3.9398772916341032e+00, 4.0933786892435746e+00, 4.2471110502834843e+00, 4.4010845251394572e+00, 4.5553094587783480e+00, 4.7097964017452645e+00, 4.8645561216944264e+00, 5.0195996154942355e+00, 5.1749381219506319e+00, 5.3305831351959538e+00, 5.4865464187949282e+00, 5.6428400206233480e+00, 5.7994762885802258e+00, 5.9564678871991967e+00, 6.1138278152311072e+00, 6.2715694242761426e+00, 6.4297064385510465e+00, 6.5882529758852613e+00, 6.7472235700485381e+00, 6.9066331945227768e+00, 7.0664972878418659e+00, 7.2268317806359086e+00, 7.3876531245300106e+00, 7.5489783230637100e+00, 7.7108249648145373e+00, 7.8732112589291026e+00, 8.0361560732874953e+00, 8.1996789755519419e+00, 8.3638002773794167e+00, 8.5285410821102356e+00, 8.6939233362816957e+00, 8.8599698853577831e+00, 9.0267045341142556e+00, 9.1941521121732386e+00, 9.3623385452449437e+00, 9.5312909327068294e+00, 9.7010376322345699e+00, 9.8716083522966080e+00, 1.0043034253437085e+01, 1.0215348059403579e+01, 1.0388584179329960e+01, 1.0562778842365235e+01, 1.0737970246351363e+01, 1.0914198722404091e+01, 1.1091506917547994e+01, 1.1269939997911081e+01, 1.1449545875407471e+01, 1.1630375461345015e+01, 1.1812482951007951e+01, 1.1995926144008331e+01, 1.2180766806106346e+01, 1.2367071079310476e+01, 1.2554909948437734e+01, 1.2744359774012816e+01, 1.2935502903505391e+01, 1.3128428375570619e+01, 1.3323232735334253e+01, 1.3520020983073742e+01, 1.3718907684195138e+01, 1.3920018275613611e+01, 1.4123490613100632e+01, 1.4329476816694543e+01, 1.4538145488075983e+01, 1.4749684396618285e+01, 1.4964303762199654e+01, 1.5182240306661464e+01, 1.5403762307923412e+01, 1.5629175980464554e+01, 1.5858833637952957e+01, 1.6093144292573264e+01, 1.6332587652172350e+01, 1.6577732962488266e+01, 1.6829264937408070e+01, 1.7088020370809854e+01, 1.7355041415469405e+01, 1.7631655968298805e+01, 1.7919604408706316e+01, 1.8221250688860252e+01, 1.8539959593913657e+01, 1.8880837640701767e+01, 1.9252396116029669e+01, 1.9671145428267970e+01, 2.0180280152078982e+01}, + w: []float64{8.0790134837724204e-178, 4.0123708332001955e-169, 4.1608342695810454e-162, 5.3647010323313458e-156, 1.7249035730335862e-150, 1.9898962894711550e-145, 1.0270178951244021e-140, 2.7462859803070011e-136, 4.2216443703754674e-132, 4.0296773344706320e-128, 2.5341526783446447e-124, 1.1002243777181162e-120, 3.4246772430261828e-117, 7.8839348684832184e-114, 1.3776135348531781e-110, 1.8677560466742519e-107, 2.0021556471031417e-104, 1.7247770196475562e-101, 1.2111464936797437e-98, 7.0196501028640057e-96, 3.3954234881610162e-93, 1.3842435843570204e-90, 4.7985036069815231e-88, 1.4256947701704702e-85, 3.6567711491235357e-83, 8.1499750643585127e-81, 1.5877740343548737e-78, 2.7187040652791320e-76, 4.1119602314337377e-74, 5.5188731969772834e-72, 6.6010643664052121e-70, 7.0639875689587789e-68, 6.7880577161215916e-66, 5.8772891020073188e-64, 4.5996045356018730e-62, 3.2633290432137694e-60, 2.1047497049395128e-58, 1.2372745780617511e-56, 6.6453150452727337e-55, 3.2684621263244055e-53, 1.4753196845067616e-51, 6.1238771021510087e-50, 2.3420591906941631e-48, 8.2677634302135741e-47, 2.6986236644096577e-45, 8.1576808396884509e-44, 2.2873393442828659e-42, 5.9575720207549899e-41, 1.4433986536815081e-39, 3.2572816931648467e-38, 6.8552334632687487e-37, 1.3471217671214917e-35, 2.4745963539025701e-34, 4.2538970187949130e-33, 6.8502295544213803e-32, 1.0344007225282243e-30, 1.4660497224001333e-29, 1.9519881038552925e-28, 2.4437079996027598e-27, 2.8788818637419581e-26, 3.1940663724110344e-25, 3.3399348780894923e-24, 3.2939758359327470e-23, 3.0661414593245886e-22, 2.6955142404467904e-21, 2.2394681775190790e-20, 1.7594079537257698e-19, 1.3078564789171130e-18, 9.2038260248200122e-18, 6.1351365453804107e-17, 3.8757039748543155e-16, 2.3214598330581677e-15, 1.3190482037051148e-14, 7.1128747627508331e-14, 3.6416855631427732e-13, 1.7709744825377116e-12, 8.1836457113383607e-12, 3.5947660428421198e-11, 1.5015547963310099e-10, 5.9663534866912190e-10, 2.2558892777245505e-09, 8.1190427548544262e-09, 2.7822813440253852e-08, 9.0809483027322313e-08, 2.8236711509871372e-07, 8.3668655155751835e-07, 2.3631134387385760e-06, 6.3632839492173400e-06, 1.6339902252008705e-05, 4.0020290652701539e-05, 9.3510362001206373e-05, 2.0848221478522648e-04, 4.4359250162546185e-04, 9.0090002804434576e-04, 1.7466777765574378e-03, 3.2333646918818863e-03, 5.7155709629331409e-03, 9.6489576482962046e-03, 1.5558416546311961e-02, 2.3963959563684092e-02, 3.5261402555428784e-02, 4.9570551047913969e-02, 6.6582815385485522e-02, 8.5455825791019971e-02, 1.0480572103134121e-01, 1.2283174514792664e-01, 1.3757292020567533e-01, 1.4725235676872742e-01, 1.5062763955757250e-01, 1.4725235676872742e-01, 1.3757292020567533e-01, 1.2283174514792664e-01, 1.0480572103134121e-01, 8.5455825791019971e-02, 6.6582815385485522e-02, 4.9570551047913969e-02, 3.5261402555428784e-02, 2.3963959563684092e-02, 1.5558416546311961e-02, 9.6489576482962046e-03, 5.7155709629331409e-03, 3.2333646918818863e-03, 1.7466777765574378e-03, 9.0090002804434576e-04, 4.4359250162546185e-04, 2.0848221478522648e-04, 9.3510362001206373e-05, 4.0020290652701539e-05, 1.6339902252008705e-05, 6.3632839492173400e-06, 2.3631134387385760e-06, 8.3668655155751835e-07, 2.8236711509871372e-07, 9.0809483027322313e-08, 2.7822813440253852e-08, 8.1190427548544262e-09, 2.2558892777245505e-09, 5.9663534866912190e-10, 1.5015547963310099e-10, 3.5947660428421198e-11, 8.1836457113383607e-12, 1.7709744825377116e-12, 3.6416855631427732e-13, 7.1128747627508331e-14, 1.3190482037051148e-14, 2.3214598330581677e-15, 3.8757039748543155e-16, 6.1351365453804107e-17, 9.2038260248200122e-18, 1.3078564789171130e-18, 1.7594079537257698e-19, 2.2394681775190790e-20, 2.6955142404467904e-21, 3.0661414593245886e-22, 3.2939758359327470e-23, 3.3399348780894923e-24, 3.1940663724110344e-25, 2.8788818637419581e-26, 2.4437079996027598e-27, 1.9519881038552925e-28, 1.4660497224001333e-29, 1.0344007225282243e-30, 6.8502295544213803e-32, 4.2538970187949130e-33, 2.4745963539025701e-34, 1.3471217671214917e-35, 6.8552334632687487e-37, 3.2572816931648467e-38, 1.4433986536815081e-39, 5.9575720207549899e-41, 2.2873393442828659e-42, 8.1576808396884509e-44, 2.6986236644096577e-45, 8.2677634302135741e-47, 2.3420591906941631e-48, 6.1238771021510087e-50, 1.4753196845067616e-51, 3.2684621263244055e-53, 6.6453150452727337e-55, 1.2372745780617511e-56, 2.1047497049395128e-58, 3.2633290432137694e-60, 4.5996045356018730e-62, 5.8772891020073188e-64, 6.7880577161215916e-66, 7.0639875689587789e-68, 6.6010643664052121e-70, 5.5188731969772834e-72, 4.1119602314337377e-74, 2.7187040652791320e-76, 1.5877740343548737e-78, 8.1499750643585127e-81, 3.6567711491235357e-83, 1.4256947701704702e-85, 4.7985036069815231e-88, 1.3842435843570204e-90, 3.3954234881610162e-93, 7.0196501028640057e-96, 1.2111464936797437e-98, 1.7247770196475562e-101, 2.0021556471031417e-104, 1.8677560466742519e-107, 1.3776135348531781e-110, 7.8839348684832184e-114, 3.4246772430261828e-117, 1.1002243777181162e-120, 2.5341526783446447e-124, 4.0296773344706320e-128, 4.2216443703754674e-132, 2.7462859803070011e-136, 1.0270178951244021e-140, 1.9898962894711550e-145, 1.7249035730335862e-150, 5.3647010323313458e-156, 4.1608342695810454e-162, 4.0123708332001955e-169, 8.0790134837724204e-178}, + }, + + { + n: 218, + x: []float64{-2.0228695170577915e+01, -1.9719963830858333e+01, -1.9301552400253843e+01, -1.8930298474919816e+01, -1.8589703851801165e+01, -1.8271263496827501e+01, -1.7969874624529179e+01, -1.7682174897106314e+01, -1.7405802075069708e+01, -1.7139017035820078e+01, -1.6880492838899503e+01, -1.6629188080724916e+01, -1.6384266568226192e+01, -1.6145044078855118e+01, -1.5910951775414047e+01, -1.5681510294638914e+01, -1.5456310918627016e+01, -1.5235001587812036e+01, -1.5017276309282583e+01, -1.4802867000027815e+01, -1.4591537111039028e+01, -1.4383076576817141e+01, -1.4177297766812716e+01, -1.3974032204957940e+01, -1.3773127885530926e+01, -1.3574447057358521e+01, -1.3377864379717227e+01, -1.3183265376084384e+01, -1.2990545128683925e+01, -1.2799607169295788e+01, -1.2610362531246457e+01, -1.2422728934700823e+01, -1.2236630082919943e+01, -1.2051995051456386e+01, -1.1868757755632400e+01, -1.1686856484310367e+01, -1.1506233490083723e+01, -1.1326834627713886e+01, -1.1148609034007171e+01, -1.0971508843435563e+01, -1.0795488934711024e+01, -1.0620506704266159e+01, -1.0446521863206758e+01, -1.0273496254809785e+01, -1.0101393690063306e+01, -9.9301797990985268e+00, -9.7598218966614141e+00, -9.5902888600219054e+00, -9.4215510179308293e+00, -9.2535800494152092e+00, -9.0863488913560904e+00, -8.9198316539249092e+00, -8.7540035430671104e+00, -8.5888407893192067e+00, -8.4243205823293916e+00, -8.2604210105245137e+00, -8.0971210054295799e+00, -7.9344002902008972e+00, -7.7722393319820444e+00, -7.6106192977338623e+00, -7.4495220132267015e+00, -7.2889299249154647e+00, -7.1288260644465895e+00, -6.9691940155714960e+00, -6.8100178832631793e+00, -6.6512822648525844e+00, -6.4929722230189020e+00, -6.3350732604836884e+00, -6.1775712962725331e+00, -6.0204526434206276e+00, -5.8637039880096422e+00, -5.7073123694332661e+00, -5.5512651617979705e+00, -5.3955500563732679e+00, -5.2401550450133421e+00, -5.0850684044781733e+00, -4.9302786815884012e+00, -4.7757746791533817e+00, -4.6215454426166902e+00, -4.4675802473678914e+00, -4.3138685866729931e+00, -4.1604001601800418e+00, -4.0071648629591818e+00, -3.8541527750397258e+00, -3.7013541514093888e+00, -3.5487594124432715e+00, -3.3963591347324886e+00, -3.2441440422843915e+00, -3.0921049980680149e+00, -2.9402329958803848e+00, -2.7885191525106028e+00, -2.6369547001801932e+00, -2.4855309792393636e+00, -2.3342394311001944e+00, -2.1830715913886820e+00, -2.0320190832985223e+00, -1.8810736111306099e+00, -1.7302269540027844e+00, -1.5794709597152470e+00, -1.4287975387577758e+00, -1.2781986584451195e+00, -1.1276663371680935e+00, -9.7719263874768358e-01, -8.2676966688043974e-01, -6.7638955966349490e-01, -5.2604448418800387e-01, -3.7572663118998539e-01, -2.2542820974780486e-01, -7.5141442015907556e-02, 7.5141442015907556e-02, 2.2542820974780486e-01, 3.7572663118998539e-01, 5.2604448418800387e-01, 6.7638955966349490e-01, 8.2676966688043974e-01, 9.7719263874768358e-01, 1.1276663371680935e+00, 1.2781986584451195e+00, 1.4287975387577758e+00, 1.5794709597152470e+00, 1.7302269540027844e+00, 1.8810736111306099e+00, 2.0320190832985223e+00, 2.1830715913886820e+00, 2.3342394311001944e+00, 2.4855309792393636e+00, 2.6369547001801932e+00, 2.7885191525106028e+00, 2.9402329958803848e+00, 3.0921049980680149e+00, 3.2441440422843915e+00, 3.3963591347324886e+00, 3.5487594124432715e+00, 3.7013541514093888e+00, 3.8541527750397258e+00, 4.0071648629591818e+00, 4.1604001601800418e+00, 4.3138685866729931e+00, 4.4675802473678914e+00, 4.6215454426166902e+00, 4.7757746791533817e+00, 4.9302786815884012e+00, 5.0850684044781733e+00, 5.2401550450133421e+00, 5.3955500563732679e+00, 5.5512651617979705e+00, 5.7073123694332661e+00, 5.8637039880096422e+00, 6.0204526434206276e+00, 6.1775712962725331e+00, 6.3350732604836884e+00, 6.4929722230189020e+00, 6.6512822648525844e+00, 6.8100178832631793e+00, 6.9691940155714960e+00, 7.1288260644465895e+00, 7.2889299249154647e+00, 7.4495220132267015e+00, 7.6106192977338623e+00, 7.7722393319820444e+00, 7.9344002902008972e+00, 8.0971210054295799e+00, 8.2604210105245137e+00, 8.4243205823293916e+00, 8.5888407893192067e+00, 8.7540035430671104e+00, 8.9198316539249092e+00, 9.0863488913560904e+00, 9.2535800494152092e+00, 9.4215510179308293e+00, 9.5902888600219054e+00, 9.7598218966614141e+00, 9.9301797990985268e+00, 1.0101393690063306e+01, 1.0273496254809785e+01, 1.0446521863206758e+01, 1.0620506704266159e+01, 1.0795488934711024e+01, 1.0971508843435563e+01, 1.1148609034007171e+01, 1.1326834627713886e+01, 1.1506233490083723e+01, 1.1686856484310367e+01, 1.1868757755632400e+01, 1.2051995051456386e+01, 1.2236630082919943e+01, 1.2422728934700823e+01, 1.2610362531246457e+01, 1.2799607169295788e+01, 1.2990545128683925e+01, 1.3183265376084384e+01, 1.3377864379717227e+01, 1.3574447057358521e+01, 1.3773127885530926e+01, 1.3974032204957940e+01, 1.4177297766812716e+01, 1.4383076576817141e+01, 1.4591537111039028e+01, 1.4802867000027815e+01, 1.5017276309282583e+01, 1.5235001587812036e+01, 1.5456310918627016e+01, 1.5681510294638914e+01, 1.5910951775414047e+01, 1.6145044078855118e+01, 1.6384266568226192e+01, 1.6629188080724916e+01, 1.6880492838899503e+01, 1.7139017035820078e+01, 1.7405802075069708e+01, 1.7682174897106314e+01, 1.7969874624529179e+01, 1.8271263496827501e+01, 1.8589703851801165e+01, 1.8930298474919816e+01, 1.9301552400253843e+01, 1.9719963830858333e+01, 2.0228695170577915e+01}, + w: []float64{1.1412038714903467e-178, 5.8600364276414301e-170, 6.2483530291970031e-163, 8.2600389517381484e-157, 2.7180946943728827e-151, 3.2050447674896954e-146, 1.6891299829881347e-141, 4.6087117363873922e-137, 7.2242769320344098e-133, 7.0281073750791237e-129, 4.5026465211632589e-125, 1.9907761957745900e-121, 6.3085296819235091e-118, 1.4780807064034936e-114, 2.6279883692096037e-111, 3.6246331337631131e-108, 3.9519127727199950e-105, 3.4620642776922925e-102, 2.4718758245223020e-99, 1.4565168188237643e-96, 7.1616419809360768e-94, 2.9675903948483656e-91, 1.0455125036940855e-88, 3.1567897170935801e-86, 8.2277370866559977e-84, 1.8632623782187992e-81, 3.6882177983197069e-79, 6.4162031293430147e-77, 9.8590364210588088e-75, 1.3442782637610740e-72, 1.6333988316711487e-70, 1.7756459769101764e-68, 1.7332892347041021e-66, 1.5244548820160086e-64, 1.2118948225793116e-62, 8.7339153184655864e-61, 5.7220382749093667e-59, 3.4167937984322514e-57, 1.8641137908561576e-55, 9.3133897167275065e-54, 4.2703424814876432e-52, 1.8006175119892686e-50, 6.9955013175656585e-49, 2.5086717527911961e-47, 8.3184624948029151e-46, 2.5546048751257637e-44, 7.2770684318833216e-43, 1.9256515369002052e-41, 4.7401499620934791e-40, 1.0868621062998897e-38, 2.3241907456347607e-37, 4.6409284690005433e-36, 8.6630347696542139e-35, 1.5133539937177412e-33, 2.4766678429636503e-32, 3.8008678166597364e-31, 5.4751646602962371e-30, 7.4097643192715769e-29, 9.4293221065635326e-28, 1.1292370018541933e-26, 1.2736861289852883e-25, 1.3540721404735189e-24, 1.3578087095789605e-23, 1.2851527881373697e-22, 1.1488929806753338e-21, 9.7071144039920359e-21, 7.7562537574525747e-20, 5.8643464026904450e-19, 4.1979458289914584e-18, 2.8466716026161652e-17, 1.8295539696950399e-16, 1.1150004956688747e-15, 6.4466274804790879e-15, 3.5376499268729578e-14, 1.8433622668090456e-13, 9.1243282637242511e-13, 4.2919888935314847e-12, 1.9193290587578772e-11, 8.1626646177788407e-11, 3.3026130822100178e-10, 1.2716614885102940e-09, 4.6613505196508951e-09, 1.6270858113762294e-08, 5.4099533071374670e-08, 1.7138819219313466e-07, 5.1747190361086424e-07, 1.4894285947831174e-06, 4.0877345728852175e-06, 1.0699746166171350e-05, 2.6716804837681635e-05, 6.3650699225936851e-05, 1.4471442394637491e-04, 3.1404212609163355e-04, 6.5058509971884274e-04, 1.2868513657693481e-03, 2.4306591608453860e-03, 4.3848013160776717e-03, 7.5554485133504786e-03, 1.2436693679604333e-02, 1.9558227968032915e-02, 2.9388347600235249e-02, 4.2196739277833864e-02, 5.7899315166709715e-02, 7.5925444911783990e-02, 9.5157950558542009e-02, 1.1399005091049424e-01, 1.3051762867943345e-01, 1.4284462872400217e-01, 1.4943738595687683e-01, 1.4943738595687683e-01, 1.4284462872400217e-01, 1.3051762867943345e-01, 1.1399005091049424e-01, 9.5157950558542009e-02, 7.5925444911783990e-02, 5.7899315166709715e-02, 4.2196739277833864e-02, 2.9388347600235249e-02, 1.9558227968032915e-02, 1.2436693679604333e-02, 7.5554485133504786e-03, 4.3848013160776717e-03, 2.4306591608453860e-03, 1.2868513657693481e-03, 6.5058509971884274e-04, 3.1404212609163355e-04, 1.4471442394637491e-04, 6.3650699225936851e-05, 2.6716804837681635e-05, 1.0699746166171350e-05, 4.0877345728852175e-06, 1.4894285947831174e-06, 5.1747190361086424e-07, 1.7138819219313466e-07, 5.4099533071374670e-08, 1.6270858113762294e-08, 4.6613505196508951e-09, 1.2716614885102940e-09, 3.3026130822100178e-10, 8.1626646177788407e-11, 1.9193290587578772e-11, 4.2919888935314847e-12, 9.1243282637242511e-13, 1.8433622668090456e-13, 3.5376499268729578e-14, 6.4466274804790879e-15, 1.1150004956688747e-15, 1.8295539696950399e-16, 2.8466716026161652e-17, 4.1979458289914584e-18, 5.8643464026904450e-19, 7.7562537574525747e-20, 9.7071144039920359e-21, 1.1488929806753338e-21, 1.2851527881373697e-22, 1.3578087095789605e-23, 1.3540721404735189e-24, 1.2736861289852883e-25, 1.1292370018541933e-26, 9.4293221065635326e-28, 7.4097643192715769e-29, 5.4751646602962371e-30, 3.8008678166597364e-31, 2.4766678429636503e-32, 1.5133539937177412e-33, 8.6630347696542139e-35, 4.6409284690005433e-36, 2.3241907456347607e-37, 1.0868621062998897e-38, 4.7401499620934791e-40, 1.9256515369002052e-41, 7.2770684318833216e-43, 2.5546048751257637e-44, 8.3184624948029151e-46, 2.5086717527911961e-47, 6.9955013175656585e-49, 1.8006175119892686e-50, 4.2703424814876432e-52, 9.3133897167275065e-54, 1.8641137908561576e-55, 3.4167937984322514e-57, 5.7220382749093667e-59, 8.7339153184655864e-61, 1.2118948225793116e-62, 1.5244548820160086e-64, 1.7332892347041021e-66, 1.7756459769101764e-68, 1.6333988316711487e-70, 1.3442782637610740e-72, 9.8590364210588088e-75, 6.4162031293430147e-77, 3.6882177983197069e-79, 1.8632623782187992e-81, 8.2277370866559977e-84, 3.1567897170935801e-86, 1.0455125036940855e-88, 2.9675903948483656e-91, 7.1616419809360768e-94, 1.4565168188237643e-96, 2.4718758245223020e-99, 3.4620642776922925e-102, 3.9519127727199950e-105, 3.6246331337631131e-108, 2.6279883692096037e-111, 1.4780807064034936e-114, 6.3085296819235091e-118, 1.9907761957745900e-121, 4.5026465211632589e-125, 7.0281073750791237e-129, 7.2242769320344098e-133, 4.6087117363873922e-137, 1.6891299829881347e-141, 3.2050447674896954e-146, 2.7180946943728827e-151, 8.2600389517381484e-157, 6.2483530291970031e-163, 5.8600364276414301e-170, 1.1412038714903467e-178}, + }, + { + n: 219, + x: []float64{-2.0276997908046905e+01, -1.9768667748260523e+01, -1.9350592328749663e+01, -1.8979641248255188e+01, -1.8639328445512675e+01, -1.8321155106754730e+01, -1.8020022158568153e+01, -1.7732569697856896e+01, -1.7456437188959409e+01, -1.7189886759582706e+01, -1.6931592420762687e+01, -1.6680513514209245e+01, -1.6435814444517028e+01, -1.6196811477889465e+01, -1.5962936183500821e+01, -1.5733709540823362e+01, -1.5508723124641774e+01, -1.5287625128097030e+01, -1.5070109778611977e+01, -1.4855909186982135e+01, -1.4644786976036578e+01, -1.4436533233749541e+01, -1.4230960467563948e+01, -1.4027900326255610e+01, -1.3827200917702472e+01, -1.3628724594657513e+01, -1.3432346111954516e+01, -1.3237951081351927e+01, -1.3045434667000123e+01, -1.2854700477033081e+01, -1.2665659616227074e+01, -1.2478229871866438e+01, -1.2292335010497055e+01, -1.2107904167551959e+01, -1.1924871315204850e+01, -1.1743174796469416e+01, -1.1562756915679721e+01, -1.1383563577182978e+01, -1.1205543965443459e+01, -1.1028650260865531e+01, -1.0852837386548828e+01, -1.0678062781931233e+01, -1.0504286199887655e+01, -1.0331469524360219e+01, -1.0159576606018058e+01, -9.9885731137985694e+00, -9.8184264004786943e+00, -9.6491053806754916e+00, -9.4805804198871506e+00, -9.3128232333657657e+00, -9.1458067937670240e+00, -8.9795052466532344e+00, -8.8138938330391774e+00, -8.6489488182673355e+00, -8.4846474265831215e+00, -8.3209677808533336e+00, -8.1578888469343305e+00, -7.9953903822513528e+00, -7.8334528881984324e+00, -7.6720575660104693e+00, -7.5111862757957555e+00, -7.3508214984498235e+00, -7.1909463001999656e+00, -7.0315442995549828e+00, -6.8725996364571813e+00, -6.7140969434532645e+00, -6.5560213187184688e+00, -6.3983583007839497e+00, -6.2410938448312283e+00, -6.0842143004302391e+00, -5.9277063906083614e+00, -5.7715571921480873e+00, -5.6157541170197165e+00, -5.4602848948636904e+00, -5.3051375564443513e+00, -5.1503004180034342e+00, -4.9957620664475568e+00, -4.8415113453092564e+00, -4.6875373414259709e+00, -4.5338293722856466e+00, -4.3803769739918419e+00, -4.2271698898044328e+00, -4.0741980592156279e+00, -3.9214516075238026e+00, -3.7689208358703388e+00, -3.6165962117072561e+00, -3.4644683596654966e+00, -3.3125280527959076e+00, -3.1607662041567641e+00, -3.0091738587233952e+00, -2.8577421855969432e+00, -2.7064624704909552e+00, -2.5553261084754681e+00, -2.4043245969596510e+00, -2.2534495288951528e+00, -2.1026925861830650e+00, -1.9520455332686681e+00, -1.8015002109084974e+00, -1.6510485300954487e+00, -1.5006824661279821e+00, -1.3503940528101779e+00, -1.2001753767700742e+00, -1.0500185718839765e+00, -8.9991581379505270e-01, -7.4985931451474896e-01, -5.9984131709602384e-01, -4.4985409036765389e-01, -2.9988992371893503e-01, -1.4994112192465620e-01, 8.0217422708380516e-15, 1.4994112192465620e-01, 2.9988992371893503e-01, 4.4985409036765389e-01, 5.9984131709602384e-01, 7.4985931451474896e-01, 8.9991581379505270e-01, 1.0500185718839765e+00, 1.2001753767700742e+00, 1.3503940528101779e+00, 1.5006824661279821e+00, 1.6510485300954487e+00, 1.8015002109084974e+00, 1.9520455332686681e+00, 2.1026925861830650e+00, 2.2534495288951528e+00, 2.4043245969596510e+00, 2.5553261084754681e+00, 2.7064624704909552e+00, 2.8577421855969432e+00, 3.0091738587233952e+00, 3.1607662041567641e+00, 3.3125280527959076e+00, 3.4644683596654966e+00, 3.6165962117072561e+00, 3.7689208358703388e+00, 3.9214516075238026e+00, 4.0741980592156279e+00, 4.2271698898044328e+00, 4.3803769739918419e+00, 4.5338293722856466e+00, 4.6875373414259709e+00, 4.8415113453092564e+00, 4.9957620664475568e+00, 5.1503004180034342e+00, 5.3051375564443513e+00, 5.4602848948636904e+00, 5.6157541170197165e+00, 5.7715571921480873e+00, 5.9277063906083614e+00, 6.0842143004302391e+00, 6.2410938448312283e+00, 6.3983583007839497e+00, 6.5560213187184688e+00, 6.7140969434532645e+00, 6.8725996364571813e+00, 7.0315442995549828e+00, 7.1909463001999656e+00, 7.3508214984498235e+00, 7.5111862757957555e+00, 7.6720575660104693e+00, 7.8334528881984324e+00, 7.9953903822513528e+00, 8.1578888469343305e+00, 8.3209677808533336e+00, 8.4846474265831215e+00, 8.6489488182673355e+00, 8.8138938330391774e+00, 8.9795052466532344e+00, 9.1458067937670240e+00, 9.3128232333657657e+00, 9.4805804198871506e+00, 9.6491053806754916e+00, 9.8184264004786943e+00, 9.9885731137985694e+00, 1.0159576606018058e+01, 1.0331469524360219e+01, 1.0504286199887655e+01, 1.0678062781931233e+01, 1.0852837386548828e+01, 1.1028650260865531e+01, 1.1205543965443459e+01, 1.1383563577182978e+01, 1.1562756915679721e+01, 1.1743174796469416e+01, 1.1924871315204850e+01, 1.2107904167551959e+01, 1.2292335010497055e+01, 1.2478229871866438e+01, 1.2665659616227074e+01, 1.2854700477033081e+01, 1.3045434667000123e+01, 1.3237951081351927e+01, 1.3432346111954516e+01, 1.3628724594657513e+01, 1.3827200917702472e+01, 1.4027900326255610e+01, 1.4230960467563948e+01, 1.4436533233749541e+01, 1.4644786976036578e+01, 1.4855909186982135e+01, 1.5070109778611977e+01, 1.5287625128097030e+01, 1.5508723124641774e+01, 1.5733709540823362e+01, 1.5962936183500821e+01, 1.6196811477889465e+01, 1.6435814444517028e+01, 1.6680513514209245e+01, 1.6931592420762687e+01, 1.7189886759582706e+01, 1.7456437188959409e+01, 1.7732569697856896e+01, 1.8020022158568153e+01, 1.8321155106754730e+01, 1.8639328445512675e+01, 1.8979641248255188e+01, 1.9350592328749663e+01, 1.9768667748260523e+01, 2.0276997908046905e+01}, + w: []float64{1.6118004761490936e-179, 8.5565157993831952e-171, 9.3801386072360495e-164, 1.2712817065467470e-157, 4.2810879764792902e-152, 5.1593581306426363e-147, 2.7763562197121041e-142, 7.7287684331971630e-138, 1.2353061004428027e-133, 1.2247428452374434e-129, 7.9930519467022852e-126, 3.5986937020445443e-122, 1.1608863141459933e-118, 2.7680773700442792e-115, 5.0074481042562811e-112, 7.0254966797767812e-109, 7.7903695739499256e-106, 6.9398586398625168e-103, 5.0378132240927281e-100, 3.0176790544586562e-97, 1.5082063803644767e-94, 6.3518001539538009e-92, 2.2741855202923794e-89, 6.9776584966048747e-87, 1.8479046829051634e-84, 4.2518674704681371e-82, 8.5507393331426323e-80, 1.5112093165489227e-77, 2.3589639789454550e-75, 3.2673822149378061e-73, 4.0328590535463278e-71, 4.4532356700297110e-69, 4.4154958570004513e-67, 3.9446173154369991e-65, 3.1851636643508064e-63, 2.3315719656364080e-61, 1.5515360955581329e-59, 9.4102483913550526e-58, 5.2146771930312127e-56, 2.6462964683019027e-54, 1.2324622103285675e-52, 5.2785960684684324e-51, 2.0830950016909702e-49, 7.5881492915547110e-48, 2.5559164938518617e-46, 7.9735166177827294e-45, 2.3073707359625722e-43, 6.2027848314701266e-42, 1.5511852212359039e-40, 3.6134675099711877e-39, 7.8508422681776689e-38, 1.5928021832222874e-36, 3.0210523716429586e-35, 5.3626533220153980e-34, 8.9182314112122594e-33, 1.3908724042317442e-31, 2.0361886950192076e-30, 2.8006915544325587e-29, 3.6224809761826824e-28, 4.4096199762595120e-27, 5.0558656605721755e-26, 5.4641111784906703e-25, 5.5704394297442813e-24, 5.3605363007899914e-23, 4.8726597293407410e-22, 4.1864031729275524e-21, 3.4017282707064429e-20, 2.6157557992877646e-19, 1.9044895750724533e-18, 1.3136464708861073e-17, 8.5885898614439566e-17, 5.3250576372585674e-16, 3.1325104388327040e-15, 1.7491400171437906e-14, 9.2749216025525341e-14, 4.6723068181067832e-13, 2.2369795792044991e-12, 1.0182840690359900e-11, 4.4087115371635113e-11, 1.8161128736541464e-10, 7.1204644180465281e-10, 2.6579545759517285e-09, 9.4491700732305002e-09, 3.2001745961210195e-08, 1.0327820095258369e-07, 3.1769761704760471e-07, 9.3174969312259845e-07, 2.6059663547935113e-06, 6.9521878670475772e-06, 1.7695019387908094e-05, 4.2977984770344540e-05, 9.9630005120895210e-05, 2.2047640877838706e-04, 4.6583912781443418e-04, 9.3989854709223869e-04, 1.8111811218635974e-03, 3.3337948402502641e-03, 5.8622951858897081e-03, 9.8491710526776490e-03, 1.5811821288832947e-02, 2.4258117817844916e-02, 3.5568359860607475e-02, 4.9846708381161745e-02, 6.6773674520725357e-02, 8.5505952447471292e-02, 1.0467230074567024e-01, 1.2249815849737687e-01, 1.3705778627617005e-01, 1.4661020932556390e-01, 1.4993984211667696e-01, 1.4661020932556390e-01, 1.3705778627617005e-01, 1.2249815849737687e-01, 1.0467230074567024e-01, 8.5505952447471292e-02, 6.6773674520725357e-02, 4.9846708381161745e-02, 3.5568359860607475e-02, 2.4258117817844916e-02, 1.5811821288832947e-02, 9.8491710526776490e-03, 5.8622951858897081e-03, 3.3337948402502641e-03, 1.8111811218635974e-03, 9.3989854709223869e-04, 4.6583912781443418e-04, 2.2047640877838706e-04, 9.9630005120895210e-05, 4.2977984770344540e-05, 1.7695019387908094e-05, 6.9521878670475772e-06, 2.6059663547935113e-06, 9.3174969312259845e-07, 3.1769761704760471e-07, 1.0327820095258369e-07, 3.2001745961210195e-08, 9.4491700732305002e-09, 2.6579545759517285e-09, 7.1204644180465281e-10, 1.8161128736541464e-10, 4.4087115371635113e-11, 1.0182840690359900e-11, 2.2369795792044991e-12, 4.6723068181067832e-13, 9.2749216025525341e-14, 1.7491400171437906e-14, 3.1325104388327040e-15, 5.3250576372585674e-16, 8.5885898614439566e-17, 1.3136464708861073e-17, 1.9044895750724533e-18, 2.6157557992877646e-19, 3.4017282707064429e-20, 4.1864031729275524e-21, 4.8726597293407410e-22, 5.3605363007899914e-23, 5.5704394297442813e-24, 5.4641111784906703e-25, 5.0558656605721755e-26, 4.4096199762595120e-27, 3.6224809761826824e-28, 2.8006915544325587e-29, 2.0361886950192076e-30, 1.3908724042317442e-31, 8.9182314112122594e-33, 5.3626533220153980e-34, 3.0210523716429586e-35, 1.5928021832222874e-36, 7.8508422681776689e-38, 3.6134675099711877e-39, 1.5511852212359039e-40, 6.2027848314701266e-42, 2.3073707359625722e-43, 7.9735166177827294e-45, 2.5559164938518617e-46, 7.5881492915547110e-48, 2.0830950016909702e-49, 5.2785960684684324e-51, 1.2324622103285675e-52, 2.6462964683019027e-54, 5.2146771930312127e-56, 9.4102483913550526e-58, 1.5515360955581329e-59, 2.3315719656364080e-61, 3.1851636643508064e-63, 3.9446173154369991e-65, 4.4154958570004513e-67, 4.4532356700297110e-69, 4.0328590535463278e-71, 3.2673822149378061e-73, 2.3589639789454550e-75, 1.5112093165489227e-77, 8.5507393331426323e-80, 4.2518674704681371e-82, 1.8479046829051634e-84, 6.9776584966048747e-87, 2.2741855202923794e-89, 6.3518001539538009e-92, 1.5082063803644767e-94, 3.0176790544586562e-97, 5.0378132240927281e-100, 6.9398586398625168e-103, 7.7903695739499256e-106, 7.0254966797767812e-109, 5.0074481042562811e-112, 2.7680773700442792e-115, 1.1608863141459933e-118, 3.5986937020445443e-122, 7.9930519467022852e-126, 1.2247428452374434e-129, 1.2353061004428027e-133, 7.7287684331971630e-138, 2.7763562197121041e-142, 5.1593581306426363e-147, 4.2810879764792902e-152, 1.2712817065467470e-157, 9.3801386072360495e-164, 8.5565157993831952e-171, 1.6118004761490936e-179}, + }, + { + n: 220, + x: []float64{-2.0325189139629405e+01, -1.9817257977795947e+01, -1.9399516717870224e+01, -1.9028866794578029e+01, -1.8688834225534919e+01, -1.8370926385157830e+01, -1.8070047892967271e+01, -1.7782841268044042e+01, -1.7506947669788651e+01, -1.7240630469775191e+01, -1.6982564625621777e+01, -1.6731710220470223e+01, -1.6487232253468321e+01, -1.6248447477010238e+01, -1.6014787864496149e+01, -1.5785774736307584e+01, -1.5560999958339213e+01, -1.5340111975060188e+01, -1.5122805233008011e+01, -1.4908812035694833e+01, -1.4697896176804390e+01, -1.4489847896889446e+01, -1.4284479840564213e+01, -1.4081623780688842e+01, -1.3881127938034011e+01, -1.3682854768615876e+01, -1.3486679122200039e+01, -1.3292486698232523e+01, -1.3100172742223814e+01, -1.2909640938118768e+01, -1.2720802461619986e+01, -1.2533575166624548e+01, -1.2347882882470566e+01, -1.2163654803990811e+01, -1.1980824959739557e+01, -1.1799331746419007e+01, -1.1619117519647554e+01, -1.1440128232906956e+01, -1.1262313117871999e+01, -1.1085624400434606e+01, -1.0910017047638791e+01, -1.0735448541485018e+01, -1.0561878676174262e+01, -1.0389269375869560e+01, -1.0217584530474927e+01, -1.0046789847284987e+01, -9.8768527166552929e+00, -9.7077420900935678e+00, -9.5394283693840993e+00, -9.3718833055374660e+00, -9.2050799065113704e+00, -9.0389923527798217e+00, -8.8735959199405876e+00, -8.7088669076480283e+00, -8.5447825742424133e+00, -8.3813210765192689e+00, -8.2184614141456525e+00, -8.0561833782850805e+00, -7.8944675040409047e+00, -7.7332950263697580e+00, -7.5726478391539116e+00, -7.4125084571532707e+00, -7.2528599805868588e+00, -7.0936860621182607e+00, -6.9349708760424020e+00, -6.7766990894903305e+00, -6.6188558354865279e+00, -6.4614266877089035e+00, -6.3043976368153372e+00, -6.1477550682134519e+00, -5.9914857411611600e+00, -5.8355767690955807e+00, -5.6800156010969900e+00, -5.5247900044023472e+00, -5.3698880478903845e+00, -5.2152980864665599e+00, -5.0610087462822682e+00, -4.9070089107279511e+00, -4.7532877071444766e+00, -4.5998344942017342e+00, -4.4466388498971172e+00, -4.2936905601303739e+00, -4.1409796078143595e+00, -3.9884961624844180e+00, -3.8362305703715940e+00, -3.6841733449075362e+00, -3.5323151576310980e+00, -3.3806468294686467e+00, -3.2291593223621100e+00, -3.0778437312202702e+00, -2.9266912761707076e+00, -2.7756932950907438e+00, -2.6248412363975424e+00, -2.4741266520783536e+00, -2.3235411909430654e+00, -2.1730765920823036e+00, -2.0227246785151167e+00, -1.8724773510110999e+00, -1.7223265820726865e+00, -1.5722644100637477e+00, -1.4222829334715719e+00, -1.2723743052896335e+00, -1.1225307275089995e+00, -9.7274444570696528e-01, -8.2300774372149477e-01, -6.7331293840074014e-01, -5.2365237441695056e-01, -3.7401841913451778e-01, -2.2440345752197671e-01, -7.4799887098051757e-02, 7.4799887098051757e-02, 2.2440345752197671e-01, 3.7401841913451778e-01, 5.2365237441695056e-01, 6.7331293840074014e-01, 8.2300774372149477e-01, 9.7274444570696528e-01, 1.1225307275089995e+00, 1.2723743052896335e+00, 1.4222829334715719e+00, 1.5722644100637477e+00, 1.7223265820726865e+00, 1.8724773510110999e+00, 2.0227246785151167e+00, 2.1730765920823036e+00, 2.3235411909430654e+00, 2.4741266520783536e+00, 2.6248412363975424e+00, 2.7756932950907438e+00, 2.9266912761707076e+00, 3.0778437312202702e+00, 3.2291593223621100e+00, 3.3806468294686467e+00, 3.5323151576310980e+00, 3.6841733449075362e+00, 3.8362305703715940e+00, 3.9884961624844180e+00, 4.1409796078143595e+00, 4.2936905601303739e+00, 4.4466388498971172e+00, 4.5998344942017342e+00, 4.7532877071444766e+00, 4.9070089107279511e+00, 5.0610087462822682e+00, 5.2152980864665599e+00, 5.3698880478903845e+00, 5.5247900044023472e+00, 5.6800156010969900e+00, 5.8355767690955807e+00, 5.9914857411611600e+00, 6.1477550682134519e+00, 6.3043976368153372e+00, 6.4614266877089035e+00, 6.6188558354865279e+00, 6.7766990894903305e+00, 6.9349708760424020e+00, 7.0936860621182607e+00, 7.2528599805868588e+00, 7.4125084571532707e+00, 7.5726478391539116e+00, 7.7332950263697580e+00, 7.8944675040409047e+00, 8.0561833782850805e+00, 8.2184614141456525e+00, 8.3813210765192689e+00, 8.5447825742424133e+00, 8.7088669076480283e+00, 8.8735959199405876e+00, 9.0389923527798217e+00, 9.2050799065113704e+00, 9.3718833055374660e+00, 9.5394283693840993e+00, 9.7077420900935678e+00, 9.8768527166552929e+00, 1.0046789847284987e+01, 1.0217584530474927e+01, 1.0389269375869560e+01, 1.0561878676174262e+01, 1.0735448541485018e+01, 1.0910017047638791e+01, 1.1085624400434606e+01, 1.1262313117871999e+01, 1.1440128232906956e+01, 1.1619117519647554e+01, 1.1799331746419007e+01, 1.1980824959739557e+01, 1.2163654803990811e+01, 1.2347882882470566e+01, 1.2533575166624548e+01, 1.2720802461619986e+01, 1.2909640938118768e+01, 1.3100172742223814e+01, 1.3292486698232523e+01, 1.3486679122200039e+01, 1.3682854768615876e+01, 1.3881127938034011e+01, 1.4081623780688842e+01, 1.4284479840564213e+01, 1.4489847896889446e+01, 1.4697896176804390e+01, 1.4908812035694833e+01, 1.5122805233008011e+01, 1.5340111975060188e+01, 1.5560999958339213e+01, 1.5785774736307584e+01, 1.6014787864496149e+01, 1.6248447477010238e+01, 1.6487232253468321e+01, 1.6731710220470223e+01, 1.6982564625621777e+01, 1.7240630469775191e+01, 1.7506947669788651e+01, 1.7782841268044042e+01, 1.8070047892967271e+01, 1.8370926385157830e+01, 1.8688834225534919e+01, 1.9028866794578029e+01, 1.9399516717870224e+01, 1.9817257977795947e+01, 2.0325189139629405e+01}, + w: []float64{2.2761605731502931e-180, 1.2490844229282551e-171, 1.4077080884426324e-164, 1.9558070725961945e-158, 6.7396164617778564e-153, 8.3007451278928549e-148, 4.5605427168506885e-143, 1.2952107195320918e-138, 2.1106922482765282e-134, 2.1325182525295938e-130, 1.4176541142180510e-126, 6.4990818384221324e-123, 2.1340663816447175e-119, 5.1782994410611593e-116, 9.5303885471678039e-113, 1.3600769560707746e-109, 1.5337501625076215e-106, 1.3892626373123839e-103, 1.0252931948997944e-100, 6.2430026550428978e-98, 3.1713496923820005e-95, 1.3573663268548106e-92, 4.9385791079870452e-90, 1.5396613562557895e-87, 4.1428768007295419e-85, 9.6845718261332366e-83, 1.9785969337019459e-80, 3.5522955000635345e-78, 5.6327088700629997e-76, 7.9248469784581938e-74, 9.9353884108905009e-72, 1.1143371044053519e-69, 1.1222249771693660e-67, 1.0182568638449594e-65, 8.3508496445242703e-64, 6.2085535684767686e-62, 4.1960840622737107e-60, 2.5847807937901128e-58, 1.4547608917709417e-56, 7.4980265458380947e-55, 3.5467498009174184e-53, 1.5428702374218767e-51, 6.1841637682672203e-50, 2.2881100073201874e-48, 7.8282784948541621e-47, 2.4806114249059706e-45, 7.2916745732054914e-44, 1.9911806078855746e-42, 5.0584298583405264e-41, 1.1970700137586669e-39, 2.6422337190194530e-38, 5.4462015155980312e-37, 1.0495069994748297e-35, 1.8928725655710039e-34, 3.1985659419085236e-33, 5.0689745622498271e-32, 7.5410079936029980e-31, 1.0540919389712685e-29, 1.3856239612378123e-28, 1.7143191474654609e-27, 1.9978524188114189e-26, 2.1947842513043781e-25, 2.2745432296820405e-24, 2.2252271383645215e-23, 2.0564749726923156e-22, 1.7964719327802204e-21, 1.4843379300503135e-20, 1.1606915413845120e-19, 8.5944540731309027e-19, 6.0293824390549243e-18, 4.0096487904356170e-17, 2.5289217277543671e-16, 1.5134484435681475e-15, 8.5980922774659504e-15, 4.6390554602844329e-14, 2.3781148094626393e-13, 1.1587426167580950e-12, 5.3685841373417416e-12, 2.3659835874748833e-11, 9.9219381603477156e-11, 3.9606009206879336e-10, 1.5053791970450186e-09, 5.4498580894419877e-09, 1.8797800781026250e-08, 6.1792198822459984e-08, 1.9363392840773747e-07, 5.7857719375034532e-07, 1.6488403637671232e-06, 4.4826356596959815e-06, 1.1628419918195159e-05, 2.8789242845201347e-05, 6.8037279449589797e-05, 1.5351500720814013e-04, 3.3076323494923371e-04, 6.8063888690970183e-04, 1.3378748383672085e-03, 2.5123201954271616e-03, 4.5076732111920138e-03, 7.7285957578851656e-03, 1.2663915587278220e-02, 1.9833481075447929e-02, 2.9691593353631068e-02, 4.2492045448586743e-02, 5.8137078835965875e-02, 7.6049788530935164e-02, 9.5118681388506904e-02, 1.1375654825578213e-01, 1.3009049092173738e-01, 1.4226074789149157e-01, 1.4876572633109977e-01, 1.4876572633109977e-01, 1.4226074789149157e-01, 1.3009049092173738e-01, 1.1375654825578213e-01, 9.5118681388506904e-02, 7.6049788530935164e-02, 5.8137078835965875e-02, 4.2492045448586743e-02, 2.9691593353631068e-02, 1.9833481075447929e-02, 1.2663915587278220e-02, 7.7285957578851656e-03, 4.5076732111920138e-03, 2.5123201954271616e-03, 1.3378748383672085e-03, 6.8063888690970183e-04, 3.3076323494923371e-04, 1.5351500720814013e-04, 6.8037279449589797e-05, 2.8789242845201347e-05, 1.1628419918195159e-05, 4.4826356596959815e-06, 1.6488403637671232e-06, 5.7857719375034532e-07, 1.9363392840773747e-07, 6.1792198822459984e-08, 1.8797800781026250e-08, 5.4498580894419877e-09, 1.5053791970450186e-09, 3.9606009206879336e-10, 9.9219381603477156e-11, 2.3659835874748833e-11, 5.3685841373417416e-12, 1.1587426167580950e-12, 2.3781148094626393e-13, 4.6390554602844329e-14, 8.5980922774659504e-15, 1.5134484435681475e-15, 2.5289217277543671e-16, 4.0096487904356170e-17, 6.0293824390549243e-18, 8.5944540731309027e-19, 1.1606915413845120e-19, 1.4843379300503135e-20, 1.7964719327802204e-21, 2.0564749726923156e-22, 2.2252271383645215e-23, 2.2745432296820405e-24, 2.1947842513043781e-25, 1.9978524188114189e-26, 1.7143191474654609e-27, 1.3856239612378123e-28, 1.0540919389712685e-29, 7.5410079936029980e-31, 5.0689745622498271e-32, 3.1985659419085236e-33, 1.8928725655710039e-34, 1.0495069994748297e-35, 5.4462015155980312e-37, 2.6422337190194530e-38, 1.1970700137586669e-39, 5.0584298583405264e-41, 1.9911806078855746e-42, 7.2916745732054914e-44, 2.4806114249059706e-45, 7.8282784948541621e-47, 2.2881100073201874e-48, 6.1841637682672203e-50, 1.5428702374218767e-51, 3.5467498009174184e-53, 7.4980265458380947e-55, 1.4547608917709417e-56, 2.5847807937901128e-58, 4.1960840622737107e-60, 6.2085535684767686e-62, 8.3508496445242703e-64, 1.0182568638449594e-65, 1.1222249771693660e-67, 1.1143371044053519e-69, 9.9353884108905009e-72, 7.9248469784581938e-74, 5.6327088700629997e-76, 3.5522955000635345e-78, 1.9785969337019459e-80, 9.6845718261332366e-83, 4.1428768007295419e-85, 1.5396613562557895e-87, 4.9385791079870452e-90, 1.3573663268548106e-92, 3.1713496923820005e-95, 6.2430026550428978e-98, 1.0252931948997944e-100, 1.3892626373123839e-103, 1.5337501625076215e-106, 1.3600769560707746e-109, 9.5303885471678039e-113, 5.1782994410611593e-116, 2.1340663816447175e-119, 6.4990818384221324e-123, 1.4176541142180510e-126, 2.1325182525295938e-130, 2.1106922482765282e-134, 1.2952107195320918e-138, 4.5605427168506885e-143, 8.3007451278928549e-148, 6.7396164617778564e-153, 1.9558070725961945e-158, 1.4077080884426324e-164, 1.2490844229282551e-171, 2.2761605731502931e-180}, + }, + } { + h := Hermite{} + x := make([]float64, test.n) + weight := make([]float64, test.n) + h.FixedLocations(x, weight, math.Inf(-1), math.Inf(1)) + if !floats.EqualApprox(x, test.x, 1e-14) { + t.Errorf("n = %v, x mismatch", test.n) + fmt.Println(x) + fmt.Println() + fmt.Println(test.x) + //t.Errorf("x mismatch. \nWant %v\ngot %v", test.x, x) + } + if !floats.EqualApprox(weight, test.w, 1e-14) { + t.Errorf("n = %v, w mismatch", test.n) + //t.Errorf("w mismatch. Want %v, got %v", test.w, weight) + } + } +} + +func TestHermiteInitialGuesses(t *testing.T) { + for _, test := range []struct { + n int + want []float64 + }{ + // Evaluated from Chebfun. + { + n: 215, + want: []float64{0, 0.151326329763712, 0.302660700793398, 0.454011159911720, 0.605385765065948, 0.756792590918330, 0.908239734470234, 1.059735320731617, 1.211287508447394, 1.362904495892717, 1.514594526749157, 1.666365896074552, 1.818226956379164, 1.970186123821706, 2.122251884538916, 2.274432801123240, 2.426737519263548, 2.579174774564779, 2.731753399562905, 2.884482330952826, 3.037370617047366, 3.190427425487010, 3.343662051220745, 3.497083924780193, 3.650702620869949, 3.804527867299248, 3.958569554281313, 4.112837744128784, 4.267342681375636, 4.422094803358200, 4.577104751290402, 4.732383381871004, 4.887941779463563, 5.043791268893151, 5.199943428907478, 5.356410106353889, 5.513203431128299, 5.670335831956713, 5.827820053075521, 5.985669171882509, 6.143896617637219, 6.302516191296349, 6.461542086578262, 6.620988912359293, 6.780871716514890, 6.941206011329554, 7.102007800612191, 7.263293608667420, 7.425080511288993, 7.587386168959320, 7.750228862458692, 7.913627531110426, 8.077601813913194, 8.242172093840729, 8.407359545621334, 8.573186187346858, 8.739674936302684, 8.906849669458699, 9.074735289116129, 9.243357794268617, 9.412744358308792, 9.582923413795772, 9.753924745096450, 9.925779589826769, 10.098520750150884, 10.272182715150265, 10.446801795655594, 10.622416273146731, 10.799066564577450, 10.976795405279171, 11.155648052452676, 11.335672512180423, 11.516919793401330, 11.699444192903831, 11.883303616137852, 12.068559939553955, 12.255279421290370, 12.443533168399910, 12.633397670509774, 12.824955411930718, 13.018295576901773, 13.213514866037960, 13.410718446364541, 13.610021062878001, 13.811548346792373, 14.015438365098394, 14.221843468615116, 14.430932512542578, 14.642893546366283, 14.857937101386424, 15.076300248006383, 15.298251657131900, 15.524097989861344, 15.754192071913305, 15.988943508292977, 16.228832700713156, 16.474429717130270, 16.726420259572109, 16.985642328947012, 17.253139580754688, 17.530241825363181, 17.818691945179868, 18.120857274390474, 18.440107345774539, 18.781555607447057, 19.153723464992801, 19.573128956064245, 20.082675660407357}, + }, + { + n: 216, + want: []float64{7.5487718957947841e-02, 2.2646713089416223e-01, 3.7745846761172613e-01, 5.2846968803819716e-01, 6.7950876473020116e-01, 8.3058368936317251e-01, 9.8170247825952706e-01, 1.1328731779663146e+00, 1.2841038708939367e+00, 1.4354026810274640e+00, 1.5867777797225648e+00, 1.7382373915984026e+00, 1.8897898005400910e+00, 2.0414433558240375e+00, 2.1932064783796412e+00, 2.3450876672018457e+00, 2.4970955059292010e+00, 2.6492386696032790e+00, 2.8015259316256671e+00, 2.9539661709299665e+00, 3.1065683793869288e+00, 3.2593416694621893e+00, 3.4122952821469283e+00, 3.5654385951833136e+00, 3.7187811316079062e+00, 3.8723325686377130e+00, 4.0261027469252912e+00, 4.1801016802112088e+00, 4.3343395654041350e+00, 4.4888267931211692e+00, 4.6435739587232687e+00, 4.7985918738836766e+00, 4.9538915787298405e+00, 5.1094843546028494e+00, 5.2653817374818566e+00, 5.4215955321250595e+00, 5.5781378269829656e+00, 5.7350210099447425e+00, 5.8922577849835758e+00, 6.0498611897730488e+00, 6.2078446143528714e+00, 6.3662218209298418e+00, 6.5250069649076838e+00, 6.6842146172486627e+00, 6.8438597882796577e+00, 7.0039579530666876e+00, 7.1645250784943162e+00, 7.3255776522003675e+00, 7.4871327135320032e+00, 7.6492078867069049e+00, 7.8118214163831334e+00, 7.9749922058635363e+00, 8.1387398581859554e+00, 8.3030847203790454e+00, 8.4680479311960379e+00, 8.6336514726757141e+00, 8.7999182259219690e+00, 8.9668720315415094e+00, 9.1345377552342626e+00, 9.3029413590944845e+00, 9.4721099792532808e+00, 9.6420720105775217e+00, 9.8128571992374614e+00, 9.9844967440684584e+00, 1.0157023407784097e+01, 1.0330471639251822e+01, 1.0504877708222864e+01, 1.0680279854120787e+01, 1.0856718450743809e+01, 1.1034236189033734e+01, 1.1212878280418622e+01, 1.1392692683659751e+01, 1.1573730358642214e+01, 1.1756045551162156e+01, 1.1939696113507749e+01, 1.2124743866538131e+01, 1.2311255010076101e+01, 1.2499300589800702e+01, 1.2688957030525529e+01, 1.2880306747870632e+01, 1.3073438853003600e+01, 1.3268449968504161e+01, 1.3465445177719724e+01, 1.3664539135531767e+01, 1.3865857375666192e+01, 1.4069537859142688e+01, 1.4275732821001174e+01, 1.4484610989259913e+01, 1.4696360272885402e+01, 1.4911191046953165e+01, 1.5129340207007946e+01, 1.5351076226802732e+01, 1.5576705543358910e+01, 1.5806580725457744e+01, 1.6041111080581306e+01, 1.6280776662107755e+01, 1.6526147125048691e+01, 1.6777907674840002e+01, 1.7036895705202610e+01, 1.7304154114531990e+01, 1.7581011746684457e+01, 1.7869210214084568e+01, 1.8171115120332015e+01, 1.8490093525334313e+01, 1.8831255107137672e+01, 1.9203114954794152e+01, 1.9622178785373663e+01, 2.0131752068311702e+01}, + }, + } { + got := make([]float64, test.n/2+test.n%2) + for i := range got { + got[i] = Hermite{}.hermiteInitialGuess(i, test.n) + } + if !floats.EqualApprox(got, test.want, 1e-14) { + t.Errorf("n = %v, hermite initial guesses mismatch", test.n) + } + } +} + +func TestHermiteLocationsAsy0(t *testing.T) { + for _, test := range []struct { + n int + x []float64 + w []float64 + }{ + // Evaluated from Chebfun. + { + n: 215, + x: []float64{-7.9483151672010196e-15, 1.5132632976672361e-01, 3.0266070079942864e-01, 4.5401115992078167e-01, 6.0538576507805808e-01, 7.5679259093351370e-01, 9.0823973448851325e-01, 1.0597353207530273e+00, 1.2112875084719879e+00, 1.3629044959205205e+00, 1.5145945267802365e+00, 1.6663658961089640e+00, 1.8182269564169717e+00, 1.9701861238629792e+00, 2.1222518845837395e+00, 2.2744328011717010e+00, 2.4267375193157439e+00, 2.5791747746208049e+00, 2.7317533996228827e+00, 2.8844823310168755e+00, 3.0373706171156218e+00, 3.1904274255596032e+00, 3.3436620512978501e+00, 3.4970839248619634e+00, 3.6507026209565665e+00, 3.8045278673909002e+00, 3.9585695543782120e+00, 4.1128377442311503e+00, 4.2673426814837114e+00, 4.4220948034722349e+00, 4.5771047514106780e+00, 4.7323833819978187e+00, 4.8879417795972326e+00, 5.0437912690340267e+00, 5.1999434290559226e+00, 5.3564101065103049e+00, 5.5132034312931157e+00, 5.6703358321303936e+00, 5.8278200532585673e+00, 5.9856691720754620e+00, 6.1438966178406549e+00, 6.3025161915109100e+00, 6.4615420868046280e+00, 6.6209889125982082e+00, 6.7808717167671544e+00, 6.9412060115960434e+00, 7.1020078008938672e+00, 7.2632936089653120e+00, 7.4250805116042331e+00, 7.5873861692931381e+00, 7.7502288628124383e+00, 7.9136275314855800e+00, 8.0776018143113824e+00, 8.2421720942637187e+00, 8.4073595460710955e+00, 8.5731861878255415e+00, 8.7396749368126798e+00, 8.9068496700026394e+00, 9.0747352896969389e+00, 9.2433577948895387e+00, 9.4127443589734394e+00, 9.5829234145081710e+00, 9.7539247458611111e+00, 9.9257795906487338e+00, 1.0098520751035824e+01, 1.0272182716104577e+01, 1.0446801796686490e+01, 1.0622416274262394e+01, 1.0799066565787168e+01, 1.0976795406593546e+01, 1.1155648053883823e+01, 1.1335672513742256e+01, 1.1516919795109878e+01, 1.1699444194777641e+01, 1.1883303618198463e+01, 1.2068559941826503e+01, 1.2255279423804318e+01, 1.2443533171189967e+01, 1.2633397673617059e+01, 1.2824955415404188e+01, 1.3018295580800100e+01, 1.3213514870431910e+01, 1.3410718451340038e+01, 1.3610021068540190e+01, 1.3811548353270942e+01, 1.4015438372554696e+01, 1.4221843477251845e+01, 1.4430932522616979e+01, 1.4642893558208563e+01, 1.4857937115425768e+01, 1.5076300264808333e+01, 1.5298251677453143e+01, 1.5524098014731747e+01, 1.5754192102761674e+01, 1.5988943547145137e+01, 1.6228832750513551e+01, 1.6474429782282726e+01, 1.6726420346886542e+01, 1.6985642449377284e+01, 1.7253139752773148e+01, 1.7530242081974308e+01, 1.7818692349773503e+01, 1.8120857960601569e+01, 1.8440108632764016e+01, 1.8781558404513735e+01, 1.9153731166695263e+01, 1.9573161931385755e+01, 2.0083110126223993e+01}, + w: []float64{5.8004562850365771e-04, 5.6692877486338696e-04, 5.2932867305102921e-04, 4.7211368597165944e-04, 4.0223648470876573e-04, 3.2735218319190782e-04, 2.5446548811048362e-04, 1.8892919855999243e-04, 1.3396711152850057e-04, 9.0718165504482523e-05, 5.8661199606591556e-05, 3.6218251240150691e-05, 2.1349054444552587e-05, 1.2013089019084848e-05, 6.4521031002773646e-06, 3.3071925113778075e-06, 1.6175791039359969e-06, 7.5483313427524376e-07, 3.3600239642860852e-07, 1.4264659961771696e-07, 5.7746366478382785e-08, 2.2286582090203475e-08, 8.1983021699506761e-09, 2.8738670556378732e-09, 9.5976924324201262e-10, 3.0529085215378481e-10, 9.2467927287192434e-11, 2.6660996519674056e-11, 7.3154481204350507e-12, 1.9096325566425540e-12, 4.7409073505752031e-13, 1.1189936218333804e-13, 2.5101111888653927e-14, 5.3492761412487281e-15, 1.0825895304391782e-15, 2.0798005039728529e-16, 3.7912539356931888e-17, 6.5547084049896133e-18, 1.0743122119399353e-18, 1.6684093877262400e-19, 2.4538539136228336e-20, 3.4161583900178126e-21, 4.4991409209589655e-22, 5.6023724685401444e-23, 6.5917775903350454e-24, 7.3239791710744789e-25, 7.6792588730186891e-26, 7.5931172671070367e-27, 7.0751732949679160e-28, 6.2078867832748634e-29, 5.1250608797215456e-30, 3.9778286806416675e-31, 2.9000923323091595e-32, 1.9842934651116758e-33, 1.2729744163019100e-34, 7.6493618655638258e-36, 4.3010461850159373e-37, 2.2604572504006732e-38, 1.1091714341886240e-39, 5.0753225126752125e-41, 2.1629552371814077e-42, 8.5739087326714758e-44, 3.1568681170134092e-45, 1.0780709245918455e-46, 3.4094518277810594e-48, 9.9692987408874913e-50, 2.6905726285477170e-51, 6.6902112757430557e-53, 1.5297458011420645e-54, 3.2099851519180199e-56, 6.1681886704578063e-58, 1.0829083084555836e-59, 1.7328083889009238e-61, 2.5206396804555329e-63, 3.3240965181095399e-65, 3.9623955222122382e-67, 4.2558991248868728e-69, 4.1048947183601511e-71, 3.5424776999043975e-73, 2.7245890408644923e-75, 1.8596929038788086e-77, 1.1213274238978696e-79, 5.9430256314002078e-82, 2.7536336403486887e-84, 1.1087876280230634e-86, 3.8548279808836764e-89, 1.1488445098745636e-91, 2.9118805234147757e-94, 6.2218187764965726e-97, 1.1097458975689325e-99, 1.6341809683598844e-102, 1.9621625424695376e-105, 1.8939702898325753e-108, 1.4459753551186440e-111, 8.5692594596311645e-115, 3.8565449589488849e-118, 1.2843410590864927e-121, 3.0685300780965873e-125, 5.0651104293759753e-129, 5.5131423653412833e-133, 3.7300165435945031e-137, 1.4525522232777015e-141, 2.9352196847507026e-146, 2.6587623615117695e-151, 8.6633861029598960e-157, 7.0653364942986233e-163, 7.2051505413036788e-170, 1.5514139491189097e-178}, + }, + { + n: 216, + x: []float64{7.5487718959414210e-02, 2.2646713089859094e-01, 3.7745846761911317e-01, 5.2846968804856509e-01, 6.7950876474356448e-01, 8.3058368937955573e-01, 9.8170247827895785e-01, 1.1328731779888348e+00, 1.2841038709195900e+00, 1.4354026810562848e+00, 1.5867777797546210e+00, 1.7382373916337388e+00, 1.8897898005787916e+00, 2.0414433558661624e+00, 2.1932064784252856e+00, 2.3450876672510903e+00, 2.4970955059821409e+00, 2.6492386696600243e+00, 2.8015259316863266e+00, 2.9539661709946619e+00, 3.1065683794558021e+00, 3.2593416695353823e+00, 3.4122952822245907e+00, 3.5654385952656149e+00, 3.7187811316950210e+00, 3.8723325687298416e+00, 4.0261027470226392e+00, 4.1801016803139959e+00, 4.3343395655126109e+00, 4.4888267932355790e+00, 4.6435739588438905e+00, 4.7985918740108131e+00, 4.9538915788638089e+00, 5.1094843547439881e+00, 5.2653817376305465e+00, 5.4215955322816969e+00, 5.5781378271479722e+00, 5.7350210101185848e+00, 5.8922577851667635e+00, 6.0498611899661094e+00, 6.2078446145563948e+00, 6.3662218211444577e+00, 6.5250069651340752e+00, 6.6842146174875827e+00, 6.8438597885318986e+00, 7.0039579533331269e+00, 7.1645250787759087e+00, 7.3255776524981444e+00, 7.4871327138470951e+00, 7.6492078870405447e+00, 7.8118214167366684e+00, 7.9749922062384426e+00, 8.1387398585838486e+00, 8.3030847208017082e+00, 8.4680479316454296e+00, 8.6336514731539875e+00, 8.7999182264315081e+00, 8.9668720320849413e+00, 9.1345377558145096e+00, 9.3029413597147883e+00, 9.4721099799172528e+00, 9.6420720112891818e+00, 9.8128572000013108e+00, 9.9844967448895385e+00, 1.0157023408668081e+01, 1.0330471640205081e+01, 1.0504877709252620e+01, 1.0680279855235202e+01, 1.0856718451952171e+01, 1.1034236190346626e+01, 1.1212878281848150e+01, 1.1392692685219812e+01, 1.1573730360348824e+01, 1.1756045553033841e+01, 1.1939696115566026e+01, 1.2124743868808109e+01, 1.2311255012587219e+01, 1.2499300592587632e+01, 1.2688957033629340e+01, 1.2880306751340244e+01, 1.3073438856897617e+01, 1.3268449972893279e+01, 1.3465445182689793e+01, 1.3664539141187824e+01, 1.3865857382137794e+01, 1.4069537866591046e+01, 1.4275732829628778e+01, 1.4484610999323769e+01, 1.4696360284715409e+01, 1.4911191060978103e+01, 1.5129340223792830e+01, 1.5351076247103551e+01, 1.5576705568204593e+01, 1.5806580756275796e+01, 1.6041111119395726e+01, 1.6280776711860355e+01, 1.6526147190139376e+01, 1.6777907762072694e+01, 1.7036895825521608e+01, 1.7304154286393636e+01, 1.7581012003064874e+01, 1.7869210618319627e+01, 1.8171115805943941e+01, 1.8490094811217439e+01, 1.8831257901839155e+01, 1.9203122650098184e+01, 1.9622211733828486e+01, 2.0131752068397390e+01}, + w: []float64{5.7408951238509774e-04, 5.4853385977693967e-04, 5.0077995633045094e-04, 4.3681926493182888e-04, 3.6404534695321319e-04, 2.8986205027358900e-04, 2.2048980967270541e-04, 1.6022189177224014e-04, 1.1121464501100074e-04, 7.3735261435177744e-05, 4.6689968632275442e-05, 2.8233496634858870e-05, 1.6302404527221912e-05, 8.9873835313609794e-06, 4.7299184092204348e-06, 2.3760322139117827e-06, 1.1391060264678187e-06, 5.2109775739704647e-07, 2.2742736124678848e-07, 9.4679280581569520e-08, 3.7589897335857270e-08, 1.4229883676778969e-08, 5.1351173480468011e-09, 1.7661093963625318e-09, 5.7875785413194057e-10, 1.8066600901602130e-10, 5.3707955985666741e-11, 1.5200567246892033e-11, 4.0945877360252466e-12, 1.0494304449814065e-12, 2.5582770078364328e-13, 5.9298335011290506e-14, 1.3064177735039720e-14, 2.7346561920969734e-15, 5.4366757055637182e-16, 1.0261135273171614e-16, 1.8378155831501011e-17, 3.1221798154524404e-18, 5.0287455392773255e-19, 7.6752848097550855e-20, 1.1095334788910946e-20, 1.5183281292392555e-21, 1.9657499371912346e-22, 2.4064442018314010e-23, 2.7838422576260478e-24, 3.0413021389695441e-25, 3.1356913424697775e-26, 3.0490587561112177e-27, 2.7941107980138270e-28, 2.4112340295373517e-29, 1.9579916032501855e-30, 1.4948591683644822e-31, 1.0720958700672810e-32, 7.2163812209007653e-34, 4.5545782039839515e-35, 2.6927171840186886e-36, 1.4896964129251313e-37, 7.7036780004272946e-39, 3.7196117693798106e-40, 1.6748563396289038e-41, 7.0241404150854973e-43, 2.7401344340734534e-44, 9.9291319468776600e-46, 3.3371619908503302e-47, 1.0387276524925886e-48, 2.9893704843803614e-50, 7.9408570659652511e-52, 1.9434716944530867e-53, 4.3740144067322860e-55, 9.0342460240718143e-57, 1.7087495134365174e-58, 2.9528859528856670e-60, 4.6509376421165100e-62, 6.6593952486160953e-64, 8.6442830921042970e-66, 1.0142381095581560e-67, 1.0722439547251424e-69, 1.0179251007077803e-71, 8.6461259693742430e-74, 6.5448969088799971e-76, 4.3965762236216239e-78, 2.6089085327841006e-80, 1.3607099985773063e-82, 6.2039892663366641e-85, 2.4580575133840935e-87, 8.4080554628125066e-90, 2.4652597109139967e-92, 6.1467455174872763e-95, 1.2918545805718045e-97, 2.2661732049781124e-100, 3.2815976681148591e-103, 3.8741015126651295e-106, 3.6760977386321105e-109, 2.7584831111443303e-112, 1.6064052012003602e-115, 7.1024252453209961e-119, 2.3230796238780657e-122, 5.4494213912665180e-126, 8.8284366174946482e-130, 9.4271378060446301e-134, 6.2539251873936211e-138, 2.3865140957941506e-142, 4.7220323342515999e-147, 4.1840743138172546e-152, 1.3319161291512504e-157, 1.0592510752538756e-163, 1.0503755670967946e-170, 2.1869674690632971e-179}, + }, + } { + n := test.n + x := make([]float64, n/2+n%2) + w := make([]float64, n/2+n%2) + for i := range x { + x[i], w[i] = Hermite{}.locationsAsy0(i, n) + } + if !floats.EqualApprox(x, test.x, 1e-13) { + t.Errorf("n = %v, x mismatch", n) + fmt.Println(x[107]) + fmt.Println(test.x[107]) + } + if !floats.EqualApprox(w, test.w, 1e-13) { + t.Errorf("n = %v, w mismatch", n) + } + } +} + +func TestHermiteAsyAiry(t *testing.T) { + for _, test := range []struct { + n int + theta []float64 + val []float64 + dval []float64 + }{ + { + n: 215, + theta: []float64{1.5707963267948966e+00, 1.5635071294267224e+00, 1.5562171573546757e+00, 1.5489256352159648e+00, 1.5416317863284521e+00, 1.5343348320272066e+00, 1.5270339909965103e+00, 1.5197284785957685e+00, 1.5124175061777518e+00, 1.5051002803975593e+00, 1.4977760025106577e+00, 1.4904438676582881e+00, 1.4831030641384946e+00, 1.4757527726609410e+00, 1.4683921655836265e+00, 1.4610204061295120e+00, 1.4536366475809854e+00, 1.4462400324499760e+00, 1.4388296916214274e+00, 1.4314047434676882e+00, 1.4239642929312548e+00, 1.4165074305731233e+00, 1.4090332315838545e+00, 1.4015407547542300e+00, 1.3940290414022056e+00, 1.3864971142525955e+00, 1.3789439762656834e+00, 1.3713686094106747e+00, 1.3637699733795743e+00, 1.3561470042367485e+00, 1.3484986129990375e+00, 1.3408236841408716e+00, 1.3331210740183812e+00, 1.3253896092059803e+00, 1.3176280847383373e+00, 1.3098352622500289e+00, 1.3020098680044709e+00, 1.2941505908029671e+00, 1.2862560797638511e+00, 1.2783249419607658e+00, 1.2703557399080556e+00, 1.2623469888800907e+00, 1.2542971540500127e+00, 1.2462046474319508e+00, 1.2380678246090893e+00, 1.2298849812281600e+00, 1.2216543492388388e+00, 1.2133740928542220e+00, 1.2050423042059359e+00, 1.1966569986644591e+00, 1.1882161097919153e+00, 1.1797174838907749e+00, 1.1711588741076131e+00, 1.1625379340461441e+00, 1.1538522108381697e+00, 1.1450991376146524e+00, 1.1362760253118058e+00, 1.1273800537386238e+00, 1.1184082618225748e+00, 1.1093575369389341e+00, 1.1002246032162142e+00, 1.0910060086950395e+00, 1.0816981112001869e+00, 1.0722970627649082e+00, 1.0627987924225111e+00, 1.0531989871517369e+00, 1.0434930707289145e+00, 1.0336761802000907e+00, 1.0237431396389916e+00, 1.0136884308001370e+00, 1.0035061602085740e+00, 9.9319002214595331e-01, 9.8273325689369295e-01, 9.7212860347355579e-01, 9.6136824597870241e-01, 9.5044375240720391e-01, 9.3934600468605900e-01, 9.2806511829511895e-01, 9.1659034955139063e-01, 9.0490998817422319e-01, 8.9301123219309975e-01, 8.8088004154453947e-01, 8.6850096578161351e-01, 8.5585694011780433e-01, 8.4292904244735056e-01, 8.2969620188675874e-01, 8.1613484656631152e-01, 8.0221847457494289e-01, 7.8791712669745728e-01, 7.7319673223616503e-01, 7.5801828879746735e-01, 7.4233682191908168e-01, 7.2610004838413222e-01, 7.0924663405346811e-01, 6.9170388642137270e-01, 6.7338464244284535e-01, 6.5418298314185364e-01, 6.3396819041411068e-01, 6.1257598542667102e-01, 5.8979540387821172e-01, 5.6534835113739590e-01, 5.3885619819698471e-01, 5.0978185232293227e-01, 4.7732127920035572e-01, 4.4017830784988765e-01, 3.9602307074600884e-01, 3.3985069280702440e-01, 2.5624520569356829e-01}, + val: []float64{-2.7524590607067879e-13, -1.2484792737707130e-10, 2.5043777255407545e-10, -3.7621487726711831e-10, 5.0266571286479591e-10, -6.3022107051014496e-10, 7.5847898514904004e-10, -8.8850597267422281e-10, 1.0201287099545048e-09, -1.1532700149758681e-09, 1.2885402426941860e-09, -1.4262514564750722e-09, 1.5667774694950304e-09, -1.7098460348004283e-09, 1.8563663242006209e-09, -2.0060430373954962e-09, 2.1597272205910619e-09, -2.3174687646872261e-09, 2.4795270439737100e-09, -2.6462815453642877e-09, 2.8188431716836157e-09, -2.9962948915230151e-09, 3.1805879826447352e-09, -3.3709772507788239e-09, 3.5681573894354513e-09, -3.7732681484183285e-09, 3.9863813736176932e-09, -4.2080297462347532e-09, 4.4391671460302399e-09, -4.6802436355831232e-09, 4.9322546933533433e-09, -5.1957881449299223e-09, 5.4715433664057677e-09, -5.7608265327475837e-09, 6.0644153161437157e-09, -6.3835515563504339e-09, 6.7192819880764795e-09, -7.0729371214636086e-09, 7.4458702579674617e-09, -7.8396410076078555e-09, 8.2556088536449877e-09, -8.6960989460562939e-09, 9.1626310723815202e-09, -9.6575986146054327e-09, 1.0182896152806950e-08, -1.0741758184989815e-08, 1.1337214303287172e-08, -1.1971481080324528e-08, 1.2648762056240369e-08, -1.3372488830525768e-08, 1.4147041859097387e-08, -1.4977276046958432e-08, 1.5868475891599271e-08, -1.6825823997480545e-08, 1.7856900524878266e-08, -1.8967833880184117e-08, 2.0167708166421882e-08, -2.1465280681285451e-08, 2.2870631970634630e-08, -2.4395881051717265e-08, 2.6054060647767539e-08, -2.7859818527100110e-08, 2.9830454146699167e-08, -3.1984835487787522e-08, 3.4345470368342559e-08, -3.6937900081988413e-08, 3.9790883510012329e-08, -4.2938418365980210e-08, 4.6419377177480922e-08, -5.0279213559974237e-08, 5.4570799296449321e-08, -5.9356303125081130e-08, 6.4708755363671345e-08, -7.0714511032393380e-08, 7.7475892426711618e-08, -8.5115456468135130e-08, 9.3779863576446978e-08, -1.0364644483987255e-07, 1.1493006182865740e-07, -1.2789317815470753e-07, 1.4285900893044798e-07, -1.6022759919461249e-07, 1.8049814080062288e-07, -2.0429953256541455e-07, 2.3243044535889061e-07, -2.6591504027157263e-07, 3.0608147425737922e-07, -3.5467098673335754e-07, 4.1399606056878556e-07, -4.8716979156405424e-07, 5.7844824292016844e-07, -6.9374768843585542e-07, 8.4144962449118331e-07, -1.0336795693201387e-06, 1.2884020459910342e-06, -1.6329629222918408e-06, 2.1103031286712709e-06, -2.7903321871954755e-06, 3.7918023218017778e-06, -5.3269144947324421e-06, 7.7989206456257246e-06, -1.2034979469568085e-05, 1.9905658561076196e-05, -3.6224899321604820e-05, 7.5828952282754516e-05, -1.9870421394114517e-04, 7.9136577883937422e-04, -9.1266148556594703e-03}, + dval: []float64{-2.9359856130945122e+01, 2.9359466144908318e+01, -2.9358296010652477e+01, 2.9356345199427643e+01, -2.9353612829040124e+01, 2.9350097662433203e+01, -2.9345798105693621e+01, 2.9340712205476308e+01, -2.9334837645838910e+01, 2.9328171744474840e+01, -2.9320711448331572e+01, 2.9312453328598885e+01, -2.9303393575049100e+01, 2.9293527989709109e+01, -2.9282851979841201e+01, 2.9271360550207458e+01, -2.9259048294588819e+01, 2.9245909386527540e+01, -2.9231937569258221e+01, 2.9217126144788914e+01, -2.9201467962090302e+01, 2.9184955404346876e+01, -2.9167580375219231e+01, 2.9149334284062498e+01, -2.9130208030040425e+01, 2.9110191985068752e+01, -2.9089275975516287e+01, 2.9067449262584436e+01, -2.9044700521279459e+01, 2.9021017817883425e+01, -2.8996388585821325e+01, 2.8970799599811933e+01, -2.8944236948180023e+01, 2.8916686003195348e+01, -2.8888131389291605e+01, 2.8858556949003951e+01, -2.8827945706448649e+01, 2.8796279828150279e+01, -2.8763540581003511e+01, 2.8729708287134507e+01, -2.8694762275403512e+01, 2.8658680829263385e+01, -2.8621441130659093e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061927e+01, -2.8460401380051497e+01, 2.8416985091874277e+01, -2.8372246774642264e+01, 2.8326153912823031e+01, -2.8278672247129006e+01, 2.8229765661486788e+01, -2.8179396060166667e+01, 2.8127523234037287e+01, -2.8074104714780372e+01, 2.8019095615750665e+01, -2.7962448457994284e+01, 2.7904112979739956e+01, -2.7844035927448619e+01, 2.7782160826241125e+01, -2.7718427727214667e+01, 2.7652772928798932e+01, -2.7585128668881747e+01, 2.7515422783940370e+01, -2.7443578330833645e+01, 2.7369513166223737e+01, -2.7293139477783004e+01, 2.7214363260373997e+01, -2.7133083729234610e+01, 2.7049192660814331e+01, -2.6962573650237655e+01, 2.6873101272350414e+01, -2.6780640130847800e+01, 2.6685043776981303e+01, -2.6586153475654008e+01, 2.6483796792158788e+01, -2.6377785967154090e+01, 2.6267916040395331e+01, -2.6153962674834343e+01, 2.6035679621411951e+01, -2.5912795750458177e+01, 2.5785011557068390e+01, -2.5651995023754676e+01, 2.5513376692151432e+01, -2.5368743753874771e+01, 2.5217632914945654e+01, -2.5059521712941240e+01, 2.4893817863127197e+01, -2.4719846067215368e+01, 2.4536831517922174e+01, -2.4343879046260469e+01, 2.4139946442705973e+01, -2.3923809867871942e+01, 2.3694018337866666e+01, -2.3448832829666316e+01, 2.3186143264519330e+01, -2.2903352884396824e+01, 2.2597213200674400e+01, -2.2263581543467414e+01, 2.1897052703993687e+01, -2.1490376258364485e+01, 2.1033488463000687e+01, -2.0511802124454178e+01, 1.9902938182242686e+01, -1.9169784832381577e+01, 1.8243381598901596e+01, -1.6969663168974311e+01, 1.4853826851969115e+01}, + }, + { + n: 215, + theta: []float64{1.5707963267948968e+00, 1.5635071294265777e+00, 1.5562171573543850e+00, 1.5489256352155283e+00, 1.5416317863278686e+00, 1.5343348320264747e+00, 1.5270339909956292e+00, 1.5197284785947358e+00, 1.5124175061765655e+00, 1.5051002803962170e+00, 1.4977760025091569e+00, 1.4904438676566254e+00, 1.4831030641366665e+00, 1.4757527726589439e+00, 1.4683921655814560e+00, 1.4610204061271637e+00, 1.4536366475784539e+00, 1.4462400324472560e+00, 1.4388296916185130e+00, 1.4314047434645731e+00, 1.4239642929279313e+00, 1.4165074305695844e+00, 1.4090332315800913e+00, 1.4015407547502341e+00, 1.3940290413979675e+00, 1.3864971142481046e+00, 1.3789439762609286e+00, 1.3713686094056443e+00, 1.3637699733742550e+00, 1.3561470042311266e+00, 1.3484986129930978e+00, 1.3408236841345980e+00, 1.3331210740117563e+00, 1.3253896091989852e+00, 1.3176280847309516e+00, 1.3098352622422307e+00, 1.3020098679962364e+00, 1.2941505907942705e+00, 1.2862560797546647e+00, 1.2783249419510594e+00, 1.2703557398977969e+00, 1.2623469888692436e+00, 1.2542971540385390e+00, 1.2462046474198085e+00, 1.2380678245962331e+00, 1.2298849812145400e+00, 1.2216543492243996e+00, 1.2133740928389052e+00, 1.2050423041896758e+00, 1.1966569986471847e+00, 1.1882161097735480e+00, 1.1797174838712285e+00, 1.1711588740867924e+00, 1.1625379340239450e+00, 1.1538522108144755e+00, 1.1450991375893356e+00, 1.1362760252847235e+00, 1.1273800537096179e+00, 1.1184082617914692e+00, 1.1093575369055320e+00, 1.1002246031802951e+00, 1.0910060086563567e+00, 1.0816981111584625e+00, 1.0722970627198296e+00, 1.0627987923737243e+00, 1.0531989870988405e+00, 1.0434930706714527e+00, 1.0336761801375436e+00, 1.0237431395707643e+00, 1.0136884307255469e+00, 1.0035061601268345e+00, 9.9319002205615470e-01, 9.8273325679477930e-01, 9.7212860336429585e-01, 9.6136824585765468e-01, 9.5044375227267230e-01, 9.3934600453603823e-01, 9.2806511812722514e-01, 9.1659034936277473e-01, 9.0490998796145916e-01, 8.9301123195204113e-01, 8.8088004127013353e-01, 8.6850096546765831e-01, 8.5585693975662547e-01, 8.4292904202937069e-01, 8.2969620139991496e-01, 8.1613484599525510e-01, 8.0221847389992995e-01, 7.8791712589278218e-01, 7.7319673126791522e-01, 7.5801828762024448e-01, 7.4233682047111893e-01, 7.2610004657985505e-01, 7.0924663177187774e-01, 6.9170388348738876e-01, 6.7338463859636577e-01, 6.5418297798453895e-01, 6.3396818331389482e-01, 6.1257597533770680e-01, 5.8979538898074346e-01, 5.6534832806423485e-01, 5.3885616021897675e-01, 5.0978178458826806e-01, 4.7732114425935024e-01, 4.4017799165717791e-01, 3.9602210904603868e-01, 3.3984592789666196e-01, 2.5616263514373872e-01}, + val: []float64{-2.7524577037687927e-13, -1.3157296144588393e-13, -1.4217705189589319e-13, -9.3051784272423659e-14, 6.2263913433904649e-14, -7.2338165854311426e-14, 1.6489823942055246e-13, 8.2086154015730068e-14, 1.7030857773598118e-13, 1.9200825273544764e-13, 3.4144423192398587e-13, -1.3350292964848512e-13, 7.7406393378692183e-16, 3.0802286839980475e-15, 1.0626665274130983e-13, 9.7508116816654928e-14, -1.2286283979350783e-13, 1.6602061523803380e-13, 1.2145800400612989e-14, -2.0125760394077007e-13, 1.1752853222876857e-13, 1.5246361311903834e-13, -1.7100196342840500e-13, -9.0852635256292980e-14, -7.8101776477326909e-14, -8.6215405399587178e-14, -1.8424041061507494e-13, -1.7748959370373156e-13, 1.6659488983250428e-14, -2.3029664495695825e-14, 4.9882044749360307e-14, -1.6935708059066857e-13, -1.6889419531778083e-14, -1.5488691966202885e-13, 4.7496471682336465e-15, -6.0236075531674274e-14, -4.7790439973748918e-14, 1.0528243973915236e-14, -1.4481370116381506e-13, 4.8870674172048881e-14, 5.9145722182844837e-14, -3.6252017525118028e-14, -1.4799821290649442e-13, 7.8483748114372226e-14, -3.1698431394015554e-14, -2.1250000650523357e-13, -1.2207160366356720e-13, -4.4799710774576449e-14, -6.6076225108040054e-14, 4.9432907671096125e-14, 1.1714372287574581e-13, 7.1071624668919607e-14, -1.4699620399669987e-13, 4.9028118279404591e-14, 5.6995970859340297e-15, 1.8655926516135062e-14, 3.2409175615798361e-14, 7.1510069979380908e-14, -7.2558225742592175e-14, 4.1294505314113302e-14, -1.8304081875904709e-14, 1.3492357431194347e-13, -2.0526864648283952e-13, 1.1949578558177085e-14, 5.3441698191945163e-14, 4.9207462229933007e-14, -1.9962117626180037e-13, 8.2375100050737861e-15, 5.8811770905000782e-14, -3.8856969371752553e-15, 4.8345877891596704e-14, -1.2020353849039574e-13, 1.0795889278969854e-14, 2.7165003590955340e-14, 7.9664181703224841e-15, -3.1357633506603503e-14, 3.0114465704049404e-14, 5.4841545026050259e-14, 8.3356466046602926e-14, 3.4875109219720919e-14, 5.3887688890067731e-14, -8.5090430827758076e-15, 1.4753806570541977e-14, 4.1314792687095403e-15, 2.8114340045724569e-14, -8.9380771455156681e-15, -3.2451925819727029e-14, 5.0739464388639648e-14, 5.2751575373088884e-14, 3.8348847777085630e-14, -3.1825724566756715e-14, 6.6426259272244758e-14, -6.4295491511138863e-14, 8.9401622475124014e-15, 2.5866873030708164e-14, 9.6302605421508054e-14, 4.6623114840341440e-14, -1.7497072577375209e-14, 3.3453526916664849e-14, -5.5592329550244261e-14, 1.4115683421722400e-13, -3.9306913138151204e-13, 1.2007938611150981e-12, -4.7530501604406474e-12, 2.5399685303214922e-11, -2.2827587443604869e-10, 5.3187001008179367e-09, -1.4222383864770318e-06}, + dval: []float64{-2.9359856130945126e+01, 2.9359466144908307e+01, -2.9358296010652474e+01, 2.9356345199427643e+01, -2.9353612829040117e+01, 2.9350097662433203e+01, -2.9345798105693628e+01, 2.9340712205476311e+01, -2.9334837645838906e+01, 2.9328171744474847e+01, -2.9320711448331569e+01, 2.9312453328598881e+01, -2.9303393575049114e+01, 2.9293527989709105e+01, -2.9282851979841208e+01, 2.9271360550207465e+01, -2.9259048294588812e+01, 2.9245909386527540e+01, -2.9231937569258211e+01, 2.9217126144788910e+01, -2.9201467962090309e+01, 2.9184955404346905e+01, -2.9167580375219234e+01, 2.9149334284062515e+01, -2.9130208030040418e+01, 2.9110191985068738e+01, -2.9089275975516284e+01, 2.9067449262584432e+01, -2.9044700521279456e+01, 2.9021017817883422e+01, -2.8996388585821315e+01, 2.8970799599811926e+01, -2.8944236948180027e+01, 2.8916686003195355e+01, -2.8888131389291594e+01, 2.8858556949003940e+01, -2.8827945706448645e+01, 2.8796279828150276e+01, -2.8763540581003515e+01, 2.8729708287134510e+01, -2.8694762275403530e+01, 2.8658680829263389e+01, -2.8621441130659079e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061930e+01, -2.8460401380051490e+01, 2.8416985091874288e+01, -2.8372246774642264e+01, 2.8326153912823038e+01, -2.8278672247129016e+01, 2.8229765661486780e+01, -2.8179396060166667e+01, 2.8127523234037294e+01, -2.8074104714780368e+01, 2.8019095615750661e+01, -2.7962448457994284e+01, 2.7904112979739949e+01, -2.7844035927448619e+01, 2.7782160826241114e+01, -2.7718427727214678e+01, 2.7652772928798946e+01, -2.7585128668881751e+01, 2.7515422783940377e+01, -2.7443578330833653e+01, 2.7369513166223744e+01, -2.7293139477783015e+01, 2.7214363260374000e+01, -2.7133083729234624e+01, 2.7049192660814349e+01, -2.6962573650237655e+01, 2.6873101272350418e+01, -2.6780640130847814e+01, 2.6685043776981328e+01, -2.6586153475654026e+01, 2.6483796792158806e+01, -2.6377785967154097e+01, 2.6267916040395356e+01, -2.6153962674834389e+01, 2.6035679621411997e+01, -2.5912795750458240e+01, 2.5785011557068451e+01, -2.5651995023754750e+01, 2.5513376692151542e+01, -2.5368743753874902e+01, 2.5217632914945817e+01, -2.5059521712941454e+01, 2.4893817863127474e+01, -2.4719846067215741e+01, 2.4536831517922678e+01, -2.4343879046261161e+01, 2.4139946442706947e+01, -2.3923809867873366e+01, 2.3694018337868730e+01, -2.3448832829669414e+01, 2.3186143264524166e+01, -2.2903352884404576e+01, 2.2597213200687420e+01, -2.2263581543490410e+01, 2.1897052704036881e+01, -2.1490376258452002e+01, 2.1033488463196051e+01, -2.0511802124949831e+01, 1.9902938183741984e+01, -1.9169784838249630e+01, 1.8243381633602635e+01, -1.6969663610835688e+01, 1.4853865657323199e+01}, + }, + { + n: 215, + theta: []float64{1.5707963267948970e+00, 1.5635071294265774e+00, 1.5562171573543853e+00, 1.5489256352155283e+00, 1.5416317863278686e+00, 1.5343348320264747e+00, 1.5270339909956290e+00, 1.5197284785947358e+00, 1.5124175061765652e+00, 1.5051002803962172e+00, 1.4977760025091564e+00, 1.4904438676566252e+00, 1.4831030641366665e+00, 1.4757527726589439e+00, 1.4683921655814558e+00, 1.4610204061271639e+00, 1.4536366475784541e+00, 1.4462400324472562e+00, 1.4388296916185130e+00, 1.4314047434645729e+00, 1.4239642929279310e+00, 1.4165074305695846e+00, 1.4090332315800915e+00, 1.4015407547502341e+00, 1.3940290413979675e+00, 1.3864971142481046e+00, 1.3789439762609288e+00, 1.3713686094056441e+00, 1.3637699733742550e+00, 1.3561470042311266e+00, 1.3484986129930978e+00, 1.3408236841345977e+00, 1.3331210740117563e+00, 1.3253896091989850e+00, 1.3176280847309516e+00, 1.3098352622422307e+00, 1.3020098679962364e+00, 1.2941505907942705e+00, 1.2862560797546649e+00, 1.2783249419510594e+00, 1.2703557398977969e+00, 1.2623469888692436e+00, 1.2542971540385393e+00, 1.2462046474198085e+00, 1.2380678245962331e+00, 1.2298849812145398e+00, 1.2216543492243999e+00, 1.2133740928389052e+00, 1.2050423041896758e+00, 1.1966569986471847e+00, 1.1882161097735477e+00, 1.1797174838712285e+00, 1.1711588740867926e+00, 1.1625379340239450e+00, 1.1538522108144755e+00, 1.1450991375893356e+00, 1.1362760252847235e+00, 1.1273800537096179e+00, 1.1184082617914692e+00, 1.1093575369055320e+00, 1.1002246031802951e+00, 1.0910060086563569e+00, 1.0816981111584627e+00, 1.0722970627198296e+00, 1.0627987923737243e+00, 1.0531989870988405e+00, 1.0434930706714529e+00, 1.0336761801375436e+00, 1.0237431395707643e+00, 1.0136884307255469e+00, 1.0035061601268345e+00, 9.9319002205615448e-01, 9.8273325679477930e-01, 9.7212860336429585e-01, 9.6136824585765468e-01, 9.5044375227267230e-01, 9.3934600453603823e-01, 9.2806511812722525e-01, 9.1659034936277461e-01, 9.0490998796145927e-01, 8.9301123195204102e-01, 8.8088004127013353e-01, 8.6850096546765831e-01, 8.5585693975662547e-01, 8.4292904202937069e-01, 8.2969620139991496e-01, 8.1613484599525521e-01, 8.0221847389993006e-01, 7.8791712589278207e-01, 7.7319673126791533e-01, 7.5801828762024459e-01, 7.4233682047111904e-01, 7.2610004657985516e-01, 7.0924663177187774e-01, 6.9170388348738865e-01, 6.7338463859636599e-01, 6.5418297798453884e-01, 6.3396818331389482e-01, 6.1257597533770669e-01, 5.8979538898074335e-01, 5.6534832806423441e-01, 5.3885616021897553e-01, 5.0978178458826395e-01, 4.7732114425933253e-01, 4.4017799165707200e-01, 3.9602210904493385e-01, 3.3984592786463697e-01, 2.5616262227240338e-01}, + val: []float64{-4.8194502666337268e-14, -1.8219292956257052e-14, 8.5393034645390052e-14, -9.3051784272423659e-14, 6.2263913433904649e-14, -7.2338165854311426e-14, -6.2580913476718581e-14, 8.2086154015730068e-14, -5.7165830534287467e-14, -3.5936383892293965e-14, -1.1380084519138131e-13, 9.4176333524136458e-14, 7.7406393378692183e-16, 3.0802286839980475e-15, -2.3573275472589349e-13, -1.3018327378045775e-13, 1.0520206501483371e-13, -6.2213644291038904e-14, 1.2145800400612989e-14, 2.7271297683652584e-14, -2.2535922871268711e-13, -7.6298928186738198e-14, 1.7255690675064885e-13, -9.0852635256292980e-14, -7.8101776477326909e-14, -8.6215405399587178e-14, 4.5189259409156241e-14, 1.6773935900994068e-13, 1.6659488983250428e-14, -2.3029664495695825e-14, 4.9882044749360307e-14, 1.1850055135335312e-13, -1.6889419531778083e-14, 7.5802404690310745e-14, 4.7496471682336465e-15, -6.0236075531674274e-14, -4.7790439973748918e-14, 1.0528243973915236e-14, 2.0302122716337677e-13, 4.8870674172048881e-14, 5.9145722182844837e-14, -3.6252017525118028e-14, 2.6839385139099395e-14, 7.8483748114372226e-14, -3.1698431394015554e-14, -3.7141479062747567e-14, 1.1275835568784933e-13, -4.4799710774576449e-14, -6.6076225108040054e-14, 4.9432907671096125e-14, -1.1915508175098585e-13, 7.1071624668919607e-14, 1.4874359999295257e-13, 4.9028118279404591e-14, 5.6995970859340297e-15, 1.8655926516135062e-14, 3.2409175615798361e-14, 7.1510069979380908e-14, -7.2558225742592175e-14, 4.1294505314113302e-14, -1.8304081875904709e-14, -4.6448090671875563e-14, 9.6949756857760571e-14, 1.1949578558177085e-14, 5.3441698191945163e-14, 4.9207462229933007e-14, -1.6005168277506475e-14, 8.2375100050737861e-15, 5.8811770905000782e-14, -3.8856969371752553e-15, 4.8345877891596704e-14, 9.6875037765842389e-14, 1.0795889278969854e-14, 2.7165003590955340e-14, 7.9664181703224841e-15, -3.1357633506603503e-14, 3.0114465704049404e-14, 5.4841606599486569e-14, 1.9665914005907120e-14, -2.8849555274550242e-14, -4.2752529356173103e-14, -8.5090430827758076e-15, 1.4753806570541977e-14, 4.1314792687095403e-15, 2.8114340045724569e-14, -8.9380771455156681e-15, 3.6308713608736668e-16, -4.9851972317585696e-14, -9.9115770904832069e-14, -1.2903366624947848e-14, 5.3938844852967152e-14, -3.7521135648997941e-14, 4.0086325460559029e-14, 8.9401622475124014e-15, -9.8967441436620103e-14, -6.5207531930586132e-14, 4.6622484011593159e-14, -1.7497072577375209e-14, 3.3453526916664849e-14, 4.8715471045751314e-14, 3.3943255654417215e-14, 5.7122398702729805e-15, -9.4574045519538209e-16, 7.2999684957756045e-15, 2.7503783126358897e-14, -7.8728766754343666e-15, 3.5695346037194369e-14, -6.2144904069338325e-14}, + dval: []float64{-2.9359856130945122e+01, 2.9359466144908321e+01, -2.9358296010652467e+01, 2.9356345199427643e+01, -2.9353612829040117e+01, 2.9350097662433203e+01, -2.9345798105693628e+01, 2.9340712205476311e+01, -2.9334837645838913e+01, 2.9328171744474844e+01, -2.9320711448331572e+01, 2.9312453328598878e+01, -2.9303393575049114e+01, 2.9293527989709105e+01, -2.9282851979841219e+01, 2.9271360550207469e+01, -2.9259048294588819e+01, 2.9245909386527547e+01, -2.9231937569258211e+01, 2.9217126144788914e+01, -2.9201467962090305e+01, 2.9184955404346880e+01, -2.9167580375219234e+01, 2.9149334284062515e+01, -2.9130208030040418e+01, 2.9110191985068738e+01, -2.9089275975516287e+01, 2.9067449262584439e+01, -2.9044700521279456e+01, 2.9021017817883422e+01, -2.8996388585821315e+01, 2.8970799599811929e+01, -2.8944236948180027e+01, 2.8916686003195352e+01, -2.8888131389291594e+01, 2.8858556949003940e+01, -2.8827945706448645e+01, 2.8796279828150276e+01, -2.8763540581003500e+01, 2.8729708287134510e+01, -2.8694762275403530e+01, 2.8658680829263389e+01, -2.8621441130659086e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061934e+01, -2.8460401380051490e+01, 2.8416985091874288e+01, -2.8372246774642264e+01, 2.8326153912823038e+01, -2.8278672247129023e+01, 2.8229765661486780e+01, -2.8179396060166667e+01, 2.8127523234037294e+01, -2.8074104714780368e+01, 2.8019095615750661e+01, -2.7962448457994284e+01, 2.7904112979739949e+01, -2.7844035927448619e+01, 2.7782160826241114e+01, -2.7718427727214678e+01, 2.7652772928798939e+01, -2.7585128668881751e+01, 2.7515422783940377e+01, -2.7443578330833653e+01, 2.7369513166223744e+01, -2.7293139477783015e+01, 2.7214363260374000e+01, -2.7133083729234624e+01, 2.7049192660814349e+01, -2.6962573650237655e+01, 2.6873101272350418e+01, -2.6780640130847814e+01, 2.6685043776981328e+01, -2.6586153475654026e+01, 2.6483796792158806e+01, -2.6377785967154097e+01, 2.6267916040395356e+01, -2.6153962674834375e+01, 2.6035679621411987e+01, -2.5912795750458244e+01, 2.5785011557068451e+01, -2.5651995023754750e+01, 2.5513376692151542e+01, -2.5368743753874902e+01, 2.5217632914945817e+01, -2.5059521712941446e+01, 2.4893817863127481e+01, -2.4719846067215748e+01, 2.4536831517922678e+01, -2.4343879046261172e+01, 2.4139946442706954e+01, -2.3923809867873342e+01, 2.3694018337868730e+01, -2.3448832829669424e+01, 2.3186143264524159e+01, -2.2903352884404576e+01, 2.2597213200687420e+01, -2.2263581543490410e+01, 2.1897052704036888e+01, -2.1490376258451999e+01, 2.1033488463196083e+01, -2.0511802124949803e+01, 1.9902938183742044e+01, -1.9169784838249644e+01, 1.8243381633602628e+01, -1.6969663610835667e+01, 1.4853865657324123e+01}, + }, + { + n: 216, + theta: []float64{1.5671686105755729e+00, 1.5599127961686350e+00, 1.5526558355349958e+00, 1.5453969634500344e+00, 1.5381354130763418e+00, 1.5308704153134880e+00, 1.5236011981426352e+00, 1.5163269859644990e+00, 1.5090469989291080e+00, 1.5017604522557937e+00, 1.4944665555417909e+00, 1.4871645120577743e+00, 1.4798535180286077e+00, 1.4725327618975033e+00, 1.4652014235717277e+00, 1.4578586736478822e+00, 1.4505036726147191e+00, 1.4431355700313173e+00, 1.4357535036783504e+00, 1.4283565986800277e+00, 1.4209439665941588e+00, 1.4135147044676193e+00, 1.4060678938543345e+00, 1.3986025997926903e+00, 1.3911178697390723e+00, 1.3836127324540022e+00, 1.3760861968370792e+00, 1.3685372507066480e+00, 1.3609648595198076e+00, 1.3533679650280226e+00, 1.3457454838632317e+00, 1.3380963060489126e+00, 1.3304192934301153e+00, 1.3227132780159603e+00, 1.3149770602275335e+00, 1.3072094070434859e+00, 1.2994090500349611e+00, 1.2915746832807011e+00, 1.2837049611523335e+00, 1.2757984959588993e+00, 1.2678538554386305e+00, 1.2598695600848058e+00, 1.2518440802912205e+00, 1.2437758333013242e+00, 1.2356631799434625e+00, 1.2275044211328083e+00, 1.2192977941185159e+00, 1.2110414684522999e+00, 1.2027335416520410e+00, 1.1943720345310531e+00, 1.1859548861603062e+00, 1.1774799484271210e+00, 1.1689449801495315e+00, 1.1603476407006212e+00, 1.1516854830915373e+00, 1.1429559464555037e+00, 1.1341563478678038e+00, 1.1252838734282915e+00, 1.1163355685232694e+00, 1.1073083271723616e+00, 1.0981988803530085e+00, 1.0890037831801158e+00, 1.0797194008007944e+00, 1.0703418928435628e+00, 1.0608671962372638e+00, 1.0512910061865695e+00, 1.0416087550574320e+00, 1.0318155888861182e+00, 1.0219063411782010e+00, 1.0118755036074250e+00, 1.0017171931566209e+00, 9.9142511516121901e-01, 9.8099252161709072e-01, 9.7041216399420693e-01, 9.5967623965057169e-01, 9.4877633076008561e-01, 9.3770333444439402e-01, 9.2644738252057113e-01, 9.1499774892808761e-01, 9.0334274245922008e-01, 8.9146958185913860e-01, 8.7936424964779292e-01, 8.6701132009412707e-01, 8.5439375557323693e-01, 8.4149266395991695e-01, 8.2828700761781482e-01, 8.1475325173188318e-01, 8.0086493591225205e-01, 7.8659214774134534e-01, 7.7190086960046345e-01, 7.5675215971653753e-01, 7.4110111338801099e-01, 7.2489552835323978e-01, 7.0807416530075917e-01, 6.9056444397251160e-01, 6.7227933577676646e-01, 6.5311308498739518e-01, 6.3293517484306561e-01, 6.1158157942775537e-01, 5.8884165912926645e-01, 5.6443774724725360e-01, 5.3799179737419422e-01, 5.0896754324534177e-01, 4.7656218794974137e-01, 4.3948155571863207e-01, 3.9539936631707273e-01, 3.3931845258954985e-01, 2.5576413756997579e-01}, + val: []float64{6.1063360924047490e-11, -1.8435203658490556e-10, 3.0743162265786900e-10, -4.3161999307057153e-10, 5.5600184481941261e-10, -6.8154103751235407e-10, 8.0806640731641332e-10, -9.3648670703302450e-10, 1.0665511846836497e-09, -1.1984227187029326e-09, 1.3320294714997634e-09, -1.4683350272554789e-09, 1.6073141540400390e-09, -1.7488108299475996e-09, 1.8942373170611600e-09, -2.0425637634202854e-09, 2.1952560444756934e-09, -2.3517907718469464e-09, 2.5131243047743498e-09, -2.6788312866718815e-09, 2.8501736508238295e-09, -3.0272882762354559e-09, 3.2101466593235099e-09, -3.3995591281295402e-09, 3.5962230906180571e-09, -3.8005765479605162e-09, 4.0130477356611703e-09, -4.2339156669326267e-09, 4.4646349512119503e-09, -4.7049927091960580e-09, 4.9561002253847192e-09, -5.2191334055490069e-09, 5.4945583626542044e-09, -5.7832433193687254e-09, 6.0863314853460021e-09, -6.4051174909280434e-09, 6.7403553891566650e-09, -7.0933989938263408e-09, 7.4659234299589640e-09, -7.8591408458401506e-09, 8.2751055799843569e-09, -8.7148794606644850e-09, 9.1813301061361439e-09, -9.6760514978089342e-09, 1.0201632305616356e-08, -1.0760129925294149e-08, 1.1355163586751651e-08, -1.1989527720947381e-08, 1.2666360398983932e-08, -1.3390280463762196e-08, 1.4164961106968852e-08, -1.4995012747245716e-08, 1.5885976564229918e-08, -1.6843921766929025e-08, 1.7874947115661739e-08, -1.8986267082409428e-08, 2.0186191955347422e-08, -2.1484132370733845e-08, 2.2890126360750540e-08, -2.4415809556224372e-08, 2.6074391376958674e-08, -2.7880720950296676e-08, 2.9852038341333996e-08, -3.2007470796983141e-08, 3.4369209413828328e-08, -3.6962720963996261e-08, 3.9816961736227733e-08, -4.2965941232291533e-08, 4.6448638367911141e-08, -5.0310249303133202e-08, 5.4604204622873211e-08, -5.9392177920227513e-08, 6.4747522871256546e-08, -7.0756457006013807e-08, 7.7521575966439530e-08, -8.5165469547851754e-08, 9.3834858505459719e-08, -1.0370708662191418e-07, 1.1499734508496046e-07, -1.2796816261852297e-07, 1.4294288769073078e-07, -1.6032201969864769e-07, 1.8060502833216690e-07, -2.0442120587020166e-07, 2.3256958638562142e-07, -2.6607532013847684e-07, 3.0626738095928866e-07, -3.5488829260119791e-07, 4.1425182777935264e-07, -4.8747349724306658e-07, 5.7881217418665015e-07, -6.9418829303134906e-07, 8.4198941248161877e-07, -1.0343491900465793e-06, 1.2892453275257475e-06, -1.6340426463170451e-06, 2.1117130712431397e-06, -2.7922162634453614e-06, 3.7943899196860205e-06, -5.3305886421188924e-06, 7.8043580879824044e-06, -1.2043461755474721e-05, 1.9919842840142057e-05, -3.6251001189673213e-05, 7.5884216611786810e-05, -1.9885074842226311e-04, 7.9195669340038259e-04, -1.8028552886227383e-09}, + dval: []float64{-2.9427800603424885e+01, 2.9427025985916121e+01, -2.9425476404186753e+01, 2.9423151164251298e+01, -2.9420049223750460e+01, 2.9416169190288226e+01, -2.9411509319206207e+01, 2.9406067510787029e+01, -2.9399841306877359e+01, 2.9392827886918830e+01, -2.9385024063373031e+01, 2.9376426276524445e+01, -2.9367030588643040e+01, 2.9356832677485638e+01, -2.9345827829112856e+01, 2.9334010929995458e+01, -2.9321376458381245e+01, 2.9307918474890496e+01, -2.9293630612304742e+01, 2.9278506064510260e+01, -2.9262537574553473e+01, 2.9245717421762187e+01, -2.9228037407881232e+01, 2.9209488842167364e+01, -2.9190062525382210e+01, 2.9169748732617208e+01, -2.9148537194877900e+01, 2.9126417079348521e+01, -2.9103376968250728e+01, 2.9079404836201942e+01, -2.9054488025970496e+01, 2.9028613222515041e+01, -2.9001766425185139e+01, 2.8973932917948382e+01, -2.8945097237496739e+01, 2.8915243139070405e+01, -2.8884353559822184e+01, 2.8852410579527451e+01, -2.8819395378426641e+01, 2.8785288191964121e+01, -2.8750068262165129e+01, 2.8713713785364632e+01, -2.8676201855972838e+01, 2.8637508405928582e+01, -2.8597608139454216e+01, 2.8556474462684317e+01, -2.8514079407692357e+01, 2.8470393550387154e+01, -2.8425385921689980e+01, 2.8379023911335469e+01, -2.8331273163562241e+01, 2.8282097463870919e+01, -2.8231458615927721e+01, 2.8179316307577007e+01, -2.8125627964795978e+01, 2.8070348592274335e+01, -2.8013430599129791e+01, 2.7954823608071283e+01, -2.7894474246092045e+01, 2.7832325914509102e+01, -2.7768318535855649e+01, 2.7702388274772812e+01, -2.7634467229625290e+01, 2.7564483091071313e+01, -2.7492358763234872e+01, 2.7418011942441147e+01, -2.7341354647661582e+01, 2.7262292695845463e+01, -2.7180725114157759e+01, 2.7096543479754125e+01, -2.7009631176051933e+01, 2.6919862552432274e+01, -2.6827101971847423e+01, 2.6731202727801637e+01, -2.6632005808479860e+01, 2.6529338481236699e+01, -2.6423012664989045e+01, 2.6312823050968596e+01, -2.6198544923370154e+01, 2.6079931620126878e+01, -2.5956711559610614e+01, 2.5828584740479602e+01, -2.5695218597789456e+01, 2.5556243066913400e+01, -2.5411244665072719e+01, 2.5259759344501671e+01, -2.5101263795907457e+01, 2.4935164777812641e+01, -2.4760785904535670e+01, 2.4577351124781824e+01, -2.4383963836126313e+01, 2.4179580164227872e+01, -2.3962974319140965e+01, 2.3732693009179656e+01, -2.3486994450692443e+01, 2.3223765221215142e+01, -2.2940404454619134e+01, 2.2633658531147908e+01, -2.2299378247064869e+01, 2.1932149880547183e+01, -2.1524711604262862e+01, 2.1066983867982440e+01, -2.0544356598262947e+01, 1.9934415682618429e+01, -1.9199991275984207e+01, 1.8272015227078569e+01, -1.6996182114611788e+01, 1.4876958810870860e+01}, + }, + { + n: 216, + theta: []float64{1.5671686105755023e+00, 1.5599127961684220e+00, 1.5526558355346407e+00, 1.5453969634495357e+00, 1.5381354130756992e+00, 1.5308704153127000e+00, 1.5236011981417006e+00, 1.5163269859634152e+00, 1.5090469989278730e+00, 1.5017604522544048e+00, 1.4944665555402459e+00, 1.4871645120560699e+00, 1.4798535180267400e+00, 1.4725327618954691e+00, 1.4652014235695219e+00, 1.4578586736455008e+00, 1.4505036726121565e+00, 1.4431355700285682e+00, 1.4357535036754083e+00, 1.4283565986768869e+00, 1.4209439665908115e+00, 1.4135147044640579e+00, 1.4060678938505511e+00, 1.3986025997886760e+00, 1.3911178697348172e+00, 1.3836127324494960e+00, 1.3760861968323106e+00, 1.3685372507016056e+00, 1.3609648595144777e+00, 1.3533679650223920e+00, 1.3457454838572851e+00, 1.3380963060426339e+00, 1.3304192934234869e+00, 1.3227132780089634e+00, 1.3149770602201478e+00, 1.3072094070356892e+00, 1.2994090500267301e+00, 1.2915746832720101e+00, 1.2837049611431546e+00, 1.2757984959492026e+00, 1.2678538554283829e+00, 1.2598695600739727e+00, 1.2518440802797628e+00, 1.2437758332892002e+00, 1.2356631799306261e+00, 1.2275044211192108e+00, 1.2192977941041021e+00, 1.2110414684370108e+00, 1.2027335416358120e+00, 1.1943720345138122e+00, 1.1859548861419755e+00, 1.1774799484076148e+00, 1.1689449801287550e+00, 1.1603476406784692e+00, 1.1516854830678944e+00, 1.1429559464302423e+00, 1.1341563478407819e+00, 1.1252838733993509e+00, 1.1163355684922343e+00, 1.1073083271390356e+00, 1.0981988803171721e+00, 1.0890037831415225e+00, 1.0797194007591668e+00, 1.0703418927985888e+00, 1.0608671961885900e+00, 1.0512910061337959e+00, 1.0416087550001036e+00, 1.0318155888237164e+00, 1.0219063411101317e+00, 1.0118755035330074e+00, 1.0017171930750695e+00, 9.9142511507162645e-01, 9.8099252151840288e-01, 9.7041216388519547e-01, 9.5967623952979786e-01, 9.4877633062585665e-01, 9.3770333429470865e-01, 9.2644738235305046e-01, 9.1499774873988793e-01, 9.0334274224692235e-01, 8.9146958161860457e-01, 8.7936424937397950e-01, 8.6701131978084423e-01, 8.5439375521282512e-01, 8.4149266354281749e-01, 8.2828700713198744e-01, 8.1475325116200825e-01, 8.0086493523862246e-01, 7.8659214693830359e-01, 7.7190086863415974e-01, 7.5675215854165734e-01, 7.4110111194290051e-01, 7.2489552655247935e-01, 7.0807416302356885e-01, 6.9056444104412407e-01, 6.7227933193754241e-01, 6.5311307983969791e-01, 6.3293516775593595e-01, 6.1158156935716357e-01, 5.8884164425859431e-01, 5.6443772421506910e-01, 5.3799175946275157e-01, 5.0896747562778555e-01, 4.7656205323872197e-01, 4.3948124005672007e-01, 3.9539840620540745e-01, 3.3931369540774287e-01, 2.5576413755369809e-01}, + val: []float64{-2.1420664007171084e-13, 5.3170379037842784e-14, -3.4734236933038639e-15, 2.3242110868118431e-13, 3.7943143720204046e-14, -5.7160511614569708e-14, 2.1177269961331864e-13, -3.4948583926844979e-14, 1.7369271883827313e-13, 3.5623756291990570e-13, 6.5520118362261941e-14, 1.1255590127344777e-13, 9.4867994932892441e-14, -6.1601712969494469e-14, 4.7023788875015558e-14, -1.4272998866826663e-13, -2.6605445153274162e-14, -2.5223571223200907e-13, -1.3724084095111965e-13, -7.0111736669803626e-14, 5.7347666545680944e-14, -5.0924962889888544e-14, -5.2683776576685045e-15, -2.1544335394504838e-13, 4.0230445264824984e-15, 6.9175538975130938e-15, -1.1339463388095042e-13, -3.9896959286779273e-14, -8.8360560296236634e-14, -1.0474371284611670e-13, 1.2687327963040444e-14, -1.7782734520430910e-13, 2.0086781777635686e-13, -7.5400883703521135e-14, 1.2278140016266356e-13, -1.1244970732922019e-13, 1.6072100253117342e-14, 5.2340169298568757e-15, 1.1013085876614924e-13, -9.6621831158318670e-15, -1.8366177977891496e-13, 1.0601073284832238e-14, -1.3784763212103856e-13, -1.5863525424166753e-13, -1.6638681463670250e-13, 8.6360908147481066e-14, -7.8672683965135368e-14, 6.8378486764803313e-14, 9.0534733729868808e-14, 6.6505185887739604e-15, 3.3141885340142080e-15, -2.0537396911778824e-13, 7.3393589371575821e-14, 9.8483281662822096e-14, -2.3812738806298458e-13, 6.5975425886450090e-15, 8.7013139463913052e-14, 7.5278742714453987e-14, -1.0708940266003440e-13, 2.0958580081069137e-13, -1.5480716019053119e-14, 4.8469624575186930e-15, -6.1362291991375536e-14, -3.5942923464396180e-14, -7.6176865685553763e-14, 1.0095757892256693e-13, -4.2683956504767779e-14, -4.8938621882647329e-14, 1.6489272569372713e-15, -1.1390338364880240e-13, 2.1513601964632049e-14, -1.0152923724696736e-14, -3.9597826958407387e-14, -8.5123156147931521e-14, -6.5276802085245163e-14, 6.3966825794140229e-14, -2.8207572680644779e-14, -5.9767990455898208e-15, -1.1189271498293956e-13, -4.5600777141900301e-14, 1.5226732724861721e-14, 3.9473540473700922e-14, -5.6017378761616795e-15, -2.4079255903843183e-14, -3.1139558336514997e-14, -5.6034014603771978e-14, 6.9309294575728887e-14, -3.7871955014469560e-14, 4.2988763678275364e-14, 1.0661412180664073e-14, 6.2069599395465107e-14, -4.8913422170368503e-14, 3.3884911719768557e-14, 2.8191908465098299e-15, 2.1228960171536080e-14, -5.6191478942893769e-14, -1.4786950368470112e-14, -2.1665036441200809e-14, 1.4936420829725019e-14, -1.1615745673091571e-13, 1.4661728300981146e-13, -3.6088669931521093e-13, 1.1825080499589470e-12, -4.7300739521811106e-12, 2.5459387908526307e-11, -2.2842779135337983e-10, 5.3230524570865730e-09, 1.8504694403187737e-14}, + dval: []float64{-2.9427800603424888e+01, 2.9427025985916128e+01, -2.9425476404186732e+01, 2.9423151164251305e+01, -2.9420049223750453e+01, 2.9416169190288219e+01, -2.9411509319206210e+01, 2.9406067510787015e+01, -2.9399841306877356e+01, 2.9392827886918813e+01, -2.9385024063373031e+01, 2.9376426276524445e+01, -2.9367030588643043e+01, 2.9356832677485624e+01, -2.9345827829112846e+01, 2.9334010929995465e+01, -2.9321376458381234e+01, 2.9307918474890485e+01, -2.9293630612304742e+01, 2.9278506064510257e+01, -2.9262537574553480e+01, 2.9245717421762187e+01, -2.9228037407881235e+01, 2.9209488842167364e+01, -2.9190062525382206e+01, 2.9169748732617215e+01, -2.9148537194877896e+01, 2.9126417079348521e+01, -2.9103376968250736e+01, 2.9079404836201938e+01, -2.9054488025970500e+01, 2.9028613222515034e+01, -2.9001766425185131e+01, 2.8973932917948375e+01, -2.8945097237496743e+01, 2.8915243139070423e+01, -2.8884353559822181e+01, 2.8852410579527444e+01, -2.8819395378426645e+01, 2.8785288191964142e+01, -2.8750068262165122e+01, 2.8713713785364636e+01, -2.8676201855972852e+01, 2.8637508405928578e+01, -2.8597608139454227e+01, 2.8556474462684314e+01, -2.8514079407692350e+01, 2.8470393550387161e+01, -2.8425385921689987e+01, 2.8379023911335462e+01, -2.8331273163562233e+01, 2.8282097463870926e+01, -2.8231458615927728e+01, 2.8179316307577018e+01, -2.8125627964795974e+01, 2.8070348592274335e+01, -2.8013430599129794e+01, 2.7954823608071287e+01, -2.7894474246092045e+01, 2.7832325914509109e+01, -2.7768318535855656e+01, 2.7702388274772812e+01, -2.7634467229625294e+01, 2.7564483091071331e+01, -2.7492358763234883e+01, 2.7418011942441158e+01, -2.7341354647661582e+01, 2.7262292695845463e+01, -2.7180725114157763e+01, 2.7096543479754128e+01, -2.7009631176051940e+01, 2.6919862552432292e+01, -2.6827101971847430e+01, 2.6731202727801641e+01, -2.6632005808479885e+01, 2.6529338481236724e+01, -2.6423012664989066e+01, 2.6312823050968632e+01, -2.6198544923370196e+01, 2.6079931620126928e+01, -2.5956711559610671e+01, 2.5828584740479652e+01, -2.5695218597789530e+01, 2.5556243066913513e+01, -2.5411244665072843e+01, 2.5259759344501834e+01, -2.5101263795907666e+01, 2.4935164777812918e+01, -2.4760785904536036e+01, 2.4577351124782325e+01, -2.4383963836127013e+01, 2.4179580164228856e+01, -2.3962974319142369e+01, 2.3732693009181720e+01, -2.3486994450695558e+01, 2.3223765221219963e+01, -2.2940404454626893e+01, 2.2633658531160954e+01, -2.2299378247087898e+01, 2.1932149880590437e+01, -2.1524711604350518e+01, 2.1066983868178077e+01, -2.0544356598759389e+01, 1.9934415684120079e+01, -1.9199991281861426e+01, 1.8272015261833435e+01, -1.6996182557157578e+01, 1.4876958810870862e+01}, + }, + } { + got := make([]float64, len(test.theta)) + gotD := make([]float64, len(test.theta)) + for i := range got { + got[i], gotD[i] = Hermite{}.hermpolyAsyAiry(i, test.n, test.theta[i]) + } + if !floats.EqualApprox(test.val, got, 1e-12) { + t.Errorf("n = %v, hermpolyAsyAiry mismatch", test.n) + } + if !floats.EqualApprox(test.dval, gotD, 1e-12) { + t.Errorf("n = %v, hermpolyAsyAiry deriv mismatch", test.n) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/internal/PrintGoSlice.m b/vendor/gonum.org/v1/gonum/integrate/quad/internal/PrintGoSlice.m new file mode 100644 index 00000000..d3a51b28 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/internal/PrintGoSlice.m @@ -0,0 +1,11 @@ +% Copyright 2016 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +function PrintGoSlice(a) + fprintf('[]float64{') + for i = 1:length(a) + fprintf('%1.16e, ',a(i)) + end + fprintf('}\n') +end \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/internal/genherm.m b/vendor/gonum.org/v1/gonum/integrate/quad/internal/genherm.m new file mode 100644 index 00000000..f673f97d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/internal/genherm.m @@ -0,0 +1,32 @@ +% Copyright 2016 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +clc +clear all +close all + +% Generate herm points +min = 216; +max = 216; +fprintf('xCache = [][]float64{\n') +for i = min:max + [x,w] = hermpts(i); + fprintf('{') + for j = 1:i-1 + fprintf('%1.16e, ',x(j)) + end + fprintf('%1.16e},\n',x(i)) +end +fprintf('}\n') + +fprintf('wCache = [][]float64{\n') +for i = min:max + [x,w] = hermpts(i); + fprintf('{') + for j = 1:i-1 + fprintf('%1.16e, ',w(j)) + end + fprintf('%1.16e},\n',w(i)) +end +fprintf('}\n') diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/internal/hermpts.m b/vendor/gonum.org/v1/gonum/integrate/quad/internal/hermpts.m new file mode 100644 index 00000000..9306ad60 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/internal/hermpts.m @@ -0,0 +1,609 @@ +% Copyright (c) 2015, The Chancellor, Masters and Scholars of the University +% of Oxford, and the Chebfun Developers. +% Copyright (c) 2016 The gonum Authors +% 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 the University of Oxford 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. + + +function [x, w, v] = hermpts(n, varargin) +%HERMPTS Hermite points and Gauss-Hermite Quadrature Weights. +% HERMPTS(N) returns N Hermite points X in (-inf, inf). By default these are +% roots of the 'physicist'-type Hermite polynomials, which are orthogonal with +% respect to the weight exp(-x.^2). +% +% HERMPTS(N, 'PROB') normalises instead by the probablist's definition (with +% weight exp(-x.^2/2)), which gives rise to monomials. +% +% [X, W] = HERMPTS(N) returns also a row vector W of weights for Gauss-Hermite +% quadrature. [X,W,V] = HERMPTS(N) returns in addition a column vector V of +% the barycentric weights corresponding to X. +% +% [X, W] = HERMPTS(N, METHOD) where METHOD is one of 'GW', 'REC', 'GLR', or +% 'ASY' allows the user to select which method is used. 'GW' will use the +% traditional Golub-Welsch eigenvalue method [1], best when n<=20. 'REC' +% uses Newton's method with polynomial evaluation via the 3-term +% recurrence for Hermite polynomials. 'GLR' uses Glaser-Liu-Rokhlin +% fast algorithm which is much faster for large N [2]. 'ASY' uses Newton's +% method with polynomial evaluation via asymptotic formula. 'ASY' is the +% fastest for N>=200, 'GLR' is the most accurate for nodes close to 0. +% By default HERMPTS uses 'GW' when N <= 20, 'REC' for 21<=N<200, and +% 'ASY' when N>=200. +% +% References: +% [1] G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature +% rules", Math. Comp. 23:221-230, 1969, +% [2] A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the +% calculation of the roots of special functions", SIAM Journal +% on Scientific Computing", 29(4):1420-1438:, 2007. +% [3] A. Townsend, T. Trogdon and S. Olver, Fast computation of Gauss +% nodes and weights on the whole real line, submitted, 2014. +% +% See also CHEBPTS, LEGPTS, LAGPTS, and JACPTS. + +% Copyright 2015 by The University of Oxford and The Chebfun Developers. +% See http://www.chebfun.org/ for Chebfun information. +% +% 'GW' by Nick Trefethen, March 2009 - algorithm adapted from [1]. +% 'GLR' by Nick Hale, March 2010 - algorithm adapted from [2]. + +% Defaults: +method = 'default'; +type = 'phys'; + +if ( n < 0 ) + error('CHEBFUN:hermpts:n', 'First input should be a positive integer.'); +end + +% Return empty vector if n = 0. +if ( n == 0 ) + [x, w, v] = deal([]); + return +end + +% Check the inputs +while ( ~isempty(varargin) ) + s = varargin{1}; + varargin(1) = []; + if ( strcmpi(s, 'GW') ) + method = 'GW'; + elseif ( strcmpi(s,'glr') ) + method = 'GLR'; + elseif ( strcmpi(s,'rec') ) + method = 'REC'; + elseif ( strcmpi(s,'asy') ) + method = 'ASY'; + elseif ( strncmpi(s, 'phys', 3) ) + type = 'phys'; + elseif ( strncmpi(s, 'prob', 3) ) + type = 'prob'; + else + error('CHEBFUN:hermpts:input', 'Unrecognised input string; %s.', s); + end +end + +% Three cases: +% +% N <= 20: Use GW +% 21<=N<200: Use REC +% N>=200: Use ASY +if ( n == 1 ) + % n = 1 case is trivial + x = 0; + w = sqrt(pi); + v = 1; + +elseif ( (n < 21 && strcmpi(method,'default')) || strcmpi(method,'GW') ) + % GW, see [1] + + beta = sqrt(.5*(1:n-1)); % 3-term recurrence coeffs + T = diag(beta, 1) + diag(beta, -1); % Jacobi matrix + [V, D] = eig(T); % Eigenvalue decomposition + [x, indx] = sort(diag(D)); % Hermite points + w = sqrt(pi)*V(1, indx).^2; % weights + v = abs(V(1, indx)).'; % Barycentric weights + v = v./max(v); % Normalize + v(2:2:n) = -v(2:2:n); + + % Enforce symmetry: + ii = 1:floor(n/2); + x = x(ii); + w = w(ii); + vmid = v(floor(n/2)+1); + v = v(ii); + if ( mod(n, 2) ) + x = [x ; 0 ; -x(end:-1:1)]; + w = [w, sqrt(pi) - sum(2*w), w(end:-1:1)]; + v = [v ; vmid ; v(end:-1:1)]; + else + x = [x ; -x(end:-1:1)]; + w = [w, w(end:-1:1)]; + v = [v ; -v(end:-1:1)]; + end + +elseif ( strcmpi(method,'GLR') ) + % Fast, see [2] + + [x, ders] = alg0_Herm(n); % Nodes and H_n'(x) + w = (2*exp(-x.^2)./ders.^2)'; % Quadrature weights + v = exp(-x.^2/2)./ders; % Barycentric weights + v = v./max(abs(v)); % Normalize + if ( ~mod(n, 2) ) + ii = (n/2+1):n; + v(ii) = -v(ii); + end + +elseif ( (n < 200 && strcmpi(method,'default')) || strcmpi(method,'REC') ) + + [x, w, v] = hermpts_rec( n ); + +else + + [x, w, v] = hermpts_asy( n ); + +end + +% Normalise so that sum(w) = sqrt(pi) +w = (sqrt(pi)/sum(w))*w; + +if ( strcmpi(type, 'prob') ) + x = x*sqrt(2); + w = w*sqrt(2); +end + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for GLR algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Driver for 'GLR'. +function [roots, ders] = alg0_Herm(n) +% Compute coefficients of H_m(0), H_m'(0), m = 0,..,N. + +Hm2 = 0; +Hm1 = pi^(-1/4); +Hpm2 = 0; +Hpm1 = 0; +for k = 0:n-1 + H = -sqrt(k/(k+1))*Hm2; + Hp = sqrt(2/(k+1))*Hm1-sqrt(k/(k+1))*Hpm2; + Hm2 = Hm1; + Hm1 = H; + Hpm2 = Hpm1; + Hpm1 = Hp; +end + +% allocate storage +roots = zeros(n, 1); +ders = zeros(n, 1); +if ( mod(n,2) ) + % zero is a root: + roots((n-1)/2) = 0; + ders((n+1)/2) = Hp; +else + % find first root: + [roots(n/2+1), ders(n/2+1)] = alg2_Herm(H,n); +end + +% compute roots and derivatives: +[roots, ders] = alg1_Herm(roots, ders); + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Main algorithm for 'GLR' +function [roots, ders] = alg1_Herm(roots, ders) + +n = length(roots); +s = mod(n, 2); +N = (n - s) / 2; + +% number of terms in Taylor expansion +m = 30; + +% initialise +hh1 = ones(m + 1, 1); +u = zeros(1, m + 1); +up = zeros(1, m + 1); + +for j = (N + 1):(n - 1) + + % previous root + x = roots(j); + + % initial approx + h = rk2_Herm(pi/2,-pi/2,x,n) - x; + + % scaling + M = 1/h; + + % recurrence relation for Hermite polynomials + c1 = -(2*n+1-x^2)/M^2; + c2 = 2*x./M^3; + c3 = 1./M^4; + u(1) = 0; + u(2) = ders(j)/M; + u(3) = .5*c1*u(1); + u(4) = (c1*u(2) + c2*u(1))/6; + up(1) = u(2); + up(2) = 2*u(3)*M; + up(3) = 3*u(4)*M; + up(m+1) = 0; + + for k = 2:m-2 + u(k+3) = (c1*u(k+1) + c2*u(k) + c3*u(k-1))/((k+1)*(k+2)); + up(k+2) = (k+2)*u(k+3)*M; + end + + % flip for more accuracy in inner product calculation + u = u(m+1:-1:1); + up = up(m+1:-1:1); + + % Newton iteration + hh = hh1; + hh(end) = M; + step = inf; + l = 0; + z = zeros(m, 1); + while ( (abs(step) > eps) && (l < 10) ) + l = l + 1; + step = (u*hh)/(up*hh); + h = h - step; + % powers of h (This is the fastest way!) + hh = [M ; cumprod(M*h + z)]; + % flip for more accuracy in inner product calculation + hh = hh(end:-1:1); + end + + % update + roots(j+1) = x + h; + ders(j+1) = up*hh; +end + +% nodes are symmetric +roots(1:N+s) = -roots(n:-1:N+1); +ders(1:N+s) = ders(n:-1:N+1); + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% find the first root (note H_n'(0) = 0) +function [x1, d1] = alg2_Herm(Hn0, n) + +% advance ODE via Runge-Kutta for initial approx +x1 = rk2_Herm(0, -pi/2, 0, n); + +% number of terms in Taylor expansion +m = 30; + +% scaling +M = 1/x1; +% c = log10(n); +% M = 1./x1.^(1-1.25/(c)); + +% initialise +u = zeros(1,m+1); +up = zeros(1,m+1); + +% recurrence relation for Legendre polynomials +u(1) = Hn0; +u(3) = -.5*(2*n+1)*u(1)/M^2; +up(1) = 0; +up(2) = 2*u(3)*M; +for k = 2:2:m-2 + u(k+3) = (-(2*n+1)*u(k+1)/M^2 + u(k-1)/M^4)/((k+1)*(k+2)); + up(k+2) = (k+2)*u(k+3)*M; +end + +% flip for more accuracy in inner product calculation +u = u(m+1:-1:1); +up = up(m+1:-1:1); + +z = zeros(m, 1); +x1k = [M ; cumprod(M*x1 + z)]; +step = inf; +l = 0; +% Newton iteration +while ( (abs(step) > eps) && (l < 10) ) + l = l + 1; + step = (u*x1k)/(up*x1k); + x1 = x1 - step; + % powers of h (This is the fastest way!) + x1k = [1 ; cumprod(M*x1 + z)]; + x1k = x1k(end:-1:1); +end + +% Update derivative +d1 = up*x1k; + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Runge-Kutta for Hermite Equation +function x = rk2_Herm(t, tn, x, n) +m = 10; +h = (tn-t)/m; +for j = 1:m + k1 = -h/(sqrt(2*n+1-x^2) - .5*x*sin(2*t)/(2*n+1-x^2)); + t = t + h; + k2 = -h/(sqrt(2*n+1-(x+k1)^2) - .5*x*sin(2*t)/(2*n+1-(x+k1)^2)); + x = x + .5*(k1 + k2); +end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for ASY algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [x, w, v] = hermpts_asy(n) +% HERMPTS_ASY, fast algorithm for computing Gauss-Hermite nodes and weights +% using Newton's method with polynomial evaluation via asymptotic expansions. +% +% x = Gauss-Hermite nodes, w = quad weights, v = bary weights. +% +% See [3]. + +[x, w, v] = hermpts_asy0( n ); + +if mod(n,2) == 1 % fold out + x = [-x(end:-1:1);x(2:end)]; + w = [w(end:-1:1) w(2:end)]; w = (sqrt(pi)/sum(w))*w; + v = [v(end:-1:1);v(2:end)]; v = v./max(abs(v)); +else + x = [-x(end:-1:1);x]; + w = [w(end:-1:1) w]; w = (sqrt(pi)/sum(w))*w; + v = [v(end:-1:1);-v]; v = v./max(abs(v)); +end + +% debug +%tic, exact = hermpts(n); toc +%semilogy(abs(exact-x)) +end + +function [x, w, v] = hermpts_asy0(n) +% Compute Hermite nodes and weights using asymptotic formula + +x0 = HermiteInitialGuesses(n); % get initial guesses +t0 = x0./sqrt(2*n+1); +theta0 = acos(t0); % convert to theta-variable +for k = 1:20 + [val, dval] = hermpoly_asy_airy(n, theta0); + dt = -val./(sqrt(2)*sqrt(2*n+1)*dval.*sin(theta0)); + theta0 = theta0 - dt; % Newton update + if norm(dt,inf) < sqrt(eps)/10, break; end +end +t0 = cos(theta0); +x = sqrt(2*n+1)*t0; % back to x-variable + +ders = x.*val + sqrt(2)*dval; +%ders = dval; +w = (exp(-x.^2)./ders.^2)'; % quadrature weights + +v = exp(-x.^2/2)./ders; % Barycentric weights +end + +function [val, dval] = hermpoly_asy_airy(n, theta) +% HERMPOLY_ASY evaluation hermite poly using Airy asymptotic formula in +% theta-space. + +musq = 2*n+1; +cosT = cos(theta); sinT = sin(theta); +sin2T = 2*cosT.*sinT; +eta = .5*theta - .25*sin2T; +chi = -(3*eta/2).^(2/3); +phi = (-chi./sinT.^2).^(1/4); +const = 2*sqrt(pi)*musq^(1/6)*phi; +Airy0 = real(airy(musq.^(2/3)*chi)); +Airy1 = real(airy(1,musq.^(2/3)*chi)); + +% Terms in (12.10.43): +a0 = 1; b0 = 1; +a1 = 15/144; b1 = -7/5*a1; +a2 = 5*7*9*11/2/144^2; b2 = -13/11*a2; +a3 = 7*9*11*13*15*17/6/144^3; +b3 = -19/17*a3; + +% u polynomials in (12.10.9) +u0 = 1; u1 = (cosT.^3-6*cosT)/24; +u2 = (-9*cosT.^4 + 249*cosT.^2 + 145)/1152; +u3 = (-4042*cosT.^9+18189*cosT.^7-28287*cosT.^5-151995*cosT.^3-259290*cosT)/414720; + +%first term +A0 = 1; +val = A0*Airy0; + +%second term +B0 = -(a0*phi.^6.*u1+a1*u0)./chi.^2; +val = val + B0.*Airy1./musq.^(4/3); + +%third term +A1 = (b0*phi.^12.*u2 + b1*phi.^6.*u1 + b2*u0)./chi.^3; +val = val + A1.*Airy0/musq.^2; + +%fourth term +B1 = -(phi.^18.*u3 + a1*phi.^12.*u2 + a2*phi.^6.*u1 + a3*u0)./chi.^5; +val = val + B1.*Airy1./musq.^(4/3+2); + +val = const.*val; + +%% Derivative + +eta = .5*theta - .25*sin2T; +chi = -(3*eta/2).^(2/3); +phi = (-chi./sinT.^2).^(1/4); +const = sqrt(2*pi)*musq^(1/3)./phi; + +% v polynomials in (12.10.10) +v0 = 1; v1 = (cosT.^3+6*cosT)/24; +v2 = (15*cosT.^4-327*cosT.^2-143)/1152; +v3 = (259290*cosT + 238425*cosT.^3 - 36387*cosT.^5 + 18189*cosT.^7 -... + 4042*cosT.^9)/414720; + +%first term +C0 = -(b0*phi.^6.*v1 + b1.*v0)./chi; +dval = C0.*Airy0/musq.^(2/3); + +% %second term +D0 = a0*v0; +dval = dval + D0*Airy1; + +% %third term +C1 = -(phi.^18.*v3 + b1*phi.^12.*v2 + b2*phi.^6.*v1 + b3*v0)./chi.^4; +dval = dval + C1.*Airy0/musq.^(2/3+2); + +%fourth term +D1 = (a0*phi.^12.*v2 + a1*phi.^6.*v1 + a2*v0)./chi.^3; +dval = dval + D1.*Airy1/musq.^2; + +dval = const.*dval; + +end + +function x_init = HermiteInitialGuesses(n) +%HERMITEINTITIALGUESSES(N), Initial guesses for Hermite zeros. +% +% [1] L. Gatteschi, Asymptotics and bounds for the zeros of Laguerre +% polynomials: a survey, J. Comput. Appl. Math., 144 (2002), pp. 7-27. +% +% [2] F. G. Tricomi, Sugli zeri delle funzioni di cui si conosce una +% rappresentazione asintotica, Ann. Mat. Pura Appl. 26 (1947), pp. 283-300. + +% Gatteschi formula involving airy roots [1]. +% These initial guess are good near x = sqrt(n+1/2); +if mod(n,2) == 1 + m = (n-1)/2; bess = (1:m)'*pi; a = .5; +else + m = n/2; bess = ((0:m-1)'+.5)*pi; a = -.5; +end +nu = 4*m + 2*a + 2; +T = @(t) t.^(2/3).*(1+5/48*t.^(-2)-5/36*t.^(-4)+(77125/82944)*t.^(-6) -... + 108056875/6967296*t.^(-8)+162375596875/334430208*t.^(-10)); +airyrts = -T(3/8*pi*(4*(1:m)'-1)); + +airyrts_exact = [ -2.338107410459762 % Exact Airy roots. + -4.087949444130970 + -5.520559828095555 + -6.786708090071765 + -7.944133587120863 + -9.022650853340979 + -10.040174341558084 + -11.008524303733260 + -11.936015563236262 + -12.828776752865757]; +airyrts(1:10) = airyrts_exact; % correct first 10. + +x_init = sqrt(nu + 2^(2/3)*airyrts*nu^(1/3) +... + 1/5*2^(4/3)*airyrts.^2*nu^(-1/3) +... + (11/35-a^2-12/175*airyrts.^3)/nu +... + (16/1575*airyrts+92/7875*airyrts.^4)*2^(2/3)*nu^(-5/3) -... + (15152/3031875*airyrts.^5+1088/121275*airyrts.^2)*2^(1/3)*nu^(-7/3)); +x_init_airy = real(x_init(end:-1:1)); + +% Tricomi initial guesses. Equation (2.1) in [1]. Originally in [2]. +% These initial guesses are good near x = 0 . Note: zeros of besselj(+/-.5,x) +% are integer and half-integer multiples of pi. +% x_init_bess = bess/sqrt(nu).*sqrt((1+ (bess.^2+2*(a^2-1))/3/nu^2) ); +Tnk0 = pi/2*ones(m,1); +nu = (4*m+2*a+2); +rhs = (4*m-4*(1:m)'+3)./nu*pi; + +for k = 1:7 + val = Tnk0 - sin(Tnk0) - rhs; + dval = 1 - cos(Tnk0); + dTnk0 = val./dval; + Tnk0 = Tnk0 - dTnk0; +end + +tnk = cos(Tnk0/2).^2; +x_init_sin = sqrt(nu*tnk - (5./(4*(1-tnk).^2) - 1./(1-tnk)-1+3*a^2)/3/nu); + +% Patch together +p = 0.4985+eps; +x_init = [x_init_sin(1:floor(p*n));x_init_airy(ceil(p*n):end)]; + + +if mod(n,2) == 1 + x_init = [0;x_init]; + x_init = x_init(1:m+1); +else + x_init = x_init(1:m); +end + +% debug: +%y = hermpts(n); +%semilogy(abs(y - x_init)); +%yhalf = -y(m:-1:1); +%semilogy(abs(yhalf - x_init)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for REC algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [x, w, v] = hermpts_rec(n) +% Compute Hermite nodes and weights using recurrence relation. + +x0 = HermiteInitialGuesses(n); +x0 = x0.*sqrt(2); + +for kk = 1:10 + [val, dval] = hermpoly_rec(n, x0); + dx = val./dval; + dx(isnan(dx)) = 0; + x0 = x0 - dx; + if norm(dx, inf)= max { + panic("legendre: min >= max") + } + if math.IsInf(min, 0) || math.IsInf(max, 0) { + panic("legendre: infinite bound") + } + for i := range x { + x[i], weight[i] = l.boundedLocation(len(x), i, min, max) + } +} + +func (l Legendre) FixedLocationSingle(n, k int, min, max float64) (x, weight float64) { + if min >= max { + panic("legendre: min >= max") + } + if math.IsInf(min, 0) || math.IsInf(max, 0) { + panic("legendre: infinite bound") + } + return l.boundedLocation(n, k, min, max) +} + +func (l Legendre) boundedLocation(n, k int, min, max float64) (x, weight float64) { + x, weight = l.location(n, k) + return (x+1)/2*(max-min) + min, weight * (max - min) / 2 +} + +// Algorithm adapted from http://sourceforge.net/projects/fastgausslegendrequadrature. + +// Original Copyright Notice: +//******************************************* +// Copyright (C) 2014 by Ignace Bogaert * +//******************************************* + +// This software package is based on the paper +// I. Bogaert, "Iteration-Free Computation of Gauss-Legendre Quadrature Nodes and Weights", +// to be published in the SIAM Journal of Scientific Computing. + +// The main features of this software are: +// - Speed: due to the simple formulas and the O(1) complexity computation of individual Gauss-Legendre +// quadrature nodes and weights. This makes it compatible with parallel computing paradigms. +// - Accuracy: the error on the nodes and weights is within a few ulps (see the paper for details). + +// Disclaimer: +// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 REGENTS 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. + +// location finds the location and weight for location k given n total samples. +func (l Legendre) location(n, k int) (x, weight float64) { + // Note: k is 1-indexed in the original algorithm. It has been translated to + // zero-indexed here. + if n < 101 { + theta, weight := l.tabulated(n, k) + return math.Cos(theta), weight + } + if 2*k+1 > n { + theta, weight := l.computed(n, n-k) + return math.Cos(math.Pi - theta), weight + } + theta, weight := l.computed(n, k+1) + return math.Cos(theta), weight +} + +// Returns tabulated theta and weight values: valid for l <= 100 +func (l Legendre) tabulated(n, k int) (theta, weight float64) { + if n%2 == 1 { + n2 := (n - 1) / 2 + if k == n2 { + return math.Pi / 2, 2.0 / (cl[n] * cl[n]) + } + if k < n2 { + return oddThetaZeros[n2-1][n2-k-1], oddWeights[n2-1][n2-k-1] + } + return math.Pi - oddThetaZeros[n2-1][k-n2-1], oddWeights[n2-1][k-n2-1] + } + n2 := n / 2 + if k < n2 { + return evenThetaZeros[n2-1][n2-k-1], evenWeights[n2-1][n2-k-1] + } + return math.Pi - evenThetaZeros[n2-1][k-n2], evenWeights[n2-1][k-n2] +} + +func (l Legendre) computed(n, k int) (theta, weight float64) { + // First, get the bessel zero + w := 1.0 / (float64(n) + 0.5) + nu := besselJZero(k) + theta = w * nu + x := theta * theta + + // Get the asymptotic BesselJ(1, nu) squared + b := besselJ1Squared(k) + + // Get the Chebyshev interpolants for the nodes. + sf1t := (((((-1.29052996274280508473467968379e-12*x+2.40724685864330121825976175184e-10)*x-3.13148654635992041468855740012e-8)*x+0.275573168962061235623801563453e-5)*x-0.148809523713909147898955880165e-3)*x+0.416666666665193394525296923981e-2)*x - 0.416666666666662959639712457549e-1 + sf2t := (((((+2.20639421781871003734786884322e-9*x-7.53036771373769326811030753538e-8)*x+0.161969259453836261731700382098e-5)*x-0.253300326008232025914059965302e-4)*x+0.282116886057560434805998583817e-3)*x-0.209022248387852902722635654229e-2)*x + 0.815972221772932265640401128517e-2 + sf3t := (((((-2.97058225375526229899781956673e-8*x+5.55845330223796209655886325712e-7)*x-0.567797841356833081642185432056e-5)*x+0.418498100329504574443885193835e-4)*x-0.251395293283965914823026348764e-3)*x+0.128654198542845137196151147483e-2)*x - 0.416012165620204364833694266818e-2 + + // and the weights + wsf1t := ((((((((-2.20902861044616638398573427475e-14*x+2.30365726860377376873232578871e-12)*x-1.75257700735423807659851042318e-10)*x+1.03756066927916795821098009353e-8)*x-4.63968647553221331251529631098e-7)*x+0.149644593625028648361395938176e-4)*x-0.326278659594412170300449074873e-3)*x+0.436507936507598105249726413120e-2)*x-0.305555555555553028279487898503e-1)*x + 0.833333333333333302184063103900e-1 + wsf2t := (((((((+3.63117412152654783455929483029e-12*x+7.67643545069893130779501844323e-11)*x-7.12912857233642220650643150625e-9)*x+2.11483880685947151466370130277e-7)*x-0.381817918680045468483009307090e-5)*x+0.465969530694968391417927388162e-4)*x-0.407297185611335764191683161117e-3)*x+0.268959435694729660779984493795e-2)*x - 0.111111111111214923138249347172e-1 + wsf3t := (((((((+2.01826791256703301806643264922e-9*x-4.38647122520206649251063212545e-8)*x+5.08898347288671653137451093208e-7)*x-0.397933316519135275712977531366e-5)*x+0.200559326396458326778521795392e-4)*x-0.422888059282921161626339411388e-4)*x-0.105646050254076140548678457002e-3)*x-0.947969308958577323145923317955e-4)*x + 0.656966489926484797412985260842e-2 + + // Then refine with the paper expansions + nuSin := nu / math.Sin(theta) + bNuSin := b * nuSin + wInvSinc := w * w * nuSin + wIS2 := wInvSinc * wInvSinc + + // Finally, compute the node and the weight + theta = w * (nu + theta*wInvSinc*(sf1t+wIS2*(sf2t+wIS2*sf3t))) + deno := bNuSin + bNuSin*wIS2*(wsf1t+wIS2*(wsf2t+wIS2*wsf3t)) + weight = 2.0 * w / deno + return theta, weight +} + +func besselJZero(k int) float64 { + if k < 20 { + return jz[k-1] + } + z := math.Pi * (float64(k) - 0.25) + r := 1.0 / z + r2 := r * r + z += r * (0.125 + r2*(-0.807291666666666666666666666667e-1+r2*(0.246028645833333333333333333333+r2*(-1.82443876720610119047619047619+r2*(25.3364147973439050099206349206+r2*(-567.644412135183381139802038240+r2*(18690.4765282320653831636345064+r2*(-8.49353580299148769921876983660e5+5.09225462402226769498681286758e7*r2)))))))) + return z +} + +func besselJ1Squared(k int) float64 { + if k < 21 { + return j1[k-1] + } + x := 1.0 / (float64(k) - 0.25) + x2 := x * x + return x * (0.202642367284675542887758926420 + x2*x2*(-0.303380429711290253026202643516e-3+x2*(0.198924364245969295201137972743e-3+x2*(-0.228969902772111653038747229723e-3+x2*(0.433710719130746277915572905025e-3+x2*(-0.123632349727175414724737657367e-2+x2*(0.496101423268883102872271417616e-2+x2*(-0.266837393702323757700998557826e-1+.185395398206345628711318848386*x2)))))))) +} + +// Tabulated values +var jz = [20]float64{2.40482555769577276862163187933, 5.52007811028631064959660411281, 8.65372791291101221695419871266, 11.7915344390142816137430449119, 14.9309177084877859477625939974, 18.0710639679109225431478829756, 21.2116366298792589590783933505, 24.3524715307493027370579447632, 27.4934791320402547958772882346, 30.6346064684319751175495789269, 33.7758202135735686842385463467, 36.9170983536640439797694930633, 40.0584257646282392947993073740, 43.1997917131767303575240727287, 46.3411883716618140186857888791, 49.4826098973978171736027615332, 52.6240518411149960292512853804, 55.7655107550199793116834927735, 58.9069839260809421328344066346, 62.0484691902271698828525002646} +var j1 = [21]float64{0.269514123941916926139021992911, 0.115780138582203695807812836182, 0.0736863511364082151406476811985, 0.0540375731981162820417749182758, 0.0426614290172430912655106063495, 0.0352421034909961013587473033648, 0.0300210701030546726750888157688, 0.0261473914953080885904584675399, 0.0231591218246913922652676382178, 0.0207838291222678576039808057297, 0.0188504506693176678161056800214, 0.0172461575696650082995240053542, 0.0158935181059235978027065594287, 0.0147376260964721895895742982592, 0.0137384651453871179182880484134, 0.0128661817376151328791406637228, 0.0120980515486267975471075438497, 0.0114164712244916085168627222986, 0.0108075927911802040115547286830, 0.0102603729262807628110423992790, 0.00976589713979105054059846736696} + +// Tabulated nodes and weights +// The required theta values for the Legendre nodes for l <= 100 +var evenThetaZeros = [][]float64{ + {0.9553166181245092781638573e0}, + {0.1223899586470372591854100e1, 0.5332956802491269896325121e0}, + {0.1329852612388110166006182e1, 0.8483666264874876548310910e0, 0.3696066519448289481138796e0}, + {0.1386317078892131346282665e1, 0.1017455539490153431016397e1, 0.6490365804607796100719162e0, 0.2827570635937967783987981e0}, + {0.1421366498439524924081833e1, 0.1122539327631709474018620e1, 0.8238386589997556048023640e0, 0.5255196555285001171749362e0, 0.2289442988470260178701589e0}, + {0.1445233238471440081118261e1, 0.1194120375947706635968399e1, 0.9430552870605735796668951e0, 0.6921076988818410126677201e0, 0.4414870814893317611922530e0, 0.1923346793046672033050762e0}, + {0.1462529992921481833498746e1, 0.1246003586776677662375070e1, 0.1029498592525136749641068e1, 0.8130407055389454598609888e0, 0.5966877608172733931509619e0, 0.3806189306666775272453522e0, 0.1658171411523664030454318e0}, + {0.1475640280808194256470687e1, 0.1285331444322965257106517e1, 0.1095033401803444343034890e1, 0.9047575323895165085030778e0, 0.7145252532340252146626998e0, 0.5243866409035941583262629e0, 0.3344986386876292124968005e0, 0.1457246820036738335698855e0}, + {0.1485919440392653014379727e1, 0.1316167494718022699851110e1, 0.1146421481056642228295923e1, 0.9766871104439832694094465e0, 0.8069738930788195349918620e0, 0.6373005058706191519531139e0, 0.4677113145328286263205134e0, 0.2983460782092324727528346e0, 0.1299747364196768405406564e0}, + {0.1494194914310399553510039e1, 0.1340993178589955138305166e1, 0.1187794926634098887711586e1, 0.1034603297590104231043189e1, 0.8814230742890135843662021e0, 0.7282625848696072912405713e0, 0.5751385026314284688366450e0, 0.4220907301111166004529037e0, 0.2692452880289302424376614e0, 0.1172969277059561308491253e0}, + {0.1501000399130816063282492e1, 0.1361409225664372117193308e1, 0.1221820208990359866348145e1, 0.1082235198111836788818162e1, 0.9426568273796608630446470e0, 0.8030892957063359443650460e0, 0.6635400754448062852164288e0, 0.5240242709487281141128643e0, 0.3845781703583910933413978e0, 0.2453165389983612942439953e0, 0.1068723357985259945018899e0}, + {0.1506695545558101030878728e1, 0.1378494427506219143960887e1, 0.1250294703417272987066314e1, 0.1122097523267250692925104e1, 0.9939044422989454674968570e0, 0.8657177770401081355080608e0, 0.7375413075437535618804594e0, 0.6093818382449565759195927e0, 0.4812531951313686873528891e0, 0.3531886675690780704072227e0, 0.2252936226353075734690198e0, 0.9814932949793685067733311e-1}, + {0.1511531546703289231944719e1, 0.1393002286179807923400254e1, 0.1274473959424494104852958e1, 0.1155947313793812040125722e1, 0.1037423319077439147088755e1, 0.9189033445598992550553862e0, 0.8003894803353296871788647e0, 0.6818851814129298518332401e0, 0.5633967073169293284500428e0, 0.4449368152119130526034289e0, 0.3265362611165358134766736e0, 0.2082924425598466358987549e0, 0.9074274842993199730441784e-1}, + {0.1515689149557281132993364e1, 0.1405475003062348722192382e1, 0.1295261501292316172835393e1, 0.1185049147889021579229406e1, 0.1074838574917869281769567e1, 0.9646306371285440922680794e0, 0.8544265718392254369377945e0, 0.7442282945111358297916378e0, 0.6340389954584301734412433e0, 0.5238644768825679339859620e0, 0.4137165857369637683488098e0, 0.3036239070914333637971179e0, 0.1936769929947376175341314e0, 0.8437551461511597225722252e-1}, + {0.1519301729274526620713294e1, 0.1416312682230741743401738e1, 0.1313324092045794720169874e1, 0.1210336308624476413072722e1, 0.1107349759228459143499061e1, 0.1004365001539081003659288e1, 0.9013828087667156388167226e0, 0.7984043170121235411718744e0, 0.6954313000299367256853883e0, 0.5924667257887385542924194e0, 0.4895160050896970092628705e0, 0.3865901987860504829542802e0, 0.2837160095793466884313556e0, 0.1809780449917272162574031e0, 0.7884320726554945051322849e-1}, + {0.1522469852641529230282387e1, 0.1425817011963825344615095e1, 0.1329164502391080681347666e1, 0.1232512573416362994802398e1, 0.1135861522840293704616614e1, 0.1039211728068951568003361e1, 0.9425636940046777101926515e0, 0.8459181315837993237739032e0, 0.7492760951181414487254243e0, 0.6526392394594561548023681e0, 0.5560103418005302722406995e0, 0.4593944730762095704649700e0, 0.3628020075350028174968692e0, 0.2662579994723859636910796e0, 0.1698418454282150179319973e0, 0.7399171309970959768773072e-1}, + {0.1525270780617194430047563e1, 0.1434219768045409606267345e1, 0.1343169000217435981125683e1, 0.1252118659062444379491066e1, 0.1161068957629157748792749e1, 0.1070020159291475075961444e1, 0.9789726059789103169325141e0, 0.8879267623988119819560021e0, 0.7968832893748414870413015e0, 0.7058431727509840105946884e0, 0.6148079652926100198490992e0, 0.5237802779694730663856110e0, 0.4327648832448234459097574e0, 0.3417715500266717765568488e0, 0.2508238767288223767569849e0, 0.1599966542668327644694431e0, 0.6970264809814094464033170e-1}, + {0.1527764849261740485876940e1, 0.1441701954349064743573367e1, 0.1355639243522655042028688e1, 0.1269576852063768424508476e1, 0.1183514935851550608323947e1, 0.1097453683555812711123880e1, 0.1011393333949027021740881e1, 0.9253342019812867059380523e0, 0.8392767201322475821509486e0, 0.7532215073977623159515351e0, 0.6671694908788198522546767e0, 0.5811221342350705406265672e0, 0.4950819018993074588093747e0, 0.4090533017972007314666814e0, 0.3230455648729987995657071e0, 0.2370809940997936908335290e0, 0.1512302802537625099602687e0, 0.6588357082399222649528476e-1}, + {0.1529999863223206659623262e1, 0.1448406982124841835685420e1, 0.1366814241651488684482888e1, 0.1285221744143731581870833e1, 0.1203629605904952775544878e1, 0.1122037965173751996510051e1, 0.1040446993107623345153211e1, 0.9588569097730895525404200e0, 0.8772680085516152329147030e0, 0.7956806951062012653043722e0, 0.7140955526031660805347356e0, 0.6325134568448222221560326e0, 0.5509357927460004487348532e0, 0.4693648943475422765864580e0, 0.3878050333015201414955289e0, 0.3062649591511896679168503e0, 0.2247658146033686460963295e0, 0.1433746167818849555570557e0, 0.6246124541276674097388211e-1}, + {0.1532014188279762793560699e1, 0.1454449946977268522285131e1, 0.1376885814601482670609845e1, 0.1299321869764876494939757e1, 0.1221758200747475205847413e1, 0.1144194910846247537582396e1, 0.1066632125552939823863593e1, 0.9890700026972186303565530e0, 0.9115087474225932692070479e0, 0.8339486352158799520695092e0, 0.7563900488174808348719219e0, 0.6788335401193977027577509e0, 0.6012799395312684623216685e0, 0.5237305617022755897200291e0, 0.4461876237541810478131970e0, 0.3686551849119556335824055e0, 0.2911415613085158758589405e0, 0.2136668503694680525340165e0, 0.1362947587312224822844743e0, 0.5937690028966411906487257e-1}, + {0.1533838971193864306068338e1, 0.1459924288056445029654271e1, 0.1386009690354996919044862e1, 0.1312095239305276612560739e1, 0.1238181002944535867235042e1, 0.1164267059803796726229370e1, 0.1090353503721897748980095e1, 0.1016440450472067349837507e1, 0.9425280472651469176638349e0, 0.8686164868955467866176243e0, 0.7947060295895204342519786e0, 0.7207970381018823842440224e0, 0.6468900366403721167107352e0, 0.5729858150363658839291287e0, 0.4990856247464946058899833e0, 0.4251915773724379089467945e0, 0.3513075400485981451355368e0, 0.2774414365914335857735201e0, 0.2036124177925793565507033e0, 0.1298811916061515892914930e0, 0.5658282534660210272754152e-1}, + {0.1535499761264077326499892e1, 0.1464906652494521470377318e1, 0.1394313611500109323616335e1, 0.1323720686538524176057236e1, 0.1253127930763390908996314e1, 0.1182535404796980113294400e1, 0.1111943180033868679273393e1, 0.1041351343083674290731439e1, 0.9707600019805773720746280e0, 0.9001692951667510715040632e0, 0.8295794049297955988640329e0, 0.7589905782114329186155957e0, 0.6884031600807736268672129e0, 0.6178176499732537480601935e0, 0.5472348011493452159473826e0, 0.4766558078624760377875119e0, 0.4060826859477620301047824e0, 0.3355191279517093844978473e0, 0.2649727008485465487101933e0, 0.1944616940738156405895778e0, 0.1240440866043499301839465e0, 0.5403988657613871827831605e-1}, + {0.1537017713608809830855653e1, 0.1469460505124226636602925e1, 0.1401903350962364703169699e1, 0.1334346289590505369693957e1, 0.1266789363044399933941254e1, 0.1199232618763735058848455e1, 0.1131676111906105521856066e1, 0.1064119908394702657537061e1, 0.9965640890815034701957497e0, 0.9290087556203499065939494e0, 0.8614540390091103102510609e0, 0.7939001124053586164046432e0, 0.7263472110048245091518914e0, 0.6587956640463586742461796e0, 0.5912459486086227271608064e0, 0.5236987847717837556177452e0, 0.4561553147193391989386660e0, 0.3886174669444433167860783e0, 0.3210887745896478259115420e0, 0.2535764786314617292100029e0, 0.1860980813776342452540915e0, 0.1187090676924131329841811e0, 0.5171568198966901682810573e-1}, + {0.1538410494858190444190279e1, 0.1473638845472165977392911e1, 0.1408867240039222913928858e1, 0.1344095709533508756473909e1, 0.1279324287566779722061664e1, 0.1214553011719528935181709e1, 0.1149781925191718586091000e1, 0.1085011078936665906275419e1, 0.1020240534516704208782618e1, 0.9554703680422404498752066e0, 0.8907006757608306209160649e0, 0.8259315822134856671969566e0, 0.7611632524946588128425351e0, 0.6963959112887657683892237e0, 0.6316298735371143844913976e0, 0.5668655960010826255149266e0, 0.5021037684870694065589284e0, 0.4373454855522296089897130e0, 0.3725925956833896735786860e0, 0.3078484858841616878136371e0, 0.2431200981264999375962973e0, 0.1784242126043536701754986e0, 0.1138140258514833068653307e0, 0.4958315373802413441075340e-1}, + {0.1539692973716708504412697e1, 0.1477486279394502338589519e1, 0.1415279620944410339318226e1, 0.1353073023537942666830874e1, 0.1290866514321280958405103e1, 0.1228660123395079609266898e1, 0.1166453885011658611362850e1, 0.1104247839096738022319035e1, 0.1042042033248543055386770e1, 0.9798365254403234947595400e0, 0.9176313877712591840677176e0, 0.8554267118081827231209625e0, 0.7932226163976800550406599e0, 0.7310192594231560707888939e0, 0.6688168560730805146438886e0, 0.6066157082814543103941755e0, 0.5444162542389049922529553e0, 0.4822191559963931133878621e0, 0.4200254643636986308379697e0, 0.3578369542536859435571624e0, 0.2956568781922605524959448e0, 0.2334919029083292837123583e0, 0.1713581437497397360313735e0, 0.1093066902335822942650053e0, 0.4761952998197036029817629e-1}, + {0.1540877753740080417345045e1, 0.1481040617373741365390254e1, 0.1421203510518656600018143e1, 0.1361366453804322852131292e1, 0.1301529469356044341206877e1, 0.1241692581525935716830402e1, 0.1181855817774264617619371e1, 0.1122019209772750368801179e1, 0.1062182794829879659341536e1, 0.1002346617783007482854908e1, 0.9425107335729934538419206e0, 0.8826752108319277463183701e0, 0.8228401370047382776784725e0, 0.7630056258499810562932058e0, 0.7031718287376427885875898e0, 0.6433389522119553277924537e0, 0.5835072863023426715977658e0, 0.5236772521416453354847559e0, 0.4638494862268433259444639e0, 0.4040249990308909882616381e0, 0.3442054975680110060507306e0, 0.2843941101955779333389742e0, 0.2245972494281051799602510e0, 0.1648304164747050021714385e0, 0.1051427544146599992432949e0, 0.4580550859172367960799915e-1}, + {0.1541975588842621898865181e1, 0.1484334121018556567335167e1, 0.1426692677652358867201800e1, 0.1369051275783071487471360e1, 0.1311409933595114953831618e1, 0.1253768670970438091691833e1, 0.1196127510146226323327062e1, 0.1138486476526912406867032e1, 0.1080845599717322003702293e1, 0.1023204914871722785830020e1, 0.9655644644970043364617272e0, 0.9079243009168822510582606e0, 0.8502844897148263889326479e0, 0.7926451146568312828354346e0, 0.7350062849078710810840430e0, 0.6773681459074923011631400e0, 0.6197308962817025162722438e0, 0.5620948151095422609589585e0, 0.5044603077892199488064657e0, 0.4468279872027509013135997e0, 0.3891988265038338944044115e0, 0.3315744698431505326770711e0, 0.2739579305700525818998611e0, 0.2163553856859193758294342e0, 0.1587817673749480300092784e0, 0.1012844151694839452028589e0, 0.4412462056235422293371300e-1}, + {0.1542995710582548837472073e1, 0.1487394484904746766220933e1, 0.1431793279635669382208875e1, 0.1376192108950239363921811e1, 0.1320590987909222553912422e1, 0.1264989932881031519687125e1, 0.1209388962038683919740547e1, 0.1153788095965648154683658e1, 0.1098187358416032947576489e1, 0.1042586777292402877200408e1, 0.9869863859317282394719449e0, 0.9313862248321055503829503e0, 0.8757863440192765677772914e0, 0.8201868063589761051746975e0, 0.7645876922981545448147078e0, 0.7089891068198449136125464e0, 0.6533911899285832425290628e0, 0.5977941329592257586198087e0, 0.5421982048745539015834188e0, 0.4866037965045890355211229e0, 0.4310114988353693539492225e0, 0.3754222503860499120445385e0, 0.3198376369331602148544626e0, 0.2642605649958747239907310e0, 0.2086969927688100977274751e0, 0.1531613237261629042774314e0, 0.9769922156300582041279299e-1, 0.4256272861907242306694832e-1}, + {0.1543946088331101630230404e1, 0.1490245617072432741470241e1, 0.1436545162952171175361532e1, 0.1382844737841275627385236e1, 0.1329144354302189376680665e1, 0.1275444025914442882448630e1, 0.1221743767654456436125309e1, 0.1168043596353244531685999e1, 0.1114343531263457295536939e1, 0.1060643594778787047442989e1, 0.1006943813366184678568021e1, 0.9532442187977767941200107e0, 0.8995448498101763729640445e0, 0.8458457543830885615091264e0, 0.7921469929325243736682034e0, 0.7384486428849507503612470e0, 0.6847508053901545384892447e0, 0.6310536154445759741044291e0, 0.5773572576394624029563656e0, 0.5236619915567428835581025e0, 0.4699681944935857341529219e0, 0.4162764370726533962791279e0, 0.3625876255789859906927245e0, 0.3089032914359211154562848e0, 0.2552262416643531728802047e0, 0.2015622306384971766058615e0, 0.1479251692966707827334002e0, 0.9435916010280739398532997e-1, 0.4110762866287674188292735e-1}, + {0.1544833637851665335244669e1, 0.1492908264756388370493025e1, 0.1440982906138650837480037e1, 0.1389057572001580364167786e1, 0.1337132272892735072773304e1, 0.1285207020157876647295968e1, 0.1233281826234298389291217e1, 0.1181356705000596722238457e1, 0.1129431672204958843918638e1, 0.1077506746001711267258715e1, 0.1025581947637229234301640e1, 0.9736573023432582093437126e0, 0.9217328405213548692702866e0, 0.8698085993416727107979968e0, 0.8178846249414537373941032e0, 0.7659609755086193214466010e0, 0.7140377257012462393241274e0, 0.6621149731355525426273686e0, 0.6101928481720243483360470e0, 0.5582715291407654489802101e0, 0.5063512668959282414914789e0, 0.4544324261262307197237056e0, 0.4025155584642650335664553e0, 0.3506015401168133792671488e0, 0.2986918517703509333332016e0, 0.2467892075469457255751440e0, 0.1948991714956708008247732e0, 0.1430351946011564171352354e0, 0.9123992133264713232350199e-1, 0.3974873026126591246235829e-1}, + {0.1545664389841685834178882e1, 0.1495400520006868605194165e1, 0.1445136662469633349524466e1, 0.1394872825707861196682996e1, 0.1344609018631531661347402e1, 0.1294345250782284139500904e1, 0.1244081532562166402923175e1, 0.1193817875503760392032898e1, 0.1143554292597402872188167e1, 0.1093290798696377946301336e1, 0.1043027411028491785799717e1, 0.9927641498535133311947588e0, 0.9425010393224361375194941e0, 0.8922381086194002226900769e0, 0.8419753935054036625982058e0, 0.7917129384431112475049142e0, 0.7414507995789214800057706e0, 0.6911890490185720721582180e0, 0.6409277811053987947460976e0, 0.5906671218914768219060599e0, 0.5404072438741681591850965e0, 0.4901483897634232956856935e0, 0.4398909124691513811974471e0, 0.3896353458699818240468259e0, 0.3393825380385224469051922e0, 0.2891339221891949677776928e0, 0.2388921255071779766209942e0, 0.1886625339124777570188312e0, 0.1384581678870181657476050e0, 0.8832030722827102577102185e-1, 0.3847679847963676404657822e-1}, + {0.1546443627125265521960044e1, 0.1497738231263909315513507e1, 0.1449032845902631477147772e1, 0.1400327478265391242178337e1, 0.1351622135921668846451224e1, 0.1302916826944702448727527e1, 0.1254211560091483702838765e1, 0.1205506345013417018443405e1, 0.1156801192508980685500292e1, 0.1108096114833249453312212e1, 0.1059391126084216587933501e1, 0.1010686242693213908544820e1, 0.9619814840575052973573711e0, 0.9132768733691264344256970e0, 0.8645724387181842642305406e0, 0.8158682145859558652971026e0, 0.7671642439014559105969752e0, 0.7184605809290069459742089e0, 0.6697572954095121564500879e0, 0.6210544786425143220264938e0, 0.5723522526623283741373995e0, 0.5236507845164779831804685e0, 0.4749503092950064087413842e0, 0.4262511688770346357064771e0, 0.3775538805043668894422883e0, 0.3288592658750793954850446e0, 0.2801687136893753887834348e0, 0.2314847695998852605184853e0, 0.1828126524563463299986617e0, 0.1341649789468091132459783e0, 0.8558174883654483804697753e-1, 0.3728374374031613183399036e-1}, + {0.1547175997094614757138430e1, 0.1499935340679181525271649e1, 0.1452694693272706215568985e1, 0.1405454061061768876728643e1, 0.1358213450511184239883293e1, 0.1310972868490444296079765e1, 0.1263732322416537730871712e1, 0.1216491820419724046503073e1, 0.1169251371540540180758674e1, 0.1122010985968754004469355e1, 0.1074770675338453464761893e1, 0.1027530453098431393666936e1, 0.9802903349842005856557204e0, 0.9330503396284544173873149e0, 0.8858104893623263267477775e0, 0.8385708112832335506864354e0, 0.7913313387011139500976360e0, 0.7440921131314510897906335e0, 0.6968531870945337206139839e0, 0.6496146281309018959581539e0, 0.6023765246993705639765525e0, 0.5551389950762090311242875e0, 0.5079022012032895030848024e0, 0.4606663710240282967569630e0, 0.4134318360639670775957014e0, 0.3661990979414348851212686e0, 0.3189689535781378596191439e0, 0.2717427498485401725509746e0, 0.2245229557871702595200694e0, 0.1773146332323969343091350e0, 0.1301300193754780766338959e0, 0.8300791095077070533235660e-1, 0.3616244959900389221395842e-1}, + {0.1547865604457777747119921e1, 0.1502004162357357213441384e1, 0.1456142728021903760325049e1, 0.1410281306774684706589738e1, 0.1364419904164498130803254e1, 0.1318558526067441138200403e1, 0.1272697178801115154796514e1, 0.1226835869256177571730448e1, 0.1180974605051351016009903e1, 0.1135113394719709026888693e1, 0.1089252247936466574864114e1, 0.1043391175801911243726755e1, 0.9975301911979639874925565e0, 0.9516693092438447484954432e0, 0.9058085478865097428655118e0, 0.8599479286766250282572181e0, 0.8140874778035996603018790e0, 0.7682272274981820559251592e0, 0.7223672179660643783333797e0, 0.6765075001043380283085699e0, 0.6306481393987597674748178e0, 0.5847892216487432573582268e0, 0.5389308616059791284685642e0, 0.4930732164176132508179420e0, 0.4472165073094733435432890e0, 0.4013610560689043520551232e0, 0.3555073496130768130758891e0, 0.3096561615434305328219637e0, 0.2638087993597793691714182e0, 0.2179676599607749036552390e0, 0.1721376573496165890967450e0, 0.1263306713881449555499955e0, 0.8058436603519718986295825e-1, 0.3510663068970053260227480e-1}, + {0.1548516088202564202943238e1, 0.1503955613246577879586994e1, 0.1459395145012190281751360e1, 0.1414834688100222735099866e1, 0.1370274247295441414922756e1, 0.1325713827649021532002630e1, 0.1281153434570536124285912e1, 0.1236593073933169034954499e1, 0.1192032752196710979323473e1, 0.1147472476554108430135576e1, 0.1102912255109027578275434e1, 0.1058352097094263144928973e1, 0.1013792013144153206047048e1, 0.9692320156388929821870602e0, 0.9246721191454417746654622e0, 0.8801123409896300773149632e0, 0.8355527020087518049947413e0, 0.7909932275560464363973909e0, 0.7464339488624693592395086e0, 0.7018749049145358048463504e0, 0.6573161450929179933243905e0, 0.6127577329584494909986789e0, 0.5681997518140860838771656e0, 0.5236423130979094957496400e0, 0.4790855694444512920982626e0, 0.4345297357523596151738496e0, 0.3899751246318782591316393e0, 0.3454222091410984787772492e0, 0.3008717408917773811461237e0, 0.2563249902500918978614004e0, 0.2117842860782107775954396e0, 0.1672544029381415755198150e0, 0.1227468836419337342946123e0, 0.7829832364814667171382217e-1, 0.3411071484766340151578357e-1}, + {0.1549130685823945998342524e1, 0.1505799405819664254557106e1, 0.1462468131657470292685966e1, 0.1419136867330461353369368e1, 0.1375805616982638895139986e1, 0.1332474384976155365522566e1, 0.1289143175965912901391449e1, 0.1245811994984327181800398e1, 0.1202480847539690438616688e1, 0.1159149739732435788417226e1, 0.1115818678394807971862305e1, 0.1072487671261111519215409e1, 0.1029156727178025494814510e1, 0.9858258563677261466814511e0, 0.9424950707611702085500992e0, 0.8991643844255133860018485e0, 0.8558338141192845596532563e0, 0.8125033800232146117493243e0, 0.7691731067161328174004981e0, 0.7258430244984030733808537e0, 0.6825131712172895509836733e0, 0.6391835948321685576634513e0, 0.5958543570955633038336902e0, 0.5525255389612023677479152e0, 0.5091972487450747080139606e0, 0.4658696348260689008126722e0, 0.4225429061321313393543928e0, 0.3792173666095906812269559e0, 0.3358934762285008809293807e0, 0.2925719658301625547639832e0, 0.2492540707015179370724365e0, 0.2059420554273186332219697e0, 0.1626405628266886976038507e0, 0.1193608172622853851645011e0, 0.7613840464754681957544313e-1, 0.3316974474186058622824911e-1}, + {0.1549712287207882890839045e1, 0.1507544209724862511636878e1, 0.1465376137339015815734558e1, 0.1423208073529702865859582e1, 0.1381040021900765225468989e1, 0.1338871986235691269778498e1, 0.1296703970558498635765633e1, 0.1254535979202491212629656e1, 0.1212368016889500927716256e1, 0.1170200088822853513468851e1, 0.1128032200798161849314963e1, 0.1085864359337236600941540e1, 0.1043696571852037437540940e1, 0.1001528846847853898635169e1, 0.9593611941780778060127795e0, 0.9171936253674231737318512e0, 0.8750261540268988114426643e0, 0.8328587963932301252176965e0, 0.7906915720393251716472997e0, 0.7485245048233193695739358e0, 0.7063576241759074809548715e0, 0.6641909668761970070284373e0, 0.6220245795476036586681135e0, 0.5798585222396645710869275e0, 0.5376928736905555113005422e0, 0.4955277392687366749125653e0, 0.4533632633323484070376718e0, 0.4111996491651493998151895e0, 0.3690371925202636251212886e0, 0.3268763409876008462653069e0, 0.2847178057580674399826003e0, 0.2425627889274157106498810e0, 0.2004134942584602007834507e0, 0.1582744399049656648660257e0, 0.1161565488818554609430574e0, 0.7409445176394481360104851e-1, 0.3227929535095246410912398e-1}, + {0.1550263480064160377720298e1, 0.1509197788083808185665328e1, 0.1468132100566875710992083e1, 0.1427066420556418463513913e1, 0.1386000751198712817289420e1, 0.1344935095788765217267069e1, 0.1303869457820298477498722e1, 0.1262803841041882838326682e1, 0.1221738249521212843639205e1, 0.1180672687719991159061894e1, 0.1139607160582508034089119e1, 0.1098541673641858946868449e1, 0.1057476233148907719560749e1, 0.1016410846230700992453501e1, 0.9753455210872527645472818e0, 0.9342802672387126698703291e0, 0.8932150958393123732306518e0, 0.8521500200807685012223049e0, 0.8110850557169691024167180e0, 0.7700202217553081279468270e0, 0.7289555413804262510029339e0, 0.6878910432074509889956044e0, 0.6468267630110350344178276e0, 0.6057627461556542068727688e0, 0.5646990510834698732732127e0, 0.5236357544389875315454201e0, 0.4825729588028297682338108e0, 0.4415108047277878179738561e0, 0.4004494901533595099830119e0, 0.3593893030723592157150581e0, 0.3183306793460978083354355e0, 0.2772743115465352362860883e0, 0.2362213703174823832436869e0, 0.1951740017836102296584907e0, 0.1541366059551230775894261e0, 0.1131198202589878992052369e0, 0.7215736988593890187079586e-1, 0.3143540438351454384152236e-1}, + {0.1550786588415152297375587e1, 0.1510767112957397367780716e1, 0.1470747641421582916022579e1, 0.1430728176478592843861361e1, 0.1390708720885325111445925e1, 0.1350689277522434511387126e1, 0.1310669849435604714836514e1, 0.1270650439881648370588402e1, 0.1230631052380981613091250e1, 0.1190611690778358944744052e1, 0.1150592359314214516523625e1, 0.1110573062709576809284752e1, 0.1070553806268363352417161e1, 0.1030534596002003296175373e1, 0.9905154387828984834423913e0, 0.9504963425353941517573974e0, 0.9104773164759498161192732e0, 0.8704583714184727086854142e0, 0.8304395201669023270865304e0, 0.7904207780260519973626051e0, 0.7504021634749074983118715e0, 0.7103836990664583264642972e0, 0.6703654126486745769832673e0, 0.6303473390491956215820085e0, 0.5903295224434431765765323e0, 0.5503120197533818815098408e0, 0.5102949056413983084126817e0, 0.4702782800468414863285692e0, 0.4302622799152491769326599e0, 0.3902470981180917254123191e0, 0.3502330152869736207185960e0, 0.3102204561556976356809728e0, 0.2702100956292792195263915e0, 0.2302030745053307298726703e0, 0.1902014842102915167005070e0, 0.1502096126336221315300686e0, 0.1102378261690820867329259e0, 0.7031899075931525095025389e-1, 0.3063451333411226493032265e-1}, + {0.1551283705347968314195100e1, 0.1512258463601911009913297e1, 0.1473233225313284690780287e1, 0.1434207992834186122366616e1, 0.1395182768588723275108301e1, 0.1356157555104474252423723e1, 0.1317132355046745793679891e1, 0.1278107171256650000336432e1, 0.1239082006794203284097135e1, 0.1200056864987904389011051e1, 0.1161031749492588664002624e1, 0.1122006664357811755961100e1, 0.1082981614109627397900573e1, 0.1043956603849447575483550e1, 0.1004931639374790125389322e1, 0.9659067273282460489273148e0, 0.9268818753831082867718635e0, 0.8878570924770502938457708e0, 0.8488323891094102606331406e0, 0.8098077777236123075833052e0, 0.7707832732049530424809748e0, 0.7317588935368492604710264e0, 0.6927346606780251833003950e0, 0.6537106017528970872810663e0, 0.6146867506941756306797580e0, 0.5756631505519364744300804e0, 0.5366398568077528417370132e0, 0.4976169422443344500752625e0, 0.4585945042946725387136724e0, 0.4195726764797194195007418e0, 0.3805516468579533335376469e0, 0.3415316890685593880011997e0, 0.3025132172735989410463832e0, 0.2634968895917008761291809e0, 0.2244838184598823563259898e0, 0.1854760433267094750424413e0, 0.1464777455344068532549101e0, 0.1074990339130794792907032e0, 0.6857195785426972961368108e-1, 0.2987341732561906608807860e-1}, + {0.1551756721003315464043007e1, 0.1513677510435354867644006e1, 0.1475598302924814895692182e1, 0.1437519100549654116408972e1, 0.1399439905448387106945081e1, 0.1361360719846430407096351e1, 0.1323281546084682430842605e1, 0.1285202386651141609385598e1, 0.1247123244216506877361870e1, 0.1209044121674894401873626e1, 0.1170965022191058363946285e1, 0.1132885949255841486220662e1, 0.1094806906752030657845562e1, 0.1056727899033393535018723e1, 0.1018648931020478788570327e1, 0.9805700083178549567966928e0, 0.9424911373589552049711100e0, 0.9044123255867553868253384e0, 0.8663335816813894348633149e0, 0.8282549158498738099497389e0, 0.7901763401989443875774432e0, 0.7520978692204962458482329e0, 0.7140195204316730003387055e0, 0.6759413152305656820841666e0, 0.6378632800575392064866756e0, 0.5997854479978337579981629e0, 0.5617078610344953281799357e0, 0.5236305732820186728652802e0, 0.4855536557378012985520074e0, 0.4474772034530068342865487e0, 0.4094013466928584958758982e0, 0.3713262689388439070717808e0, 0.3332522371792479009733062e0, 0.2951796555193184134657530e0, 0.2571091661074227554417865e0, 0.2190418543971735546480404e0, 0.1809797103814301725822348e0, 0.1429268140230164119614409e0, 0.1048930290780323497410212e0, 0.6690962797843649866645769e-1, 0.2914922224685900914817542e-1}, + {0.1552207346590136182648920e1, 0.1515029387081184115266415e1, 0.1477851430283927973458023e1, 0.1440673478039699629370259e1, 0.1403495532240969264030648e1, 0.1366317594853508812224152e1, 0.1329139667940348087929429e1, 0.1291961753688162615428688e1, 0.1254783854436838464182091e1, 0.1217605972713102930414639e1, 0.1180428111269300876868432e1, 0.1143250273128649048802100e1, 0.1106072461638634327789036e1, 0.1068894680534663975270023e1, 0.1031716934016664760314029e1, 0.9945392268421176498894610e0, 0.9573615644400829018748874e0, 0.9201839530522288586731642e0, 0.8830063999088902711516820e0, 0.8458289134509915302518266e0, 0.8086515036126424512848147e0, 0.7714741821849085841225787e0, 0.7342969632895448309937051e0, 0.6971198640037406540069491e0, 0.6599429051953912854163132e0, 0.6227661126567800124770610e0, 0.5855895186691062254659102e0, 0.5484131642019636734351025e0, 0.5112371020703309674589504e0, 0.4740614015734592960802666e0, 0.4368861554959151187817336e0, 0.3997114910036376358365916e0, 0.3625375872199777754435892e0, 0.3253647047992267079974806e0, 0.2881932382678453273830096e0, 0.2510238145617968753500674e0, 0.2138574934303919974438356e0, 0.1766962177535783269128215e0, 0.1395439709154010255199071e0, 0.1024103832005221866954023e0, 0.6532598686141261097119747e-1, 0.2845930797694291389393445e-1}, + {0.1552637135069155811491072e1, 0.1516318752418798211357541e1, 0.1480000372180291690418989e1, 0.1443681995989991700140976e1, 0.1407363625527612735973164e1, 0.1371045262534953065860219e1, 0.1334726908836065747097909e1, 0.1298408566359386697763653e1, 0.1262090237162411913706886e1, 0.1225771923459625279363960e1, 0.1189453627654523146514386e1, 0.1153135352376772077918208e1, 0.1116817100525785826106551e1, 0.1080498875322336017099434e1, 0.1044180680370244915946738e1, 0.1007862519730785566833872e1, 0.9715443980131875264637689e0, 0.9352263204856910439167915e0, 0.8989082932130182550456316e0, 0.8625903232280967802521182e0, 0.8262724187486163930514201e0, 0.7899545894528804342126058e0, 0.7536368468349768085155075e0, 0.7173192046673890278545072e0, 0.6810016796111441673128480e0, 0.6446842920316340773745262e0, 0.6083670671059611518530899e0, 0.5720500363511797523369558e0, 0.5357332397728172506411618e0, 0.4994167289487775362163415e0, 0.4631005715608865274454686e0, 0.4267848582339839676363509e0, 0.3904697131799790288672503e0, 0.3541553113674441557740819e0, 0.3178419074113077198829473e0, 0.2815298867038369044519273e0, 0.2452198616736214006194288e0, 0.2089128675558041239775998e0, 0.1726108022974787183994402e0, 0.1363175571713249458600521e0, 0.1000425397881322914313825e0, 0.6381557644960651200944222e-1, 0.2780129671121636039734655e-1}, + {0.1553047499032218401181962e1, 0.1517549844221432542461907e1, 0.1482052191561582448658478e1, 0.1446554542510861055782865e1, 0.1411056898564365493121105e1, 0.1375559261269981001734724e1, 0.1340061632245437638964436e1, 0.1304564013196950335363525e1, 0.1269066405939915513649123e1, 0.1233568812422221364483924e1, 0.1198071234750839346739124e1, 0.1162573675222508872274463e1, 0.1127076136359515473862368e1, 0.1091578620951808778363231e1, 0.1056081132107029235444226e1, 0.1020583673310438024843461e1, 0.9850862484973095869616622e0, 0.9495888621411026369897815e0, 0.9140915193617473526041913e0, 0.8785942260597805964360395e0, 0.8430969890839839780181254e0, 0.8075998164428632814935249e0, 0.7721027175741014967901450e0, 0.7366057036915554827257553e0, 0.7011087882372792641869964e0, 0.6656119874777629720186974e0, 0.6301153213012084608241887e0, 0.5946188142997514629085459e0, 0.5591224972630766104664894e0, 0.5236264092783024624074546e0, 0.4881306007441175888503326e0, 0.4526351377998500905914452e0, 0.4171401090099414677462070e0, 0.3816456357674021470057899e0, 0.3461518890753412856675063e0, 0.3106591177837409768492156e0, 0.2751676985649013361686770e0, 0.2396782299970584002479842e0, 0.2041917239104339765549482e0, 0.1687100353513348647833163e0, 0.1332369676454340307348264e0, 0.9778171579501174586520881e-1, 0.6237343205901608270979365e-1, 0.2717302558182235133513210e-1}, + {0.1553439726211153891540573e1, 0.1518726525682668668950427e1, 0.1484013327077361052080319e1, 0.1449300131698066374929113e1, 0.1414586940879145218883617e1, 0.1379873756000009717714844e1, 0.1345160578499605494109603e1, 0.1310447409892181029407508e1, 0.1275734251784724823396464e1, 0.1241021105896515467487132e1, 0.1206307974081314658309029e1, 0.1171594858352843571506531e1, 0.1136881760914326165420300e1, 0.1102168684193068774494217e1, 0.1067455630881287279906518e1, 0.1032742603984709761582283e1, 0.9980296068808995413713835e0, 0.9633166433897968474836258e0, 0.9286037178597176902839922e0, 0.8938908352730483454962679e0, 0.8591780013772376740585140e0, 0.8244652228485703565016715e0, 0.7897525074988288740747291e0, 0.7550398645386622329842600e0, 0.7203273049167972965433221e0, 0.6856148417619669061621766e0, 0.6509024909658764678789680e0, 0.6161902719627732109904446e0, 0.5814782087876726421060849e0, 0.5467663315368932859708410e0, 0.5120546784214694424751802e0, 0.4773432987146161851453875e0, 0.4426322570828636775769209e0, 0.4079216401227574252826633e0, 0.3732115665343573673240355e0, 0.3385022035318641142927744e0, 0.3037937944563405612019789e0, 0.2690867076466992914990193e0, 0.2343815284441088285495466e0, 0.1996792463094099012688324e0, 0.1649816752853099621072722e0, 0.1302925346385956500837770e0, 0.9562081616094948269905207e-1, 0.6099502786102040135198395e-1, 0.2657252290854776665952679e-1}, + {0.1553814992974904767594241e1, 0.1519852325907741898557817e1, 0.1485889660564341242674032e1, 0.1451926998111647785152899e1, 0.1417964339743630985906479e1, 0.1384001686692845945859686e1, 0.1350039040242776872946770e1, 0.1316076401741232369348729e1, 0.1282113772615099921371445e1, 0.1248151154386817288949698e1, 0.1214188548692984168143550e1, 0.1180225957305622474388020e1, 0.1146263382156703179022046e1, 0.1112300825366698998613230e1, 0.1078338289278105103916832e1, 0.1044375776495107627552926e1, 0.1010413289930890288650173e1, 0.9764508328644780886953041e0, 0.9424884090095589354132202e0, 0.9085260225984488659490189e0, 0.8745636784853451215455853e0, 0.8406013822743460048537475e0, 0.8066391404795569177534715e0, 0.7726769607271702244889884e0, 0.7387148520130367387469271e0, 0.7047528250344497011443004e0, 0.6707908926224332706815892e0, 0.6368290703120276715090693e0, 0.6028673771049329733376093e0, 0.5689058365047911420524623e0, 0.5349444779460832748774921e0, 0.5009833388030907720537138e0, 0.4670224672735823328060142e0, 0.4330619266162571710985599e0, 0.3991018015460700850326972e0, 0.3651422081877256344485503e0, 0.3311833101314466311103548e0, 0.2972253454486352538763297e0, 0.2632686745061683534910424e0, 0.2293138699815081215985284e0, 0.1953618999343470689252174e0, 0.1614145391777897730914718e0, 0.1274754265555317105245073e0, 0.9355335943686297111639257e-1, 0.5967622944002585907962555e-1, 0.2599798753052849047032580e-1}, + {0.1554174376112911655131098e1, 0.1520930475263640362170511e1, 0.1487686575963027013435604e1, 0.1454442679258803180913942e1, 0.1421198786221944168258440e1, 0.1387954897956585365296993e1, 0.1354711015610581847809736e1, 0.1321467140386931222410853e1, 0.1288223273556309404505081e1, 0.1254979416471008337267759e1, 0.1221735570580615776412743e1, 0.1188491737449843097435062e1, 0.1155247918778991542491874e1, 0.1122004116427655660730083e1, 0.1088760332442401967089102e1, 0.1055516569089340593777585e1, 0.1022272828892740925095715e1, 0.9890291146811467076264609e0, 0.9557854296428465678959260e0, 0.9225417773930866874628226e0, 0.8892981620561221868061383e0, 0.8560545883661619186153440e0, 0.8228110617925680415850631e0, 0.7895675886964734656602191e0, 0.7563241765284943282959446e0, 0.7230808340807681383862155e0, 0.6898375718116413059811978e0, 0.6565944022687408111136058e0, 0.6233513406471279431598408e0, 0.5901084055357449335782332e0, 0.5568656199307345199294838e0, 0.5236230126340485109018232e0, 0.4903806202198476810807501e0, 0.4571384898571183050552302e0, 0.4238966834573972483152713e0, 0.3906552839347125500730013e0, 0.3574144049483910279156003e0, 0.3241742066189948531421192e0, 0.2909349219721993995636414e0, 0.2576969037411283384416169e0, 0.2244607124763750082606152e0, 0.1912272957431274569912962e0, 0.1579983907861406744991899e0, 0.1247775594308675650267811e0, 0.9157341285433675818728635e-1, 0.5841325237532701385812948e-1, 0.2544777076240816313972829e-1}, + {0.1554518863153354618809409e1, 0.1521963936333782670214978e1, 0.1489409010908686292228052e1, 0.1456854087820918568482631e1, 0.1424299168033388494075931e1, 0.1391744252537595165009714e1, 0.1359189342362693116905575e1, 0.1326634438585269225516707e1, 0.1294079542340034988016159e1, 0.1261524654831668904330407e1, 0.1228969777348083696352705e1, 0.1196414911275444418157033e1, 0.1163860058115329026827193e1, 0.1131305219504506571098859e1, 0.1098750397237914982841550e1, 0.1066195593295557461150055e1, 0.1033640809874212986016967e1, 0.1001086049425085324651032e1, 0.9685313146988134601280153e0, 0.9359766087996588330547245e0, 0.9034219352512048766203636e0, 0.8708672980765996496647291e0, 0.8383127018973108640833295e0, 0.8057581520556423644789438e0, 0.7732036547680256450048242e0, 0.7406492173185620802637676e0, 0.7080948483057714882525616e0, 0.6755405579604902654406567e0, 0.6429863585601198571817691e0, 0.6104322649751623629236805e0, 0.5778782954001507969801437e0, 0.5453244723459250134170285e0, 0.5127708240092147734858477e0, 0.4802173861982495342372455e0, 0.4476642050968422792532389e0, 0.4151113413261211455132671e0, 0.3825588760747025757978563e0, 0.3500069206395502661556462e0, 0.3174556318161704671189642e0, 0.2849052377944113082878058e0, 0.2523560839907875626097181e0, 0.2198087193323827316322426e0, 0.1872640717400572601243546e0, 0.1547238424480887172335593e0, 0.1221915194567498709631299e0, 0.8967553546914315204781840e-1, 0.5720262597323678474637133e-1, 0.2492036059421555107245208e-1}, + {0.1554849361424470843090118e1, 0.1522955431101933730645303e1, 0.1491061502037751976297424e1, 0.1459167575082261894770634e1, 0.1427273651103158170602525e1, 0.1395379730992862183093282e1, 0.1363485815676330697886480e1, 0.1331591906119453530640248e1, 0.1299698003338207337770238e1, 0.1267804108408757103237650e1, 0.1235910222478728395590872e1, 0.1204016346779913703159712e1, 0.1172122482642727288439229e1, 0.1140228631512787910483320e1, 0.1108334794970091261912531e1, 0.1076440974751339138680154e1, 0.1044547172776127017814204e1, 0.1012653391177865049408482e1, 0.9807596323405319627306720e0, 0.9488658989426541583823449e0, 0.9169721940102869797082899e0, 0.8850785209812848825432963e0, 0.8531848837838285971960304e0, 0.8212912869330969580404013e0, 0.7893977356512249782795147e0, 0.7575042360174185552669765e0, 0.7256107951575083863622461e0, 0.6937174214856350398887716e0, 0.6618241250156435481462849e0, 0.6299309177668761147121611e0, 0.5980378142995696297245189e0, 0.5661448324309071185385071e0, 0.5342519942071113461815355e0, 0.5023593272451872220760104e0, 0.4704668666194035162003700e0, 0.4385746575692260390945883e0, 0.4066827594785525726660483e0, 0.3747912518813925812276922e0, 0.3429002438089823350625543e0, 0.3110098888674705209106637e0, 0.2791204106078991711912441e0, 0.2472321474279120600810915e0, 0.2153456371036966567922014e0, 0.1834617887100953140198272e0, 0.1515822689338083535939382e0, 0.1197104949484175660714864e0, 0.8785472823121690639967810e-1, 0.5604116141749524467628553e-1, 0.2441436781606819510490200e-1}, + {0.1555166706034023842787706e1, 0.1523907464890582273398300e1, 0.1492648224885016483409279e1, 0.1461388986785839210767990e1, 0.1430129751376631035251350e1, 0.1398870519462421720845393e1, 0.1367611291876438076975682e1, 0.1336352069487341263827064e1, 0.1305092853207091240256110e1, 0.1273833643999595441027728e1, 0.1242574442890323705495464e1, 0.1211315250977103200801981e1, 0.1180056069442347222927677e1, 0.1148796899567022469820701e1, 0.1117537742746723499546780e1, 0.1086278600510304367969825e1, 0.1055019474541620880304106e1, 0.1023760366705069175705639e1, 0.9925012790757765081567637e0, 0.9612422139755203374385844e0, 0.9299831740157389822411293e0, 0.8987241621493743180375722e0, 0.8674651817337867269827651e0, 0.8362062366076504452859926e0, 0.8049473311856388413561914e0, 0.7736884705759381993127359e0, 0.7424296607273230664538510e0, 0.7111709086148904840060001e0, 0.6799122224768919982385331e0, 0.6486536121198915829209739e0, 0.6173950893164463798129595e0, 0.5861366683298159921278400e0, 0.5548783666157332634604655e0, 0.5236202057751242467455922e0, 0.4923622128691229579358494e0, 0.4611044222679868504944176e0, 0.4298468783051183048132298e0, 0.3985896391770900735176252e0, 0.3673327828297899556279530e0, 0.3360764161195064368209114e0, 0.3048206895905456571224703e0, 0.2735658223403245791263072e0, 0.2423121460275046288225596e0, 0.2110601877217048587999889e0, 0.1798108384023314561549010e0, 0.1485657315840060835766576e0, 0.1173282164330337207824850e0, 0.8610639001623934211634967e-1, 0.5492592372249737419414775e-1, 0.2392851379957687254895331e-1}, +} + +var oddThetaZeros = [][]float64{ + {0.6847192030022829138880982e0}, + {0.1002176803643121641749915e1, 0.4366349492255221620374655e0}, + {0.1152892953722227341986065e1, 0.7354466143229520469385622e0, 0.3204050902900619825355950e0}, + {0.1240573923404363422789550e1, 0.9104740292261473250358755e0, 0.5807869795060065580284919e0, 0.2530224166119306882187233e0}, + {0.1297877729331450368298142e1, 0.1025003226369574843297844e1, 0.7522519395990821317003373e0, 0.4798534223256743217333579e0, 0.2090492874137409414071522e0}, + {0.1338247676100454369194835e1, 0.1105718066248490075175419e1, 0.8732366099401630367220948e0, 0.6408663264733867770811230e0, 0.4088002373420211722955679e0, 0.1780944581262765470585931e0}, + {0.1368219536992351783359098e1, 0.1165652065603030148723847e1, 0.9631067821301481995711685e0, 0.7606069572889918619145483e0, 0.5582062109125313357140248e0, 0.3560718303314725022788878e0, 0.1551231069747375098418591e0}, + {0.1391350647015287461874435e1, 0.1211909966211469688151240e1, 0.1032480728417239563449772e1, 0.8530732514258505686069670e0, 0.6737074594242522259878462e0, 0.4944303818194983217354808e0, 0.3153898594929282395996014e0, 0.1373998952992547671039022e0}, + {0.1409742336767428999667236e1, 0.1248691224331339221187704e1, 0.1087646521650454938943641e1, 0.9266134127998189551499083e0, 0.7656007620508340547558669e0, 0.6046261769405451549818494e0, 0.4437316659960951760051408e0, 0.2830497588453068048261493e0, 0.1233108673082312764916251e0}, + {0.1424715475176742734932665e1, 0.1278636375242898727771561e1, 0.1132561101012537613667002e1, 0.9864925055883793730483278e0, 0.8404350520135058972624775e0, 0.6943966110110701016065380e0, 0.5483930281810389839680525e0, 0.4024623099018152227701990e0, 0.2567245837448891192759858e0, 0.1118422651428890834760883e0}, + {0.1437141935303526306632113e1, 0.1303488659735581140681362e1, 0.1169837785762829821262819e1, 0.1036190996404462300207004e1, 0.9025507517347875930425807e0, 0.7689210263823624893974324e0, 0.6353089402976822861185532e0, 0.5017289283414202278167583e0, 0.3682157131008289798868520e0, 0.2348791589702580223688923e0, 0.1023252788872632487579640e0}, + {0.1447620393135667144403507e1, 0.1324445197736386798102445e1, 0.1201271573324181312770120e1, 0.1078100568411879956441542e1, 0.9549336362382321811515336e0, 0.8317729718814276781352878e0, 0.7086221837538611370849622e0, 0.5854877911108011727748238e0, 0.4623830630132757357909198e0, 0.3393399712563371486343129e0, 0.2164597408964339264361902e0, 0.9430083986305519349231898e-1}, + {0.1456575541704195839944967e1, 0.1342355260834552126304154e1, 0.1228136043468909663499174e1, 0.1113918572282611841378549e1, 0.9997037539874953933323299e0, 0.8854928869950799998575862e0, 0.7712879690777516856072467e0, 0.6570923167092416238233585e0, 0.5429119513798658239789812e0, 0.4287591577660783587509129e0, 0.3146635662674373982102762e0, 0.2007190266590380629766487e0, 0.8744338280630300217927750e-1}, + {0.1464317002991565219979113e1, 0.1357838033080061766980173e1, 0.1251359804334884770836945e1, 0.1144882777708662655968171e1, 0.1038407544520296695714932e1, 0.9319349156915986836657782e0, 0.8254660749671546663859351e0, 0.7190028636037068047812305e0, 0.6125483562383020473196681e0, 0.5061081521562999836102547e0, 0.3996936914666951732317457e0, 0.2933325857619472952507468e0, 0.1871123137498061864373407e0, 0.8151560650977882057817999e-1}, + {0.1471075823713997440657641e1, 0.1371355574944658989649887e1, 0.1271635855736122280723838e1, 0.1171916986981363820797100e1, 0.1072199368669106404814915e1, 0.9724835301003496870596165e0, 0.8727702114891848603047954e0, 0.7730605060747958359120755e0, 0.6733561257504194406005404e0, 0.5736599396529727772420934e0, 0.4739771829190733570809765e0, 0.3743185619229329461021810e0, 0.2747099287638327553949437e0, 0.1752332025619508475799133e0, 0.7634046205384429302353073e-1}, + {0.1477027911291552393547878e1, 0.1383259682348271685979143e1, 0.1289491840051302622319481e1, 0.1195724613675799550484673e1, 0.1101958282220461402990667e1, 0.1008193204014774090964219e1, 0.9144298626454031699590564e0, 0.8206689427646120483710056e0, 0.7269114630504563073034288e0, 0.6331590254855162126233733e0, 0.5394143214244183829842424e0, 0.4456822679082866369288652e0, 0.3519729273095236644049666e0, 0.2583106041071417718760275e0, 0.1647723231643112502628240e0, 0.7178317184275122449502857e-1}, + {0.1482309554825692463999299e1, 0.1393822922226542123661077e1, 0.1305336577335833571381699e1, 0.1216850687682353365944624e1, 0.1128365453024608460982204e1, 0.1039881123511957522668140e1, 0.9513980267579228357946521e0, 0.8629166105524045911461307e0, 0.7744375139383604902604254e0, 0.6859616923374368587817328e0, 0.5974906525247623278123711e0, 0.5090269299866796725116786e0, 0.4205751610647263669405267e0, 0.3321448379994943116084719e0, 0.2437588931448048912587688e0, 0.1554900095178924564386865e0, 0.6773932498157585698088354e-1}, + {0.1487027983239550912222135e1, 0.1403259745496922270264564e1, 0.1319491725464661433609663e1, 0.1235724047968681189212364e1, 0.1151956859289811446164825e1, 0.1068190338689553494802072e1, 0.9844247150109837231349622e0, 0.9006602918737365182850484e0, 0.8168974877846821404275069e0, 0.7331369031796229223580227e0, 0.6493794386888650054486281e0, 0.5656265174356596757139537e0, 0.4818805368222631487731579e0, 0.3981458834052590173509113e0, 0.3144315409387123154212535e0, 0.2307592167302372059759857e0, 0.1471977156945989772472748e0, 0.6412678117309944052403703e-1}, + {0.1491268718102344688271411e1, 0.1411741190914640487505771e1, 0.1332213830951015404441941e1, 0.1252686732830809999680267e1, 0.1173160005794509313174730e1, 0.1093633781237958896879965e1, 0.1014108223243148393065201e1, 0.9345835440325075907377330e0, 0.8550600276575269107773349e0, 0.7755380679025248517258532e0, 0.6960182317959841585145109e0, 0.6165013717819833504477346e0, 0.5369888366794912945318079e0, 0.4574829005269902932408889e0, 0.3779877260196973978940863e0, 0.2985118404618624984946326e0, 0.2190758506462427957069113e0, 0.1397450765119767349146353e0, 0.6088003363863534825005464e-1}, + {0.1495100801651051409999732e1, 0.1419405340110198552778393e1, 0.1343710008748627892724810e1, 0.1268014880389353000310414e1, 0.1192320038028903827079750e1, 0.1116625579891689469044026e1, 0.1040931626310454794079799e1, 0.9652383295306942866661884e0, 0.8895458882533946571137358e0, 0.8138545700535261740447950e0, 0.7381647473570304814395029e0, 0.6624769578126105498149624e0, 0.5867920109947446493391737e0, 0.5111111891461744489290992e0, 0.4354366553151050147918632e0, 0.3597723703299625354660452e0, 0.2841264494060559943920389e0, 0.2085185052177154996230005e0, 0.1330107089065635461375419e0, 0.5794620170990797798650123e-1}, + {0.1498580583401444174317386e1, 0.1426364890228584522673414e1, 0.1354149299629923281192036e1, 0.1281933868420423988034246e1, 0.1209718660626713399048551e1, 0.1137503750956414845248481e1, 0.1065289229411733880607916e1, 0.9930752076949068878557126e0, 0.9208618284397049456535757e0, 0.8486492789905562098591586e0, 0.7764378127156926158031943e0, 0.7042277832708635930867344e0, 0.6320197021480767602848178e0, 0.5598143404345395912377042e0, 0.4876129202946139420188428e0, 0.4154175043169533365541148e0, 0.3432318703096418027524597e0, 0.2710637595435203246492797e0, 0.1989318822110657561806962e0, 0.1268955503926593166308254e0, 0.5528212871240371048241379e-1}, + {0.1501754508594837337089856e1, 0.1432712730475143340404518e1, 0.1363671034069754274950592e1, 0.1294629464249430679064317e1, 0.1225588071083248538559259e1, 0.1156546912269029268686830e1, 0.1087506056298747798071893e1, 0.1018465586752840651469411e1, 0.9494256083335850798964741e0, 0.8803862556198167553278643e0, 0.8113477061841624760598814e0, 0.7423102009244498727845341e0, 0.6732740767851639064676858e0, 0.6042398217472142478598295e0, 0.5352081720899522889584566e0, 0.4661802954366277026594659e0, 0.3971581629712621730826920e0, 0.3281453857685808451825081e0, 0.2591493642052661979197670e0, 0.1901879854885491785792565e0, 0.1213179541186130699071317e0, 0.5285224511635143601147552e-1}, + {0.1504661202517196460191540e1, 0.1438526110541037227495230e1, 0.1372391084315255737540026e1, 0.1306256159670931796771616e1, 0.1240121376243315949825014e1, 0.1173986779205849344923421e1, 0.1107852421486856229076325e1, 0.1041718366715156747157745e1, 0.9755846932657442605621389e0, 0.9094514999854931965227238e0, 0.8433189145364798253029042e0, 0.7771871059265138564989363e0, 0.7110563039566125173946002e0, 0.6449268305419475123120585e0, 0.5787991523675322133651034e0, 0.5126739740395088296453592e0, 0.4465524134105889084933393e0, 0.3804363581140941600870992e0, 0.3143292666717729726674543e0, 0.2482382273986418438740754e0, 0.1821803739336923550363257e0, 0.1162100228791666307841708e0, 0.5062697144246344520692308e-1}, + {0.1507333049739684406957329e1, 0.1443869798951040686809862e1, 0.1380406601553595646811530e1, 0.1316943486448336467960940e1, 0.1253480485358734060913055e1, 0.1190017634088428795118215e1, 0.1126554974102287077081806e1, 0.1063092554588577221978254e1, 0.9996304352342330000643921e0, 0.9361686900661624628632729e0, 0.8727074129127595264965883e0, 0.8092467253835331800652228e0, 0.7457867888716805068068402e0, 0.6823278231980088937854296e0, 0.6188701366516795329577182e0, 0.5554141765061554178407906e0, 0.4919606183965743300387332e0, 0.4285105345527885639657014e0, 0.3650657359209552112046854e0, 0.3016295408979540017854803e0, 0.2382087510453128743250072e0, 0.1748198074104535338147956e0, 0.1115148317291502081079519e0, 0.4858150828905663931389750e-1}, + {0.1509797405521643600800862e1, 0.1448798505784201776188819e1, 0.1387799649767640868379247e1, 0.1326800860997572277878513e1, 0.1265802165120213614545418e1, 0.1204803590828283748583827e1, 0.1143805171007496028164312e1, 0.1082806944206958485218487e1, 0.1021808956582037259849130e1, 0.9608112645303606832220554e0, 0.8998139383584991342974664e0, 0.8388170675106567024157190e0, 0.7778207682214244793380700e0, 0.7168251950382156442798800e0, 0.6558305587295081487906238e0, 0.5948371551492265376377962e0, 0.5338454137827292925154468e0, 0.4728559836463229599006206e0, 0.4118698949811841042358258e0, 0.3508888880839026413717319e0, 0.2899161521835467942607342e0, 0.2289582244272697168835150e0, 0.1680309071251709912058722e0, 0.1071842976730454709494914e0, 0.4669490825917857848258897e-1}, + {0.1512077535592702651885542e1, 0.1453358762182399391553360e1, 0.1394640024852448295479492e1, 0.1335921342914185177270306e1, 0.1277202737290683500323248e1, 0.1218484231207691826029908e1, 0.1159765851037557179133987e1, 0.1101047627365156083369632e1, 0.1042329596373083545617043e1, 0.9836118016874520301049009e0, 0.9248942968954766185908511e0, 0.8661771490588063053774554e0, 0.8074604437333368789787031e0, 0.7487442923247565105494255e0, 0.6900288431709550365296138e0, 0.6313142987730108226833704e0, 0.5726009435739572428629866e0, 0.5138891906843943809444838e0, 0.4551796645660731149033106e0, 0.3964733566771858874923011e0, 0.3377719420068963817561906e0, 0.2790784903284342592940125e0, 0.2203992941938221111139898e0, 0.1617495649772923108686624e0, 0.1031775271253784724197264e0, 0.4494935602951385601335598e-1}, + {0.1514193352804819997509006e1, 0.1457590393617468793209691e1, 0.1400987464419153080392546e1, 0.1344384581184662080889348e1, 0.1287781761126833878758488e1, 0.1231179023218584237510462e1, 0.1174576388822640925688125e1, 0.1117973882475943676285829e1, 0.1061371532893653466992815e1, 0.1004769374285310770780417e1, 0.9481674481184788854172919e0, 0.8915658055327279211293483e0, 0.8349645107156934027761499e0, 0.7783636457331086848148917e0, 0.7217633176118399859733190e0, 0.6651636690166557413471029e0, 0.6085648948549621671933311e0, 0.5519672690500084950513985e0, 0.4953711895788266953367288e0, 0.4387772581729219934583483e0, 0.3821864303519236078766179e0, 0.3256003205491779498477363e0, 0.2690218877324958059454348e0, 0.2124571975249336244841297e0, 0.1559209129891515317090843e0, 0.9945952063842375053227931e-1, 0.4332960406341033436157524e-1}, + {0.1516162000094549207021851e1, 0.1461527685790782385188426e1, 0.1406893396579229558427657e1, 0.1352259145769086826235918e1, 0.1297624947629923059740243e1, 0.1242990817790597917328601e1, 0.1188356773715062198539162e1, 0.1133722835287525783953663e1, 0.1079089025551156002698850e1, 0.1024455371662101389801169e1, 0.9698219061474760364582928e0, 0.9151886685974009713577537e0, 0.8605557079864861100238346e0, 0.8059230859253162466918892e0, 0.7512908813164713594661588e0, 0.6966591971861112012613682e0, 0.6420281709850565965229799e0, 0.5873979906122764301937499e0, 0.5327689202536826556885353e0, 0.4781413438508069051295597e0, 0.4235158420269503798571552e0, 0.3688933369002844229314675e0, 0.3142753865947702189467806e0, 0.2596648470121556361200229e0, 0.2050675726616484232653526e0, 0.1504977164639767777858359e0, 0.9600014792058154736462106e-1, 0.4182252607645932321862773e-1}, + {0.1517998315905975681819213e1, 0.1465200315462026532129551e1, 0.1412402336143180968579639e1, 0.1359604389111228213837104e1, 0.1306806486279734731351497e1, 0.1254008640622089183072742e1, 0.1201210866535131048800458e1, 0.1148413180281179970113571e1, 0.1095615600538999408768381e1, 0.1042818149105710558651372e1, 0.9900208518088600875617620e0, 0.9372237397138955502862203e0, 0.8844268507524555199840381e0, 0.8316302319600398731649744e0, 0.7788339426133210890795576e0, 0.7260380587255163256281298e0, 0.6732426796448045921910045e0, 0.6204479380061240544867289e0, 0.5676540152134466427854705e0, 0.5148611664077887834613451e0, 0.4620697624728053757183766e0, 0.4092803643735033357684553e0, 0.3564938631002461237979451e0, 0.3037117642790043703921396e0, 0.2509368276982060978106092e0, 0.1981747109679032915697317e0, 0.1454390911823840643137232e0, 0.9277332955453467429763451e-1, 0.4041676055113025684436480e-1}, + {0.1519715208823086817411929e1, 0.1468634099702062550682430e1, 0.1417553008469014674939490e1, 0.1366471944542347269659860e1, 0.1315390917933946912760115e1, 0.1264309939489363760018555e1, 0.1213229021168654147755139e1, 0.1162148176384137345494752e1, 0.1111067420416500738111992e1, 0.1059986770938296676746064e1, 0.1008906248685091746434581e1, 0.9578258783312407255956784e0, 0.9067456896525242756445150e0, 0.8556657190967860708153477e0, 0.8045860119448479090873824e0, 0.7535066253423996943740445e0, 0.7024276326462752642452137e0, 0.6513491298057893513225544e0, 0.6002712449887427739045163e0, 0.5491941535583390603837715e0, 0.4981181022276018128369963e0, 0.4470434496975185070560821e0, 0.3959707385770101868486847e0, 0.3449008307748737032772825e0, 0.2938351828535981363494671e0, 0.2427764647581323719392653e0, 0.1917301500230701193408602e0, 0.1407094708800750523796875e0, 0.8975637836633630394302762e-1, 0.3910242380354419363081899e-1}, + {0.1521323961422700444944464e1, 0.1471851603590422118622546e1, 0.1422379260986849454727777e1, 0.1372906941604798453293218e1, 0.1323434653909307929892118e1, 0.1273962407026590487708892e1, 0.1224490210963055761921526e1, 0.1175018076866133593082748e1, 0.1125546017342156230227131e1, 0.1076074046851682267877939e1, 0.1026602182210094558879809e1, 0.9771304432322302018639612e0, 0.9276588535760335871906045e0, 0.8781874418647315968408864e0, 0.8287162432047307488040550e0, 0.7792453012756761070555010e0, 0.7297746712644485550469075e0, 0.6803044240724808212528033e0, 0.6308346524943159683026367e0, 0.5813654805388740483542438e0, 0.5318970779332963132260134e0, 0.4824296835154055410257004e0, 0.4329636445908698102350729e0, 0.3834994865870752458854056e0, 0.3340380441799942088370002e0, 0.2845807279748544733570760e0, 0.2351301237470960623526672e0, 0.1856915325646991222655151e0, 0.1362777698319134965765757e0, 0.8692946525012054120187353e-1, 0.3787087726949234365520114e-1}, + {0.1522834478472358672931947e1, 0.1474872636605138418026177e1, 0.1426910807768284322082436e1, 0.1378948998781055367310047e1, 0.1330987216841224680164684e1, 0.1283025469674968454386883e1, 0.1235063765709222885799986e1, 0.1187102114275073728898860e1, 0.1139140525853183114841234e1, 0.1091179012375759666645271e1, 0.1043217587604604879578741e1, 0.9952562676120370548458597e0, 0.9472950714021223337048082e0, 0.8993340217254078241758816e0, 0.8513731461641338285808219e0, 0.8034124786014693431693904e0, 0.7554520612457602368887930e0, 0.7074919474732165281510693e0, 0.6595322059052657580628641e0, 0.6115729263971504325174172e0, 0.5636142290734363894767612e0, 0.5156562783879918167717991e0, 0.4676993058012953469089537e0, 0.4197436479350834076514896e0, 0.3717898140987174444032373e0, 0.3238386134116156886828960e0, 0.2758914133405791810724762e0, 0.2279507206431424610498769e0, 0.1800216744637006612298520e0, 0.1321166988439841543825694e0, 0.8427518284958235696897899e-1, 0.3671453742186897322954009e-1}, + {0.1524255491013576804195881e1, 0.1477714660784952783237945e1, 0.1431173841758652772349485e1, 0.1384633039781787069436630e1, 0.1338092261006965672253841e1, 0.1291551512012124788593875e1, 0.1245010799937299944123195e1, 0.1198470132644670409416924e1, 0.1151929518909907204916554e1, 0.1105388968655282680015213e1, 0.1058848493238442193822372e1, 0.1012308105815651361079674e1, 0.9657678218054126734684090e0, 0.9192276594886802366068293e0, 0.8726876407972167893294764e0, 0.8261477923647281669131478e0, 0.7796081469509049827753598e0, 0.7330687454042532567721262e0, 0.6865296394193009886613469e0, 0.6399908954920466591029822e0, 0.5934526007301573325059582e0, 0.5469148716199143611697357e0, 0.5003778676688561814362271e0, 0.4538418134105091550464446e0, 0.4073070354279485829740435e0, 0.3607740278788822846227453e0, 0.3142435758510728338330843e0, 0.2677170062389944640113953e0, 0.2211967514739567668334169e0, 0.1746877983807874325844051e0, 0.1282022028383479964348629e0, 0.8177818680168764430245080e-1, 0.3562671947817428176226631e-1}, + {0.1525594725214770881206476e1, 0.1480393128432045740356817e1, 0.1435191541323085582529217e1, 0.1389989968924959812091252e1, 0.1344788416522907866060817e1, 0.1299586889746827997174554e1, 0.1254385394680661996389736e1, 0.1209183937989395175829969e1, 0.1163982527069600127515982e1, 0.1118781170231154762473596e1, 0.1073579876920155012130433e1, 0.1028378657996412636748477e1, 0.9831775260837211038023103e0, 0.9379764960179657076015136e0, 0.8927755854282048597997986e0, 0.8475748155007347757967789e0, 0.8023742119985848209905761e0, 0.7571738066433708695662393e0, 0.7119736390205872251796930e0, 0.6667737592565460745639184e0, 0.6215742318591892056934095e0, 0.5763751413603713322640298e0, 0.5311766008298875656047892e0, 0.4859787651249621588538330e0, 0.4407818522612533891543536e0, 0.3955861793705505114602136e0, 0.3503922263398633798966312e0, 0.3052007556167344348049303e0, 0.2600130558662051177480644e0, 0.2148314894784555841956251e0, 0.1696608997322034095150907e0, 0.1245129955389270002683579e0, 0.7942489891978153749097006e-1, 0.3460150809198016850782325e-1}, + {0.1526859042890589526378487e1, 0.1482921763148403842276533e1, 0.1438984491795164536567108e1, 0.1395047233189252525231459e1, 0.1351109991891878034957302e1, 0.1307172772745304669260382e1, 0.1263235580960968906699379e1, 0.1219298422221050703835127e1, 0.1175361302797916700875697e1, 0.1131424229697065895207730e1, 0.1087487210830887883186060e1, 0.1043550255232887174273672e1, 0.9996133733253190253881393e0, 0.9556765772578535710715874e0, 0.9117398813415957196221754e0, 0.8678033026125661948850687e0, 0.8238668615732247310812836e0, 0.7799305831824293601507400e0, 0.7359944981977457886183921e0, 0.6920586450266629333858465e0, 0.6481230723279649663476697e0, 0.6041878427445000852182582e0, 0.5602530383870993537615272e0, 0.5163187691099712879003757e0, 0.4723851853891499571797438e0, 0.4284524990953311047063058e0, 0.3845210184454249891341793e0, 0.3405912098612419399584605e0, 0.2966638144233703899038032e0, 0.2527400847124078576715667e0, 0.2088223170017057788708674e0, 0.1649152190599722827308055e0, 0.1210301722471160155498167e0, 0.7720326018898817828206987e-1, 0.3363364974516995102167462e-1}, + {0.1528054559083405137047563e1, 0.1485312794997097705446883e1, 0.1442571038214470776579613e1, 0.1399829292522320013570493e1, 0.1357087561874166765548658e1, 0.1314345850454078759228779e1, 0.1271604162748143389685638e1, 0.1228862503626296926524085e1, 0.1186120878437839368895715e1, 0.1143379293124832099340074e1, 0.1100637754358770795248912e1, 0.1057896269707576280860569e1, 0.1015154847842238156769126e1, 0.9724134987956584339974640e0, 0.9296722342907946818431047e0, 0.8869310681617368097575324e0, 0.8441900169008687429295884e0, 0.8014491003793523040286325e0, 0.7587083428093935362576859e0, 0.7159677740493625646700975e0, 0.6732274314040501413860867e0, 0.6304873621547357085895928e0, 0.5877476271899241333221832e0, 0.5450083063396327078463020e0, 0.5022695064252395155059223e0, 0.4595313737871711838065652e0, 0.4167941144922007176438387e0, 0.3740580283336802289311736e0, 0.3313235690067746553700419e0, 0.2885914573933480330041531e0, 0.2458629119584249278750153e0, 0.2031401664615301668533461e0, 0.1604278005405711652039491e0, 0.1177368858339244458607172e0, 0.7510252408650086658441596e-1, 0.3271846270775478856070884e-1}, + {0.1529186740959505109653289e1, 0.1487577158293388707508111e1, 0.1445967582009979387718202e1, 0.1404358015412336440816745e1, 0.1362748461941311565399969e1, 0.1321138925227929972823825e1, 0.1279529409151733277951100e1, 0.1237919917907156982173977e1, 0.1196310456080472987418488e1, 0.1154701028740456700905269e1, 0.1113091641546798022997704e1, 0.1071482300881451340842721e1, 0.1029873014009735917989475e1, 0.9882637892802373569245916e0, 0.9466546363756944528310758e0, 0.9050455666314926033869497e0, 0.8634365934447506520344540e0, 0.8218277328062565148449433e0, 0.7802190040012226850703573e0, 0.7386104305454957746359112e0, 0.6970020414556031913861513e0, 0.6553938730008771105113861e0, 0.6137859711661063914322283e0, 0.5721783951857430999179669e0, 0.5305712227365694155165922e0, 0.4889645577740232855661796e0, 0.4473585427277744403333139e0, 0.4057533781735039172217875e0, 0.3641493559322687127223795e0, 0.3225469176515179389138545e0, 0.2809467650889194227770571e0, 0.2393500844055270891104500e0, 0.1977590501629603151642330e0, 0.1561781206604067112364815e0, 0.1146180742271483316267615e0, 0.7311308274978660184520447e-1, 0.3185176130791400787169333e-1}, + {0.1530260491394766313570510e1, 0.1489724658775115137266557e1, 0.1449188831753177403184250e1, 0.1408653013220734918131897e1, 0.1368117206184034069757975e1, 0.1327581413807020172726043e1, 0.1287045639459248683416470e1, 0.1246509886770075360771330e1, 0.1205974159691064843702080e1, 0.1165438462569017837684371e1, 0.1124902800232641860108690e1, 0.1084367178096737546333982e1, 0.1043831602288925654461738e1, 0.1003296079805520648394589e1, 0.9627606187053432591598275e0, 0.9222252283533212928777294e0, 0.8816899197300536544215117e0, 0.8411547058297167490229198e0, 0.8006196021777239861105672e0, 0.7600846275129127849719743e0, 0.7195498046991648764002008e0, 0.6790151619622966197448464e0, 0.6384807345966275863946969e0, 0.5979465673637771458800754e0, 0.5574127179353942966481713e0, 0.5168792619515766918187819e0, 0.4763463006547495614450433e0, 0.4358139727703203523144583e0, 0.3952824736706231680817472e0, 0.3547520876199503791717895e0, 0.3142232448436673832093046e0, 0.2736966289659020439688229e0, 0.2331733955144496369946707e0, 0.1926556629116315949109922e0, 0.1521477743835989472840536e0, 0.1116602300918232453371161e0, 0.7122632005925390425640031e-1, 0.3102979192734513847869512e-1}, + {0.1531280219945530918862887e1, 0.1491764115543711582608611e1, 0.1452248016067723206269747e1, 0.1412731924058150689920340e1, 0.1373215842151127100608219e1, 0.1333699773114208203180680e1, 0.1294183719885939986844436e1, 0.1254667685620366764206205e1, 0.1215151673737978313041594e1, 0.1175635687984935008823566e1, 0.1136119732502868295328130e1, 0.1096603811912170337964094e1, 0.1057087931412518476253055e1, 0.1017572096905509113863513e1, 0.9780563151458206514020694e0, 0.9385405939294598498464432e0, 0.8990249423306286659734381e0, 0.8595093710029676968794279e0, 0.8199938925669823205931282e0, 0.7804785221142635001130339e0, 0.7409632778721439753645470e0, 0.7014481820920565808095373e0, 0.6619332622550151160558599e0, 0.6224185527349885679868616e0, 0.5829040971371158016902326e0, 0.5433899516536147244946347e0, 0.5038761899947552937603140e0, 0.4643629108305196256509391e0, 0.4248502493722176391609139e0, 0.3853383960541810555628366e0, 0.3458276279674767760058527e0, 0.3063183644932167228808922e0, 0.2668112720373341483108662e0, 0.2273074770384765519559169e0, 0.1878090446069578429818381e0, 0.1483202086882449059764783e0, 0.1088512052741322662621244e0, 0.6943448689600673838300180e-1, 0.3024917865720923179577363e-1}, + {0.1532249903371281818085917e1, 0.1493703482108998740614827e1, 0.1455157065195200346809599e1, 0.1416610654869340270223431e1, 0.1378064253450997606022340e1, 0.1339517863369794055919890e1, 0.1300971487198245305453001e1, 0.1262425127688525048786896e1, 0.1223878787814308166546501e1, 0.1185332470819113339105535e1, 0.1146786180272904774996439e1, 0.1108239920139165765487189e1, 0.1069693694855262920629379e1, 0.1031147509429735196850587e1, 0.9926013695612463310882198e0, 0.9540552817854489715123326e0, 0.9155092536580933534978986e0, 0.8769632939856246206308699e0, 0.8384174131186299393233148e0, 0.7998716233293992826192237e0, 0.7613259393034545837300323e0, 0.7227803787876118667749166e0, 0.6842349634562860931661901e0, 0.6456897200871628101751519e0, 0.6071446821835496233813653e0, 0.5685998922550279415939221e0, 0.5300554050908430047380815e0, 0.4915112925697217767572364e0, 0.4529676509187802579380104e0, 0.4144246120108054286121629e0, 0.3758823615873930314093573e0, 0.3373411699211847213003570e0, 0.2988014460838619282843952e0, 0.2602638401106843145315994e0, 0.2217294507811754336425535e0, 0.1832002925124018168986342e0, 0.1446804953347050655563166e0, 0.1061800440374660771048480e0, 0.6773059476567831336488402e-1, 0.2950687695527422224851832e-1}, + {0.1533173137460634461235066e1, 0.1495549950040734249895393e1, 0.1457926766471340970762709e1, 0.1420303588732694442267846e1, 0.1382680418872520759663065e1, 0.1345057259031099988676433e1, 0.1307434111468678960501903e1, 0.1269810978596001635506341e1, 0.1232187863008871596257323e1, 0.1194564767527851916244615e1, 0.1156941695244461089553108e1, 0.1119318649575559636172662e1, 0.1081695634328067979412755e1, 0.1044072653776750930510111e1, 0.1006449712758602402124214e1, 0.9688268167884441336521039e0, 0.9312039722018274751677424e0, 0.8935811863333633591901354e0, 0.8559584677414483220357356e0, 0.8183358264943738874932307e0, 0.7807132745385688213392421e0, 0.7430908261781095392995681e0, 0.7054684987070400358784448e0, 0.6678463132547297820965882e0, 0.6302242959332082940279826e0, 0.5926024794204980683238426e0, 0.5549809051864955237054951e0, 0.5173596266878257139037738e0, 0.4797387140623364241772428e0, 0.4421182612140318859822955e0, 0.4044983968396638104610711e0, 0.3668793022152994411560368e0, 0.3292612411240570212440856e0, 0.2916446128242035199998930e0, 0.2540300517665934607689814e0, 0.2164186303985620085027010e0, 0.1788123148742007754778852e0, 0.1412151362884411752920148e0, 0.1036368402634645114775150e0, 0.6610832470916409695729856e-1, 0.2880013396280840229218334e-1}, + {0.1534053181584449084854269e1, 0.1497310038074501005766978e1, 0.1460566897984002644464183e1, 0.1423823763069232867789940e1, 0.1387080635143547965139117e1, 0.1350337516098480646600889e1, 0.1313594407926723776707731e1, 0.1276851312747612578778902e1, 0.1240108232835827171448969e1, 0.1203365170654181674634873e1, 0.1166622128891556900019450e1, 0.1129879110507284864268762e1, 0.1093136118783624474731954e1, 0.1056393157388405786003046e1, 0.1019650230450503114577901e1, 0.9829073426515786199715451e0, 0.9461644993385942743541994e0, 0.9094217066630320811486021e0, 0.8726789717547518480094350e0, 0.8359363029411928866147184e0, 0.7991937100265521402467844e0, 0.7624512046511992388808212e0, 0.7257088007597790982554974e0, 0.6889665152185689899094400e0, 0.6522243686409073299342467e0, 0.6154823865075504175164916e0, 0.5787406007128420496638175e0, 0.5419990517384125648087865e0, 0.5052577917731960988645056e0, 0.4685168892980173635234519e0, 0.4317764360047099160222576e0, 0.3950365575646972937604113e0, 0.3582974309994310205507555e0, 0.3215593139080007759227897e0, 0.2848225961961619069649047e0, 0.2480878974611689122432227e0, 0.2113562650517154915467591e0, 0.1746296191183898065201571e0, 0.1379118964507339113271975e0, 0.1012126146941469342401701e0, 0.6456194899726137278760257e-1, 0.2812645439079299219187419e-1}, + {0.1534892997139557227614279e1, 0.1498989668998897501276994e1, 0.1463086343903285773505644e1, 0.1427183023414814244376429e1, 0.1391279709144040438287602e1, 0.1355376402767821814937864e1, 0.1319473106048673173924451e1, 0.1283569820856137399848247e1, 0.1247666549190742942502495e1, 0.1211763293211231530413995e1, 0.1175860055265884319525693e1, 0.1139956837928964066704190e1, 0.1104053644043538840797350e1, 0.1068150476772278342447444e1, 0.1032247339658243608912598e1, 0.9963442366982618328585493e0, 0.9604411724322426430586723e0, 0.9245381520528253319358567e0, 0.8886351815411563067305273e0, 0.8527322678365406966379400e0, 0.8168294190504262166761188e0, 0.7809266447390142664026016e0, 0.7450239562542930157586944e0, 0.7091213672012904985883029e0, 0.6732188940411854039055226e0, 0.6373165568977466866717861e0, 0.6014143806519714388063208e0, 0.5655123964528129857845238e0, 0.5296106438411039715966193e0, 0.4937091737981756577948229e0, 0.4578080532255782153525438e0, 0.4219073717059785387344039e0, 0.3860072520255396095683859e0, 0.3501078671472635990145335e0, 0.3142094687704932495909488e0, 0.2783124378775218384923333e0, 0.2424173798924625361874772e0, 0.2065253182141071551836492e0, 0.1706381290938671641708352e0, 0.1347596593282315198612592e0, 0.9889920900871122533586553e-1, 0.6308626356388784057588631e-1, 0.2748357108440508277394892e-1}, + {0.1535695280838629983064694e1, 0.1500594236235067817656313e1, 0.1465493194350303789230585e1, 0.1430392156577492526495371e1, 0.1395291124351096810858349e1, 0.1360190099162024176252063e1, 0.1325089082574000089379322e1, 0.1289988076241572027256558e1, 0.1254887081930202663795858e1, 0.1219786101538994920367859e1, 0.1184685137126702182946916e1, 0.1149584190941820846004092e1, 0.1114483265457749469332035e1, 0.1079382363414242848588494e1, 0.1044281487866708939888712e1, 0.1009180642245317812316634e1, 0.9740798304264509422659935e0, 0.9389790568197674899837757e0, 0.9038783264751749171405213e0, 0.8687776452153701566068907e0, 0.8336770198015192229270720e0, 0.7985764581422970742698971e0, 0.7634759695602610192254430e0, 0.7283755651349081311799055e0, 0.6932752581495918103871962e0, 0.6581750646810479477537782e0, 0.6230750043877162525265513e0, 0.5879751015798285374141491e0, 0.5528753866962970290878822e0, 0.5177758983811020490994086e0, 0.4826766864637186565865902e0, 0.4475778163386701445336738e0, 0.4124793755752883735361361e0, 0.3773814842049053432591527e0, 0.3422843113148581639684411e0, 0.3071881029697497767338606e0, 0.2720932316284942932084102e0, 0.2370002891767127567222407e0, 0.2019102761348421810146637e0, 0.1668250268181992892198073e0, 0.1317483020532982541977987e0, 0.9668919410176593344830717e-1, 0.6167652949817792358742135e-1, 0.2686941953400762687915995e-1}, + {0.1536462493634653558154673e1, 0.1502128661685489464262068e1, 0.1467794832169950298839286e1, 0.1433461006333747476463744e1, 0.1399127185457927306909792e1, 0.1364793370871767472755746e1, 0.1330459563966682507229700e1, 0.1296125766211456950047804e1, 0.1261791979169174443914592e1, 0.1227458204516276373551266e1, 0.1193124444064268679881601e1, 0.1158790699784705540565424e1, 0.1124456973838220917338613e1, 0.1090123268608563332983681e1, 0.1055789586742829027889885e1, 0.1021455931199402224481903e1, 0.9871223053055240306873772e0, 0.9527887128269590857605072e0, 0.9184551580529615732874848e0, 0.8841216459007313197085517e0, 0.8497881820448998068986446e0, 0.8154547730794463756650640e0, 0.7811214267220410983907210e0, 0.7467881520744805288579630e0, 0.7124549599581423848996086e0, 0.6781218633510390484774053e0, 0.6437888779643722276961833e0, 0.6094560230135452763170614e0, 0.5751233222647905281576305e0, 0.5407908054797110156395425e0, 0.5064585104462232763044121e0, 0.4721264858937837018545325e0, 0.4377947957771643018072936e0, 0.4034635257416918872885646e0, 0.3691327931855416440777167e0, 0.3348027634909946151567752e0, 0.3004736773353657517478163e0, 0.2661458990278703974149616e0, 0.2318200075085118064771005e0, 0.1974969814205034596217949e0, 0.1631786149772797106698111e0, 0.1288685867945150272796250e0, 0.9457579039019365184018477e-1, 0.6032842220945916819748797e-1, 0.2628211572883546008386342e-1}, + {0.1537196885933572311910085e1, 0.1503597446159129663218426e1, 0.1469998008568304160871417e1, 0.1436398574277729377094190e1, 0.1402799144434368418084898e1, 0.1369199720226542342210552e1, 0.1335600302895785666466344e1, 0.1302000893749787833197270e1, 0.1268401494176718217187838e1, 0.1234802105661283063077015e1, 0.1201202729802928570677208e1, 0.1167603368336689119731474e1, 0.1134004023157288628212183e1, 0.1100404696347243386055709e1, 0.1066805390209896030700280e1, 0.1033206107308545748870827e1, 0.9996068505131472996246808e0, 0.9660076230564559666956844e0, 0.9324084286020318648375284e0, 0.8988092713272342656758064e0, 0.8652101560253048754543914e0, 0.8316110882319595313175680e0, 0.7980120743837286767240920e0, 0.7644131220178278512956878e0, 0.7308142400269308414762795e0, 0.6972154389873656296775555e0, 0.6636167315867435235683334e0, 0.6300181331881122315700717e0, 0.5964196625844131090385918e0, 0.5628213430226633060114218e0, 0.5292232036175455988770345e0, 0.4956252813388603291268380e0, 0.4620276238643496856689332e0, 0.4284302937718012609061760e0, 0.3948333748659561479104270e0, 0.3612369820255324850503899e0, 0.3276412770872600895283016e0, 0.2940464955725917238672137e0, 0.2604529939906062681054034e0, 0.2268613388903867245835696e0, 0.1932724879746856807613294e0, 0.1596881970714452359218090e0, 0.1261120661032951679792394e0, 0.9255279834764232165670211e-1, 0.5903798711627596210077655e-1, 0.2571993685288741305807485e-1}, + {0.1537900519639177351485509e1, 0.1505004713461118831562885e1, 0.1472108909246876714959093e1, 0.1439213107999753788389740e1, 0.1406317310749171844429399e1, 0.1373421518560135827011261e1, 0.1340525732543378926238078e1, 0.1307629953866399941713193e1, 0.1274734183765634621652739e1, 0.1241838423560042429086765e1, 0.1208942674666441461574345e1, 0.1176046938616989970936899e1, 0.1143151217079296988032361e1, 0.1110255511879752164142939e1, 0.1077359825030803093319347e1, 0.1044464158763086533573607e1, 0.1011568515563550961534623e1, 0.9786728982210094134846821e0, 0.9457773098809579873452675e0, 0.9128817541120207886160886e0, 0.8799862349870845994262022e0, 0.8470907571831347751008168e0, 0.8141953261050969543263697e0, 0.7812999480407721032432037e0, 0.7484046303564402266425896e0, 0.7155093817462244075628281e0, 0.6826142125533466396520346e0, 0.6497191351887403950357432e0, 0.6168241646833332909207560e0, 0.5839293194266532352434130e0, 0.5510346221695150324949297e0, 0.5181401014079633610544426e0, 0.4852457933290632607369490e0, 0.4523517446039431388003505e0, 0.4194580164920722423612656e0, 0.3865646910356375140534892e0, 0.3536718807003189971969294e0, 0.3207797439266498255416416e0, 0.2878885112969848452450724e0, 0.2549985318477515756044100e0, 0.2221103602568508117102717e0, 0.1892249341643785313168465e0, 0.1563439726212394862316010e0, 0.1234710001537068179882843e0, 0.9061453776736619019094845e-1, 0.5780160090309369034797044e-1, 0.2518130440638251656980999e-1}, + {0.1538575287485045780713568e1, 0.1506354249056545799167351e1, 0.1474133212398093554231315e1, 0.1441912178413208451704314e1, 0.1409691148027973881079186e1, 0.1377470122199186272616473e1, 0.1345249101923067139210221e1, 0.1313028088244711409410919e1, 0.1280807082268469343020428e1, 0.1248586085169490583375238e1, 0.1216365098206699074213627e1, 0.1184144122737518830558069e1, 0.1151923160234735793613503e1, 0.1119702212305964062886069e1, 0.1087481280716290811591462e1, 0.1055260367414810028339009e1, 0.1023039474565930165787482e1, 0.9908186045865674272211987e0, 0.9585977601906320722299056e0, 0.9263769444426036830464570e0, 0.8941561608225061952846411e0, 0.8619354133052817812042663e0, 0.8297147064584916186566054e0, 0.7974940455635382827549679e0, 0.7652734367673509855003551e0, 0.7330528872739117793257283e0, 0.7008324055884451343305450e0, 0.6686120018320298047193041e0, 0.6363916881515750209117372e0, 0.6041714792607289968809847e0, 0.5719513931632926368357825e0, 0.5397314521353000325496229e0, 0.5075116840805377280486923e0, 0.4752921244363891783961832e0, 0.4430728189095547215892704e0, 0.4108538274961112658763390e0, 0.3786352305487998074788803e0, 0.3464171382200184643128623e0, 0.3141997056941599156198233e0, 0.2819831588178046655599196e0, 0.2497678394619649260592757e0, 0.2175542909210219972765731e0, 0.1853434315961135904158300e0, 0.1531369452704970394027659e0, 0.1209382841678252589048669e0, 0.8875579450016283173293810e-1, 0.5661593754525190873771522e-1, 0.2466476940450737058975552e-1}, + {0.1539222930035210331902410e1, 0.1507649534071729882214386e1, 0.1476076139707032453353232e1, 0.1444502747756546556830706e1, 0.1412929359055252480197337e1, 0.1381355974464721552102928e1, 0.1349782594880622732927647e1, 0.1318209221240839295255046e1, 0.1286635854534357387243172e1, 0.1255062495811112994872428e1, 0.1223489146193015470717893e1, 0.1191915806886406014313715e1, 0.1160342479196260434661502e1, 0.1128769164542510055952304e1, 0.1097195864478936528824546e1, 0.1065622580715200621234508e1, 0.1034049315142698534418744e1, 0.1002476069865111021377467e1, 0.9709028472347329448081481e0, 0.9393296498959608456620406e0, 0.9077564808376970380335442e0, 0.8761833434569334264096395e0, 0.8446102416364528348063321e0, 0.8130371798404960344077378e0, 0.7814641632334840064334645e0, 0.7498911978285964532098456e0, 0.7183182906753955596314298e0, 0.6867454500990591398232408e0, 0.6551726860086246453663390e0, 0.6236000102986843027011345e0, 0.5920274373793840619034224e0, 0.5604549848852622707385612e0, 0.5288826746375584896948472e0, 0.4973105339724571989307663e0, 0.4657385976085971045914307e0, 0.4341669103277770901346174e0, 0.4025955309141879357899857e0, 0.3710245380997234377015025e0, 0.3394540398171456073906403e0, 0.3078841881262277508367562e0, 0.2763152043287541015913350e0, 0.2447474234189502677044064e0, 0.2131813777658572006989977e0, 0.1816179673056091210434906e0, 0.1500588419721174291665790e0, 0.1185073845935281602210493e0, 0.8697177361567243680812898e-1, 0.5547793843128156580348541e-1, 0.2416899936118312040170588e-1}, +} + +// The weights of these nodes +var evenWeights = [][]float64{ + {1.0}, + {0.6521451548625461426269364e0, 0.3478548451374538573730642e0}, + {0.4679139345726910473898704e0, 0.3607615730481386075698336e0, 0.1713244923791703450402969e0}, + {0.3626837833783619829651504e0, 0.3137066458778872873379622e0, 0.2223810344533744705443556e0, 0.1012285362903762591525320e0}, + {0.2955242247147528701738930e0, 0.2692667193099963550912268e0, 0.2190863625159820439955350e0, 0.1494513491505805931457764e0, 0.6667134430868813759356850e-1}, + {0.2491470458134027850005624e0, 0.2334925365383548087608498e0, 0.2031674267230659217490644e0, 0.1600783285433462263346522e0, 0.1069393259953184309602552e0, 0.4717533638651182719461626e-1}, + {0.2152638534631577901958766e0, 0.2051984637212956039659240e0, 0.1855383974779378137417164e0, 0.1572031671581935345696019e0, 0.1215185706879031846894145e0, 0.8015808715976020980563266e-1, 0.3511946033175186303183410e-1}, + {0.1894506104550684962853967e0, 0.1826034150449235888667636e0, 0.1691565193950025381893119e0, 0.1495959888165767320815019e0, 0.1246289712555338720524763e0, 0.9515851168249278480992520e-1, 0.6225352393864789286284360e-1, 0.2715245941175409485178166e-1}, + {0.1691423829631435918406565e0, 0.1642764837458327229860538e0, 0.1546846751262652449254180e0, 0.1406429146706506512047311e0, 0.1225552067114784601845192e0, 0.1009420441062871655628144e0, 0.7642573025488905652912984e-1, 0.4971454889496979645333512e-1, 0.2161601352648331031334248e-1}, + {0.1527533871307258506980843e0, 0.1491729864726037467878288e0, 0.1420961093183820513292985e0, 0.1316886384491766268984948e0, 0.1181945319615184173123774e0, 0.1019301198172404350367504e0, 0.8327674157670474872475850e-1, 0.6267204833410906356950596e-1, 0.4060142980038694133103928e-1, 0.1761400713915211831186249e-1}, + {0.1392518728556319933754102e0, 0.1365414983460151713525738e0, 0.1311735047870623707329649e0, 0.1232523768105124242855609e0, 0.1129322960805392183934005e0, 0.1004141444428809649320786e0, 0.8594160621706772741444398e-1, 0.6979646842452048809496104e-1, 0.5229333515268328594031142e-1, 0.3377490158481415479330258e-1, 0.1462799529827220068498987e-1}, + {0.1279381953467521569740562e0, 0.1258374563468282961213754e0, 0.1216704729278033912044631e0, 0.1155056680537256013533445e0, 0.1074442701159656347825772e0, 0.9761865210411388826988072e-1, 0.8619016153195327591718514e-1, 0.7334648141108030573403386e-1, 0.5929858491543678074636724e-1, 0.4427743881741980616860272e-1, 0.2853138862893366318130802e-1, 0.1234122979998719954680507e-1}, + {0.1183214152792622765163711e0, 0.1166604434852965820446624e0, 0.1133618165463196665494407e0, 0.1084718405285765906565795e0, 0.1020591610944254232384142e0, 0.9421380035591414846366474e-1, 0.8504589431348523921044770e-1, 0.7468414976565974588707538e-1, 0.6327404632957483553945402e-1, 0.5097582529714781199831990e-1, 0.3796238329436276395030342e-1, 0.2441785109263190878961718e-1, 0, .1055137261734300715565387e-1}, + {0.1100470130164751962823763e0, 0.1087111922582941352535716e0, 0.1060557659228464179104165e0, 0.1021129675780607698142166e0, 0.9693065799792991585048880e-1, 0.9057174439303284094218612e-1, 0.8311341722890121839039666e-1, 0.7464621423456877902393178e-1, 0.6527292396699959579339794e-1, 0.5510734567571674543148330e-1, 0.4427293475900422783958756e-1, 0.3290142778230437997763004e-1, 0.2113211259277125975149896e-1, 0.9124282593094517738816778e-2}, + {0.1028526528935588403412856e0, 0.1017623897484055045964290e0, 0.9959342058679526706278018e-1, 0.9636873717464425963946864e-1, 0.9212252223778612871763266e-1, 0.8689978720108297980238752e-1, 0.8075589522942021535469516e-1, 0.7375597473770520626824384e-1, 0.6597422988218049512812820e-1, 0.5749315621761906648172152e-1, 0.4840267283059405290293858e-1, 0.3879919256962704959680230e-1, 0.2878470788332336934971862e-1, 0.1846646831109095914230276e-1, 0.7968192496166605615469690e-2}, + {0.9654008851472780056676488e-1, 0.9563872007927485941908208e-1, 0.9384439908080456563918026e-1, 0.9117387869576388471286854e-1, 0.8765209300440381114277140e-1, 0.8331192422694675522219922e-1, 0.7819389578707030647174106e-1, 0.7234579410884850622539954e-1, 0.6582222277636184683765034e-1, 0.5868409347853554714528360e-1, 0.5099805926237617619616316e-1, 0.4283589802222668065687810e-1, 0.3427386291302143310268716e-1, 0.2539206530926205945575196e-1, 0.1627439473090567060516896e-1, 0.7018610009470096600404748e-2}, + {0.9095674033025987361533764e-1, 0.9020304437064072957394216e-1, 0.8870189783569386928707642e-1, 0.8646573974703574978424688e-1, 0.8351309969984565518702044e-1, 0.7986844433977184473881888e-1, 0.7556197466003193127083398e-1, 0.7062937581425572499903896e-1, 0.6511152155407641137854442e-1, 0.5905413582752449319396124e-1, 0.5250741457267810616824590e-1, 0.4552561152335327245382266e-1, 0.3816659379638751632176606e-1, 0.3049138063844613180944194e-1, 0.2256372198549497008409476e-1, 0.1445016274859503541520101e-1, 0.6229140555908684718603220e-2}, + {0.8598327567039474749008516e-1, 0.8534668573933862749185052e-1, 0.8407821897966193493345756e-1, 0.8218726670433970951722338e-1, 0.7968782891207160190872470e-1, 0.7659841064587067452875784e-1, 0.7294188500565306135387342e-1, 0.6874532383573644261368974e-1, 0.6403979735501548955638454e-1, 0.5886014424532481730967550e-1, 0.5324471397775991909202590e-1, 0.4723508349026597841661708e-1, 0.4087575092364489547411412e-1, 0.3421381077030722992124474e-1, 0.2729862149856877909441690e-1, 0.2018151529773547153209770e-1, 0.1291594728406557440450307e-1, 0.5565719664245045361251818e-2}, + {0.8152502928038578669921876e-1, 0.8098249377059710062326952e-1, 0.7990103324352782158602774e-1, 0.7828784465821094807537540e-1, 0.7615366354844639606599344e-1, 0.7351269258474345714520658e-1, 0.7038250706689895473928292e-1, 0.6678393797914041193504612e-1, 0.6274093339213305405296984e-1, 0.5828039914699720602230556e-1, 0.5343201991033231997375704e-1, 0.4822806186075868337435238e-1, 0.4270315850467443423587832e-1, 0.3689408159402473816493978e-1, 0.3083950054517505465873166e-1, 0.2457973973823237589520214e-1, 0.1815657770961323689887502e-1, 0.1161344471646867417766868e-1, 0.5002880749639345675901886e-2}, + {0.7750594797842481126372404e-1, 0.7703981816424796558830758e-1, 0.7611036190062624237155810e-1, 0.7472316905796826420018930e-1, 0.7288658239580405906051074e-1, 0.7061164739128677969548346e-1, 0.6791204581523390382569024e-1, 0.6480401345660103807455446e-1, 0.6130624249292893916653822e-1, 0.5743976909939155136661768e-1, 0.5322784698393682435499678e-1, 0.4869580763507223206143380e-1, 0.4387090818567327199167442e-1, 0.3878216797447201763997196e-1, 0.3346019528254784739267780e-1, 0.2793700698002340109848970e-1, 0.2224584919416695726150432e-1, 0.1642105838190788871286396e-1, 0.1049828453115281361474434e-1, 0.4521277098533191258471490e-2}, + {0.7386423423217287999638556e-1, 0.7346081345346752826402828e-1, 0.7265617524380410488790570e-1, 0.7145471426517098292181042e-1, 0.6986299249259415976615480e-1, 0.6788970337652194485536350e-1, 0.6554562436490897892700504e-1, 0.6284355804500257640931846e-1, 0.5979826222758665431283142e-1, 0.5642636935801838164642686e-1, 0.5274629569917407034394234e-1, 0.4877814079280324502744954e-1, 0.4454357777196587787431674e-1, 0.4006573518069226176059618e-1, 0.3536907109759211083266214e-1, 0.3047924069960346836290502e-1, 0.2542295952611304788674188e-1, 0.2022786956905264475705664e-1, 0.1492244369735749414467869e-1, 0.9536220301748502411822340e-2, 0.4105998604649084610599928e-2}, + {0.7054915778935406881133824e-1, 0.7019768547355821258714200e-1, 0.6949649186157257803708402e-1, 0.6844907026936666098545864e-1, 0.6706063890629365239570506e-1, 0.6533811487918143498424096e-1, 0.6329007973320385495013890e-1, 0.6092673670156196803855800e-1, 0.5825985987759549533421064e-1, 0.5530273556372805254874660e-1, 0.5207009609170446188123162e-1, 0.4857804644835203752763920e-1, 0.4484398408197003144624282e-1, 0.4088651231034621890844686e-1, 0.3672534781380887364290888e-1, 0.3238122281206982088084682e-1, 0.2787578282128101008111450e-1, 0.2323148190201921062895910e-1, 0.1847148173681474917204335e-1, 0.1361958675557998552020491e-1, 0.8700481367524844122565470e-2, 0.3745404803112777515171456e-2}, + {0.6751868584903645882021418e-1, 0.6721061360067817586237416e-1, 0.6659587476845488737576196e-1, 0.6567727426778120737875756e-1, 0.6445900346713906958827948e-1, 0.6294662106439450817895206e-1, 0.6114702772465048101535670e-1, 0.5906843459554631480755080e-1, 0.5672032584399123581687444e-1, 0.5411341538585675449163752e-1, 0.5125959800714302133536554e-1, 0.4817189510171220053046892e-1, 0.4486439527731812676709458e-1, 0.4135219010967872970421980e-1, 0.3765130535738607132766076e-1, 0.3377862799910689652060416e-1, 0.2975182955220275579905234e-1, 0.2558928639713001063470016e-1, 0.2130999875413650105447862e-1, 0.1693351400783623804623151e-1, 0.1247988377098868420673525e-1, 0.7969898229724622451610710e-2, 0.3430300868107048286016700e-2}, + {0.6473769681268392250302496e-1, 0.6446616443595008220650418e-1, 0.6392423858464818662390622e-1, 0.6311419228625402565712596e-1, 0.6203942315989266390419786e-1, 0.6070443916589388005296916e-1, 0.5911483969839563574647484e-1, 0.5727729210040321570515042e-1, 0.5519950369998416286820356e-1, 0.5289018948519366709550490e-1, 0.5035903555385447495780746e-1, 0.4761665849249047482590674e-1, 0.4467456085669428041944838e-1, 0.4154508294346474921405856e-1, 0.3824135106583070631721688e-1, 0.3477722256477043889254814e-1, 0.3116722783279808890206628e-1, 0.2742650970835694820007336e-1, 0.2357076083932437914051962e-1, 0.1961616045735552781446139e-1, 0.1557931572294384872817736e-1, 0.1147723457923453948959265e-1, 0.7327553901276262102386656e-2, 0.3153346052305838632678320e-2}, + {0.6217661665534726232103316e-1, 0.6193606742068324338408750e-1, 0.6145589959031666375640678e-1, 0.6073797084177021603175000e-1, 0.5978505870426545750957640e-1, 0.5860084981322244583512250e-1, 0.5718992564772838372302946e-1, 0.5555774480621251762356746e-1, 0.5371062188899624652345868e-1, 0.5165570306958113848990528e-1, 0.4940093844946631492124360e-1, 0.4695505130394843296563322e-1, 0.4432750433880327549202254e-1, 0.4152846309014769742241230e-1, 0.3856875661258767524477018e-1, 0.3545983561514615416073452e-1, 0.3221372822357801664816538e-1, 0.2884299358053519802990658e-1, 0.2536067357001239044019428e-1, 0.2178024317012479298159128e-1, 0.1811556071348939035125903e-1, 0.1438082276148557441937880e-1, 0.1059054838365096926356876e-1, 0.6759799195745401502778824e-2, 0.2908622553155140958394976e-2}, + {0.5981036574529186024778538e-1, 0.5959626017124815825831088e-1, 0.5916881546604297036933200e-1, 0.5852956177181386855029062e-1, 0.5768078745252682765393200e-1, 0.5662553090236859719080832e-1, 0.5536756966930265254904124e-1, 0.5391140693275726475083694e-1, 0.5226225538390699303439404e-1, 0.5042601856634237721821144e-1, 0.4840926974407489685396032e-1, 0.4621922837278479350764582e-1, 0.4386373425900040799512978e-1, 0.4135121950056027167904044e-1, 0.3869067831042397898510146e-1, 0.3589163483509723294194276e-1, 0.3296410908971879791501014e-1, 0.2991858114714394664128188e-1, 0.2676595374650401344949324e-1, 0.2351751355398446159032286e-1, 0.2018489150798079220298930e-1, 0.1678002339630073567792252e-1, 0.1331511498234096065660116e-1, 0.9802634579462752061952706e-2, 0.6255523962973276899717754e-2, 0.2691316950047111118946698e-2}, + {0.5761753670714702467237616e-1, 0.5742613705411211485929010e-1, 0.5704397355879459856782852e-1, 0.5647231573062596503104434e-1, 0.5571306256058998768336982e-1, 0.5476873621305798630622270e-1, 0.5364247364755361127210060e-1, 0.5233801619829874466558872e-1, 0.5085969714618814431970910e-1, 0.4921242732452888606879048e-1, 0.4740167880644499105857626e-1, 0.4543346672827671397485208e-1, 0.4331432930959701544192564e-1, 0.4105130613664497422171834e-1, 0.3865191478210251683685736e-1, 0.3612412584038355258288694e-1, 0.3347633646437264571604038e-1, 0.3071734249787067605400450e-1, 0.2785630931059587028700164e-1, 0.2490274146720877305005456e-1, 0.2186645142285308594551102e-1, 0.1875752762146937791200757e-1, 0.1558630303592413170296832e-1, 0.1236332812884764416646861e-1, 0.9099369455509396948032734e-2, 0.5805611015239984878826112e-2, 0.2497481835761585775945054e-2}, + {0.5557974630651439584627342e-1, 0.5540795250324512321779340e-1, 0.5506489590176242579630464e-1, 0.5455163687088942106175058e-1, 0.5386976186571448570895448e-1, 0.5302137852401076396799152e-1, 0.5200910915174139984305222e-1, 0.5083608261779848056012412e-1, 0.4950592468304757891996610e-1, 0.4802274679360025812073550e-1, 0.4639113337300189676219012e-1, 0.4461612765269228321341510e-1, 0.4270321608466708651103858e-1, 0.4065831138474451788012514e-1, 0.3848773425924766248682568e-1, 0.3619819387231518603588452e-1, 0.3379676711561176129542654e-1, 0.3129087674731044786783572e-1, 0.2868826847382274172988602e-1, 0.2599698705839195219181960e-1, 0.2322535156256531693725830e-1, 0.2038192988240257263480560e-1, 0.1747551291140094650495930e-1, 0.1451508927802147180777130e-1, 0.1150982434038338217377419e-1, 0.8469063163307887661628584e-2, 0.5402522246015337761313780e-2, 0.2323855375773215501098716e-2}, + {0.5368111986333484886390600e-1, 0.5352634330405825210061082e-1, 0.5321723644657901410348096e-1, 0.5275469052637083342964580e-1, 0.5214003918366981897126058e-1, 0.5137505461828572547451486e-1, 0.5046194247995312529765992e-1, 0.4940333550896239286651076e-1, 0.4820228594541774840657052e-1, 0.4686225672902634691841818e-1, 0.4538711151481980250398048e-1, 0.4378110353364025103902560e-1, 0.4204886332958212599457020e-1, 0.4019538540986779688807676e-1, 0.3822601384585843322945902e-1, 0.3614642686708727054078062e-1, 0.3396262049341601079772722e-1, 0.3168089125380932732029244e-1, 0.2930781804416049071839382e-1, 0.2685024318198186847590714e-1, 0.2431525272496395254025850e-1, 0.2171015614014623576691612e-1, 0.1904246546189340865578709e-1, 0.1631987423497096505212063e-1, 0.1355023711298881214517933e-1, 0.1074155353287877411685532e-1, 0.7901973849998674754018608e-2, 0.5039981612650243085015810e-2, 0.2167723249627449943047768e-2}, + {0.5190787763122063973286496e-1, 0.5176794317491018754380368e-1, 0.5148845150098093399504444e-1, 0.5107015606985562740454910e-1, 0.5051418453250937459823872e-1, 0.4982203569055018101115930e-1, 0.4899557545575683538947578e-1, 0.4803703181997118096366674e-1, 0.4694898884891220484701330e-1, 0.4573437971611448664719662e-1, 0.4439647879578711332778398e-1, 0.4293889283593564195423128e-1, 0.4136555123558475561316394e-1, 0.3968069545238079947012286e-1, 0.3788886756924344403094056e-1, 0.3599489805108450306657888e-1, 0.3400389272494642283491466e-1, 0.3192121901929632894945890e-1, 0.2975249150078894524083642e-1, 0.2750355674992479163522324e-1, 0.2518047762152124837957096e-1, 0.2278951694399781986378308e-1, 0.2033712072945728677503268e-1, 0.1782990101420772026039605e-1, 0.1527461859678479930672510e-1, 0.1267816647681596013149540e-1, 0.1004755718228798435788578e-1, 0.7389931163345455531517530e-2, 0.4712729926953568640893942e-2, 0.2026811968873758496433874e-2}, + {0.5024800037525628168840300e-1, 0.5012106956904328807480410e-1, 0.4986752859495239424476130e-1, 0.4948801791969929252786578e-1, 0.4898349622051783710485112e-1, 0.4835523796347767283480314e-1, 0.4760483018410123227045008e-1, 0.4673416847841552480220700e-1, 0.4574545221457018077723242e-1, 0.4464117897712441429364478e-1, 0.4342413825804741958006920e-1, 0.4209740441038509664302268e-1, 0.4066432888241744096828524e-1, 0.3912853175196308412331100e-1, 0.3749389258228002998561838e-1, 0.3576454062276814128558760e-1, 0.3394484437941054509111762e-1, 0.3203940058162467810633926e-1, 0.3005302257398987007700934e-1, 0.2799072816331463754123820e-1, 0.2585772695402469802709536e-1, 0.2365940720868279257451652e-1, 0.2140132227766996884117906e-1, 0.1908917665857319873250324e-1, 0.1672881179017731628855027e-1, 0.1432619182380651776740340e-1, 0.1188739011701050194481938e-1, 0.9418579428420387637936636e-2, 0.6926041901830960871704530e-2, 0.4416333456930904813271960e-2, 0.1899205679513690480402948e-2}, + {0.4869095700913972038336538e-1, 0.4857546744150342693479908e-1, 0.4834476223480295716976954e-1, 0.4799938859645830772812614e-1, 0.4754016571483030866228214e-1, 0.4696818281621001732532634e-1, 0.4628479658131441729595326e-1, 0.4549162792741814447977098e-1, 0.4459055816375656306013478e-1, 0.4358372452932345337682780e-1, 0.4247351512365358900733972e-1, 0.4126256324262352861015628e-1, 0.3995374113272034138665686e-1, 0.3855015317861562912896262e-1, 0.3705512854024004604041492e-1, 0.3547221325688238381069330e-1, 0.3380516183714160939156536e-1, 0.3205792835485155358546770e-1, 0.3023465707240247886797386e-1, 0.2833967261425948322751098e-1, 0.2637746971505465867169136e-1, 0.2435270256871087333817770e-1, 0.2227017380838325415929788e-1, 0.2013482315353020937234076e-1, 0.1795171577569734308504602e-1, 0.1572603047602471932196614e-1, 0.1346304789671864259806029e-1, 0.1116813946013112881859029e-1, 0.8846759826363947723030856e-2, 0.6504457968978362856118112e-2, 0.4147033260562467635287472e-2, 0.1783280721696432947292054e-2}, + {0.4722748126299855484563332e-1, 0.4712209828764473218544518e-1, 0.4691156748762082774625404e-1, 0.4659635863958410362582412e-1, 0.4617717509791597547166640e-1, 0.4565495222527305612043888e-1, 0.4503085530544150021519278e-1, 0.4430627694315316190460328e-1, 0.4348283395666747864757528e-1, 0.4256236377005571631890662e-1, 0.4154692031324188131773448e-1, 0.4043876943895497912586836e-1, 0.3924038386682833018781280e-1, 0.3795443766594162094913028e-1, 0.3658380028813909441368980e-1, 0.3513153016547255590064132e-1, 0.3360086788611223267034862e-1, 0.3199522896404688727128174e-1, 0.3031819621886851919364104e-1, 0.2857351178293187118282268e-1, 0.2676506875425000190879332e-1, 0.2489690251475737263773110e-1, 0.2297318173532665591809836e-1, 0.2099819909186462577733052e-1, 0.1897636172277132593486659e-1, 0.1691218147224521718035102e-1, 0.1481026500273396017364296e-1, 0.1267530398126168187644599e-1, 0.1051206598770575465737803e-1, 0.8325388765990901416725080e-2, 0.6120192018447936365568516e-2, 0.3901625641744248259228942e-2, 0.1677653744007238599334225e-2}, + {0.4584938738725097468656398e-1, 0.4575296541606795051900614e-1, 0.4556032425064828598070770e-1, 0.4527186901844377786941174e-1, 0.4488820634542666782635216e-1, 0.4441014308035275590934876e-1, 0.4383868459795605201060492e-1, 0.4317503268464422322584344e-1, 0.4242058301114249930061428e-1, 0.4157692219740291648457550e-1, 0.4064582447595407614088174e-1, 0.3962924796071230802540652e-1, 0.3852933052910671449325372e-1, 0.3734838532618666771607896e-1, 0.3608889590017987071497568e-1, 0.3475351097975151316679320e-1, 0.3334503890398068790314300e-1, 0.3186644171682106493934736e-1, 0.3032082893855398034157906e-1, 0.2871145102748499071080394e-1, 0.2704169254590396155797848e-1, 0.2531506504517639832390244e-1, 0.2353519968587633336129308e-1, 0.2170583961037807980146532e-1, 0.1983083208795549829102926e-1, 0.1791412045792315248940600e-1, 0.1595973590961380007213420e-1, 0.1397178917445765581596455e-1, 0.1195446231976944210322336e-1, 0.9912001251585937209131520e-2, 0.7848711393177167415052160e-2, 0.5768969918729952021468320e-2, 0.3677366595011730633570254e-2, 0.1581140256372912939103728e-2}, + {0.4454941715975466720216750e-1, 0.4446096841724637082355728e-1, 0.4428424653905540677579966e-1, 0.4401960239018345875735580e-1, 0.4366756139720144025254848e-1, 0.4322882250506869978939520e-1, 0.4270425678944977776996576e-1, 0.4209490572728440602098398e-1, 0.4140197912904520863822652e-1, 0.4062685273678961635122600e-1, 0.3977106549277656747784952e-1, 0.3883631648407340397900292e-1, 0.3782446156922281719727230e-1, 0.3673750969367269534804046e-1, 0.3557761890129238053276980e-1, 0.3434709204990653756854510e-1, 0.3304837223937242047087430e-1, 0.3168403796130848173465310e-1, 0.3025679798015423781653688e-1, 0.2876948595580828066131070e-1, 0.2722505481866441715910742e-1, 0.2562657090846848279898494e-1, 0.2397720788910029227868640e-1, 0.2228024045225659583389064e-1, 0.2053903782432645338449270e-1, 0.1875705709313342341545081e-1, 0.1693783637630293253183738e-1, 0.1508498786544312768229492e-1, 0.1320219081467674762507440e-1, 0.1129318464993153764963015e-1, 0.9361762769699026811498692e-2, 0.7411769363190210362109460e-2, 0.5447111874217218312821680e-2, 0.3471894893078143254999524e-2, 0.1492721288844515731042666e-2}, + {0.4332111216548653707639384e-1, 0.4323978130522261748526514e-1, 0.4307727227491369974525036e-1, 0.4283389016833881366683982e-1, 0.4251009191005772007780078e-1, 0.4210648539758646414658732e-1, 0.4162382836013859820760788e-1, 0.4106302693607506110193610e-1, 0.4042513397173397004332898e-1, 0.3971134704483490178239872e-1, 0.3892300621616966379996300e-1, 0.3806159151380216383437540e-1, 0.3712872015450289946055536e-1, 0.3612614350763799298563092e-1, 0.3505574380721787043413848e-1, 0.3391953061828605949719618e-1, 0.3271963706429384670431246e-1, 0.3145831582256181397777608e-1, 0.3013793489537547929298290e-1, 0.2876097316470176109512506e-1, 0.2733001573895093443379638e-1, 0.2584774910065589028389804e-1, 0.2431695606441916432634724e-1, 0.2274051055503575445593134e-1, 0.2112137221644055350981986e-1, 0.1946258086329427804301667e-1, 0.1776725078920065359435915e-1, 0.1603856495028515521816122e-1, 0.1427976905455419326655572e-1, 0.1249416561987375776778277e-1, 0.1068510816535189715895734e-1, 0.8855996073706153383956510e-2, 0.7010272321861863296081600e-2, 0.5151436018790886908248502e-2, 0.3283169774667495801897558e-2, 0.1411516393973434135715864e-2}, + {0.4215870660994342212223066e-1, 0.4208374996915697247489576e-1, 0.4193396995777702146995522e-1, 0.4170963287924075437870998e-1, 0.4141113759675351082006810e-1, 0.4103901482412726684741876e-1, 0.4059392618219472805807676e-1, 0.4007666302247696675915112e-1, 0.3948814502019646832363280e-1, 0.3882941853913770775808220e-1, 0.3810165477126324889635168e-1, 0.3730614765439415573370658e-1, 0.3644431157165856448181076e-1, 0.3551767883680095992585374e-1, 0.3452789696982646100333388e-1, 0.3347672576782876626372244e-1, 0.3236603417621699952527994e-1, 0.3119779696591542603337254e-1, 0.2997409122246118733996502e-1, 0.2869709265326987534209508e-1, 0.2736907171967935230243778e-1, 0.2599238960072378786677346e-1, 0.2456949399594276724564910e-1, 0.2310291477491582303093246e-1, 0.2159525948167588896969968e-1, 0.2004920870279494425273506e-1, 0.1846751130897987978285368e-1, 0.1685297958202485358484807e-1, 0.1520848424340123480887426e-1, 0.1353694941178749434105245e-1, 0.1184134754749966732316814e-1, 0.1012469453828730542112095e-1, 0.8390045433971397064089364e-2, 0.6640492909114357634760192e-2, 0.4879179758594144584288316e-2, 0.3109420149896754678673688e-2, 0.1336761650069883550325931e-2}, + {0.4105703691622942259325972e-1, 0.4098780546479395154130842e-1, 0.4084945930182849228039176e-1, 0.4064223171029473877745496e-1, 0.4036647212284402315409558e-1, 0.4002264553259682611646172e-1, 0.3961133170906205842314674e-1, 0.3913322422051844076750754e-1, 0.3858912926450673834292118e-1, 0.3797996430840528319523540e-1, 0.3730675654238160982756716e-1, 0.3657064114732961700724404e-1, 0.3577285938071394752777924e-1, 0.3491475648355076744412550e-1, 0.3399777941205638084674262e-1, 0.3302347439779174100654158e-1, 0.3199348434042160006853510e-1, 0.3090954603749159538993714e-1, 0.2977348725590504095670750e-1, 0.2858722365005400377397500e-1, 0.2735275553182752167415270e-1, 0.2607216449798598352427480e-1, 0.2474760992065967164326474e-1, 0.2338132530701118662247962e-1, 0.2197561453441624916801320e-1, 0.2053284796790802109297466e-1, 0.1905545846719058280680223e-1, 0.1754593729147423095419928e-1, 0.1600682991224857088850986e-1, 0.1444073174827667993988980e-1, 0.1285028384751014494492467e-1, 0.1123816856966768723967455e-1, 0.9607105414713754082404616e-2, 0.7959847477239734621118374e-2, 0.6299180497328445866575096e-2, 0.4627935228037421326126844e-2, 0.2949102953642474900394994e-2, 0.1267791634085359663272804e-2}, + {0.4001146511842048298877858e-1, 0.3994739036908802487930490e-1, 0.3981934348036408922503176e-1, 0.3962752950781054295639346e-1, 0.3937225562423312193722022e-1, 0.3905393062777341314731136e-1, 0.3867306428725767400389548e-1, 0.3823026652585098764962036e-1, 0.3772624644432424786429014e-1, 0.3716181118549838685067108e-1, 0.3653786464168470064819248e-1, 0.3585540600719169544500572e-1, 0.3511552817821718947488010e-1, 0.3431941600268909029029166e-1, 0.3346834438285897797298150e-1, 0.3256367623368904440805548e-1, 0.3160686030030479773888294e-1, 0.3059942883801304528943330e-1, 0.2954299515860694641162030e-1, 0.2843925104689751626239046e-1, 0.2728996405162436486456432e-1, 0.2609697465510883502983394e-1, 0.2486219332622245076144308e-1, 0.2358759746145747209645146e-1, 0.2227522821911388676305032e-1, 0.2092718725187772678537816e-1, 0.1954563334339992337791787e-1, 0.1813277895498232864440684e-1, 0.1669088668934389186621294e-1, 0.1522226568017845169331591e-1, 0.1372926792014414839372596e-1, 0.1221428454978988639768250e-1, 0.1067974215748111335351669e-1, 0.9128099227255087276943326e-2, 0.7561843189439718826977318e-2, 0.5983489944440407989648850e-2, 0.4395596039460346742737866e-2, 0.2800868811838630411609396e-2, 0.1204024566067353280336448e-2}, + {0.3901781365630665481128044e-1, 0.3895839596276953119862554e-1, 0.3883965105905196893177418e-1, 0.3866175977407646332707712e-1, 0.3842499300695942318521238e-1, 0.3812971131447763834420674e-1, 0.3777636436200139748977496e-1, 0.3736549023873049002670538e-1, 0.3689771463827600883915092e-1, 0.3637374990583597804396502e-1, 0.3579439395341605460286146e-1, 0.3516052904474759349552658e-1, 0.3447312045175392879436434e-1, 0.3373321498461152281667534e-1, 0.3294193939764540138283636e-1, 0.3210049867348777314805654e-1, 0.3121017418811470164244288e-1, 0.3027232175955798066122008e-1, 0.2928836958326784769276746e-1, 0.2825981605727686239675312e-1, 0.2718822750048638067441898e-1, 0.2607523576756511790296854e-1, 0.2492253576411549110511808e-1, 0.2373188286593010129319242e-1, 0.2250509024633246192622164e-1, 0.2124402611578200638871032e-1, 0.1995061087814199892889169e-1, 0.1862681420829903142873492e-1, 0.1727465205626930635858456e-1, 0.1589618358372568804490352e-1, 0.1449350804050907611696272e-1, 0.1306876159240133929378674e-1, 0.1162411412079782691646643e-1, 0.1016176604110306452083288e-1, 0.8683945269260858426408640e-2, 0.7192904768117312752674654e-2, 0.5690922451403198649270494e-2, 0.4180313124694895236739096e-2, 0.2663533589512681669292770e-2, 0.1144950003186941534544369e-2}, + {0.3807230964014187120769602e-1, 0.3801710843143526990530278e-1, 0.3790678605050578477946422e-1, 0.3774150245427586967153708e-1, 0.3752149728818502087157412e-1, 0.3724708953872766418784006e-1, 0.3691867707095445699853162e-1, 0.3653673605160765284219780e-1, 0.3610182025872702307569544e-1, 0.3561456027872747268049598e-1, 0.3507566259211269038478042e-1, 0.3448590854915070550737888e-1, 0.3384615323699685874463648e-1, 0.3315732423990721132775848e-1, 0.3242042029434060507783656e-1, 0.3163650984090024553762352e-1, 0.3080672947521562981366802e-1, 0.2993228230001272463508596e-1, 0.2901443618076440396145302e-1, 0.2805452190745423047171398e-1, 0.2705393126512477151978662e-1, 0.2601411501601702375386842e-1, 0.2493658079624075515577230e-1, 0.2382289093004782634222678e-1, 0.2267466016491410310244200e-1, 0.2149355333077484404348958e-1, 0.2028128292691215890157032e-1, 0.1903960664017892507303976e-1, 0.1777032479849840714698234e-1, 0.1647527776398370889101217e-1, 0.1515634327076256178846848e-1, 0.1381543371412645938772740e-1, 0.1245449340114210467973318e-1, 0.1107549578175989632022419e-1, 0.9680440704371073736965104e-2, 0.8271351818383685604431294e-2, 0.6850274534183526184325356e-2, 0.5419276232446765090703842e-2, 0.3980457937856074619030326e-2, 0.2536054696856106109823094e-2, 0.1090118595275830866109234e-2}, + {0.3717153701903406760328362e-1, 0.3712016261260209427372758e-1, 0.3701748480379452058524442e-1, 0.3686364550259030771845208e-1, 0.3665885732875907563657692e-1, 0.3640340331800212248862624e-1, 0.3609763653077256670175260e-1, 0.3574197956431530727788894e-1, 0.3533692396860127616038866e-1, 0.3488302956696330845641672e-1, 0.3438092368237270062133504e-1, 0.3383130027042598480372494e-1, 0.3323491896024044407471552e-1, 0.3259260400458425718361322e-1, 0.3190524314069272748402282e-1, 0.3117378636334566129196750e-1, 0.3039924461190246977311372e-1, 0.2958268837311084528960516e-1, 0.2872524620162180221266452e-1, 0.2782810316025840603576668e-1, 0.2689249918219763751581640e-1, 0.2591972735733464772516052e-1, 0.2491113214520642888439108e-1, 0.2386810751695823938471552e-1, 0.2279209502894212933888898e-1, 0.2168458183064482298924430e-1, 0.2054709860975627861152400e-1, 0.1938121747731880864780669e-1, 0.1818854979605654992760044e-1, 0.1697074395521161134308213e-1, 0.1572948309558359820159970e-1, 0.1446648278916118624227443e-1, 0.1318348867918234598679997e-1, 0.1188227408980122349505120e-1, 0.1056463762300824526484878e-1, 0.9232400784190247014382770e-2, 0.7887405752648146382107148e-2, 0.6531513687713654601121566e-2, 0.5166605182746808329881136e-2, 0.3794591650452349696393000e-2, 0.2417511265443122855238466e-2, 0.1039133516451971889197062e-2}, + {0.3631239537581333828231516e-1, 0.3626450208420238743149194e-1, 0.3616877866860063758274494e-1, 0.3602535138093525771008956e-1, 0.3583440939092405578977942e-1, 0.3559620453657549559069116e-1, 0.3531105099203420508058466e-1, 0.3497932485321009937141316e-1, 0.3460146364173769225993442e-1, 0.3417796572791990463423808e-1, 0.3370938967341755486497158e-1, 0.3319635349455159712009034e-1, 0.3263953384718992195609868e-1, 0.3203966513429401611022852e-1, 0.3139753853730286555853332e-1, 0.3071400097263205318303994e-1, 0.2998995397466493249133840e-1, 0.2922635250670994458366154e-1, 0.2842420370149349475731242e-1, 0.2758456553285124838738412e-1, 0.2670854542037220957530654e-1, 0.2579729876883953540777106e-1, 0.2485202744439983591832606e-1, 0.2387397818947900497321768e-1, 0.2286444097854800644577274e-1, 0.2182474731692762780068420e-1, 0.2075626848490914279058154e-1, 0.1966041372956217980740210e-1, 0.1853862840670985920631482e-1, 0.1739239207569054238672012e-1, 0.1622321654972902258808405e-1, 0.1503264390508137868494523e-1, 0.1382224445276667086664874e-1, 0.1259361467806969781040954e-1, 0.1134837515617770397716730e-1, 0.1008816846038610565467284e-1, 0.8814657101954815703782366e-2, 0.7529521612194562606844596e-2, 0.6234459139140123463885784e-2, 0.4931184096960103696423408e-2, 0.3621439249610901437553882e-2, 0.2307087488809902925963262e-2, 0.9916432666203635255681510e-3}, + {0.3549206430171454529606746e-1, 0.3544734460447076970614316e-1, 0.3535796155642384379366902e-1, 0.3522402777945910853287866e-1, 0.3504571202900426139658624e-1, 0.3482323898139935499312912e-1, 0.3455688895080708413486530e-1, 0.3424699753602007873736958e-1, 0.3389395519761025923989258e-1, 0.3349820676595309252806520e-1, 0.3306025088074670014528066e-1, 0.3258063936273210868623942e-1, 0.3205997651840638806926700e-1, 0.3149891837860489232004182e-1, 0.3089817187191219763370292e-1, 0.3025849393394352533513752e-1, 0.2958069055361934911335230e-1, 0.2886561575763542924647688e-1, 0.2811417053440861349157908e-1, 0.2732730169885533083562360e-1, 0.2650600069943473772140906e-1, 0.2565130236896194788477952e-1, 0.2476428362076873302532156e-1, 0.2384606209185966126357838e-1, 0.2289779473478114232724788e-1, 0.2192067635998985359563460e-1, 0.2091593813057662423225406e-1, 0.1988484601127411324360109e-1, 0.1882869917375545139470985e-1, 0.1774882836032407455649534e-1, 0.1664659420821765604511323e-1, 0.1552338553693355384016474e-1, 0.1438061760129994423593466e-1, 0.1321973031362791170818164e-1, 0.1204218643958121230973900e-1, 0.1084946977542927125940107e-1, 0.9643083322053204400769368e-2, 0.8424547492702473015098308e-2, 0.7195398459796372059759572e-2, 0.5957186996138046583131162e-2, 0.4711479279598661743021848e-2, 0.3459867667862796423976646e-2, 0.2204058563143696628535344e-2, 0.9473355981619272667700360e-3}, + {0.3470797248895005792046014e-1, 0.3466615208568824018827232e-1, 0.3458256166949689141805380e-1, 0.3445730196032425617459566e-1, 0.3429052388637504193169728e-1, 0.3408242840225399546360508e-1, 0.3383326624683168725792750e-1, 0.3354333764112427668293316e-1, 0.3321299192655131651404080e-1, 0.3284262714400750457863018e-1, 0.3243268955425561691178950e-1, 0.3198367310021857603945600e-1, 0.3149611881181863607695780e-1, 0.3097061415408092094593650e-1, 0.3040779231928695269039426e-1, 0.2980833146403127548714788e-1, 0.2917295389210074248655798e-1, 0.2850242518416141631875546e-1, 0.2779755327530227515803874e-1, 0.2705918748154795852161408e-1, 0.2628821747651458736159580e-1, 0.2548557221944322848446706e-1, 0.2465221883590485293596628e-1, 0.2378916145252872321010090e-1, 0.2289743998716318463498862e-1, 0.2197812889593413383869188e-1, 0.2103233587872256311706242e-1, 0.2006120054463959596453232e-1, 0.1906589303913731842532399e-1, 0.1804761263446023616404962e-1, 0.1700758628522267570939747e-1, 0.1594706715100663901320649e-1, 0.1486733308804332405038481e-1, 0.1376968511233709343075118e-1, 0.1265544583716812886887583e-1, 0.1152595788914805885059348e-1, 0.1038258230989321461380844e-1, 0.9226696957741990940319884e-2, 0.8059694944620015658670990e-2, 0.6882983208463284314729370e-2, 0.5697981560747352600849438e-2, 0.4506123613674977864136850e-2, 0.3308867243336018195431340e-2, 0.2107778774526329891473788e-2, 0.9059323712148330937360098e-3}, + {0.3395777082810234796700260e-1, 0.3391860442372254949502722e-1, 0.3384031678893360189141840e-1, 0.3372299821957387169380074e-1, 0.3356678402920367631007550e-1, 0.3337185439303681030780114e-1, 0.3313843414012938182262046e-1, 0.3286679249406566032646806e-1, 0.3255724276244004524316198e-1, 0.3221014197549332953574452e-1, 0.3182589047432008582597260e-1, 0.3140493144912217791614030e-1, 0.3094775042804103166804096e-1, 0.3045487471715832098063528e-1, 0.2992687279231107330786762e-1, 0.2936435364342281261274650e-1, 0.2876796607210717582237958e-1, 0.2813839794335440451445112e-1, 0.2747637539216417339517938e-1, 0.2678266198604032330048838e-1, 0.2605805784431417922245786e-1, 0.2530339871531322569754810e-1, 0.2451955501244097425717108e-1, 0.2370743081028191239353720e-1, 0.2286796280189254240434106e-1, 0.2200211921848585739874382e-1, 0.2111089871276246180997612e-1, 0.2019532920718748374956428e-1, 0.1925646670855947471237209e-1, 0.1829539409026755729118717e-1, 0.1731321984368977636114053e-1, 0.1631107680025595800481463e-1, 0.1529012082579650150690625e-1, 0.1425152948895392526580707e-1, 0.1319650070571113802911160e-1, 0.1212625136263771052929676e-1, 0.1104201592263539422398575e-1, 0.9945045019726082041770092e-2, 0.8836604056467877374547944e-2, 0.7717971837373568504533128e-2, 0.6590439334214895223179124e-2, 0.5455308908000870987158870e-2, 0.4313895331861700472339122e-2, 0.3167535943396097874261610e-2, 0.2017671366262838591883234e-2, 0.8671851787671421353540866e-3}, + {0.3323930891781532080070524e-1, 0.3320257661860686379876634e-1, 0.3312915261254696321600516e-1, 0.3301911803949165507667076e-1, 0.3287259449712959072614770e-1, 0.3268974390660630715252838e-1, 0.3247076833358767948450850e-1, 0.3221590976496030711281812e-1, 0.3192544984141561392584074e-1, 0.3159970954621320046477392e-1, 0.3123904885046741788219108e-1, 0.3084386631534918741110674e-1, 0.3041459865164271220328128e-1, 0.2995172023714386920008800e-1, 0.2945574259243367639719146e-1, 0.2892721381560625584227516e-1, 0.2836671797657610681272962e-1, 0.2777487447163422062065088e-1, 0.2715233733896656472388262e-1, 0.2649979453589169919669406e-1, 0.2581796717861672816440260e-1, 0.2510760874535240512858038e-1, 0.2436950424366898830634656e-1, 0.2360446934301438228050796e-1, 0.2281334947335523641001192e-1, 0.2199701889094007717339700e-1, 0.2115637971222138981504522e-1, 0.2029236091701113217988866e-1, 0.1940591732198200488605189e-1, 0.1849802852566591095380957e-1, 0.1756969782614325199872555e-1, 0.1662195111266549663832874e-1, 0.1565583573251555786002188e-1, 0.1467241933449946420426407e-1, 0.1367278869060687850644038e-1, 0.1265804849763899444482439e-1, 0.1162932016112241459607371e-1, 0.1058774056495412223672440e-1, 0.9534460832865158250063918e-2, 0.8470645094534635999910406e-2, 0.7397469288142356200862272e-2, 0.6316120091036448223107804e-2, 0.5227794289507767545307002e-2, 0.4133699875407776483295790e-2, 0.3035065891038628027389626e-2, 0.1933219888725418943121000e-2, 0.8308716126821624946495838e-3}, + {0.3255061449236316624196142e-1, 0.3251611871386883598720548e-1, 0.3244716371406426936401278e-1, 0.3234382256857592842877486e-1, 0.3220620479403025066866710e-1, 0.3203445623199266321813896e-1, 0.3182875889441100653475374e-1, 0.3158933077072716855802074e-1, 0.3131642559686135581278434e-1, 0.3101033258631383742324982e-1, 0.3067137612366914901422878e-1, 0.3029991542082759379408878e-1, 0.2989634413632838598438796e-1, 0.2946108995816790597043632e-1, 0.2899461415055523654267862e-1, 0.2849741106508538564559948e-1, 0.2797000761684833443981840e-1, 0.2741296272602924282342110e-1, 0.2682686672559176219805676e-1, 0.2621234073567241391345816e-1, 0.2557003600534936149879724e-1, 0.2490063322248361028838244e-1, 0.2420484179236469128226730e-1, 0.2348339908592621984223612e-1, 0.2273706965832937400134754e-1, 0.2196664443874434919475618e-1, 0.2117293989219129898767356e-1, 0.2035679715433332459524556e-1, 0.1951908114014502241008485e-1, 0.1866067962741146738515655e-1, 0.1778250231604526083761406e-1, 0.1688547986424517245047785e-1, 0.1597056290256229138061685e-1, 0.1503872102699493800587588e-1, 0.1409094177231486091586166e-1, 0.1312822956696157263706415e-1, 0.1215160467108831963518178e-1, 0.1116210209983849859121361e-1, 0.1016077053500841575758671e-1, 0.9148671230783386632584044e-2, 0.8126876925698759217383246e-2, 0.7096470791153865269143206e-2, 0.6058545504235961683315686e-2, 0.5014202742927517692471308e-2, 0.3964554338444686673733524e-2, 0.2910731817934946408411678e-2, 0.1853960788946921732331620e-2, 0.7967920655520124294367096e-3}, + {0.3188987535287646727794502e-1, 0.3185743815812401071309920e-1, 0.3179259676252863019831786e-1, 0.3169541712034925160907410e-1, 0.3156599807910805290145092e-1, 0.3140447127904656151748860e-1, 0.3121100101922626441684056e-1, 0.3098578409040993463104290e-1, 0.3072904957489366992001356e-1, 0.3044105861349325839490764e-1, 0.3012210413992189884853100e-1, 0.2977251058282947626617570e-1, 0.2939263353580649216776328e-1, 0.2898285939568834204744914e-1, 0.2854360496952788570349054e-1, 0.2807531705063613875324586e-1, 0.2757847196412239390009986e-1, 0.2705357508239612827767608e-1, 0.2650116031112363935248738e-1, 0.2592178954616244891846836e-1, 0.2531605210202609734314644e-1, 0.2468456411246099618197954e-1, 0.2402796790374549880324124e-1, 0.2334693134134927471268304e-1, 0.2264214715061843311126274e-1, 0.2191433221217865041901888e-1, 0.2116422683277485691127980e-1, 0.2039259399229191457948346e-1, 0.1960021856772633077323700e-1, 0.1878790653490468656148738e-1, 0.1795648414877062812244296e-1, 0.1710679710308990026235402e-1, 0.1623970967045369565272614e-1, 0.1535610382349775576849818e-1, 0.1445687833830440197756895e-1, 0.1354294788102946514364726e-1, 0.1261524207892195285778215e-1, 0.1167470457713812428742924e-1, 0.1072229208322431712024324e-1, 0.9758973402174096835348026e-2, 0.8785728467392263202699392e-2, 0.7803547379100754890979542e-2, 0.6813429479165215998771186e-2, 0.5816382546439639112764538e-2, 0.4813422398586770918478190e-2, 0.3805574085352359565512666e-2, 0.2793881135722130870629084e-2, 0.1779477041014528741695358e-2, 0.7647669822743134580383448e-3}, + {0.3125542345386335694764248e-1, 0.3122488425484935773237650e-1, 0.3116383569620990678381832e-1, 0.3107233742756651658781016e-1, 0.3095047885049098823406346e-1, 0.3079837903115259042771392e-1, 0.3061618658398044849645950e-1, 0.3040407952645482001650792e-1, 0.3016226510516914491906862e-1, 0.2989097959333283091683684e-1, 0.2959048805991264251175454e-1, 0.2926108411063827662011896e-1, 0.2890308960112520313487610e-1, 0.2851685432239509799093676e-1, 0.2810275565910117331764820e-1, 0.2766119822079238829420408e-1, 0.2719261344657688013649158e-1, 0.2669745918357096266038448e-1, 0.2617621923954567634230892e-1, 0.2562940291020811607564182e-1, 0.2505754448157958970376402e-1, 0.2446120270795705271997480e-1, 0.2384096026596820596256040e-1, 0.2319742318525412162248878e-1, 0.2253122025633627270179672e-1, 0.2184300241624738631395360e-1, 0.2113344211252764154267220e-1, 0.2040323264620943276683910e-1, 0.1965308749443530586538157e-1, 0.1888373961337490455294131e-1, 0.1809594072212811666439111e-1, 0.1729046056832358243934388e-1, 0.1646808617614521264310506e-1, 0.1562962107754600272393719e-1, 0.1477588452744130176887969e-1, 0.1390771070371877268795387e-1, 0.1302594789297154228555807e-1, 0.1213145766297949740774437e-1, 0.1122511402318597711722209e-1, 0.1030780257486896958578198e-1, 0.9380419653694457951417628e-2, 0.8443871469668971402620252e-2, 0.7499073255464711578829804e-2, 0.6546948450845322764152444e-2, 0.5588428003865515157213478e-2, 0.4624450063422119351093868e-2, 0.3655961201326375182342828e-2, 0.2683925371553482419437272e-2, 0.1709392653518105239533969e-2, 0.7346344905056717304142370e-3}, +} + +var oddWeights = [][]float64{ + {0.5555555555555555555555555}, + {0.4786286704993664680412916e0, 0.2369268850561890875142644e0}, + {0.3818300505051189449503698e0, 0.2797053914892766679014680e0, 0.1294849661688696932706118e0}, + {0.3123470770400028400686304e0, 0.2606106964029354623187428e0, 0.1806481606948574040584721e0, 0.8127438836157441197189206e-1}, + {0.2628045445102466621806890e0, 0.2331937645919904799185238e0, 0.1862902109277342514260979e0, 0.1255803694649046246346947e0, 0.5566856711617366648275374e-1}, + {0.2262831802628972384120902e0, 0.2078160475368885023125234e0, 0.1781459807619457382800468e0, 0.1388735102197872384636019e0, 0.9212149983772844791442126e-1, 0.4048400476531587952001996e-1}, + {0.1984314853271115764561182e0, 0.1861610000155622110268006e0, 0.1662692058169939335532006e0, 0.1395706779261543144478051e0, 0.1071592204671719350118693e0, 0.7036604748810812470926662e-1, 0.3075324199611726835462762e-1}, + {0.1765627053669926463252710e0, 0.1680041021564500445099705e0, 0.1540457610768102880814317e0, 0.1351363684685254732863199e0, 0.1118838471934039710947887e0, 0.8503614831717918088353538e-1, 0.5545952937398720112944102e-1, 0.2414830286854793196010920e-1}, + {0.1589688433939543476499565e0, 0.1527660420658596667788553e0, 0.1426067021736066117757460e0, 0.1287539625393362276755159e0, 0.1115666455473339947160242e0, 0.9149002162244999946446222e-1, 0.6904454273764122658070790e-1, 0.4481422676569960033283728e-1, 0.1946178822972647703631351e-1}, + {0.1445244039899700590638271e0, 0.1398873947910731547221335e0, 0.1322689386333374617810526e0, 0.1218314160537285341953671e0, 0.1087972991671483776634747e0, 0.9344442345603386155329010e-1, 0.7610011362837930201705132e-1, 0.5713442542685720828363528e-1, 0.3695378977085249379995034e-1, 0.1601722825777433332422273e-1}, + {0.1324620394046966173716425e0, 0.1289057221880821499785954e0, 0.1230490843067295304675784e0, 0.1149966402224113649416434e0, 0.1048920914645414100740861e0, 0.9291576606003514747701876e-1, 0.7928141177671895492289248e-1, 0.6423242140852585212716980e-1, 0.4803767173108466857164124e-1, 0.3098800585697944431069484e-1, 0.1341185948714177208130864e-1}, + {0.1222424429903100416889594e0, 0.1194557635357847722281782e0, 0.1148582591457116483393255e0, 0.1085196244742636531160939e0, 0.1005359490670506442022068e0, 0.9102826198296364981149704e-1, 0.8014070033500101801323524e-1, 0.6803833381235691720718712e-1, 0.5490469597583519192593686e-1, 0.4093915670130631265562402e-1, 0.2635498661503213726190216e-1, 0.1139379850102628794789998e-1}, + {0.1134763461089651486203700e0, 0.1112524883568451926721632e0, 0.1075782857885331872121629e0, 0.1025016378177457986712478e0, 0.9608872737002850756565252e-1, 0.8842315854375695019432262e-1, 0.7960486777305777126307488e-1, 0.6974882376624559298432254e-1, 0.5898353685983359911030058e-1, 0.4744941252061506270409646e-1, 0.3529705375741971102257772e-1, 0.2268623159618062319603554e-1, 0.9798996051294360261149438e-2}, + {0.1058761550973209414065914e0, 0.1040733100777293739133284e0, 0.1010912737599149661218204e0, 0.9696383409440860630190016e-1, 0.9173775713925876334796636e-1, 0.8547225736617252754534480e-1, 0.7823832713576378382814484e-1, 0.7011793325505127856958160e-1, 0.6120309065707913854210970e-1, 0.5159482690249792391259412e-1, 0.4140206251868283610482948e-1, 0.3074049220209362264440778e-1, 0.1973208505612270598385931e-1, 0.8516903878746409654261436e-2}, + {0.9922501122667230787487546e-1, 0.9774333538632872509347402e-1, 0.9529024291231951280720412e-1, 0.9189011389364147821536290e-1, 0.8757674060847787612619794e-1, 0.8239299176158926390382334e-1, 0.7639038659877661642635764e-1, 0.6962858323541036616775632e-1, 0.6217478656102842691034334e-1, 0.5410308242491685371166596e-1, 0.4549370752720110290231576e-1, 0.3643227391238546402439264e-1, 0.2700901918497942180060860e-1, 0.1731862079031058246315918e-1, 0.7470831579248775858700554e-2}, + {0.9335642606559611616099912e-1, 0.9212398664331684621324104e-1, 0.9008195866063857723974370e-1, 0.8724828761884433760728158e-1, 0.8364787606703870761392808e-1, 0.7931236479488673836390848e-1, 0.7427985484395414934247216e-1, 0.6859457281865671280595482e-1, 0.6230648253031748003162750e-1, 0.5547084663166356128494468e-1, 0.4814774281871169567014706e-1, 0.4040154133166959156340938e-1, 0.3230035863232895328156104e-1, 0.2391554810174948035053310e-1, 0.1532170151293467612794584e-1, 0.6606227847587378058647800e-2}, + {0.8814053043027546297073886e-1, 0.8710444699718353424332214e-1, 0.8538665339209912522594402e-1, 0.8300059372885658837992644e-1, 0.7996494224232426293266204e-1, 0.7630345715544205353865872e-1, 0.7204479477256006466546180e-1, 0.6722228526908690396430546e-1, 0.6187367196608018888701398e-1, 0.5604081621237012857832772e-1, 0.4976937040135352980519956e-1, 0.4310842232617021878230592e-1, 0.3611011586346338053271748e-1, 0.2882926010889425404871630e-1, 0.2132297991148358088343844e-1, 0.1365082834836149226640441e-1, 0.5883433420443084975750336e-2}, + {0.8347457362586278725225302e-1, 0.8259527223643725089123018e-1, 0.8113662450846503050987774e-1, 0.7910886183752938076721222e-1, 0.7652620757052923788588804e-1, 0.7340677724848817272462668e-1, 0.6977245155570034488508154e-1, 0.6564872287275124948402376e-1, 0.6106451652322598613098804e-1, 0.5605198799827491780853916e-1, 0.5064629765482460160387558e-1, 0.4488536466243716665741054e-1, 0.3880960250193454448896226e-1, 0.3246163984752148106723444e-1, 0.2588603699055893352275954e-1, 0.1912904448908396604350259e-1, 0.1223878010030755652630649e-1, 0.5273057279497939351724544e-2}, + {0.7927622256836847101015574e-1, 0.7852361328737117672506330e-1, 0.7727455254468201672851160e-1, 0.7553693732283605770478448e-1, 0.7332175341426861738115402e-1, 0.7064300597060876077011486e-1, 0.6751763096623126536302120e-1, 0.6396538813868238898670650e-1, 0.6000873608859614957494160e-1, 0.5567269034091629990739094e-1, 0.5098466529212940521402098e-1, 0.4597430110891663188417682e-1, 0.4067327684793384393905618e-1, 0.3511511149813133076106530e-1, 0.2933495598390337859215654e-1, 0.2336938483217816459471240e-1, 0.1725622909372491904080491e-1, 0.1103478893916459424267603e-1, 0.4752944691635101370775866e-2}, + {0.7547874709271582402724706e-1, 0.7482962317622155189130518e-1, 0.7375188202722346993928094e-1, 0.7225169686102307339634646e-1, 0.7033766062081749748165896e-1, 0.6802073676087676673553342e-1, 0.6531419645352741043616384e-1, 0.6223354258096631647157330e-1, 0.5879642094987194499118590e-1, 0.5502251924257874188014710e-1, 0.5093345429461749478117008e-1, 0.4655264836901434206075674e-1, 0.4190519519590968942934048e-1, 0.3701771670350798843526154e-1, 0.3191821173169928178706676e-1, 0.2663589920711044546754900e-1, 0.2120106336877955307569710e-1, 0.1564493840781858853082666e-1, 0.9999938773905945338496546e-2, 0.4306140358164887684003630e-2}, + {0.7202750197142197434530754e-1, 0.7146373425251414129758106e-1, 0.7052738776508502812628636e-1, 0.6922334419365668428229950e-1, 0.6755840222936516919240796e-1, 0.6554124212632279749123378e-1, 0.6318238044939611232562970e-1, 0.6049411524999129451967862e-1, 0.5749046195691051942760910e-1, 0.5418708031888178686337342e-1, 0.5060119278439015652385048e-1, 0.4675149475434658001064704e-1, 0.4265805719798208376380686e-1, 0.3834222219413265757212856e-1, 0.3382649208686029234496834e-1, 0.2913441326149849491594084e-1, 0.2429045661383881590201850e-1, 0.1931990142368390039612543e-1, 0.1424875643157648610854214e-1, 0.9103996637401403318866628e-2, 0.3919490253844127282968528e-2}, + {0.6887731697766132288200278e-1, 0.6838457737866967453169206e-1, 0.6756595416360753627091012e-1, 0.6642534844984252808291474e-1, 0.6496819575072343085382664e-1, 0.6320144007381993774996374e-1, 0.6113350083106652250188634e-1, 0.5877423271884173857436156e-1, 0.5613487875978647664392382e-1, 0.5322801673126895194590376e-1, 0.5006749923795202979913194e-1, 0.4666838771837336526776814e-1, 0.4304688070916497115169120e-1, 0.3922023672930244756418756e-1, 0.3520669220160901624770010e-1, 0.3102537493451546716250854e-1, 0.2669621396757766480567536e-1, 0.2223984755057873239395080e-1, 0.1767753525793759061709347e-1, 0.1303110499158278432063191e-1, 0.8323189296218241645734836e-2, 0.3582663155283558931145652e-2}, + {0.6599053358881047453357062e-1, 0.6555737776654974025114294e-1, 0.6483755623894572670260402e-1, 0.6383421660571703063129384e-1, 0.6255174622092166264056434e-1, 0.6099575300873964533071060e-1, 0.5917304094233887597615438e-1, 0.5709158029323154022201646e-1, 0.5476047278153022595712512e-1, 0.5218991178005714487221170e-1, 0.4939113774736116960457022e-1, 0.4637638908650591120440168e-1, 0.4315884864847953826830162e-1, 0.3975258612253100378090162e-1, 0.3617249658417495161345948e-1, 0.3243423551518475676761786e-1, 0.2855415070064338650473990e-1, 0.2454921165965881853783378e-1, 0.2043693814766842764203432e-1, 0.1623533314643305967072624e-1, 0.1196284846431232096394232e-1, 0.7638616295848833614105174e-2, 0.3287453842528014883248206e-2}, + {0.6333550929649174859083696e-1, 0.6295270746519569947439960e-1, 0.6231641732005726740107682e-1, 0.6142920097919293629682652e-1, 0.6029463095315201730310616e-1, 0.5891727576002726602452756e-1, 0.5730268153018747548516450e-1, 0.5545734967480358869043158e-1, 0.5338871070825896852794302e-1, 0.5110509433014459067462262e-1, 0.4861569588782824027765094e-1, 0.4593053935559585354249958e-1, 0.4306043698125959798834538e-1, 0.4001694576637302136860494e-1, 0.3681232096300068981946734e-1, 0.3345946679162217434248744e-1, 0.2997188462058382535069014e-1, 0.2636361892706601696094518e-1, 0.2264920158744667649877160e-1, 0.1884359585308945844445106e-1, 0.1496214493562465102958377e-1, 0.1102055103159358049750846e-1, 0.7035099590086451473452956e-2, 0.3027278988922905077484090e-2}, + {0.6088546484485634388119860e-1, 0.6054550693473779513812526e-1, 0.5998031577750325209006396e-1, 0.5919199392296154378353896e-1, 0.5818347398259214059843780e-1, 0.5695850772025866210007778e-1, 0.5552165209573869301673704e-1, 0.5387825231304556143409938e-1, 0.5203442193669708756413650e-1, 0.4999702015005740977954886e-1, 0.4777362624062310199999514e-1, 0.4537251140765006874816670e-1, 0.4280260799788008665360980e-1, 0.4007347628549645318680892e-1, 0.3719526892326029284290846e-1, 0.3417869320418833623620910e-1, 0.3103497129016000845442504e-1, 0.2777579859416247719599602e-1, 0.2441330057378143427314164e-1, 0.2095998840170321057979252e-1, 0.1742871472340105225950284e-1, 0.1383263400647782229668883e-1, 0.1018519129782172993923731e-1, 0.6500337783252600292109494e-2, 0.2796807171089895575547228e-2}, + {0.5861758623272026331807196e-1, 0.5831431136225600755627570e-1, 0.5781001499171319631968304e-1, 0.5710643553626719177338328e-1, 0.5620599838173970980865512e-1, 0.5511180752393359900234954e-1, 0.5382763486873102904208140e-1, 0.5235790722987271819970160e-1, 0.5070769106929271529648556e-1, 0.4888267503269914042044844e-1, 0.4688915034075031402187278e-1, 0.4473398910367281021276570e-1, 0.4242462063452001359228150e-1, 0.3996900584354038212709364e-1, 0.3737560980348291567417214e-1, 0.3465337258353423795838740e-1, 0.3181167845901932306323576e-1, 0.2886032361782373626279970e-1, 0.2580948251075751771396152e-1, 0.2266967305707020839878928e-1, 0.1945172110763689538804750e-1, 0.1616672525668746392806095e-1, 0.1282602614424037917915135e-1, 0.9441202284940344386662890e-2, 0.6024276226948673281242120e-2, 0.2591683720567031811603734e-2}, + {0.5651231824977200140065834e-1, 0.5624063407108436802827906e-1, 0.5578879419528408710293598e-1, 0.5515824600250868759665114e-1, 0.5435100932991110207032224e-1, 0.5336967000160547272357054e-1, 0.5221737154563208456439348e-1, 0.5089780512449397922477522e-1, 0.4941519771155173948075862e-1, 0.4777429855120069555003682e-1, 0.4598036394628383810390480e-1, 0.4403914042160658989516800e-1, 0.4195684631771876239520718e-1, 0.3974015187433717960946388e-1, 0.3739615786796554528291572e-1, 0.3493237287358988740726862e-1, 0.3235668922618583168470572e-1, 0.2967735776516104122129630e-1, 0.2690296145639627066711996e-1, 0.2404238800972562200779126e-1, 0.2110480166801645412020978e-1, 0.1809961452072906240796732e-1, 0.1503645833351178821315019e-1, 0.1192516071984861217075236e-1, 0.8775746107058528177390204e-2, 0.5598632266560767354082364e-2, 0.2408323619979788819164582e-2}, + {0.5455280360476188648013898e-1, 0.5430847145249864313874678e-1, 0.5390206148329857464280950e-1, 0.5333478658481915842657698e-1, 0.5260833972917743244023134e-1, 0.5172488892051782472062386e-1, 0.5068707072492740865664050e-1, 0.4949798240201967899383808e-1, 0.4816117266168775126885110e-1, 0.4668063107364150378384082e-1, 0.4506077616138115779721374e-1, 0.4330644221621519659643210e-1, 0.4142286487080111036319668e-1, 0.3941566547548011408995280e-1, 0.3729083432441731735473546e-1, 0.3505471278231261750575064e-1, 0.3271397436637156854248994e-1, 0.3027560484269399945849064e-1, 0.2774688140218019232125814e-1, 0.2513535099091812264727322e-1, 0.2244880789077643807968978e-1, 0.1969527069948852038242318e-1, 0.1688295902344154903500062e-1, 0.1402027079075355617024753e-1, 0.1111576373233599014567619e-1, 0.8178160067821232626211086e-2, 0.5216533474718779390504886e-2, 0.2243753872250662909727492e-2}, + {0.5272443385912793196130422e-1, 0.5250390264782873905094128e-1, 0.5213703364837539138398724e-1, 0.5162484939089148214644000e-1, 0.5096877742539391685024800e-1, 0.5017064634299690281072034e-1, 0.4923268067936198577969374e-1, 0.4815749471460644038814684e-1, 0.4694808518696201919315986e-1, 0.4560782294050976983186828e-1, 0.4414044353029738069079808e-1, 0.4255003681106763866730838e-1, 0.4084103553868670766020196e-1, 0.3901820301616000950303072e-1, 0.3708661981887092269183778e-1, 0.3505166963640010878371850e-1, 0.3291902427104527775751116e-1, 0.3069462783611168323975056e-1, 0.2838468020053479790515332e-1, 0.2599561973129850018665014e-1, 0.2353410539371336342527500e-1, 0.2100699828843718735046168e-1, 0.1842134275361002936061624e-1, 0.1578434731308146614732024e-1, 0.1310336630634519101831859e-1, 0.1038588550099586219379846e-1, 0.7639529453487575142699186e-2, 0.4872239168265284768580414e-2, 0.2095492284541223402697724e-2}, + {0.5101448703869726354373512e-1, 0.5081476366881834320770052e-1, 0.5048247038679740464814450e-1, 0.5001847410817825342505160e-1, 0.4942398534673558993996884e-1, 0.4870055505641152608753004e-1, 0.4785007058509560716183348e-1, 0.4687475075080906597642932e-1, 0.4577714005314595937133982e-1, 0.4456010203508348827154136e-1, 0.4322681181249609790104358e-1, 0.4178074779088849206667564e-1, 0.4022568259099824736764020e-1, 0.3856567320700817274615216e-1, 0.3680505042315481738432126e-1, 0.3494840751653335109085198e-1, 0.3300058827590741063272390e-1, 0.3096667436839739482469792e-1, 0.2885197208818340150434184e-1, 0.2666199852415088966281066e-1, 0.2440246718754420291534050e-1, 0.2207927314831904400247522e-1, 0.1969847774610118133051782e-1, 0.1726629298761374359443389e-1, 0.1478906588493791454617878e-1, 0.1227326350781210462927897e-1, 0.9725461830356133736135366e-2, 0.7152354991749089585834616e-2, 0.4560924006012417184541648e-2, 0.1961453361670282671779431e-2}, + {0.4941183303991817896703964e-1, 0.4923038042374756078504314e-1, 0.4892845282051198994470936e-1, 0.4850678909788384786409014e-1, 0.4796642113799513141105276e-1, 0.4730867131226891908060508e-1, 0.4653514924538369651039536e-1, 0.4564774787629260868588592e-1, 0.4464863882594139537033256e-1, 0.4354026708302759079896428e-1, 0.4232534502081582298250554e-1, 0.4100684575966639863511004e-1, 0.3958799589154409398480778e-1, 0.3807226758434955676363856e-1, 0.3646337008545728963045232e-1, 0.3476524064535587769718026e-1, 0.3298203488377934176568344e-1, 0.3111811662221981750821608e-1, 0.2917804720828052694555162e-1, 0.2716657435909793322519012e-1, 0.2508862055334498661862972e-1, 0.2294927100488993314894282e-1, 0.2075376125803909077534152e-1, 0.1850746446016127040926083e-1, 0.1621587841033833888228333e-1, 0.1388461261611561082486681e-1, 0.1151937607688004175075116e-1, 0.9125968676326656354058462e-2, 0.6710291765960136251908410e-2, 0.4278508346863761866081200e-2, 0.1839874595577084117085868e-2}, + {0.4790669250049586203134730e-1, 0.4774134868124062155903898e-1, 0.4746619823288550315264446e-1, 0.4708187401045452224600686e-1, 0.4658925997223349830225508e-1, 0.4598948914665169696389334e-1, 0.4528394102630023065712822e-1, 0.4447423839508297442732352e-1, 0.4356224359580048653228480e-1, 0.4255005424675580271921714e-1, 0.4143999841724029302268646e-1, 0.4023462927300553381544642e-1, 0.3893671920405119761667398e-1, 0.3754925344825770980977246e-1, 0.3607542322556527393216642e-1, 0.3451861839854905862522142e-1, 0.3288241967636857498404946e-1, 0.3117059038018914246443218e-1, 0.2938706778931066806264472e-1, 0.2753595408845034394249940e-1, 0.2562150693803775821408458e-1, 0.2364812969128723669878144e-1, 0.2162036128493406284165378e-1, 0.1954286583675006282683714e-1, 0.1742042199767024849536596e-1, 0.1525791214644831034926464e-1, 0.1306031163999484633616732e-1, 0.1083267878959796862151440e-1, 0.8580148266881459893636434e-2, 0.6307942578971754550189764e-2, 0.4021524172003736347075858e-2, 0.1729258251300250898337759e-2}, + {0.4649043816026462820831466e-1, 0.4633935168241562110844706e-1, 0.4608790448976157619721740e-1, 0.4573664116106369093689412e-1, 0.4528632245466953156805004e-1, 0.4473792366088982547214182e-1, 0.4409263248975101830783160e-1, 0.4335184649869951735915584e-1, 0.4251717006583049147154770e-1, 0.4159041091519924309854838e-1, 0.4057357620174452522725164e-1, 0.3946886816430888264288692e-1, 0.3827867935617948064763712e-1, 0.3700558746349258202313488e-1, 0.3565234972274500666133270e-1, 0.3422189694953664673983902e-1, 0.3271732719153120542712204e-1, 0.3114189901947282393742616e-1, 0.2949902447094566969584718e-1, 0.2779226166243676998720012e-1, 0.2602530708621323880370460e-1, 0.2420198760967316472069180e-1, 0.2232625219645207692279754e-1, 0.2040216337134354044925720e-1, 0.1843388845680457387216616e-1, 0.1642569062253087920472674e-1, 0.1438191982720055093097663e-1, 0.1230700384928815052195302e-1, 0.1020544003410244098666155e-1, 0.8081790299023136215346300e-2, 0.5940693177582235216514606e-2, 0.3787008301825508445960626e-2, 0.1628325035240012866460003e-2}, + {0.4515543023614546051651704e-1, 0.4501700814039980219871620e-1, 0.4478661887831255754213528e-1, 0.4446473312204713809623108e-1, 0.4405200846590928438098588e-1, 0.4354928808292674103357578e-1, 0.4295759900230521387841984e-1, 0.4227815001128051285158270e-1, 0.4151232918565450208287406e-1, 0.4066170105406160053752604e-1, 0.3972800340176164120645862e-1, 0.3871314372049251393273936e-1, 0.3761919531164090650815840e-1, 0.3644839305070051405664348e-1, 0.3520312882168348614775456e-1, 0.3388594663083228949780964e-1, 0.3249953740964611124473418e-1, 0.3104673351789053903268552e-1, 0.2953050295790671177981110e-1, 0.2795394331218770599086132e-1, 0.2632027541686948379176090e-1, 0.2463283678454245536433616e-1, 0.2289507479074078565552120e-1, 0.2111053963987189462789068e-1, 0.1928287712884940278924393e-1, 0.1741582123196982913207401e-1, 0.1551318654340616473976910e-1, 0.1357886064907567099981112e-1, 0.1161679661067196554873961e-1, 0.9631006150415575588660562e-2, 0.7625555931201510611459992e-2, 0.5604579927870594828535346e-2, 0.3572416739397372609702552e-2, 0.1535976952792084075135094e-2}, + {0.4389487921178858632125256e-1, 0.4376774491340214497230982e-1, 0.4355612710410853337113396e-1, 0.4326043426324126659885626e-1, 0.4288123715758043502060704e-1, 0.4241926773962459303533940e-1, 0.4187541773473300618954268e-1, 0.4125073691986602424910896e-1, 0.4054643109724689643492514e-1, 0.3976385976685758167433708e-1, 0.3890453350226294749240264e-1, 0.3797011103483115621441804e-1, 0.3696239605198203185608278e-1, 0.3588333371564891077796844e-1, 0.3473500690768218837536532e-1, 0.3351963220945403083440624e-1, 0.3223955562344352694190700e-1, 0.3089724804509072169860608e-1, 0.2949530049370881246493644e-1, 0.2803641911174149061798030e-1, 0.2652341994215790800810512e-1, 0.2495922349431387305527612e-1, 0.2334684910922325263171504e-1, 0.2168940913598536796183230e-1, 0.1999010293235011128748561e-1, 0.1825221070467867050232934e-1, 0.1647908720746239655059230e-1, 0.1467415533461152920040808e-1, 0.1284089966808780607041846e-1, 0.1098286015429855170627475e-1, 0.9103626461992005851317578e-2, 0.7206835281831493387342912e-2, 0.5296182844025892632677844e-2, 0.3375555496730675865126842e-2, 0.1451267330029397268489446e-2}, + {0.4270273086485722207660098e-1, 0.4258568982601838702576300e-1, 0.4239085899223159440537396e-1, 0.4211859425425563626894556e-1, 0.4176939294869285375410172e-1, 0.4134389294952549452688336e-1, 0.4084287150293886154936056e-1, 0.4026724380756003336494178e-1, 0.3961806134270614331650800e-1, 0.3889650994769673952047552e-1, 0.3810390765573980059550798e-1, 0.3724170228634977315689404e-1, 0.3631146880069778469034650e-1, 0.3531490642472828750906318e-1, 0.3425383554530221541412972e-1, 0.3313019438504384067706900e-1, 0.3194603546197670648650132e-1, 0.3070352184043350493812614e-1, 0.2940492318011656010545704e-1, 0.2805261159057206032380240e-1, 0.2664905729872748295223048e-1, 0.2519682413753831281333190e-1, 0.2369856486421897462660896e-1, 0.2215701631704007205676952e-1, 0.2057499442036116916601972e-1, 0.1895538904867002168973610e-1, 0.1730115876248908300560664e-1, 0.1561532543359142299553300e-1, 0.1390096878831465086752053e-1, 0.1216122092928111272776412e-1, 0.1039926099500053220130511e-1, 0.8618310479532247613912182e-2, 0.6821631349174792362208078e-2, 0.5012538571606190263812266e-2, 0.3194524377289034522078870e-2, 0.1373376462759619223985654e-2}, + {0.4157356944178127878299940e-1, 0.4146558103261909213524834e-1, 0.4128580808246718908346088e-1, 0.4103456181139210667622250e-1, 0.4071227717293733029875788e-1, 0.4031951210114157755817430e-1, 0.3985694654465635257596536e-1, 0.3932538128963516252076754e-1, 0.3872573657343257584146640e-1, 0.3805905049151360313563098e-1, 0.3732647720033209016730652e-1, 0.3652928491929033900685118e-1, 0.3566885373524045308911856e-1, 0.3474667321333040653509838e-1, 0.3376433981833409264695562e-1, 0.3272355415093422052152286e-1, 0.3162611800374964805603220e-1, 0.3047393124221453920313760e-1, 0.2926898851572598680503318e-1, 0.2801337580478054082525924e-1, 0.2670926681012085177235442e-1, 0.2535891919021637909420806e-1, 0.2396467065371695917476570e-1, 0.2252893491386577645054636e-1, 0.2105419751228284223644546e-1, 0.1954301152012788937957076e-1, 0.1799799312564505063794604e-1, 0.1642181711902464004359937e-1, 0.1481721228981446852013731e-1, 0.1318695676282480211961300e-1, 0.1153387332830449596681366e-1, 0.9860824916114018392051822e-2, 0.8170710707327826403717118e-2, 0.6466464907037538401963982e-2, 0.4751069185015273965898868e-2, 0.3027671014606041291230134e-2, 0.1301591717375855993899257e-2}, + {0.4050253572678803195524960e-1, 0.4040269003221775617032620e-1, 0.4023646282485108419526524e-1, 0.4000412721559123741035150e-1, 0.3970606493128931068103760e-1, 0.3934276568757015193713232e-1, 0.3891482638423378562103292e-1, 0.3842295012455452367368120e-1, 0.3786794506008932026166678e-1, 0.3725072306289371887876038e-1, 0.3657229822732745453345840e-1, 0.3583378520391196260264276e-1, 0.3503639736797827845487748e-1, 0.3418144482611567926531782e-1, 0.3327033226369854530283962e-1, 0.3230455663703097559357210e-1, 0.3128570471390543339395640e-1, 0.3021545046662299869139892e-1, 0.2909555232176876134870268e-1, 0.2792785027127696854150716e-1, 0.2671426284955789083200264e-1, 0.2545678398169440375263742e-1, 0.2415747970795584494059388e-1, 0.2281848479012952051290956e-1, 0.2144199920545613550512462e-1, 0.2003028453431617639624646e-1, 0.1858566024834148550917969e-1, 0.1711049990653110417623953e-1, 0.1560722726874913129508073e-1, 0.1407831234002700405016720e-1, 0.1252626736922736518735940e-1, 0.1095364285391135423859170e-1, 0.9363023692386430769260798e-2, 0.7757025950083070731841176e-2, 0.6138296159756341839268696e-2, 0.4509523600205835333238688e-2, 0.2873553083652691657275240e-2, 0.1235291177139409614163874e-2}, + {0.3948525740129116475372166e-1, 0.3939275600474300393426418e-1, 0.3923874749659464355491890e-1, 0.3902347234287979602650502e-1, 0.3874726667023996706818530e-1, 0.3841056174110417740541666e-1, 0.3801388328032604954551756e-1, 0.3755785065432977047790708e-1, 0.3704317590404678415983790e-1, 0.3647066263315342752925638e-1, 0.3584120475334575228920704e-1, 0.3515578508861113112825058e-1, 0.3441547384067660088259166e-1, 0.3362142691803093004992252e-1, 0.3277488413113081785342150e-1, 0.3187716725661117036051890e-1, 0.3092967797352483528829388e-1, 0.2993389567483836289564858e-1, 0.2889137515760726678163634e-1, 0.2780374419544705894443552e-1, 0.2667270099710555653788310e-1, 0.2550001155512877394733978e-1, 0.2428750688879949263942200e-1, 0.2303708018571902627697914e-1, 0.2175068384660807976864198e-1, 0.2043032643814085987844290e-1, 0.1907806955893748858478357e-1, 0.1769602462431041786466318e-1, 0.1628634957619168209183741e-1, 0.1485124552635006931857919e-1, 0.1339295334482567619730830e-1, 0.1191375021511699869960077e-1, 0.1041594620451338257918368e-1, 0.8901880982652486253740074e-2, 0.7373921131330176830391914e-2, 0.5834459868763465589211910e-2, 0.4285929113126531218219446e-2, 0.2730907065754855918535274e-2, 0.1173930129956613021207112e-2}, + {0.3851778959688469523783810e-1, 0.3843192958037517210025656e-1, 0.3828897129558352443032002e-1, 0.3808912713547560183102332e-1, 0.3783269400830055924757518e-1, 0.3752005289647583785923924e-1, 0.3715166829056371214474266e-1, 0.3672808749918043951690600e-1, 0.3624993983586341279832570e-1, 0.3571793568410456853072614e-1, 0.3513286544193937941597898e-1, 0.3449559834765979589474544e-1, 0.3380708118839624555119598e-1, 0.3306833689348800442087536e-1, 0.3228046301473268887240310e-1, 0.3144463009577406641803652e-1, 0.3056207993305266189565968e-1, 0.2963412373090559765847516e-1, 0.2866214015356067622579182e-1, 0.2764757327692492691108618e-1, 0.2659193044321992109092004e-1, 0.2549678002166567706947970e-1, 0.2436374907856309733249090e-1, 0.2319452096027391988145570e-1, 0.2199083279275163277050144e-1, 0.2075447290144560853952252e-1, 0.1948727815560191821592671e-1, 0.1819113124125576115176324e-1, 0.1686795786763513947433495e-1, 0.1551972391246436293824549e-1, 0.1414843251323606554825229e-1, 0.1275612111513442100025550e-1, 0.1134485849541625576200880e-1, 0.9916741809595875499750926e-2, 0.8473893785345565449616918e-2, 0.7018460484931625511609624e-2, 0.5552611370256278902273182e-2, 0.4078551113421395586018386e-2, 0.2598622299928953013499446e-2, 0.1117029847124606606122469e-2}, + {0.3759656394395517759196934e-1, 0.3751672450373727271505762e-1, 0.3738378433575740441091762e-1, 0.3719793160197673054400130e-1, 0.3695942935618497107975802e-1, 0.3666861517167809004390068e-1, 0.3632590066346228889989584e-1, 0.3593177090566064734733082e-1, 0.3548678374494710264584324e-1, 0.3499156901097965473152462e-1, 0.3444682762495051683252180e-1, 0.3385333060751519869931002e-1, 0.3321191798750501518117324e-1, 0.3252349761296806599129116e-1, 0.3178904386622215064354856e-1, 0.3100959628473919484306724e-1, 0.3018625808981441705410184e-1, 0.2932019462510452791804122e-1, 0.2841263170724764156375054e-1, 0.2746485389090326123892810e-1, 0.2647820265067376248510830e-1, 0.2545407448248949675081806e-1, 0.2439391892715855749743432e-1, 0.2329923651890054937016126e-1, 0.2217157666180362262199056e-1, 0.2101253543726991787400918e-1, 0.1982375334565493904931242e-1, 0.1860691298547847284166721e-1, 0.1736373667382462235016547e-1, 0.1609598401193537091543832e-1, 0.1480544940071787768084914e-1, 0.1349395951237523498069998e-1, 0.1216337072779861206303406e-1, 0.1081556655803715872036043e-1, 0.9452455092479699888244178e-2, 0.8075966593123452283593892e-2, 0.6688051635243685741358420e-2, 0.5290681445859865555240374e-2, 0.3885859435353202192003776e-2, 0.2475719322545939743331242e-2, 0.1064168219666567756385077e-2}, + {0.3671834473341961622215226e-1, 0.3664397593378570248640692e-1, 0.3652013948874488485747660e-1, 0.3634700257169520376675674e-1, 0.3612479890936246037475190e-1, 0.3585382846628081255691520e-1, 0.3553445703985569908199156e-1, 0.3516711576655578824981280e-1, 0.3475230053990063752924744e-1, 0.3429057134102984670822224e-1, 0.3378255148275753033131186e-1, 0.3322892676813276976252854e-1, 0.3263044456464217818903764e-1, 0.3198791279530467445976990e-1, 0.3130219884802087044839684e-1, 0.3057422840464999572392432e-1, 0.2980498419139588737561256e-1, 0.2899550465219015208986610e-1, 0.2814688254686507584638292e-1, 0.2726026347601116478577010e-1, 0.2633684433451435982173160e-1, 0.2537787169586608847736972e-1, 0.2438464012943568314241580e-1, 0.2335849045298989189769872e-1, 0.2230080792283937418945736e-1, 0.2121302036408937967241628e-1, 0.2009659624357542174179408e-1, 0.1895304268818284044680496e-1, 0.1778390345139817090774314e-1, 0.1659075683115467007520452e-1, 0.1537521354238962687440865e-1, 0.1413891454840083293055609e-1, 0.1288352885649808429050626e-1, 0.1161075128670389800962475e-1, 0.1032230023052424589381722e-1, 0.9019915439993631278967098e-2, 0.7705355960382757079897960e-2, 0.6380398587897515098686098e-2, 0.5046838426924442725450432e-2, 0.3706500125759316706868292e-2, 0.2361331704285020896763904e-2, 0.1014971908967743695374167e-2}, + {0.3588019106018701587773518e-1, 0.3581080434383374175662560e-1, 0.3569525919440943377647946e-1, 0.3553370454416059391133478e-1, 0.3532634862941021369843054e-1, 0.3507345872215153655662536e-1, 0.3477536078554782924871120e-1, 0.3443243905378224376593820e-1, 0.3404513553679937345518354e-1, 0.3361394945057693558422230e-1, 0.3313943657366202353628890e-1, 0.3262220853080144392580048e-1, 0.3206293200458966777765818e-1, 0.3146232787615076393796228e-1, 0.3082117029596223415371898e-1, 0.3014028568601882474395096e-1, 0.2942055167462304824922484e-1, 0.2866289596517621838858744e-1, 0.2786829514042920598963448e-1, 0.2703777340373580728397710e-1, 0.2617240125893355894972542e-1, 0.2527329413055707316411874e-1, 0.2434161092616763233921348e-1, 0.2337855254266017225782364e-1, 0.2238536031848547821419758e-1, 0.2136331443380253159361604e-1, 0.2031373226065556952656956e-1, 0.1923796666535655878505047e-1, 0.1813740426535425205021816e-1, 0.1701346364300153443364516e-1, 0.1586759351882631900292224e-1, 0.1470127088723984222989451e-1, 0.1351599911824565808188095e-1, 0.1231330603004803654228712e-1, 0.1109474194056071927972064e-1, 0.9861877713701826716584494e-2, 0.8616302838488951832949878e-2, 0.7359623648818063660769462e-2, 0.6093462047634872130101964e-2, 0.4819456238501885899307624e-2, 0.3539271655388628540179688e-2, 0.2254690753752853092482060e-2, 0.9691097381770753376096654e-3}, + {0.3507942401790202531716760e-1, 0.3501458416619644336915306e-1, 0.3490660650856070989101148e-1, 0.3475562407298142092081152e-1, 0.3456182286913780813643384e-1, 0.3432544165923908781796544e-1, 0.3404677166387108716735582e-1, 0.3372615620321457070630952e-1, 0.3336399027407732093971928e-1, 0.3296072006326111707429234e-1, 0.3251684239786320696758578e-1, 0.3203290413318958550703170e-1, 0.3150950147903428365879858e-1, 0.3094727926515484478947892e-1, 0.3034693014684912934340756e-1, 0.2970919375161245962730194e-1, 0.2903485576792681183001942e-1, 0.2832474697730520722803496e-1, 0.2757974223078458253347716e-1, 0.2680075937112917771256550e-1, 0.2598875810207383625148160e-1, 0.2514473880600256862281534e-1, 0.2426974131152233927366188e-1, 0.2336484361245544582716880e-1, 0.2243116053983636712835892e-1, 0.2146984238856114084341254e-1, 0.2048207350040027021224486e-1, 0.1946907080515187313867415e-1, 0.1843208232178411567584622e-1, 0.1737238562150240166964102e-1, 0.1629128625479238457754130e-1, 0.1519011614466612339747308e-1, 0.1407023194864448281388687e-1, 0.1293301339260267729158710e-1, 0.1177986158087489217661933e-1, 0.1061219728997218803268093e-1, 0.9431459260797890539711922e-2, 0.8239102525389078730572362e-2, 0.7036596870989114137389446e-2, 0.5825425788770107459644064e-2, 0.4607087343463241433054622e-2, 0.3383104792407455132632698e-2, 0.2155112582219113764637582e-2, 0.9262871051934728155239026e-3}, + {0.3431359817623139857242020e-1, 0.3425291647165106006719224e-1, 0.3415185977541012618567448e-1, 0.3401054720622907866548866e-1, 0.3382914533369793579365620e-1, 0.3360786798193575310982430e-1, 0.3334697597754983863697838e-1, 0.3304677684219179120016898e-1, 0.3270762443007278294842040e-1, 0.3232991851086539448409380e-1, 0.3191410429848369728859888e-1, 0.3146067192629708854519032e-1, 0.3097015586939654421561894e-1, 0.3044313431459439490344712e-1, 0.2988022847890037493277136e-1, 0.2928210187727747971826382e-1, 0.2864945954054102439649608e-1, 0.2798304718432316638118606e-1, 0.2728365033008298027898986e-1, 0.2655209337919890810307922e-1, 0.2578923864123601618879028e-1, 0.2499598531753495743256148e-1, 0.2417326844132287942221788e-1, 0.2332205777559880283599600e-1, 0.2244335667009737337332098e-1, 0.2153820087868566629622426e-1, 0.2060765733859846074045938e-1, 0.1965282291296914660474199e-1, 0.1867482309816812542178599e-1, 0.1767481069752190506037194e-1, 0.1665396446306124017225753e-1, 0.1561348770705005975095101e-1, 0.1455460688520869608484063e-1, 0.1347857015383097919431856e-1, 0.1238664590355674305453526e-1, 0.1128012127376968298340906e-1, 0.1016030065441547672889225e-1, 0.9028504189234487748913298e-2, 0.7886066314628901599629988e-2, 0.6734334432268884665261132e-2, 0.5574668047479788997832340e-2, 0.4408439747302676819065170e-2, 0.3237045507972104977098260e-2, 0.2061987122032229660677942e-2, 0.8862412406694141765769646e-3}, + {0.3358047670273290820423322e-1, 0.3352360509236689973246714e-1, 0.3342889041048296629425518e-1, 0.3329643957561578934524218e-1, 0.3312640210470322597293962e-1, 0.3291896994430459113247722e-1, 0.3267437725392241575486392e-1, 0.3239290014167229270630344e-1, 0.3207485635259921958171598e-1, 0.3172060490999230883258760e-1, 0.3133054571010280192591498e-1, 0.3090511907072293590876800e-1, 0.3044480523413530949647580e-1, 0.2995012382499392416587776e-1, 0.2942163326374897748551588e-1, 0.2885993013627770636290672e-1, 0.2826564852043306435742870e-1, 0.2763945927027071971311622e-1, 0.2698206925876273304878794e-1, 0.2629422057985327475229788e-1, 0.2557668971075783892217594e-1, 0.2483028663545258189183534e-1, 0.2405585393034465615306556e-1, 0.2325426581315775168991978e-1, 0.2242642715610957188910656e-1, 0.2157327246449981801505782e-1, 0.2069576482186873448858912e-1, 0.1979489480292792866805571e-1, 0.1887167935550803461442971e-1, 0.1792716065281371317885285e-1, 0.1696240491732901090122756e-1, 0.1597850121778211678831695e-1, 0.1497656024067188095391932e-1, 0.1395771303800797072406999e-1, 0.1292310975318535045602668e-1, 0.1187391832744712509861298e-1, 0.1081132319054248938202577e-1, 0.9736523941887687826947068e-2, 0.8650734035428648314139846e-2, 0.7555179500769820751618632e-2, 0.6451097794311275889059324e-2, 0.5339737098169214613757504e-2, 0.4222357382406607998634106e-2, 0.3100240403099316775464478e-2, 0.1974768768686808388940061e-2, 0.8487371680679110048896640e-3}, + {0.3287800959763194823557646e-1, 0.3282463569369918669308888e-1, 0.3273574336068393226919658e-1, 0.3261142878598215425670652e-1, 0.3245182648620325926685946e-1, 0.3225710916161441434734840e-1, 0.3202748750926769529295728e-1, 0.3176320999501228029097900e-1, 0.3146456258463840201321734e-1, 0.3113186843444399825682258e-1, 0.3076548754155891475295788e-1, 0.3036581635440506677724356e-1, 0.2993328734371411225240016e-1, 0.2946836853456688237515152e-1, 0.2897156299996101153484194e-1, 0.2844340831645486261311894e-1, 0.2788447598247691424309350e-1, 0.2729537079993022266578380e-1, 0.2667673021976135431896846e-1, 0.2602922365220227153290076e-1, 0.2535355174243201293660006e-1, 0.2465044561244261997612948e-1, 0.2392066606993061007707546e-1, 0.2316500278507139174920030e-1, 0.2238427343606939184041926e-1, 0.2157932282441140120676856e-1, 0.2075102196078490181790884e-1, 0.1990026712265721124487174e-1, 0.1902797888454570639306994e-1, 0.1813510112204514410759734e-1, 0.1722259999071698441334003e-1, 0.1629146288099104326591566e-1, 0.1534269735028835663459242e-1, 0.1437733003365908208357459e-1, 0.1339640553436828544136536e-1, 0.1240098529611606104018197e-1, 0.1139214645908584403924275e-1, 0.1037098070311609684083942e-1, 0.9338593083876397086740596e-2, 0.8296100874530990238145090e-2, 0.7244632443933199672626606e-2, 0.6185326261033323769312750e-2, 0.5119330329927718280032034e-2, 0.4047803316371759906879922e-2, 0.2971924240818190718436604e-2, 0.1892968377922935762776147e-2, 0.8135642494541165010544716e-3}, + {0.3220431459661350533475748e-1, 0.3215415737958550153577998e-1, 0.3207061987527279934927952e-1, 0.3195378880670864194528382e-1, 0.3180378546007149044495368e-1, 0.3162076555877401604294910e-1, 0.3140491910180172362457798e-1, 0.3115647016646904145775102e-1, 0.3087567667579765382432642e-1, 0.3056283013075858386135104e-1, 0.3021825530765601453452082e-1, 0.2984230992096702903457814e-1, 0.2943538425198732086424294e-1, 0.2899790074366843187205222e-1, 0.2853031356206718751823808e-1, 0.2803310812486267752680532e-1, 0.2750680059743034256009616e-1, 0.2695193735699644067363378e-1, 0.2636909442542934975707846e-1, 0.2575887687125678489535242e-1, 0.2512191818153004673565192e-1, 0.2445887960418784729059960e-1, 0.2377044946160306882104198e-1, 0.2305734243602599579639616e-1, 0.2232029882766713237862322e-1, 0.2156008378619171827843500e-1, 0.2077748651642656849799008e-1, 0.1997331945910804688818908e-1, 0.1914841744752812933525703e-1, 0.1830363684096414082229124e-1, 0.1743985463580780463940516e-1, 0.1655796755534245662902801e-1, 0.1565889111915692052020687e-1, 0.1474355869323695017635984e-1, 0.1381292052185304327114855e-1, 0.1286794274249338667571135e-1, 0.1190960638533075683273654e-1, 0.1093890635919594895396767e-1, 0.9956850427084044948237490e-2, 0.8964458176697999432566250e-2, 0.7962759997865495595598110e-2, 0.6952796096469405526464256e-2, 0.5935615630788222954183688e-2, 0.4912276262166028130833504e-2, 0.3883845329489294421733034e-2, 0.2851409243213055771419126e-2, 0.1816146398210039609502983e-2, 0.7805332219425612457264822e-3}, + {0.3155766036791122885809208e-1, 0.3151046648162834771323796e-1, 0.3143186227722154616152128e-1, 0.3132192610907518012817474e-1, 0.3118076756395815837033438e-1, 0.3100852735178559535833486e-1, 0.3080537716535627949917920e-1, 0.3057151950920577999218210e-1, 0.3030718749774580397961262e-1, 0.3001264462289103447190280e-1, 0.2968818449140509844801766e-1, 0.2933413053222750347643324e-1, 0.2895083567407331040373860e-1, 0.2853868199362694972663692e-1, 0.2809808033468091126593440e-1, 0.2762946989859901232207604e-1, 0.2713331780651255092639320e-1, 0.2661011863368585130179228e-1, 0.2606039391651548254092866e-1, 0.2548469163265475465058230e-1, 0.2488358565478194644598738e-1, 0.2425767517855707823164026e-1, 0.2360758412533789404661778e-1, 0.2293396052025105528408320e-1, 0.2223747584623937158435550e-1, 0.2151882437473022381824646e-1, 0.2077872247359421120742490e-1, 0.2001790789308656620794778e-1, 0.1923713903048718479867380e-1, 0.1843719417417849927098560e-1, 0.1761887072792438050675710e-1, 0.1678298441613870708950299e-1, 0.1593036847096084971103802e-1, 0.1506187280199023331295260e-1, 0.1417836314957944606614279e-1, 0.1328072022265728347995425e-1, 0.1236983882217516210343368e-1, 0.1144662695149825376113323e-1, 0.1051200491552474540574917e-1, 0.9566904411326136356898158e-2, 0.8612267615478888991732218e-2, 0.7649046279335257935390770e-2, 0.6678200860575098165183170e-2, 0.5700699773395926875152328e-2, 0.4717519037520830079689318e-2, 0.3729643487243034749198276e-2, 0.2738075873626878091327392e-2, 0.1743906958219244938639563e-2, 0.7494736467374053633626714e-3}, +} + +// The factor in front of the direct product representation +var cl = [...]float64{1.0, 1.0, -0.5000000000000000000000000e0, -0.1500000000000000000000000e1, 0.3750000000000000000000000e0, 0.1875000000000000000000000e1, -0.3125000000000000000000000e0, -0.2187500000000000000000000e1, 0.2734375000000000000000000e0, 0.2460937500000000000000000e1, -0.2460937500000000000000000e0, -0.2707031250000000000000000e1, 0.2255859375000000000000000e0, 0.2932617187500000000000000e1, -0.2094726562500000000000000e0, -0.3142089843750000000000000e1, 0.1963806152343750000000000e0, 0.3338470458984375000000000e1, -0.1854705810546875000000000e0, -0.3523941040039062500000000e1, 0.1761970520019531250000000e0, 0.3700138092041015625000000e1, -0.1681880950927734375000000e0, -0.3868326187133789062500000e1, 0.1611802577972412109375000e0, 0.4029506444931030273437500e1, -0.1549810171127319335937500e0, -0.4184487462043762207031250e1, 0.1494459807872772216796875e0, 0.4333933442831039428710938e1, -0.1444644480943679809570312e0, -0.4478397890925407409667969e1, 0.1399499340914189815521240e0, 0.4618347825016826391220093e1, -0.1358337595593184232711792e0, -0.4754181584576144814491272e1, 0.1320605995715595781803131e0, 0.4886242184147704392671585e1, -0.1285853206354659050703049e0, -0.5014827504783170297741890e1, 0.1253706876195792574435472e0, 0.5140198192402749555185437e1, -0.1223856712476845132187009e0, -0.5262583863650434068404138e1, 0.1196041787193280470091850e0, 0.5382188042369762115413323e1, -0.1170040878776035242481157e0, -0.5499192130247365639661439e1, 0.1145665027134867841596133e0, 0.5613758632960852423821052e1, -0.1122751726592170484764210e0, -0.5726033805620069472297473e1, 0.1101160347234628744672591e0, 0.5836149840343532346764732e1, -0.1080768488952505990141617e0, -0.5944226689238782945778894e1, 0.1061469051649782668889088e0, 0.6050373594403761212667803e1, -0.1043167861104096760804794e0, -0.6154690380514170888748282e1, 0.1025781730085695148124714e0, 0.6257268553522740403560753e1, -0.1009236863471409742509799e0, -0.6358192239869881377811733e1, 0.9934675374796689652830833e-1, 0.6457538993617848274340042e1, -0.9784149990330073142939457e-1, -0.6555380493521149005769436e1, 0.9640265431648748537896230e-1, 0.6651783147837636491148399e1, -0.9502547354053766415926284e-1, -0.6746808621378174155307661e1, 0.9370567529691908549038419e-1, 0.6840514296675093240798046e1, -0.9243938238750126001078440e-1, -0.6932953679062594500808830e1, 0.9122307472450782237906355e-1, 0.7024176753787102323187894e1, -0.9005354812547567081010120e-1, -0.7114230301912577993997995e1, 0.8892787877390722492497493e-1, 0.7203158180686485218922970e1, -0.8784339244739616120637768e-1, -0.7291001573133881380129347e1, 0.8679763777540334976344461e-1, 0.7377799210909284729892792e1, -0.8578836291754982244061386e-1, -0.7463587573826834552333406e1, 0.8481349515712311991287961e-1, 0.7548401068983957672246285e1, -0.8387112298871064080273650e-1, -0.7632272191972668313049022e1, 0.8295948034752900340270676e-1, 0.7715231672320197316451729e1, -0.8207693268425741826012477e-1, -0.7797308605004454734711853e1, 0.8122196463546307015324847e-1, 0.7878530569639917804865102e1, -0.8039316907795834494760308e-1, -0.7958923738717876149812705e1, 0.7958923738717876149812705e-1} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/legendre_test.go b/vendor/gonum.org/v1/gonum/integrate/quad/legendre_test.go new file mode 100644 index 00000000..7fb5bb09 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/legendre_test.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum 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 quad + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestLegendre(t *testing.T) { + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, Legendre{}, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Mismatch. Case = %d, n = %d. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, Legendre{}, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Mismatch concurrent. Case = %d, n = %d. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} + +func TestLegendreSingle(t *testing.T) { + for c, test := range []struct { + n int + min, max float64 + }{ + { + n: 100, + min: -1, + max: 1, + }, + { + n: 50, + min: -3, + max: -1, + }, + { + n: 1000, + min: 2, + max: 7, + }, + } { + l := Legendre{} + n := test.n + xs := make([]float64, n) + weights := make([]float64, n) + l.FixedLocations(xs, weights, test.min, test.max) + + xsSingle := make([]float64, n) + weightsSingle := make([]float64, n) + for i := range xsSingle { + xsSingle[i], weightsSingle[i] = l.FixedLocationSingle(n, i, test.min, test.max) + } + if !floats.Equal(xs, xsSingle) { + t.Errorf("Case %d: xs mismatch batch and single", c) + } + if !floats.Equal(weights, weightsSingle) { + t.Errorf("Case %d: weights mismatch batch and single", c) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/quad.go b/vendor/gonum.org/v1/gonum/integrate/quad/quad.go new file mode 100644 index 00000000..d222641c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/quad.go @@ -0,0 +1,157 @@ +// Copyright ©2015 The gonum 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 quad + +import ( + "math" + "sync" +) + +// FixedLocationer computes a set of quadrature locations and weights and stores +// them in-place into x and weight respectively. The number of points generated is equal to +// the len(x). The weights and locations should be chosen such that +// int_min^max f(x) dx ≈ \sum_i w_i f(x_i) +type FixedLocationer interface { + FixedLocations(x, weight []float64, min, max float64) +} + +// FixedLocationSingle returns the location and weight for element k in a +// fixed quadrature rule with n total samples and integral bounds from min to max. +type FixedLocationSingler interface { + FixedLocationSingle(n, k int, min, max float64) (x, weight float64) +} + +// Fixed approximates the integral of the function f from min to max using a fixed +// n-point quadrature rule. During evaluation, f will be evaluated n times using +// the weights and locations specified by rule. That is, Fixed estimates +// int_min^max f(x) dx ≈ \sum_i w_i f(x_i) +// If rule is nil, an acceptable default is chosen, otherwise it is +// assumed that the properties of the integral match the assumptions of rule. +// For example, Legendre assumes that the integration bounds are finite. If +// rule is also a FixedLocationSingler, the quadrature points are computed +// individually rather than as a unit. +// +// If concurrent <= 0, f is evaluated serially, while if concurrent > 0, f +// may be evaluated with at most concurrent simultaneous evaluations. +// +// min must be less than or equal to max, and n must be positive, otherwise +// Fixed will panic. +func Fixed(f func(float64) float64, min, max float64, n int, rule FixedLocationer, concurrent int) float64 { + // TODO(btracey): When there are Hermite polynomial quadrature, add an additional + // example to the documentation comment that talks about weight functions. + if n <= 0 { + panic("quad: non-positive number of locations") + } + if min > max { + panic("quad: min > max") + } + if min == max { + return 0 + } + intfunc := f + // If rule is non-nil it is assumed that the function and the constraints + // of rule are aligned. If it is nil, wrap the function and do something + // reasonable. + // TODO(btracey): Replace wrapping with other quadrature rules when + // we have rules that support infinite-bound integrals. + if rule == nil { + // int_a^b f(x)dx = int_u^-1(a)^u^-1(b) f(u(t))u'(t)dt + switch { + case math.IsInf(max, 1) && math.IsInf(min, -1): + // u(t) = (t/(1-t^2)) + min = -1 + max = 1 + intfunc = func(x float64) float64 { + v := 1 - x*x + return f(x/v) * (1 + x*x) / (v * v) + } + case math.IsInf(max, 1): + // u(t) = a + t / (1-t) + a := min + min = 0 + max = 1 + intfunc = func(x float64) float64 { + v := 1 - x + return f(a+x/v) / (v * v) + } + case math.IsInf(min, -1): + // u(t) = a - (1-t)/t + a := max + min = 0 + max = 1 + intfunc = func(x float64) float64 { + return f(a-(1-x)/x) / (x * x) + } + } + rule = Legendre{} + } + singler, isSingler := rule.(FixedLocationSingler) + + var xs, weights []float64 + if !isSingler { + xs = make([]float64, n) + weights = make([]float64, n) + rule.FixedLocations(xs, weights, min, max) + } + + if concurrent > n { + concurrent = n + } + + if concurrent <= 0 { + var integral float64 + // Evaluate in serial. + if isSingler { + for k := 0; k < n; k++ { + x, weight := singler.FixedLocationSingle(n, k, min, max) + integral += weight * intfunc(x) + } + return integral + } + for i, x := range xs { + integral += weights[i] * intfunc(x) + } + return integral + } + + // Evaluate concurrently + tasks := make(chan int) + + // Launch distributor + go func() { + for i := 0; i < n; i++ { + tasks <- i + } + close(tasks) + }() + + var mux sync.Mutex + var integral float64 + var wg sync.WaitGroup + wg.Add(concurrent) + for i := 0; i < concurrent; i++ { + // Launch workers + go func() { + defer wg.Done() + var subIntegral float64 + for k := range tasks { + var x, weight float64 + if isSingler { + x, weight = singler.FixedLocationSingle(n, k, min, max) + } else { + x = xs[k] + weight = weights[k] + } + f := intfunc(x) + subIntegral += f * weight + } + mux.Lock() + integral += subIntegral + mux.Unlock() + }() + } + wg.Wait() + return integral +} diff --git a/vendor/gonum.org/v1/gonum/integrate/quad/quad_test.go b/vendor/gonum.org/v1/gonum/integrate/quad/quad_test.go new file mode 100644 index 00000000..5e25ffdd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/quad/quad_test.go @@ -0,0 +1,126 @@ +// Copyright ©2015 The gonum 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 quad + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat/distuv" +) + +func TestFixed(t *testing.T) { + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + { + f: distuv.UnitNormal.Prob, + min: math.Inf(-1), + max: math.Inf(1), + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: 1, + }, + { + f: func(x float64) float64 { return math.Exp(-x) }, + min: 5, + max: math.Inf(1), + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: math.Exp(-5), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: math.Inf(-1), + max: -5, + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: math.Exp(-5), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: 3, + max: 3, + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{0, 0, 0, 0, 0, 0}, + ans: 0, + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, nil, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, nil, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} + +// legendreNonSingle wraps Legendre but does not implement FixedLocationSingle. +type legendreNonSingle struct { + Legendre Legendre +} + +func (l legendreNonSingle) FixedLocations(x, weight []float64, min, max float64) { + l.Legendre.FixedLocations(x, weight, min, max) +} + +func TestFixedNonSingle(t *testing.T) { + // TODO(btracey): Add tests with infinite bounds when we have native support + // for indefinite integrals. + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: 3, + max: 3, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + ans: 0, + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case = %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case = %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/integrate/trapezoidal.go b/vendor/gonum.org/v1/gonum/integrate/trapezoidal.go new file mode 100644 index 00000000..3f402ac3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/trapezoidal.go @@ -0,0 +1,40 @@ +// Copyright ©2016 The gonum 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 integrate + +import "sort" + +// Trapezoidal estimates the integral of a function f +// \int_a^b f(x) dx +// from a set of evaluations of the function using the trapezoidal rule. +// The trapezoidal rule makes piecewise linear approximations to the function, +// and estimates +// \int_x[i]^x[i+1] f(x) dx +// as +// (x[i+1] - x[i]) * (f[i] + f[i+1])/2 +// where f[i] is the value of the function at x[i]. +// More details on the trapezoidal rule can be found at: +// https://en.wikipedia.org/wiki/Trapezoidal_rule +// +// The (x,f) input data points must be sorted along x. +// One can use github.com/gonum/stat.SortWeighted to do that. +// The x and f slices must be of equal length and have length > 1. +func Trapezoidal(x, f []float64) float64 { + switch { + case len(x) != len(f): + panic("integrate: slice length mismatch") + case len(x) < 2: + panic("integrate: input data too small") + case !sort.Float64sAreSorted(x): + panic("integrate: input must be sorted") + } + + integral := 0.0 + for i := 0; i < len(x)-1; i++ { + integral += 0.5 * (x[i+1] - x[i]) * (f[i+1] + f[i]) + } + + return integral +} diff --git a/vendor/gonum.org/v1/gonum/integrate/trapezoidal_test.go b/vendor/gonum.org/v1/gonum/integrate/trapezoidal_test.go new file mode 100644 index 00000000..c52ee0e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/integrate/trapezoidal_test.go @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum 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 integrate + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestTrapezoidal(t *testing.T) { + const N = 1e6 + x := floats.Span(make([]float64, N), 0, 1) + for i, test := range []struct { + x []float64 + f func(x float64) float64 + want float64 + }{ + { + x: x, + f: func(x float64) float64 { return x }, + want: 0.5, + }, + { + x: floats.Span(make([]float64, N), -1, 1), + f: func(x float64) float64 { return x }, + want: 0, + }, + { + x: x, + f: func(x float64) float64 { return x + 10 }, + want: 10.5, + }, + { + x: x, + f: func(x float64) float64 { return 3*x*x + 10 }, + want: 11, + }, + { + x: x, + f: func(x float64) float64 { return math.Exp(x) }, + want: 1.7182818284591876, + }, + { + x: floats.Span(make([]float64, N), 0, math.Pi), + f: func(x float64) float64 { return math.Cos(x) }, + want: 0, + }, + { + x: floats.Span(make([]float64, N), 0, 2*math.Pi), + f: func(x float64) float64 { return math.Cos(x) }, + want: 0, + }, + { + x: floats.Span(make([]float64, N*10), 0, math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 2, + }, + { + x: floats.Span(make([]float64, N*10), 0, 0.5*math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 1, + }, + { + x: floats.Span(make([]float64, N), 0, 2*math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 0, + }, + } { + y := make([]float64, len(test.x)) + for i, v := range test.x { + y[i] = test.f(v) + } + v := Trapezoidal(test.x, y) + if !floats.EqualWithinAbs(v, test.want, 1e-12) { + t.Errorf("test #%d: got=%v want=%v\n", i, v, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/README.md b/vendor/gonum.org/v1/gonum/internal/README.md new file mode 100644 index 00000000..dd28a1f7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/README.md @@ -0,0 +1,3 @@ +# Gonum internal [![GoDoc](https://godoc.org/gonum.org/v1/gonum/internal?status.svg)](https://godoc.org/gonum.org/v1/gonum/internal) + +This is the set of internal packages for the Gonum project. diff --git a/vendor/gonum.org/v1/gonum/internal/asm/bench_gen.sh b/vendor/gonum.org/v1/gonum/internal/asm/bench_gen.sh new file mode 100755 index 00000000..e7115c07 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/bench_gen.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright ©2016 The gonum Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +cat c64/bench_test.go \ + | gofmt -r 'complex(float32(n), float32(n)) -> float32(n)' \ + | gofmt -r 'complex64 -> float32' \ + | gofmt -r '1 + 1i -> 1' \ + | gofmt -r '2 + 2i -> 2' \ + | sed 's/C64/F32/g' \ + | sed 's/c64/f32/g' \ + > f32/bench_test.go + +cat c64/bench_test.go \ + | gofmt -r 'complex(float32(n), float32(n)) -> float64(n)' \ + | gofmt -r 'complex64 -> float64' \ + | gofmt -r '1 + 1i -> 1' \ + | gofmt -r '2 + 2i -> 2' \ + | sed 's/C64/F64/g' \ + | sed 's/c64/f64/g' \ + > f64/bench_test.go + +cat c64/bench_test.go \ + | gofmt -r 'float32 -> float64' \ + | gofmt -r 'complex64 -> complex128' \ + | sed 's/C64/C128/g' \ + | sed 's/c64/c128/g' \ + > c128/bench_test.go diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s new file mode 100644 index 00000000..c66a667b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s @@ -0,0 +1,134 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SI // SI = &x + MOVQ y_base+40(FP), DI // DI = &y + MOVQ n+64(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+88(FP), R8 // R8 = ix // Load the first index + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ iy+96(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + LEAQ (SI)(R8*1), SI // SI = &(x[ix]) + LEAQ (DI)(R9*1), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI // Separate Read/Write pointers + MOVQ incX+72(FP), R8 // R8 = incX + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ incY+80(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS (SI)(R8*1), X4 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVUPS (SI), X6 + MOVUPS (SI)(R8*1), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + ADDPD (DX)(R9*1), X5 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDPD (DX), X7 + ADDPD (DX)(R9*1), X9 + MOVUPS X3, (DI) // dst[i] = X_(i+1) + MOVUPS X5, (DI)(R9*1) + LEAQ (DI)(R9*2), DI + MOVUPS X7, (DI) + MOVUPS X9, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI), X3 + MOVUPS X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s new file mode 100644 index 00000000..edc0957c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s @@ -0,0 +1,141 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+56(FP), SI // SI = &x + MOVQ y_base+80(FP), DX // DX = &y + MOVQ n+104(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+128(FP), R8 // R8 = ix // Load the first index + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ iy+136(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVQ idst+32(FP), R10 // R10 = idst + SHLQ $4, R10 // R10 *= sizeof(complex128) + LEAQ (SI)(R8*1), SI // SI = &(x[ix]) + LEAQ (DX)(R9*1), DX // DX = &(y[iy]) + LEAQ (DI)(R10*1), DI // DI = &(dst[idst]) + MOVQ incX+112(FP), R8 // R8 = incX + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ incY+120(FP), R9 // R9 = incY + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVQ incDst+24(FP), R10 // R10 = incDst + SHLQ $4, R10 // R10 *= sizeof(complex128) + MOVUPS alpha+40(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS (SI)(R8*1), X4 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + + MOVUPS (SI), X6 + MOVUPS (SI)(R8*1), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + ADDPD (DX)(R9*1), X5 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDPD (DX), X7 + ADDPD (DX)(R9*1), X9 + MOVUPS X3, (DI) // dst[i] = X_(i+1) + MOVUPS X5, (DI)(R10*1) + LEAQ (DI)(R10*2), DI + MOVUPS X7, (DI) + MOVUPS X9, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + MOVUPS X3, (DI) // y[i] X_(i+1) + ADDQ R8, SI // SI += incX + ADDQ R9, DX // DX += incY + ADDQ R10, DI // DI += incDst + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s new file mode 100644 index 00000000..c9e119d3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s @@ -0,0 +1,122 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitary(alpha complex128, x, y []complex128) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SI // SI = &x + MOVQ y_base+40(FP), DI // DI = &y + MOVQ x_len+24(FP), CX // CX = min( len(x), len(y) ) + CMPQ y_len+48(FP), CX + CMOVQLE y_len+48(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + PXOR X0, X0 // Clear work registers and cache-align loop + PXOR X1, X1 + MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS 16(SI)(AX*8), X4 + MOVUPS 32(SI)(AX*8), X6 + MOVUPS 48(SI)(AX*8), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI)(AX*8), X3 + ADDPD 16(DI)(AX*8), X5 + ADDPD 32(DI)(AX*8), X7 + ADDPD 48(DI)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX + JNZ caxy_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI)(AX*8), X3 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + ADDQ $2, AX // i += 2 + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s new file mode 100644 index 00000000..9dcfc67e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s @@ -0,0 +1,123 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitaryTo(dst []complex128, alpha complex64, x, y []complex128) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+40(FP), SI // SI = &x + MOVQ y_base+64(FP), DX // DX = &y + MOVQ x_len+48(FP), CX // CX = min( len(x), len(y), len(dst) ) + CMPQ y_len+72(FP), CX + CMOVQLE y_len+72(FP), CX + CMPQ dst_len+8(FP), CX + CMOVQLE dst_len+8(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + MOVUPS alpha+24(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS 16(SI)(AX*8), X4 + MOVUPS 32(SI)(AX*8), X6 + MOVUPS 48(SI)(AX*8), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 // Load and duplicate imag elements (xi, xi) + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 // duplicate real elements (xr, xr) + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX)(AX*8), X3 + ADDPD 16(DX)(AX*8), X5 + ADDPD 32(DX)(AX*8), X7 + ADDPD 48(DX)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX + JNZ caxy_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // Same calculation, but read in values to avoid trampling memory + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX)(AX*8), X3 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + ADDQ $2, AX // i += 2 + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/bench_test.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/bench_test.go new file mode 100644 index 00000000..61049beb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/bench_test.go @@ -0,0 +1,284 @@ +// Copyright ©2016 The gonum 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 c128 + +import "testing" + +var ( + a = complex128(2 + 2i) + x = make([]complex128, 1000000) + y = make([]complex128, 1000000) + z = make([]complex128, 1000000) +) + +func init() { + for n := range x { + x[n] = complex(float64(n), float64(n)) + y[n] = complex(float64(n), float64(n)) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a complex128, x, y []complex128)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a complex128, x, y []complex128) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkC128AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkC128AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkC128AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkC128AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkC128AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkC128AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkC128AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkC128AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLC128AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []complex128, a complex128, x, y []complex128)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []complex128, a complex128, x, y []complex128) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkC128AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLC128AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkC128AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkC128AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLC128AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkC128AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLC128AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM10(b *testing.B) { + benchaxpyincto(b, 100000, -10, naiveaxpyincto) +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go new file mode 100644 index 00000000..3a77db39 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 c128 provides complex128 vector primitives. +package c128 // import "gonum.org/v1/gonum/internal/asm/c128" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotc.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotc.go new file mode 100644 index 00000000..a852f0d2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotc.go @@ -0,0 +1,35 @@ +// Copyright ©2015 The gonum 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 c128 + +import "math/cmplx" + +// DotcUnitary is +// for i, v := range x { +// sum += y[i] * cmplx.Conj(v) +// } +// return sum +func DotcUnitary(x, y []complex128) (sum complex128) { + for i, v := range x { + sum += y[i] * cmplx.Conj(v) + } + return sum +} + +// DotcInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * cmplx.Conj(x[ix]) +// ix += incX +// iy += incY +// } +// return sum +func DotcInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { + for i := 0; i < int(n); i++ { + sum += y[iy] * cmplx.Conj(x[ix]) + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotu.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotu.go new file mode 100644 index 00000000..d82dc467 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotu.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 c128 + +// DotuUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotuUnitary(x, y []complex128) (sum complex128) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotuInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotuInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s new file mode 100644 index 00000000..778e2fab --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s @@ -0,0 +1,69 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define SRC SI +#define DST SI +#define LEN CX +#define TAIL BX +#define INC R9 +#define INC3 R10 +#define ALPHA X0 +#define ALPHA_2 X1 + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // MOVDDUP 8(SP), X0 + +// func DscalInc(alpha float64, x []complex128, n, inc uintptr) +TEXT ·DscalInc(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SRC // SRC = &x + MOVQ n+32(FP), LEN // LEN = n + CMPQ LEN, $0 // if LEN == 0 { return } + JE dscal_end + + MOVDDUP_ALPHA // ALPHA = alpha + MOVQ inc+40(FP), INC // INC = inc + SHLQ $4, INC // INC = INC * sizeof(complex128) + LEAQ (INC)(INC*2), INC3 // INC3 = 3 * INC + MOVUPS ALPHA, ALPHA_2 // Copy ALPHA and ALPHA_2 for pipelining + MOVQ LEN, TAIL // TAIL = LEN + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ dscal_tail // if LEN == 0 { goto dscal_tail } + +dscal_loop: // do { + MOVUPS (SRC), X2 // X_i = x[i] + MOVUPS (SRC)(INC*1), X3 + MOVUPS (SRC)(INC*2), X4 + MOVUPS (SRC)(INC3*1), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (DST) // x[i] = X_i + MOVUPS X3, (DST)(INC*1) + MOVUPS X4, (DST)(INC*2) + MOVUPS X5, (DST)(INC3*1) + + LEAQ (SRC)(INC*4), SRC // SRC += INC*4 + DECQ LEN + JNZ dscal_loop // } while --LEN > 0 + +dscal_tail: + ANDQ $3, TAIL // TAIL = TAIL % 4 + JE dscal_end // if TAIL == 0 { return } + +dscal_tail_loop: // do { + MOVUPS (SRC), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (DST) // x[i] = X_i + ADDQ INC, SRC // SRC += INC + DECQ TAIL + JNZ dscal_tail_loop // } while --TAIL > 0 + +dscal_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s new file mode 100644 index 00000000..32ef1546 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s @@ -0,0 +1,66 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define SRC SI +#define DST SI +#define LEN CX +#define IDX AX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // MOVDDUP 8(SP), X0 + +// func DscalUnitary(alpha float64, x []complex128) +TEXT ·DscalUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SRC // SRC = &x + MOVQ x_len+16(FP), LEN // LEN = len(x) + CMPQ LEN, $0 // if LEN == 0 { return } + JE dscal_end + + MOVDDUP_ALPHA // ALPHA = alpha + XORQ IDX, IDX // IDX = 0 + MOVUPS ALPHA, ALPHA_2 // Copy ALPHA to ALPHA_2 for pipelining + MOVQ LEN, TAIL // TAIL = LEN + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ dscal_tail // if LEN == 0 { goto dscal_tail } + +dscal_loop: // do { + MOVUPS (SRC)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(SRC)(IDX*8), X3 + MOVUPS 32(SRC)(IDX*8), X4 + MOVUPS 48(SRC)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (DST)(IDX*8) // x[i] = X_i + MOVUPS X3, 16(DST)(IDX*8) + MOVUPS X4, 32(DST)(IDX*8) + MOVUPS X5, 48(DST)(IDX*8) + + ADDQ $8, IDX // IDX += 8 + DECQ LEN + JNZ dscal_loop // } while --LEN > 0 + +dscal_tail: + ANDQ $3, TAIL // TAIL = TAIL % 4 + JZ dscal_end // if TAIL == 0 { return } + +dscal_tail_loop: // do { + MOVUPS (SRC)(IDX*8), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (DST)(IDX*8) // x[i] = X_i + ADDQ $2, IDX // IDX += 2 + DECQ TAIL + JNZ dscal_tail_loop // } while --TAIL > 0 + +dscal_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go new file mode 100644 index 00000000..580b4d8d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go @@ -0,0 +1,31 @@ +// Copyright ©2016 The gonum 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 c128 + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []complex128, alpha complex128, x []complex128) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []complex128, incDst uintptr, alpha complex128, x []complex128, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s new file mode 100644 index 00000000..22152a0e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s @@ -0,0 +1,116 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define SRC SI +#define DST SI +#define LEN CX +#define IDX AX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_C X1 +#define ALPHA2 X10 +#define ALPHA_C2 X11 + +#define MOVDDUP_X2_X3 LONG $0xDA120FF2 // MOVDDUP X2, X3 +#define MOVDDUP_X4_X5 LONG $0xEC120FF2 // MOVDDUP X4, X5 +#define MOVDDUP_X6_X7 LONG $0xFE120FF2 // MOVDDUP X6, X7 +#define MOVDDUP_X8_X9 LONG $0x120F45F2; BYTE $0xC8 // MOVDDUP X8, X9 + +#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 +#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 +#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 +#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 + +// func ScalUnitary(alpha complex128, x []complex128) +TEXT ·ScalUnitary(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SRC // SRC = &x + MOVQ x_len+24(FP), LEN // LEN = len(x) + CMPQ LEN, $0 // if LEN == 0 { return } + JE scal_end + + MOVUPS alpha+0(FP), ALPHA // ALPHA = { imag(alpha), real(alpha) } + MOVAPS ALPHA, ALPHA_C + SHUFPD $0x1, ALPHA_C, ALPHA_C // ALPHA_C = { real(alpha), imag(alpha) } + + XORQ IDX, IDX // IDX = 0 + MOVAPS ALPHA, ALPHA2 // Copy ALPHA and ALPHA_C for pipelining + MOVAPS ALPHA_C, ALPHA_C2 + MOVQ LEN, TAIL + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ scal_tail // if BX == 0 { goto scal_tail } + +scal_loop: // do { + MOVUPS (SRC)(IDX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS 16(SRC)(IDX*8), X4 + MOVUPS 32(SRC)(IDX*8), X6 + MOVUPS 48(SRC)(IDX*8), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } + // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } + MULPD ALPHA_C, X2 + MULPD ALPHA, X3 + MULPD ALPHA_C2, X4 + MULPD ALPHA2, X5 + MULPD ALPHA_C, X6 + MULPD ALPHA, X7 + MULPD ALPHA_C2, X8 + MULPD ALPHA2, X9 + + // X_(i+1) = { + // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), + // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + MOVUPS X3, (DST)(IDX*8) // x[i] = X_(i+1) + MOVUPS X5, 16(DST)(IDX*8) + MOVUPS X7, 32(DST)(IDX*8) + MOVUPS X9, 48(DST)(IDX*8) + ADDQ $8, IDX // IDX += 8 + DECQ LEN + JNZ scal_loop // } while --LEN > 0 + +scal_tail: + ANDQ $3, TAIL // TAIL = TAIL % 4 + JZ scal_end // if TAIL == 0 { return } + +scal_tail_loop: // do { + MOVUPS (SRC)(IDX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD ALPHA_C, X2 // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } + MULPD ALPHA, X3 // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), + // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + MOVUPS X3, (DST)(IDX*8) // x[i] = X_(i+1) + ADDQ $2, IDX // IDX += 2 + DECQ TAIL + JNZ scal_tail_loop // } while --LEN > 0 + +scal_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s new file mode 100644 index 00000000..ec0f1528 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s @@ -0,0 +1,121 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define SRC SI +#define DST SI +#define LEN CX +#define TAIL BX +#define INC R9 +#define INC3 R10 +#define ALPHA X0 +#define ALPHA_C X1 +#define ALPHA2 X10 +#define ALPHA_C2 X11 + +#define MOVDDUP_X2_X3 LONG $0xDA120FF2 // MOVDDUP X2, X3 +#define MOVDDUP_X4_X5 LONG $0xEC120FF2 // MOVDDUP X4, X5 +#define MOVDDUP_X6_X7 LONG $0xFE120FF2 // MOVDDUP X6, X7 +#define MOVDDUP_X8_X9 LONG $0x120F45F2; BYTE $0xC8 // MOVDDUP X8, X9 + +#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 +#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 +#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 +#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 + +// func ScalInc(alpha complex128, x []complex128, n, inc uintptr) +TEXT ·ScalInc(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SRC // SRC = &x + MOVQ n+40(FP), LEN // LEN = len(x) + CMPQ LEN, $0 + JE scal_end // if LEN == 0 { return } + + MOVQ inc+48(FP), INC // INC = inc + SHLQ $4, INC // INC = INC * sizeof(complex128) + LEAQ (INC)(INC*2), INC3 // INC3 = 3 * INC + + MOVUPS alpha+0(FP), ALPHA // ALPHA = { imag(alpha), real(alpha) } + MOVAPS ALPHA, ALPHA_C + SHUFPD $0x1, ALPHA_C, ALPHA_C // ALPHA_C = { real(alpha), imag(alpha) } + + MOVAPS ALPHA, ALPHA2 // Copy ALPHA and ALPHA_C for pipelining + MOVAPS ALPHA_C, ALPHA_C2 + MOVQ LEN, TAIL + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ scal_tail // if BX == 0 { goto scal_tail } + +scal_loop: // do { + MOVUPS (SRC), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS (SRC)(INC*1), X4 + MOVUPS (SRC)(INC*2), X6 + MOVUPS (SRC)(INC3*1), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } + // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } + MULPD ALPHA_C, X2 + MULPD ALPHA, X3 + MULPD ALPHA_C2, X4 + MULPD ALPHA2, X5 + MULPD ALPHA_C, X6 + MULPD ALPHA, X7 + MULPD ALPHA_C2, X8 + MULPD ALPHA2, X9 + + // X_(i+1) = { + // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), + // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + MOVUPS X3, (DST) // x[i] = X_(i+1) + MOVUPS X5, (DST)(INC*1) + MOVUPS X7, (DST)(INC*2) + MOVUPS X9, (DST)(INC3*1) + + LEAQ (SRC)(INC*4), SRC // SRC = &(SRC[inc*4]) + DECQ LEN + JNZ scal_loop // } while --BX > 0 + +scal_tail: + ANDQ $3, TAIL // TAIL = TAIL % 4 + JE scal_end // if TAIL == 0 { return } + +scal_tail_loop: // do { + MOVUPS (SRC), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD ALPHA_C, X2 // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } + MULPD ALPHA, X3 // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), + // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + MOVUPS X3, (DST) // x[i] = X_i + ADDQ INC, SRC // SRC = &(SRC[incX]) + DECQ TAIL + JNZ scal_tail_loop // } while --TAIL > 0 + +scal_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go new file mode 100644 index 00000000..f3494a78 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go @@ -0,0 +1,64 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package c128 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex128, x, y []complex128) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) + +// DscalUnitary is +// for i, v := range x { +// x[i] = complex(real(v)*alpha, imag(v)*alpha) +// } +func DscalUnitary(alpha float64, x []complex128) + +// DscalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) +// ix += inc +// } +func DscalInc(alpha float64, x []complex128, n, inc uintptr) + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha complex128, x []complex128, n, inc uintptr) + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha complex128, x []complex128) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go new file mode 100644 index 00000000..008a1e6a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go @@ -0,0 +1,105 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package c128 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex128, x, y []complex128) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +// DscalUnitary is +// for i, v := range x { +// x[i] = complex(real(v)*alpha, imag(v)*alpha) +// } +func DscalUnitary(alpha float64, x []complex128) { + for i, v := range x { + x[i] = complex(real(v)*alpha, imag(v)*alpha) + } +} + +// DscalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) +// ix += inc +// } +func DscalInc(alpha float64, x []complex128, n, inc uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) + ix += inc + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha complex128, x []complex128, n, inc uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += inc + } +} + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha complex128, x []complex128) { + for i := range x { + x[i] *= alpha + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_test.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_test.go new file mode 100644 index 00000000..6af21e11 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_test.go @@ -0,0 +1,335 @@ +// Copyright ©2016 The gonum 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 c128 + +import ( + "fmt" + "testing" +) + +var tests = []struct { + incX, incY, incDst int + ix, iy, idst uintptr + a complex128 + dst, x, y []complex128 + ex []complex128 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 1i, + dst: []complex128{5}, + x: []complex128{1}, + y: []complex128{1i}, + ex: []complex128{1 + 2i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{0, 0, 0}, + x: []complex128{0, 0, 0}, + y: []complex128{1, 1, 1}, + ex: []complex128{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{0, 0, 0}, + x: []complex128{0, 0}, + y: []complex128{1, 1, 1}, + ex: []complex128{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i}, + y: []complex128{1, 2, 1}, + ex: []complex128{-1 + 1i, 1i, -1 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i}, + y: []complex128{1, 2, 1}, + ex: []complex128{2, 3, 2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i, 1i, 1i}[1:4], + y: []complex128{1, 1, 2, 1, 1}[1:4], + ex: []complex128{2, 3, 2}}, + {incX: 2, incY: 4, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -2, + dst: []complex128{1i, 1i, 1i, 1i, 1i}, + x: []complex128{2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i}, + y: []complex128{1, 1, 2, 1, 1}, + ex: []complex128{-3 - 2i, -3 - 2i, -2 - 2i, -3 - 2i, -3 - 2i}}, + // Run big test twice, once aligned once unaligned. + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: -2, incDst: -3, ix: 18, iy: 18, idst: 27, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: 2, incDst: -3, ix: 18, iy: 0, idst: 27, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, +} + +func TestAxpyUnitary(t *testing.T) { + const xGdVal, yGdVal = 1, 1 + for cas, test := range tests { + xgLn, ygLn := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + x, y := test.x[xgLn:len(test.x)-xgLn], test.y[ygLn:len(test.y)-ygLn] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if y[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, xGdVal, xgLn) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xgLn], test.x[len(test.x)-xgLn:]) + } + if !isValidGuard(test.y, yGdVal, ygLn) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:ygLn], test.y[len(test.y)-ygLn:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + const xGdVal, yGdVal, dstGdVal = 1, 1, 0 + for cas, test := range tests { + xgLn, ygLn := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + test.dst = guardVector(test.dst, dstGdVal, xgLn) + x, y := test.x[xgLn:len(test.x)-xgLn], test.y[ygLn:len(test.y)-ygLn] + dst := test.dst[xgLn : len(test.dst)-xgLn] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if dst[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, xGdVal, xgLn) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xgLn], test.x[len(test.x)-xgLn:]) + } + if !isValidGuard(test.y, yGdVal, ygLn) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:ygLn], test.y[len(test.y)-ygLn:]) + } + if !isValidGuard(test.dst, dstGdVal, xgLn) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xgLn], test.dst[len(test.dst)-xgLn:]) + } + + } +} + +func TestAxpyInc(t *testing.T) { + const xGdVal, yGdVal = 1, 1 + for cas, test := range tests { + xgLn, ygLn := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, xGdVal, test.incX, xgLn), guardIncVector(test.y, yGdVal, test.incY, ygLn) + x, y := test.x[xgLn:len(test.x)-xgLn], test.y[ygLn:len(test.y)-ygLn] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if y[int(test.iy)+i*int(test.incY)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, xGdVal, test.incX, xgLn) + checkValidIncGuard(t, test.y, yGdVal, test.incY, ygLn) + } +} + +func TestAxpyIncTo(t *testing.T) { + const xGdVal, yGdVal, dstGdVal = 1, 1, 0 + for cas, test := range tests { + xgLn, ygLn := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, xGdVal, test.incX, xgLn), guardIncVector(test.y, yGdVal, test.incY, ygLn) + test.dst = guardIncVector(test.dst, dstGdVal, test.incDst, xgLn) + x, y := test.x[xgLn:len(test.x)-xgLn], test.y[ygLn:len(test.y)-ygLn] + dst := test.dst[xgLn : len(test.dst)-xgLn] + AxpyIncTo(dst, uintptr(test.incDst), test.idst, test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if dst[int(test.idst)+i*int(test.incDst)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, xGdVal, test.incX, xgLn) + checkValidIncGuard(t, test.y, yGdVal, test.incY, ygLn) + checkValidIncGuard(t, test.dst, dstGdVal, test.incDst, xgLn) + } +} + +var dscalTests = []struct { + alpha float64 + x []complex128 + want []complex128 +}{ + { + alpha: 0, + x: []complex128{}, + want: []complex128{}, + }, + { + alpha: 1, + x: []complex128{1 + 2i}, + want: []complex128{1 + 2i}, + }, + { + alpha: 2, + x: []complex128{1 + 2i}, + want: []complex128{2 + 4i}, + }, + { + alpha: 2, + x: []complex128{1 + 2i, 3 + 5i, 6 + 11i, 12 - 23i}, + want: []complex128{2 + 4i, 6 + 10i, 12 + 22i, 24 - 46i}, + }, + { + alpha: 3, + x: []complex128{1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i}, + want: []complex128{3 + 6i, 15 + 12i, 9 + 18i, 24 + 36i, -9 - 6i, -15 + 15i}, + }, + { + alpha: 5, + x: []complex128{1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i, 1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i}, + want: []complex128{5 + 10i, 25 + 20i, 15 + 30i, 40 + 60i, -15 - 10i, -25 + 25i, 5 + 10i, 25 + 20i, 15 + 30i, 40 + 60i, -15 - 10i, -25 + 25i}, + }, +} + +func TestDscalUnitary(t *testing.T) { + const xGdVal = -0.5 + for i, test := range dscalTests { + for _, align := range align1 { + prefix := fmt.Sprintf("Test %v (x:%v)", i, align) + xgLn := 4 + align + xg := guardVector(test.x, xGdVal, xgLn) + x := xg[xgLn : len(xg)-xgLn] + + DscalUnitary(test.alpha, x) + + for i := range test.want { + if !same(x[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + } + } +} + +func TestDscalInc(t *testing.T) { + const xGdVal = -0.5 + gdLn := 4 + for i, test := range dscalTests { + n := len(test.x) + for _, incX := range []int{1, 2, 3, 4, 7, 10} { + prefix := fmt.Sprintf("Test %v (x:%v)", i, incX) + xg := guardIncVector(test.x, xGdVal, incX, gdLn) + x := xg[gdLn : len(xg)-gdLn] + + DscalInc(test.alpha, x, uintptr(n), uintptr(incX)) + + for i := range test.want { + if !same(x[i*incX], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i*incX], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, incX, gdLn) + } + } +} + +var scalTests = []struct { + alpha complex128 + x []complex128 + want []complex128 +}{ + { + alpha: 0, + x: []complex128{}, + want: []complex128{}, + }, + { + alpha: 1 + 1i, + x: []complex128{1 + 2i}, + want: []complex128{-1 + 3i}, + }, + { + alpha: 2 + 3i, + x: []complex128{1 + 2i}, + want: []complex128{-4 + 7i}, + }, + { + alpha: 2 - 4i, + x: []complex128{1 + 2i}, + want: []complex128{10}, + }, + { + alpha: 2 + 8i, + x: []complex128{1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i}, + want: []complex128{-14 + 12i, -22 + 48i, -42 + 36i, -80 + 88i, 10 - 28i, -50 - 30i}, + }, + { + alpha: 5 - 10i, + x: []complex128{1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i, 1 + 2i, 5 + 4i, 3 + 6i, 8 + 12i, -3 - 2i, -5 + 5i}, + want: []complex128{25, 65 - 30i, 75, 160 - 20i, -35 + 20i, 25 + 75i, 25, 65 - 30i, 75, 160 - 20i, -35 + 20i, 25 + 75i}, + }, +} + +func TestScalUnitary(t *testing.T) { + const xGdVal = -0.5 + for i, test := range scalTests { + for _, align := range align1 { + prefix := fmt.Sprintf("Test %v (x:%v)", i, align) + xgLn := 4 + align + xg := guardVector(test.x, xGdVal, xgLn) + x := xg[xgLn : len(xg)-xgLn] + + ScalUnitary(test.alpha, x) + + for i := range test.want { + if !same(x[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + } + } +} + +func TestScalInc(t *testing.T) { + const xGdVal = -0.5 + gdLn := 4 + for i, test := range scalTests { + n := len(test.x) + for _, inc := range []int{1, 2, 3, 4, 7, 10} { + prefix := fmt.Sprintf("Test %v (x:%v)", i, inc) + xg := guardIncVector(test.x, xGdVal, inc, gdLn) + x := xg[gdLn : len(xg)-gdLn] + + ScalInc(test.alpha, x, uintptr(n), uintptr(inc)) + + for i := range test.want { + if !same(x[i*inc], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i*inc], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, inc, gdLn) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/util_test.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/util_test.go new file mode 100644 index 00000000..e07470d9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c128/util_test.go @@ -0,0 +1,123 @@ +// Copyright ©2016 The gonum 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 c128 + +import ( + "math" + "testing" +) + +const ( + msgVal = "%v: unexpected value at %v Got: %v Expected: %v" + msgGuard = "%v: Guard violated in %s vector %v %v" +) + +func same(x, y complex128) bool { + return (x == y || + math.IsNaN(real(x)) && math.IsNaN(real(y)) && imag(x) == imag(y) || + math.IsNaN(imag(y)) && math.IsNaN(imag(x)) && real(y) == real(x) || + math.IsNaN(real(x)) && math.IsNaN(real(y)) && math.IsNaN(imag(y)) && math.IsNaN(imag(x))) +} + +func guardVector(vec []complex128, guard_val complex128, guard_len int) (guarded []complex128) { + guarded = make([]complex128, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []complex128, guard_val complex128, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func guardIncVector(vec []complex128, guard_val complex128, inc, guard_len int) (guarded []complex128) { + s_ln := len(vec) * inc + if inc < 0 { + s_ln = len(vec) * -inc + } + guarded = make([]complex128, s_ln+guard_len*2) + for i, cas := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && cas < len(vec): + guarded[i] = vec[cas] + cas++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []complex128, guard_val complex128, inc, guard_len int) { + s_ln := len(vec) - 2*guard_len + if inc < 0 { + s_ln = len(vec) * -inc + } + + for i := range vec { + switch { + case vec[i] == guard_val: + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +var ( // Offset sets for testing alignment handling in Unitary assembly functions. + align1 = []int{0, 1} + align2 = newIncSet(0, 1) + align3 = newIncToSet(0, 1) +) + +type incSet struct { + x, y int +} + +// genInc will generate all (x,y) combinations of the input increment set. +func newIncSet(inc ...int) []incSet { + n := len(inc) + is := make([]incSet, n*n) + for x := range inc { + for y := range inc { + is[x*n+y] = incSet{inc[x], inc[y]} + } + } + return is +} + +type incToSet struct { + dst, x, y int +} + +// genIncTo will generate all (dst,x,y) combinations of the input increment set. +func newIncToSet(inc ...int) []incToSet { + n := len(inc) + is := make([]incToSet, n*n*n) + for i, dst := range inc { + for x := range inc { + for y := range inc { + is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]} + } + } + } + return is +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s new file mode 100644 index 00000000..82c28862 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s @@ -0,0 +1,151 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ n+56(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+80(FP), R8 // R8 = ix + MOVQ iy+88(FP), R9 // R9 = iy + LEAQ (SI)(R8*8), SI // SI = &(x[ix]) + LEAQ (DI)(R9*8), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI // Read/Write pointers + MOVQ incX+64(FP), R8 // R8 = incX + SHLQ $3, R8 // R8 *= sizeof(complex64) + MOVQ incY+72(FP), R9 // R9 = incY + SHLQ $3, R9 // R9 *= sizeof(complex64) + MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } + MOVSD (SI)(R8*1), X5 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSD (SI), X7 + MOVSD (SI)(R8*1), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X2 + MOVSD (DX)(R9*1), X4 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + MOVSD (DX), X6 + MOVSD (DX)(R9*1), X8 + ADDPS X2, X3 + ADDPS X4, X5 + ADDPS X6, X7 + ADDPS X8, X9 + + MOVSD X3, (DI) // y[i] = X_i + MOVSD X5, (DI)(R9*1) + LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) + MOVSD X7, (DI) + MOVSD X9, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } + MOVSHDUP_X3_X2 // X_(i-1) = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 // X_i = { imag(x[i]), imag(x[i]) } + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 // (ai*x1r+ar*x1i, ar*x1r-ai*x1i) + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DI), X4 + ADDPS X4, X3 + MOVSD X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI += incX + ADDQ R9, DI // DI += incY + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s new file mode 100644 index 00000000..9fdc3ef3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s @@ -0,0 +1,156 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+48(FP), SI // SI = &x + MOVQ y_base+72(FP), DX // DX = &y + MOVQ n+96(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+120(FP), R8 // Load the first index + MOVQ iy+128(FP), R9 + MOVQ idst+32(FP), R10 + LEAQ (SI)(R8*8), SI // SI = &(x[ix]) + LEAQ (DX)(R9*8), DX // DX = &(y[iy]) + LEAQ (DI)(R10*8), DI // DI = &(dst[idst]) + MOVQ incX+104(FP), R8 // Incrementors*8 for easy iteration (ADDQ) + SHLQ $3, R8 + MOVQ incY+112(FP), R9 + SHLQ $3, R9 + MOVQ incDst+24(FP), R10 + SHLQ $3, R10 + MOVSD alpha+40(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSD (SI)(R8*1), X5 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSD (SI), X7 + MOVSD (SI)(R8*1), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X2 + MOVSD (DX)(R9*1), X4 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + MOVSD (DX), X6 + MOVSD (DX)(R9*1), X8 + ADDPS X2, X3 + ADDPS X4, X5 + ADDPS X6, X7 + ADDPS X8, X9 + + MOVSD X3, (DI) // y[i] = X_i + MOVSD X5, (DI)(R10*1) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) + MOVSD X7, (DI) + MOVSD X9, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: + MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X4 + ADDPS X4, X3 + MOVSD X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI += incX + ADDQ R9, DX // DX += incY + ADDQ R10, DI // DI += incDst + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s new file mode 100644 index 00000000..807a1c42 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitary(alpha complex64, x, y []complex64) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ x_len+16(FP), CX // CX = min( len(x), len(y) ) + CMPQ y_len+40(FP), CX + CMOVQLE y_len+40(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + PXOR X0, X0 // Clear work registers and cache-align loop + PXOR X1, X1 + MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVQ DI, BX // Align on 16-byte boundary for ADDPS + ANDQ $15, BX // BX = &y & 15 + JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } + + // Trim first value in unaligned buffer + XORPS X2, X2 // Clear work registers and cache-align loop + XORPS X3, X3 + XORPS X4, X4 + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DI)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // i++ + DECQ CX // --CX + JZ caxy_end // if CX == 0 { return } + +caxy_no_trim: + MOVAPS X0, X10 // Copy X0 and X1 for pipelineing + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $7, CX // CX = n % 8 + SHRQ $3, BX // BX = floor( n / 8 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } + MOVUPS (SI)(AX*8), X3 + MOVUPS 16(SI)(AX*8), X5 + MOVUPS 32(SI)(AX*8), X7 + MOVUPS 48(SI)(AX*8), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), + // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), + // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), + // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), + // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } + ADDPS (DI)(AX*8), X3 + ADDPS 16(DI)(AX*8), X5 + ADDPS 32(DI)(AX*8), X7 + ADDPS 48(DI)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX // --BX + JNZ caxy_loop // } while BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DI)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // ++i + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s new file mode 100644 index 00000000..ed5a8c93 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s @@ -0,0 +1,157 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+32(FP), SI // SI = &x + MOVQ y_base+56(FP), DX // DX = &y + MOVQ x_len+40(FP), CX + CMPQ y_len+64(FP), CX // CX = min( len(x), len(y), len(dst) ) + CMOVQLE y_len+64(FP), CX + CMPQ dst_len+8(FP), CX + CMOVQLE dst_len+8(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + MOVSD alpha+24(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVQ DX, BX // Align on 16-byte boundary for ADDPS + ANDQ $15, BX // BX = &y & 15 + JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } + + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DX)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // dst[i] = X3 + INCQ AX // i++ + DECQ CX // --CX + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_no_trim: + MOVAPS X0, X10 // Copy X0 and X1 for pipelineing + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $7, CX // CX = n % 8 + SHRQ $3, BX // BX = floor( n / 8 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: + // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } + MOVUPS (SI)(AX*8), X3 + MOVUPS 16(SI)(AX*8), X5 + MOVUPS 32(SI)(AX*8), X7 + MOVUPS 48(SI)(AX*8), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), + // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), + // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), + // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), + // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } + ADDPS (DX)(AX*8), X3 + ADDPS 16(DX)(AX*8), X5 + ADDPS 32(DX)(AX*8), X7 + ADDPS 48(DX)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX // --BX + JNZ caxy_loop // } while BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DX)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // ++i + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/bench_test.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/bench_test.go new file mode 100644 index 00000000..0b7b5b83 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/bench_test.go @@ -0,0 +1,282 @@ +// Copyright ©2016 The gonum 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 c64 + +import "testing" + +var ( + a = complex64(2 + 2i) + x = make([]complex64, 1000000) + y = make([]complex64, 1000000) + z = make([]complex64, 1000000) +) + +func init() { + for n := range x { + x[n] = complex(float32(n), float32(n)) + y[n] = complex(float32(n), float32(n)) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a complex64, x, y []complex64)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a complex64, x, y []complex64) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkC64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkC64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkC64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkC64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkC64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkC64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkC64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkC64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLC64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []complex64, a complex64, x, y []complex64)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []complex64, a complex64, x, y []complex64) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkC64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLC64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkC64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkC64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLC64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkC64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLC64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go new file mode 100644 index 00000000..932be953 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go @@ -0,0 +1,7 @@ +// Copyright ©2015 The gonum 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 c64 + +func conj(c complex64) complex64 { return complex(real(c), -imag(c)) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go new file mode 100644 index 00000000..a0b8862b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 c64 provides complex64 vector primitives. +package c64 // import "gonum.org/v1/gonum/internal/asm/c64" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotc.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotc.go new file mode 100644 index 00000000..cd5b862b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotc.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 c64 + +// DotcUnitary is +// for i, v := range x { +// sum += y[i] * conj(v) +// } +// return sum +func DotcUnitary(x, y []complex64) (sum complex64) { + for i, v := range x { + sum += y[i] * conj(v) + } + return sum +} + +// DotcInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * conj(x[ix]) +// ix += incX +// iy += incY +// } +// return sum +func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * conj(x[ix]) + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotu.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotu.go new file mode 100644 index 00000000..ff15d659 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotu.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 c64 + +// DotuUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotuUnitary(x, y []complex64) (sum complex64) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotuInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go new file mode 100644 index 00000000..11212813 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go @@ -0,0 +1,55 @@ +// Copyright ©2016 The gonum 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 c64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha complex64, x []complex64) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []complex64, alpha complex64, x []complex64) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha complex64, x []complex64, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []complex64, incDst uintptr, alpha complex64, x []complex64, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go new file mode 100644 index 00000000..bd6486c3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go @@ -0,0 +1,36 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package c64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex64, x, y []complex64) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go new file mode 100644 index 00000000..78aebbd6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package c64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex64, x, y []complex64) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_test.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_test.go new file mode 100644 index 00000000..8049a763 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_test.go @@ -0,0 +1,231 @@ +// Copyright ©2016 The gonum 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 c64 + +import "testing" + +var tests = []struct { + incX, incY, incDst int + ix, iy, idst uintptr + a complex64 + dst, x, y []complex64 + ex []complex64 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 1i, + dst: []complex64{5}, + x: []complex64{1}, + y: []complex64{1i}, + ex: []complex64{1 + 2i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{0, 0, 0}, + x: []complex64{0, 0, 0}, + y: []complex64{1, 1, 1}, + ex: []complex64{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{0, 0, 0}, + x: []complex64{0, 0}, + y: []complex64{1, 1, 1}, + ex: []complex64{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i}, + y: []complex64{1, 2, 1}, + ex: []complex64{-1 + 1i, 1i, -1 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i}, + y: []complex64{1, 2, 1}, + ex: []complex64{2, 3, 2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i, 1i, 1i}[1:4], + y: []complex64{1, 1, 2, 1, 1}[1:4], + ex: []complex64{2, 3, 2}}, + {incX: 2, incY: 4, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -2, + dst: []complex64{1i, 1i, 1i, 1i, 1i}, + x: []complex64{2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i}, + y: []complex64{1, 1, 2, 1, 1}, + ex: []complex64{-3 - 2i, -3 - 2i, -2 - 2i, -3 - 2i, -3 - 2i}}, + // Run big test twice, once aligned once unaligned. + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: -2, incDst: -3, ix: 18, iy: 18, idst: 27, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: 2, incDst: -3, ix: 18, iy: 0, idst: 27, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, +} + +func guardVector(vec []complex64, guard_val complex64, guard_len int) (guarded []complex64) { + guarded = make([]complex64, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []complex64, guard_val complex64, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func TestAxpyUnitary(t *testing.T) { + var x_gd, y_gd complex64 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if y[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex64 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + test.dst = guardVector(test.dst, dst_gd, xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if dst[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + if !isValidGuard(test.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xg_ln], test.dst[len(test.dst)-xg_ln:]) + } + + } +} + +func guardIncVector(vec []complex64, guard_val complex64, incV uintptr, guard_len int) (guarded []complex64) { + inc := int(incV) + s_ln := len(vec) * inc + if inc < 0 { + s_ln = len(vec) * -inc + } + guarded = make([]complex64, s_ln+guard_len*2) + for i, cas := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && cas < len(vec): + guarded[i] = vec[cas] + cas++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []complex64, guard_val complex64, incV uintptr, guard_len int) { + inc := int(incV) + s_ln := len(vec) - 2*guard_len + if inc < 0 { + s_ln = len(vec) * -inc + } + + for i := range vec { + switch { + case vec[i] == guard_val: + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +func TestAxpyInc(t *testing.T) { + var x_gd, y_gd complex64 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if y[int(test.iy)+i*int(test.incY)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + } +} + +func TestAxpyIncTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex64 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + test.dst = guardIncVector(test.dst, dst_gd, uintptr(test.incDst), xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyIncTo(dst, uintptr(test.incDst), test.idst, test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if dst[int(test.idst)+i*int(test.incDst)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + checkValidIncGuard(t, test.dst, dst_gd, uintptr(test.incDst), xg_ln) + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s new file mode 100644 index 00000000..a6462f0e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ n+56(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JLE axpyi_end + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ ix+80(FP), R8 // R8 = ix + MOVQ iy+88(FP), R9 // R9 = iy + LEAQ (SI)(R8*4), SI // SI = &(x[ix]) + LEAQ (DI)(R9*4), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI Read Pointer for y + MOVQ incX+64(FP), R8 // R8 = incX + SHLQ $2, R8 // R8 *= sizeof(float32) + MOVQ incY+72(FP), R9 // R9 = incY + SHLQ $2, R9 // R9 *= sizeof(float32) + MOVSS alpha+0(FP), X0 // X0 = alpha + MOVSS X0, X1 // X1 = X0 // for pipelining + MOVQ CX, BX + ANDQ $3, BX // BX = n % 4 + SHRQ $2, CX // CX = floor( n / 4 ) + JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } + +axpyi_loop: // Loop unrolled 4x do { + MOVSS (SI), X2 // X_i = x[i] + MOVSS (SI)(R8*1), X3 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSS (SI), X4 + MOVSS (SI)(R8*1), X5 + MULSS X1, X2 // X_i *= a + MULSS X0, X3 + MULSS X1, X4 + MULSS X0, X5 + ADDSS (DX), X2 // X_i += y[i] + ADDSS (DX)(R9*1), X3 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDSS (DX), X4 + ADDSS (DX)(R9*1), X5 + MOVSS X2, (DI) // y[i] = X_i + MOVSS X3, (DI)(R9*1) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + MOVSS X4, (DI) + MOVSS X5, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + LOOP axpyi_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpyi_end + +axpyi_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +axpyi_tail: // do { + MOVSS (SI), X2 // X2 = x[i] + MULSS X1, X2 // X2 *= a + ADDSS (DI), X2 // X2 += y[i] + MOVSS X2, (DI) // y[i] = X2 + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET + diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s new file mode 100644 index 00000000..e1c39e90 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ n+96(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JLE axpyi_end + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+48(FP), SI // SI = &x + MOVQ y_base+72(FP), DX // DX = &y + MOVQ ix+120(FP), R8 // R8 = ix // Load the first index + MOVQ iy+128(FP), R9 // R9 = iy + MOVQ idst+32(FP), R10 // R10 = idst + LEAQ (SI)(R8*4), SI // SI = &(x[ix]) + LEAQ (DX)(R9*4), DX // DX = &(y[iy]) + LEAQ (DI)(R10*4), DI // DI = &(dst[idst]) + MOVQ incX+104(FP), R8 // R8 = incX + SHLQ $2, R8 // R8 *= sizeof(float32) + MOVQ incY+112(FP), R9 // R9 = incY + SHLQ $2, R9 // R9 *= sizeof(float32) + MOVQ incDst+24(FP), R10 // R10 = incDst + SHLQ $2, R10 // R10 *= sizeof(float32) + MOVSS alpha+40(FP), X0 // X0 = alpha + MOVSS X0, X1 // X1 = X0 // for pipelining + MOVQ CX, BX + ANDQ $3, BX // BX = n % 4 + SHRQ $2, CX // CX = floor( n / 4 ) + JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } + +axpyi_loop: // Loop unrolled 4x do { + MOVSS (SI), X2 // X_i = x[i] + MOVSS (SI)(R8*1), X3 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSS (SI), X4 + MOVSS (SI)(R8*1), X5 + MULSS X1, X2 // X_i *= a + MULSS X0, X3 + MULSS X1, X4 + MULSS X0, X5 + ADDSS (DX), X2 // X_i += y[i] + ADDSS (DX)(R9*1), X3 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDSS (DX), X4 + ADDSS (DX)(R9*1), X5 + MOVSS X2, (DI) // dst[i] = X_i + MOVSS X3, (DI)(R10*1) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + MOVSS X4, (DI) + MOVSS X5, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + LOOP axpyi_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpyi_end + +axpyi_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +axpyi_tail: // do { + MOVSS (SI), X2 // X2 = x[i] + MULSS X1, X2 // X2 *= a + ADDSS (DX), X2 // X2 += y[i] + MOVSS X2, (DI) // dst[i] = X2 + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DX // DX = &(DX[incY]) + ADDQ R10, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET + diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s new file mode 100644 index 00000000..a5bfaac9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s @@ -0,0 +1,97 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyUnitary(alpha float32, x, y []float32) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ x_len+16(FP), BX // BX = min( len(x), len(y) ) + CMPQ y_len+40(FP), BX + CMOVQLE y_len+40(FP), BX + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + MOVSS alpha+0(FP), X0 + SHUFPS $0, X0, X0 // X0 = { a, a, a, a } + XORQ AX, AX // i = 0 + PXOR X2, X2 // 2 NOP instructions (PXOR) to align + PXOR X3, X3 // loop to cache line + MOVQ DI, CX + ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS + JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } + + XORQ $0xF, CX // CX = 4 - floor( BX % 16 / 4 ) + INCQ CX + SHRQ $2, CX + +axpy_align: // Trim first value(s) in unaligned buffer do { + MOVSS (SI)(AX*4), X2 // X2 = x[i] + MULSS X0, X2 // X2 *= a + ADDSS (DI)(AX*4), X2 // X2 += y[i] + MOVSS X2, (DI)(AX*4) // y[i] = X2 + INCQ AX // i++ + DECQ BX + JZ axpy_end // if --BX == 0 { return } + LOOP axpy_align // } while --CX > 0 + +axpy_no_trim: + MOVUPS X0, X1 // Copy X0 to X1 for pipelining + MOVQ BX, CX + ANDQ $0xF, BX // BX = len % 16 + SHRQ $4, CX // CX = int( len / 16 ) + JZ axpy_tail4_start // if CX == 0 { return } + +axpy_loop: // Loop unrolled 16x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] + MOVUPS 16(SI)(AX*4), X3 + MOVUPS 32(SI)(AX*4), X4 + MOVUPS 48(SI)(AX*4), X5 + MULPS X0, X2 // X2 *= a + MULPS X1, X3 + MULPS X0, X4 + MULPS X1, X5 + ADDPS (DI)(AX*4), X2 // X2 += y[i:i+4] + ADDPS 16(DI)(AX*4), X3 + ADDPS 32(DI)(AX*4), X4 + ADDPS 48(DI)(AX*4), X5 + MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 + MOVUPS X3, 16(DI)(AX*4) + MOVUPS X4, 32(DI)(AX*4) + MOVUPS X5, 48(DI)(AX*4) + ADDQ $16, AX // i += 16 + LOOP axpy_loop // while (--CX) > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + +axpy_tail4_start: // Reset loop counter for 4-wide tail loop + MOVQ BX, CX // CX = floor( BX / 4 ) + SHRQ $2, CX + JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } + +axpy_tail4: // Loop unrolled 4x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i] + MULPS X0, X2 // X2 *= a + ADDPS (DI)(AX*4), X2 // X2 += y[i] + MOVUPS X2, (DI)(AX*4) // y[i] = X2 + ADDQ $4, AX // i += 4 + LOOP axpy_tail4 // } while --CX > 0 + +axpy_tail_start: // Reset loop counter for 1-wide tail loop + MOVQ BX, CX // CX = BX % 4 + ANDQ $3, CX + JZ axpy_end // if CX == 0 { return } + +axpy_tail: + MOVSS (SI)(AX*4), X1 // X1 = x[i] + MULSS X0, X1 // X1 *= a + ADDSS (DI)(AX*4), X1 // X1 += y[i] + MOVSS X1, (DI)(AX*4) // y[i] = X1 + INCQ AX // i++ + LOOP axpy_tail // } while --CX > 0 + +axpy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s new file mode 100644 index 00000000..9a8289f8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s @@ -0,0 +1,98 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+32(FP), SI // SI = &x + MOVQ y_base+56(FP), DX // DX = &y + MOVQ x_len+40(FP), BX // BX = min( len(x), len(y), len(dst) ) + CMPQ y_len+64(FP), BX + CMOVQLE y_len+64(FP), BX + CMPQ dst_len+8(FP), BX + CMOVQLE dst_len+8(FP), BX + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + MOVSS alpha+24(FP), X0 + SHUFPS $0, X0, X0 // X0 = { a, a, a, a, } + XORQ AX, AX // i = 0 + MOVQ DX, CX + ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS + JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } + + XORQ $0xF, CX // CX = 4 - floor ( B % 16 / 4 ) + INCQ CX + SHRQ $2, CX + +axpy_align: // Trim first value(s) in unaligned buffer do { + MOVSS (SI)(AX*4), X2 // X2 = x[i] + MULSS X0, X2 // X2 *= a + ADDSS (DX)(AX*4), X2 // X2 += y[i] + MOVSS X2, (DI)(AX*4) // y[i] = X2 + INCQ AX // i++ + DECQ BX + JZ axpy_end // if --BX == 0 { return } + LOOP axpy_align // } while --CX > 0 + +axpy_no_trim: + MOVUPS X0, X1 // Copy X0 to X1 for pipelining + MOVQ BX, CX + ANDQ $0xF, BX // BX = len % 16 + SHRQ $4, CX // CX = floor( len / 16 ) + JZ axpy_tail4_start // if CX == 0 { return } + +axpy_loop: // Loop unrolled 16x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] + MOVUPS 16(SI)(AX*4), X3 + MOVUPS 32(SI)(AX*4), X4 + MOVUPS 48(SI)(AX*4), X5 + MULPS X0, X2 // X2 *= a + MULPS X1, X3 + MULPS X0, X4 + MULPS X1, X5 + ADDPS (DX)(AX*4), X2 // X2 += y[i:i+4] + ADDPS 16(DX)(AX*4), X3 + ADDPS 32(DX)(AX*4), X4 + ADDPS 48(DX)(AX*4), X5 + MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 + MOVUPS X3, 16(DI)(AX*4) + MOVUPS X4, 32(DI)(AX*4) + MOVUPS X5, 48(DI)(AX*4) + ADDQ $16, AX // i += 16 + LOOP axpy_loop // while (--CX) > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + +axpy_tail4_start: // Reset loop counter for 4-wide tail loop + MOVQ BX, CX // CX = floor( BX / 4 ) + SHRQ $2, CX + JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } + +axpy_tail4: // Loop unrolled 4x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i] + MULPS X0, X2 // X2 *= a + ADDPS (DX)(AX*4), X2 // X2 += y[i] + MOVUPS X2, (DI)(AX*4) // y[i] = X2 + ADDQ $4, AX // i += 4 + LOOP axpy_tail4 // } while --CX > 0 + +axpy_tail_start: // Reset loop counter for 1-wide tail loop + MOVQ BX, CX // CX = BX % 4 + ANDQ $3, CX + JZ axpy_end // if CX == 0 { return } + +axpy_tail: + MOVSS (SI)(AX*4), X1 // X1 = x[i] + MULSS X0, X1 // X1 *= a + ADDSS (DX)(AX*4), X1 // X1 += y[i] + MOVSS X1, (DI)(AX*4) // y[i] = X1 + INCQ AX // i++ + LOOP axpy_tail // } while --CX > 0 + +axpy_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/bench_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/bench_test.go new file mode 100644 index 00000000..a1c415ce --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/bench_test.go @@ -0,0 +1,282 @@ +// Copyright ©2016 The gonum 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 f32 + +import "testing" + +var ( + a = float32(2) + x = make([]float32, 1000000) + y = make([]float32, 1000000) + z = make([]float32, 1000000) +) + +func init() { + for n := range x { + x[n] = float32(n) + y[n] = float32(n) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a float32, x, y []float32)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a float32, x, y []float32) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkF32AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkF32AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkF32AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkF32AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkF32AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkF32AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkF32AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkF32AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLF32AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []float32, a float32, x, y []float32)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []float32, a float32, x, y []float32) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkF32AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLF32AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkF32AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkF32AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLF32AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkF32AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLF32AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ddot.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/ddot.go new file mode 100644 index 00000000..6920f659 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/ddot.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 f32 + +// DdotUnitary is +// for i, v := range x { +// sum += float64(y[i]) * float64(v) +// } +// return +func DdotUnitary(x, y []float32) (sum float64) { + for i, v := range x { + sum += float64(y[i]) * float64(v) + } + return +} + +// DdotInc is +// for i := 0; i < int(n); i++ { +// sum += float64(y[iy]) * float64(x[ix]) +// ix += incX +// iy += incY +// } +// return +func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64) { + for i := 0; i < int(n); i++ { + sum += float64(y[iy]) * float64(x[ix]) + ix += incX + iy += incY + } + return +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go new file mode 100644 index 00000000..89e9c224 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 f32 provides float32 vector primitives. +package f32 // import "gonum.org/v1/gonum/internal/asm/f32" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/dot.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/dot.go new file mode 100644 index 00000000..7a27d35e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/dot.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 f32 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float32) (sum float32) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float32) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go new file mode 100644 index 00000000..c4f61e87 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go @@ -0,0 +1,55 @@ +// Copyright ©2016 The gonum 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 f32 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float32, x []float32) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float32, alpha float32, x []float32) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float32, x []float32, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float32, incDst uintptr, alpha float32, x []float32, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go new file mode 100644 index 00000000..00ad520a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go @@ -0,0 +1,36 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package f32 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float32, x, y []float32) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go new file mode 100644 index 00000000..a6272ea5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f32 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float32, x, y []float32) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_test.go new file mode 100644 index 00000000..df7a1421 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_test.go @@ -0,0 +1,217 @@ +// Copyright ©2015 The gonum 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 f32 + +import ( + "math" + "testing" +) + +var ( + nan = float32(math.NaN()) + inf = float32(math.Inf(1)) +) + +var tests = []struct { + incX, incY, incDst uintptr + ix, iy, idst uintptr + a float32 + dst, x, y []float32 + ex []float32 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 3, + dst: []float32{5}, + x: []float32{2}, + y: []float32{1}, + ex: []float32{7}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 5, + dst: []float32{0, 0, 0}, + x: []float32{0, 0, 0}, + y: []float32{1, 1, 1}, + ex: []float32{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 5, + dst: []float32{0, 0, 0}, + x: []float32{0, 0}, + y: []float32{1, 1, 1}, + ex: []float32{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1, + dst: []float32{-1, -1, -1}, + x: []float32{1, 1, 1}, + y: []float32{1, 2, 1}, + ex: []float32{0, 1, 0}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1, + dst: []float32{1, 1, 1}, + x: []float32{1, 2, 1}, + y: []float32{-1, -2, -1}, + ex: []float32{-2, -4, -2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 2.5, + dst: []float32{1, 1, 1, 1, 1}, + x: []float32{1, 2, 3, 2, 1}, + y: []float32{0, 0, 0, 0, 0}, + ex: []float32{2.5, 5, 7.5, 5, 2.5}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, // Run big test twice, once aligned once unaligned. + a: 16.5, + dst: make([]float32, 20), + x: []float32{.5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5}, + y: []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ex: []float32{9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25, 9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 16.5, + dst: make([]float32, 10), + x: []float32{.5, .5, .5, .5, .5, .5, .5, .5, .5, .5}, + y: []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ex: []float32{9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25}}, +} + +func guardVector(vec []float32, guard_val float32, guard_len int) (guarded []float32) { + guarded = make([]float32, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []float32, guard_val float32, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func same(x, y float32) bool { + a, b := float64(x), float64(y) + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} + +func TestAxpyUnitary(t *testing.T) { + var x_gd, y_gd float32 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if !same(y[i], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + var x_gd, y_gd, dst_gd float32 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + test.dst = guardVector(test.dst, dst_gd, xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if !same(test.ex[i], dst[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + if !isValidGuard(test.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xg_ln], test.dst[len(test.dst)-xg_ln:]) + } + } +} + +func guardIncVector(vec []float32, guard_val float32, incV uintptr, guard_len int) (guarded []float32) { + inc := int(incV) + s_ln := len(vec) * (inc) + guarded = make([]float32, s_ln+guard_len*2) + for i, j := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && j < len(vec): + guarded[i] = vec[j] + j++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []float32, guard_val float32, incV uintptr, guard_len int) { + inc := int(incV) + s_ln := len(vec) - 2*guard_len + for i := range vec { + switch { + case same(vec[i], guard_val): + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +func TestAxpyInc(t *testing.T) { + var x_gd, y_gd float32 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), test.incX, test.incY, test.ix, test.iy) + for i := range test.ex { + if !same(y[i*int(test.incY)], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + } +} + +func TestAxpyIncTo(t *testing.T) { + var x_gd, y_gd, dst_gd float32 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + test.dst = guardIncVector(test.dst, dst_gd, uintptr(test.incDst), xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyIncTo(dst, test.incDst, test.idst, test.a, x, y, uintptr(len(test.ex)), test.incX, test.incY, test.ix, test.iy) + for i := range test.ex { + if !same(dst[i*int(test.incDst)], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + checkValidIncGuard(t, test.dst, dst_gd, uintptr(test.incDst), xg_ln) + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s new file mode 100644 index 00000000..7e7e5d07 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1Norm(x []float64) float64 +TEXT ·L1Norm(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), SI // SI = &x + MOVQ x_len+8(FP), CX // CX = len(x) + XORQ AX, AX // i = 0 + PXOR X0, X0 // p_sum_i = 0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + PXOR X4, X4 + PXOR X5, X5 + PXOR X6, X6 + PXOR X7, X7 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE absum_end + MOVQ CX, BX + ANDQ $7, BX // BX = len(x) % 8 + SHRQ $3, CX // CX = floor( len(x) / 8 ) + JZ absum_tail_start // if CX == 0 { goto absum_tail_start } + +absum_loop: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVUPS (SI)(AX*8), X8 // X_i = x[i:i+1] + MOVUPS 16(SI)(AX*8), X9 + MOVUPS 32(SI)(AX*8), X10 + MOVUPS 48(SI)(AX*8), X11 + ADDPD X8, X0 // p_sum_i += X_i ( positive values ) + ADDPD X9, X2 + ADDPD X10, X4 + ADDPD X11, X6 + SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) + SUBPD X9, X3 + SUBPD X10, X5 + SUBPD X11, X7 + MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) + MAXPD X3, X2 + MAXPD X5, X4 + MAXPD X7, X6 + MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i + MOVAPS X2, X3 + MOVAPS X4, X5 + MOVAPS X6, X7 + ADDQ $8, AX // i += 8 + LOOP absum_loop // } while --CX > 0 + + // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) + ADDPD X3, X0 + ADDPD X5, X7 + ADDPD X7, X0 + + // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] + MOVAPS X0, X1 + SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) + ADDSD X1, X0 + CMPQ BX, $0 + JE absum_end // if BX == 0 { goto absum_end } + +absum_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + XORPS X8, X8 // X_8 = 0 + +absum_tail: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI)(AX*8), X8 // X_8 = x[i] + MOVSD X0, X1 // p_sum_1 = p_sum_0 + ADDSD X8, X0 // p_sum_0 += X_8 + SUBSD X8, X1 // p_sum_1 -= X_8 + MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) + INCQ AX // i++ + LOOP absum_tail // } while --CX > 0 + +absum_end: // return p_sum_0 + MOVSD X0, sum+24(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s new file mode 100644 index 00000000..f4db05bd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s @@ -0,0 +1,90 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1NormInc(x []float64, n, incX int) (sum float64) +TEXT ·L1NormInc(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), SI // SI = &x + MOVQ n+24(FP), CX // CX = n + MOVQ incX+32(FP), AX // AX = increment * sizeof( float64 ) + SHLQ $3, AX + MOVQ AX, DX // DX = AX * 3 + IMULQ $3, DX + PXOR X0, X0 // p_sum_i = 0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + PXOR X4, X4 + PXOR X5, X5 + PXOR X6, X6 + PXOR X7, X7 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE absum_end + MOVQ CX, BX + ANDQ $7, BX // BX = n % 8 + SHRQ $3, CX // CX = floor( n / 8 ) + JZ absum_tail_start // if CX == 0 { goto absum_tail_start } + +absum_loop: // do { + // p_sum = max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI), X8 // X_i[0] = x[i] + MOVSD (SI)(AX*1), X9 + MOVSD (SI)(AX*2), X10 + MOVSD (SI)(DX*1), X11 + LEAQ (SI)(AX*4), SI // SI = SI + 4 + MOVHPD (SI), X8 // X_i[1] = x[i+4] + MOVHPD (SI)(AX*1), X9 + MOVHPD (SI)(AX*2), X10 + MOVHPD (SI)(DX*1), X11 + ADDPD X8, X0 // p_sum_i += X_i ( positive values ) + ADDPD X9, X2 + ADDPD X10, X4 + ADDPD X11, X6 + SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) + SUBPD X9, X3 + SUBPD X10, X5 + SUBPD X11, X7 + MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) + MAXPD X3, X2 + MAXPD X5, X4 + MAXPD X7, X6 + MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i + MOVAPS X2, X3 + MOVAPS X4, X5 + MOVAPS X6, X7 + LEAQ (SI)(AX*4), SI // SI = SI + 4 + LOOP absum_loop // } while --CX > 0 + + // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) + ADDPD X3, X0 + ADDPD X5, X7 + ADDPD X7, X0 + + // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] + MOVAPS X0, X1 + SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) + ADDSD X1, X0 + CMPQ BX, $0 + JE absum_end // if BX == 0 { goto absum_end } + +absum_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + XORPS X8, X8 // X_8 = 0 + +absum_tail: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI), X8 // X_8 = x[i] + MOVSD X0, X1 // p_sum_1 = p_sum_0 + ADDSD X8, X0 // p_sum_0 += X_8 + SUBSD X8, X1 // p_sum_1 -= X_8 + MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) + ADDQ AX, SI // i++ + LOOP absum_tail // } while --CX > 0 + +absum_end: // return p_sum_0 + MOVSD X0, sum+40(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s new file mode 100644 index 00000000..27329699 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s @@ -0,0 +1,66 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Add(dst, s []float64) +TEXT ·Add(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE add_end + XORQ AX, AX + MOVQ DI, BX + ANDQ $0x0F, BX // BX = &dst & 15 + JZ add_no_trim // if BX == 0 { goto add_no_trim } + + // Align on 16-bit boundary + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD (DI)(AX*8), X0 // X0 += dst[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // i++ + DECQ CX // --CX + JE add_end // if CX == 0 { return } + +add_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ add_tail_start // if CX == 0 { goto add_tail_start } + +add_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + ADDPD (DI)(AX*8), X0 // X_i += dst[i:i+1] + ADDPD 16(DI)(AX*8), X1 + ADDPD 32(DI)(AX*8), X2 + ADDPD 48(DI)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X_i + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP add_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE add_end + +add_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +add_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD (DI)(AX*8), X0 // X0 += dst[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + LOOP add_tail // } while --CX > 0 + +add_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s new file mode 100644 index 00000000..88fed071 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Addconst(alpha float64, x []float64) +TEXT ·AddConst(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ x_len+16(FP), CX // CX = len(x) + CMPQ CX, $0 // if len(x) == 0 { return } + JE ac_end + MOVSD alpha+0(FP), X4 // X4 = { a, a } + SHUFPD $0, X4, X4 + MOVUPS X4, X5 // X5 = X4 + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $7, BX // BX = len(x) % 8 + SHRQ $3, CX // CX = floor( len(x) / 8 ) + JZ ac_tail_start // if CX == 0 { goto ac_tail_start } + +ac_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + ADDPD X4, X0 // X_i += a + ADDPD X5, X1 + ADDPD X4, X2 + ADDPD X5, X3 + MOVUPS X0, (SI)(AX*8) // s[i:i+1] = X_i + MOVUPS X1, 16(SI)(AX*8) + MOVUPS X2, 32(SI)(AX*8) + MOVUPS X3, 48(SI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP ac_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE ac_end + +ac_tail_start: // Reset loop counters + MOVQ BX, CX // Loop counter: CX = BX + +ac_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD X4, X0 // X0 += a + MOVSD X0, (SI)(AX*8) // s[i] = X0 + INCQ AX // ++i + LOOP ac_tail // } while --CX > 0 + +ac_end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/asm_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/asm_test.go new file mode 100644 index 00000000..cca86e84 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/asm_test.go @@ -0,0 +1,204 @@ +// Copyright ©2015 The gonum 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 f64 + +import ( + "math" + "math/rand" + "testing" +) + +var ( + nan = math.NaN() + inf = math.Inf(1) +) + +// newGuardedVector allocates a new slice and returns it as three subslices. +// v is a strided vector that contains elements of data at indices i*inc and +// NaN elsewhere. frontGuard and backGuard are filled with NaN values, and +// their backing arrays are directly adjacent to v in memory. The three slices +// can be used to detect invalid memory reads and writes. +func newGuardedVector(data []float64, inc int) (v, frontGuard, backGuard []float64) { + if inc < 0 { + inc = -inc + } + guard := 2 * inc + size := (len(data)-1)*inc + 1 + whole := make([]float64, size+2*guard) + v = whole[guard : len(whole)-guard] + for i := range whole { + whole[i] = math.NaN() + } + for i, d := range data { + v[i*inc] = d + } + return v, whole[:guard], whole[len(whole)-guard:] +} + +// allNaN returns true if x contains only NaN values, and false otherwise. +func allNaN(x []float64) bool { + for _, v := range x { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// equalStrided returns true if the strided vector x contains elements of the +// dense vector ref at indices i*inc, false otherwise. +func equalStrided(ref, x []float64, inc int) bool { + if inc < 0 { + inc = -inc + } + for i, v := range ref { + if !same(x[i*inc], v) { + return false + } + } + return true +} + +// nonStridedWrite returns false if all elements of x at non-stride indices are +// equal to NaN, true otherwise. +func nonStridedWrite(x []float64, inc int) bool { + if inc < 0 { + inc = -inc + } + for i, v := range x { + if i%inc != 0 && !math.IsNaN(v) { + return true + } + } + return false +} + +// guardVector copies the source vector (vec) into a new slice with guards. +// Guards guarded[:gdLn] and guarded[len-gdLn:] will be filled with sigil value gdVal. +func guardVector(vec []float64, gdVal float64, gdLn int) (guarded []float64) { + guarded = make([]float64, len(vec)+gdLn*2) + copy(guarded[gdLn:], vec) + for i := 0; i < gdLn; i++ { + guarded[i] = gdVal + guarded[len(guarded)-1-i] = gdVal + } + return guarded +} + +// isValidGuard will test for violated guards, generated by guardVector. +func isValidGuard(vec []float64, gdVal float64, gdLn int) bool { + for i := 0; i < gdLn; i++ { + if !same(vec[i], gdVal) || !same(vec[len(vec)-1-i], gdVal) { + return false + } + } + return true +} + +// guardIncVector copies the source vector (vec) into a new incremented slice with guards. +// End guards will be length gdLen. +// Internal and end guards will be filled with sigil value gdVal. +func guardIncVector(vec []float64, gdVal float64, inc, gdLen int) (guarded []float64) { + if inc < 0 { + inc = -inc + } + inrLen := len(vec) * inc + guarded = make([]float64, inrLen+gdLen*2) + for i := range guarded { + guarded[i] = gdVal + } + for i, v := range vec { + guarded[gdLen+i*inc] = v + } + return guarded +} + +// checkValidIncGuard will test for violated guards, generated by guardIncVector +func checkValidIncGuard(t *testing.T, vec []float64, gdVal float64, inc, gdLen int) { + srcLn := len(vec) - 2*gdLen + for i := range vec { + switch { + case same(vec[i], gdVal): + // Correct value + case (i-gdLen)%inc == 0 && (i-gdLen)/inc < len(vec): + // Ignore input values + case i < gdLen: + t.Errorf("Front guard violated at %d %v", i, vec[:gdLen]) + case i > gdLen+srcLn: + t.Errorf("Back guard violated at %d %v", i-gdLen-srcLn, vec[gdLen+srcLn:]) + default: + t.Errorf("Internal guard violated at %d %v", i-gdLen, vec[gdLen:gdLen+srcLn]) + } + } +} + +// same tests for nan-aware equality. +func same(a, b float64) bool { + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} + +var ( // Offset sets for testing alignment handling in Unitary assembly functions. + align1 = []int{0, 1} + align2 = newIncSet(0, 1) + align3 = newIncToSet(0, 1) +) + +type incSet struct { + x, y int +} + +// genInc will generate all (x,y) combinations of the input increment set. +func newIncSet(inc ...int) []incSet { + n := len(inc) + is := make([]incSet, n*n) + for x := range inc { + for y := range inc { + is[x*n+y] = incSet{inc[x], inc[y]} + } + } + return is +} + +type incToSet struct { + dst, x, y int +} + +// genIncTo will generate all (dst,x,y) combinations of the input increment set. +func newIncToSet(inc ...int) []incToSet { + n := len(inc) + is := make([]incToSet, n*n*n) + for i, dst := range inc { + for x := range inc { + for y := range inc { + is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]} + } + } + } + return is +} + +var benchSink []float64 + +func randomSlice(n, inc int) []float64 { + if inc < 0 { + inc = -inc + } + x := make([]float64, (n-1)*inc+1) + for i := range x { + x[i] = rand.Float64() + } + return x +} + +func randSlice(n, inc int, r *rand.Rand) []float64 { + if inc < 0 { + inc = -inc + } + x := make([]float64, (n-1)*inc+1) + for i := range x { + x[i] = r.Float64() + } + return x +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go new file mode 100644 index 00000000..455a5d7e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go @@ -0,0 +1,57 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float64, x, y []float64) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy_test.go new file mode 100644 index 00000000..2f096aaf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy_test.go @@ -0,0 +1,274 @@ +// Copyright ©2015 The gonum 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 f64 + +import ( + "fmt" + "testing" +) + +const ( + msgVal = "%v: unexpected value at %v Got: %v Expected: %v" + msgGuard = "%v: Guard violated in %s vector %v %v" +) + +var axpyTests = []struct { + alpha float64 + x []float64 + y []float64 + want []float64 + wantRev []float64 // Result when x is traversed in reverse direction. +}{ + { + alpha: 0, + x: []float64{}, + y: []float64{}, + want: []float64{}, + wantRev: []float64{}, + }, + { + alpha: 0, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-3}, + wantRev: []float64{-3}, + }, + { + alpha: 1, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-1}, + wantRev: []float64{-1}, + }, + { + alpha: 3, + x: []float64{2}, + y: []float64{-3}, + want: []float64{3}, + wantRev: []float64{3}, + }, + { + alpha: -3, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-9}, + wantRev: []float64{-9}, + }, + { + alpha: 1, + x: []float64{1, 5}, + y: []float64{2, -3}, + want: []float64{3, 2}, + wantRev: []float64{7, -2}, + }, + { + alpha: 1, + x: []float64{2, 3, 4}, + y: []float64{-3, -2, -1}, + want: []float64{-1, 1, 3}, + wantRev: []float64{1, 1, 1}, + }, + { + alpha: 0, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 0, 3, -4, 5, -6}, + wantRev: []float64{0, 1, 0, 3, -4, 5, -6}, + }, + { + alpha: 1, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 1, 4, -2, 2, -10}, + wantRev: []float64{-4, -2, 2, 4, -3, 5, -6}, + }, + { + alpha: 3, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 3, 6, 2, -4, -18}, + wantRev: []float64{-12, -8, 6, 6, -1, 5, -6}, + }, + { + alpha: -3, + x: []float64{0, 0, 1, 1, 2, -3, -4, 0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6, 0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, -3, 0, -10, 14, 6, 0, 1, -3, 0, -10, 14, 6}, + wantRev: []float64{12, 10, -6, 0, -7, 5, -6, 12, 10, -6, 0, -7, 5, -6}, + }, + { + alpha: -5, + x: []float64{0, 0, 1, 1, 2, -3, -4, 5, 1, 2, -3, -4, 5}, + y: []float64{0, 1, 0, 3, -4, 5, -6, 7, 3, -4, 5, -6, 7}, + want: []float64{0, 1, -5, -2, -14, 20, 14, -18, -2, -14, 20, 14, -18}, + wantRev: []float64{-25, 21, 15, -7, -9, -20, 14, 22, -7, -9, 0, -6, 7}, + }, +} + +func TestAxpyUnitary(t *testing.T) { + const xGdVal, yGdVal = -1, 0.5 + for i, test := range axpyTests { + for _, align := range align2 { + prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, align.x, align.y) + xgLn, ygLn := 4+align.x, 4+align.y + xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn] + AxpyUnitary(test.alpha, x, y) + for i := range test.want { + if !same(y[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, y[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(yg, yGdVal, ygLn) { + t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5 + for i, test := range axpyTests { + for _, align := range align3 { + prefix := fmt.Sprintf("Test %v (x:%v y:%v dst:%v)", i, align.x, align.y, align.dst) + + dgLn, xgLn, ygLn := 4+align.dst, 4+align.x, 4+align.y + dstOrig := make([]float64, len(test.x)) + xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + dstg := guardVector(dstOrig, dstGdVal, dgLn) + x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn] + dst := dstg[dgLn : len(dstg)-dgLn] + + AxpyUnitaryTo(dst, test.alpha, x, y) + for i := range test.want { + if !same(dst[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(yg, yGdVal, ygLn) { + t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:]) + } + if !isValidGuard(dstg, dstGdVal, dgLn) { + t.Errorf(msgGuard, prefix, "dst", dstg[:dgLn], dstg[len(dstg)-dgLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if !equalStrided(test.y, y, 1) { + t.Errorf("%v: modified read-only y argument", prefix) + } + } + } +} + +func TestAxpyInc(t *testing.T) { + const xGdVal, yGdVal = -1, 0.5 + gdLn := 4 + for i, test := range axpyTests { + n := len(test.x) + for _, inc := range newIncSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) { + var ix, iy int + if inc.x < 0 { + ix = (-n + 1) * inc.x + } + if inc.y < 0 { + iy = (-n + 1) * inc.y + } + prefix := fmt.Sprintf("test %v, inc.x = %v, inc.y = %v", i, inc.x, inc.y) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + yg := guardIncVector(test.y, yGdVal, inc.y, gdLn) + x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn] + + AxpyInc(test.alpha, x, y, uintptr(n), + uintptr(inc.x), uintptr(inc.y), uintptr(ix), uintptr(iy)) + + want := test.want + if inc.x*inc.y < 0 { + want = test.wantRev + } + if inc.y < 0 { + inc.y = -inc.y + } + for i := range want { + if !same(y[i*inc.y], want[i]) { + t.Errorf(msgVal, prefix, i, y[iy+i*inc.y], want[i]) + } + } + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn) + } + } +} + +func TestAxpyIncTo(t *testing.T) { + const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5 + var want []float64 + gdLn := 4 + for i, test := range axpyTests { + n := len(test.x) + for _, inc := range newIncToSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) { + var ix, iy, idst uintptr + if inc.x < 0 { + ix = uintptr((-n + 1) * inc.x) + } + if inc.y < 0 { + iy = uintptr((-n + 1) * inc.y) + } + if inc.dst < 0 { + idst = uintptr((-n + 1) * inc.dst) + } + + prefix := fmt.Sprintf("Test %v: (x: %v, y: %v, dst:%v)", i, inc.x, inc.y, inc.dst) + dstOrig := make([]float64, len(test.want)) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + yg := guardIncVector(test.y, yGdVal, inc.y, gdLn) + dstg := guardIncVector(dstOrig, dstGdVal, inc.dst, gdLn) + x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn] + dst := dstg[gdLn : len(dstg)-gdLn] + + AxpyIncTo(dst, uintptr(inc.dst), idst, + test.alpha, x, y, uintptr(n), + uintptr(inc.x), uintptr(inc.y), ix, iy) + want = test.want + if inc.x*inc.y < 0 { + want = test.wantRev + } + var iW, incW int = 0, 1 + if inc.y*inc.dst < 0 { + iW, incW = len(want)-1, -1 + } + if inc.dst < 0 { + inc.dst = -inc.dst + } + for i := range want { + if !same(dst[i*inc.dst], want[iW+i*incW]) { + t.Errorf(msgVal, prefix, i, dst[i*inc.dst], want[iW+i*incW]) + } + } + + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn) + checkValidIncGuard(t, dstg, dstGdVal, inc.dst, gdLn) + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if !equalStrided(test.y, y, inc.y) { + t.Errorf("%v: modified read-only y argument", prefix) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s new file mode 100644 index 00000000..214f9704 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R11 +#define INC_Y R9 +#define INCx3_Y R12 +#define INC_DST R9 +#define INCx3_DST R12 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ y_base+32(FP), Y_PTR // Y_PTR = &y + MOVQ n+56(FP), LEN // LEN = n + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + + MOVQ ix+80(FP), INC_X + MOVQ iy+88(FP), INC_Y + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(y[iy]) + MOVQ Y_PTR, DST_PTR // DST_PTR = Y_PTR // Write pointer + + MOVQ incX+64(FP), INC_X // INC_X = incX * sizeof(float64) + SHLQ $3, INC_X + MOVQ incY+72(FP), INC_Y // INC_Y = incY * sizeof(float64) + SHLQ $3, INC_Y + + MOVSD alpha+0(FP), ALPHA // ALPHA = alpha + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = n % 4 + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVAPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 + +loop: // do { // y[i] += alpha * x[i] unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + ADDSD (Y_PTR)(INC_Y*2), X4 + ADDSD (Y_PTR)(INCx3_Y*1), X5 + + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset Loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + // y[i] += alpha * x[i] for the last n % 4 iterations. + MOVSD (X_PTR), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[i] + MOVSD X2, (DST_PTR) // y[i] = X2 + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s new file mode 100644 index 00000000..a873b1c9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s @@ -0,0 +1,148 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DX +#define IDX AX +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R11 +#define INC_Y R9 +#define INCx3_Y R12 +#define INC_DST R10 +#define INCx3_DST R13 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst + MOVQ x_base+48(FP), X_PTR // X_PTR := &x + MOVQ y_base+72(FP), Y_PTR // Y_PTR := &y + MOVQ n+96(FP), LEN // LEN := n + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + + MOVQ ix+120(FP), INC_X + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) + MOVQ iy+128(FP), INC_Y + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(dst[idst]) + MOVQ idst+32(FP), INC_DST + LEAQ (DST_PTR)(INC_DST*8), DST_PTR // DST_PTR = &(y[iy]) + + MOVQ incX+104(FP), INC_X // INC_X = incX * sizeof(float64) + SHLQ $3, INC_X + MOVQ incY+112(FP), INC_Y // INC_Y = incY * sizeof(float64) + SHLQ $3, INC_Y + MOVQ incDst+24(FP), INC_DST // INC_DST = incDst * sizeof(float64) + SHLQ $3, INC_DST + MOVSD alpha+40(FP), ALPHA + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = n % 4 + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVSD ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 + LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 + +loop: // do { // y[i] += alpha * x[i] unrolled 2x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + ADDSD (Y_PTR)(INC_Y*2), X4 + ADDSD (Y_PTR)(INCx3_Y*1), X5 + + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) + LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4] + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset Loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) + LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incY*2] + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[i] + MOVSD X2, (DST_PTR) // y[i] = X2 + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s new file mode 100644 index 00000000..668f091e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyUnitary(alpha float64, x, y []float64) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), X_PTR // X_PTR := &x + MOVQ y_base+32(FP), Y_PTR // Y_PTR := &y + MOVQ x_len+16(FP), LEN // LEN = min( len(x), len(y) ) + CMPQ y_len+40(FP), LEN + CMOVQLE y_len+40(FP), LEN + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + XORQ IDX, IDX + MOVSD alpha+0(FP), ALPHA // ALPHA := { alpha, alpha } + SHUFPD $0, ALPHA, ALPHA + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining + MOVQ Y_PTR, TAIL // Check memory alignment + ANDQ $15, TAIL // TAIL = &y % 16 + JZ no_trim // if TAIL == 0 { goto no_trim } + + // Align on 16-byte boundary + MOVSD (X_PTR), X2 // X2 := x[0] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[0] + MOVSD X2, (DST_PTR) // y[0] = X2 + INCQ IDX // i++ + DECQ LEN // LEN-- + JZ end // if LEN == 0 { return } + +no_trim: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL := n % 8 + SHRQ $3, LEN // LEN = floor( n / 8 ) + JZ tail_start // if LEN == 0 { goto tail2_start } + +loop: // do { + // y[i] += alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= a + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] + ADDPD 16(Y_PTR)(IDX*8), X3 + ADDPD 32(Y_PTR)(IDX*8), X4 + ADDPD 48(Y_PTR)(IDX*8), X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if TAIL == 0 { goto tail } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] + MULPD ALPHA, X2 // X2 *= a + ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // } while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s new file mode 100644 index 00000000..03132e9d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s @@ -0,0 +1,140 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DX +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst + MOVQ x_base+32(FP), X_PTR // X_PTR := &x + MOVQ y_base+56(FP), Y_PTR // Y_PTR := &y + MOVQ x_len+40(FP), LEN // LEN = min( len(x), len(y), len(dst) ) + CMPQ y_len+64(FP), LEN + CMOVQLE y_len+64(FP), LEN + CMPQ dst_len+8(FP), LEN + CMOVQLE dst_len+8(FP), LEN + + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + XORQ IDX, IDX // IDX = 0 + MOVSD alpha+24(FP), ALPHA + SHUFPD $0, ALPHA, ALPHA // ALPHA := { alpha, alpha } + MOVQ Y_PTR, TAIL // Check memory alignment + ANDQ $15, TAIL // TAIL = &y % 16 + JZ no_trim // if TAIL == 0 { goto no_trim } + + // Align on 16-byte boundary + MOVSD (X_PTR), X2 // X2 := x[0] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[0] + MOVSD X2, (DST_PTR) // y[0] = X2 + INCQ IDX // i++ + DECQ LEN // LEN-- + JZ end // if LEN == 0 { return } + +no_trim: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL := n % 8 + SHRQ $3, LEN // LEN = floor( n / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining + +loop: // do { + // y[i] += alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= alpha + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] + ADDPD 16(Y_PTR)(IDX*8), X3 + ADDPD 32(Y_PTR)(IDX*8), X4 + ADDPD 48(Y_PTR)(IDX*8), X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if LEN == 0 { goto tail } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] + MULPD ALPHA, X2 // X2 *= alpha + ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // } while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/benchAxpy_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/benchAxpy_test.go new file mode 100644 index 00000000..7bd3dca7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/benchAxpy_test.go @@ -0,0 +1,167 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package f64 + +import ( + "fmt" + "testing" +) + +const ( + testLen = 1e5 +) + +var ( + a = 2.0 + x = make([]float64, testLen) + y = make([]float64, testLen) + z = make([]float64, testLen) +) + +func init() { + for n := range x { + x[n] = float64(n) + y[n] = float64(n) + } +} + +func BenchmarkAxpyUnitary(t *testing.B) { + naiveaxpyu := func(a float64, x, y []float64) { + for i, v := range x { + y[i] += a * v + } + } + tests := []struct { + name string + f func(a float64, x, y []float64) + }{ + {"AxpyUnitary", AxpyUnitary}, + {"NaiveAxpyUnitary", naiveaxpyu}, + } + for _, test := range tests { + for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} { + t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y := x[:ln], y[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + test.f(a, x, y) + } + }) + } + } +} + +func BenchmarkAxpyUnitaryTo(t *testing.B) { + naiveaxpyut := func(d []float64, a float64, x, y []float64) { + for i, v := range x { + d[i] = y[i] + a*v + } + } + tests := []struct { + name string + f func(z []float64, a float64, x, y []float64) + }{ + {"AxpyUnitaryTo", AxpyUnitaryTo}, + {"NaiveAxpyUnitaryTo", naiveaxpyut}, + } + for _, test := range tests { + for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} { + t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y, z := x[:ln], y[:ln], z[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + test.f(z, a, x, y) + } + }) + } + } +} + +var incsAxpy = []struct { + len uintptr + inc []int +}{ + {1, []int{1}}, + {2, []int{1, 2, 4, 10}}, + {3, []int{1, 2, 4, 10}}, + {4, []int{1, 2, 4, 10}}, + {5, []int{1, 2, 4, 10}}, + {10, []int{1, 2, 4, 10}}, + {500, []int{1, 2, 4, 10}}, + {1e3, []int{1, 2, 4, 10}}, + {1e4, []int{1, 2, 4, 10, -1, -2, -4, -10}}, +} + +func BenchmarkAxpyInc(t *testing.B) { + naiveaxpyinc := func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } + } + tests := []struct { + name string + f func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + }{ + {"AxpyInc", AxpyInc}, + {"NaiveAxpyInc", naiveaxpyinc}, + } + for _, test := range tests { + for _, tt := range incsAxpy { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + var idx, tstInc uintptr = 0, uintptr(inc) + if inc < 0 { + idx = uintptr((-int(tt.len) + 1) * inc) + } + for i := 0; i < b.N; i++ { + test.f(a, x, y, uintptr(tt.len), tstInc, tstInc, idx, idx) + } + }) + } + } + } +} + +func BenchmarkAxpyIncTo(t *testing.B) { + naiveaxpyincto := func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } + } + tests := []struct { + name string + f func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + }{ + {"AxpyIncTo", AxpyIncTo}, + {"NaiveAxpyIncTo", naiveaxpyincto}, + } + for _, test := range tests { + for _, tt := range incsAxpy { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + var idx, tstInc uintptr = 0, uintptr(inc) + if inc < 0 { + idx = uintptr((-int(tt.len) + 1) * inc) + } + for i := 0; i < b.N; i++ { + test.f(z, tstInc, idx, a, x, y, uintptr(tt.len), + tstInc, tstInc, idx, idx) + } + }) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/benchScal_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/benchScal_test.go new file mode 100644 index 00000000..b4fb19ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/benchScal_test.go @@ -0,0 +1,87 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package f64 + +import ( + "fmt" + "testing" +) + +var uniScal = []int64{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4} + +func BenchmarkScalUnitary(t *testing.B) { + tstName := "ScalUnitary" + for _, ln := range uniScal { + t.Run(fmt.Sprintf("%s-%d", tstName, ln), func(b *testing.B) { + b.SetBytes(64 * ln) + x := x[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitary(a, x) + } + }) + } +} + +func BenchmarkScalUnitaryTo(t *testing.B) { + tstName := "ScalUnitaryTo" + for _, ln := range uniScal { + t.Run(fmt.Sprintf("%s-%d", tstName, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y := x[:ln], y[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitaryTo(y, a, x) + } + }) + } +} + +var incScal = []struct { + len uintptr + inc []int +}{ + {1, []int{1}}, + {3, []int{1, 2, 4, 10}}, + {10, []int{1, 2, 4, 10}}, + {30, []int{1, 2, 4, 10}}, + {1e2, []int{1, 2, 4, 10}}, + {3e2, []int{1, 2, 4, 10}}, + {1e3, []int{1, 2, 4, 10}}, + {3e3, []int{1, 2, 4, 10}}, + {1e4, []int{1, 2, 4, 10}}, +} + +func BenchmarkScalInc(t *testing.B) { + tstName := "ScalInc" + for _, tt := range incScal { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", tstName, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + tstInc := uintptr(inc) + for i := 0; i < b.N; i++ { + ScalInc(a, x, uintptr(tt.len), tstInc) + } + }) + } + } +} + +func BenchmarkScalIncTo(t *testing.B) { + tstName := "ScalIncTo" + for _, tt := range incScal { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", tstName, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + tstInc := uintptr(inc) + for i := 0; i < b.N; i++ { + ScalIncTo(z, tstInc, a, x, uintptr(tt.len), tstInc) + } + }) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_other_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_other_test.go new file mode 100644 index 00000000..851252ba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_other_test.go @@ -0,0 +1,443 @@ +// Copyright ©2016 The gonum 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 f64 + +import ( + "math" + "testing" +) + +func benchL1Norm(f func(x []float64) float64, sz int, t *testing.B) { + dst := y[:sz] + for i := 0; i < t.N; i++ { + f(dst) + } +} + +var naiveL1Norm = func(x []float64) (sum float64) { + for _, v := range x { + sum += math.Abs(v) + } + return sum +} + +func BenchmarkL1Norm1(t *testing.B) { benchL1Norm(L1Norm, 1, t) } +func BenchmarkL1Norm2(t *testing.B) { benchL1Norm(L1Norm, 2, t) } +func BenchmarkL1Norm3(t *testing.B) { benchL1Norm(L1Norm, 3, t) } +func BenchmarkL1Norm4(t *testing.B) { benchL1Norm(L1Norm, 4, t) } +func BenchmarkL1Norm5(t *testing.B) { benchL1Norm(L1Norm, 5, t) } +func BenchmarkL1Norm10(t *testing.B) { benchL1Norm(L1Norm, 10, t) } +func BenchmarkL1Norm100(t *testing.B) { benchL1Norm(L1Norm, 100, t) } +func BenchmarkL1Norm1000(t *testing.B) { benchL1Norm(L1Norm, 1000, t) } +func BenchmarkL1Norm10000(t *testing.B) { benchL1Norm(L1Norm, 10000, t) } +func BenchmarkL1Norm100000(t *testing.B) { benchL1Norm(L1Norm, 100000, t) } +func BenchmarkL1Norm500000(t *testing.B) { benchL1Norm(L1Norm, 500000, t) } + +func BenchmarkLL1Norm1(t *testing.B) { benchL1Norm(naiveL1Norm, 1, t) } +func BenchmarkLL1Norm2(t *testing.B) { benchL1Norm(naiveL1Norm, 2, t) } +func BenchmarkLL1Norm3(t *testing.B) { benchL1Norm(naiveL1Norm, 3, t) } +func BenchmarkLL1Norm4(t *testing.B) { benchL1Norm(naiveL1Norm, 4, t) } +func BenchmarkLL1Norm5(t *testing.B) { benchL1Norm(naiveL1Norm, 5, t) } +func BenchmarkLL1Norm10(t *testing.B) { benchL1Norm(naiveL1Norm, 10, t) } +func BenchmarkLL1Norm100(t *testing.B) { benchL1Norm(naiveL1Norm, 100, t) } +func BenchmarkLL1Norm1000(t *testing.B) { benchL1Norm(naiveL1Norm, 1000, t) } +func BenchmarkLL1Norm10000(t *testing.B) { benchL1Norm(naiveL1Norm, 10000, t) } +func BenchmarkLL1Norm100000(t *testing.B) { benchL1Norm(naiveL1Norm, 100000, t) } +func BenchmarkLL1Norm500000(t *testing.B) { benchL1Norm(naiveL1Norm, 500000, t) } + +func benchL1NormInc(t *testing.B, ln, inc int, f func(x []float64, n, incX int) float64) { + for i := 0; i < t.N; i++ { + f(x, ln, inc) + } +} + +var naiveL1NormInc = func(x []float64, n, incX int) (sum float64) { + for i := 0; i < n*incX; i += incX { + sum += math.Abs(x[i]) + } + return sum +} + +func BenchmarkF64L1NormIncN1Inc1(b *testing.B) { benchL1NormInc(b, 1, 1, L1NormInc) } + +func BenchmarkF64L1NormIncN2Inc1(b *testing.B) { benchL1NormInc(b, 2, 1, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc2(b *testing.B) { benchL1NormInc(b, 2, 2, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc4(b *testing.B) { benchL1NormInc(b, 2, 4, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc10(b *testing.B) { benchL1NormInc(b, 2, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN3Inc1(b *testing.B) { benchL1NormInc(b, 3, 1, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc2(b *testing.B) { benchL1NormInc(b, 3, 2, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc4(b *testing.B) { benchL1NormInc(b, 3, 4, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc10(b *testing.B) { benchL1NormInc(b, 3, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN4Inc1(b *testing.B) { benchL1NormInc(b, 4, 1, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc2(b *testing.B) { benchL1NormInc(b, 4, 2, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc4(b *testing.B) { benchL1NormInc(b, 4, 4, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc10(b *testing.B) { benchL1NormInc(b, 4, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN10Inc1(b *testing.B) { benchL1NormInc(b, 10, 1, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc2(b *testing.B) { benchL1NormInc(b, 10, 2, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc4(b *testing.B) { benchL1NormInc(b, 10, 4, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc10(b *testing.B) { benchL1NormInc(b, 10, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN1000Inc1(b *testing.B) { benchL1NormInc(b, 1000, 1, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc2(b *testing.B) { benchL1NormInc(b, 1000, 2, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc4(b *testing.B) { benchL1NormInc(b, 1000, 4, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc10(b *testing.B) { benchL1NormInc(b, 1000, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN100000Inc1(b *testing.B) { benchL1NormInc(b, 100000, 1, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc2(b *testing.B) { benchL1NormInc(b, 100000, 2, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc4(b *testing.B) { benchL1NormInc(b, 100000, 4, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc10(b *testing.B) { benchL1NormInc(b, 100000, 10, L1NormInc) } + +func BenchmarkLF64L1NormIncN1Inc1(b *testing.B) { benchL1NormInc(b, 1, 1, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN2Inc1(b *testing.B) { benchL1NormInc(b, 2, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc2(b *testing.B) { benchL1NormInc(b, 2, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc4(b *testing.B) { benchL1NormInc(b, 2, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc10(b *testing.B) { benchL1NormInc(b, 2, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN3Inc1(b *testing.B) { benchL1NormInc(b, 3, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc2(b *testing.B) { benchL1NormInc(b, 3, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc4(b *testing.B) { benchL1NormInc(b, 3, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc10(b *testing.B) { benchL1NormInc(b, 3, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN4Inc1(b *testing.B) { benchL1NormInc(b, 4, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc2(b *testing.B) { benchL1NormInc(b, 4, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc4(b *testing.B) { benchL1NormInc(b, 4, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc10(b *testing.B) { benchL1NormInc(b, 4, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN10Inc1(b *testing.B) { benchL1NormInc(b, 10, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc2(b *testing.B) { benchL1NormInc(b, 10, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc4(b *testing.B) { benchL1NormInc(b, 10, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc10(b *testing.B) { benchL1NormInc(b, 10, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN1000Inc1(b *testing.B) { benchL1NormInc(b, 1000, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc2(b *testing.B) { benchL1NormInc(b, 1000, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc4(b *testing.B) { benchL1NormInc(b, 1000, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc10(b *testing.B) { benchL1NormInc(b, 1000, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN100000Inc1(b *testing.B) { benchL1NormInc(b, 100000, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc2(b *testing.B) { benchL1NormInc(b, 100000, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc4(b *testing.B) { benchL1NormInc(b, 100000, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc10(b *testing.B) { benchL1NormInc(b, 100000, 10, naiveL1NormInc) } + +func benchAdd(f func(dst, s []float64), sz int, t *testing.B) { + dst, s := y[:sz], x[:sz] + for i := 0; i < t.N; i++ { + f(dst, s) + } +} + +var naiveAdd = func(dst, s []float64) { + for i, v := range s { + dst[i] += v + } +} + +func BenchmarkAdd1(t *testing.B) { benchAdd(Add, 1, t) } +func BenchmarkAdd2(t *testing.B) { benchAdd(Add, 2, t) } +func BenchmarkAdd3(t *testing.B) { benchAdd(Add, 3, t) } +func BenchmarkAdd4(t *testing.B) { benchAdd(Add, 4, t) } +func BenchmarkAdd5(t *testing.B) { benchAdd(Add, 5, t) } +func BenchmarkAdd10(t *testing.B) { benchAdd(Add, 10, t) } +func BenchmarkAdd100(t *testing.B) { benchAdd(Add, 100, t) } +func BenchmarkAdd1000(t *testing.B) { benchAdd(Add, 1000, t) } +func BenchmarkAdd10000(t *testing.B) { benchAdd(Add, 10000, t) } +func BenchmarkAdd100000(t *testing.B) { benchAdd(Add, 100000, t) } +func BenchmarkAdd500000(t *testing.B) { benchAdd(Add, 500000, t) } + +func BenchmarkLAdd1(t *testing.B) { benchAdd(naiveAdd, 1, t) } +func BenchmarkLAdd2(t *testing.B) { benchAdd(naiveAdd, 2, t) } +func BenchmarkLAdd3(t *testing.B) { benchAdd(naiveAdd, 3, t) } +func BenchmarkLAdd4(t *testing.B) { benchAdd(naiveAdd, 4, t) } +func BenchmarkLAdd5(t *testing.B) { benchAdd(naiveAdd, 5, t) } +func BenchmarkLAdd10(t *testing.B) { benchAdd(naiveAdd, 10, t) } +func BenchmarkLAdd100(t *testing.B) { benchAdd(naiveAdd, 100, t) } +func BenchmarkLAdd1000(t *testing.B) { benchAdd(naiveAdd, 1000, t) } +func BenchmarkLAdd10000(t *testing.B) { benchAdd(naiveAdd, 10000, t) } +func BenchmarkLAdd100000(t *testing.B) { benchAdd(naiveAdd, 100000, t) } +func BenchmarkLAdd500000(t *testing.B) { benchAdd(naiveAdd, 500000, t) } + +func benchAddConst(f func(a float64, x []float64), sz int, t *testing.B) { + a, x := 1., x[:sz] + for i := 0; i < t.N; i++ { + f(a, x) + } +} + +var naiveAddConst = func(a float64, x []float64) { + for i := range x { + x[i] += a + } +} + +func BenchmarkAddConst1(t *testing.B) { benchAddConst(AddConst, 1, t) } +func BenchmarkAddConst2(t *testing.B) { benchAddConst(AddConst, 2, t) } +func BenchmarkAddConst3(t *testing.B) { benchAddConst(AddConst, 3, t) } +func BenchmarkAddConst4(t *testing.B) { benchAddConst(AddConst, 4, t) } +func BenchmarkAddConst5(t *testing.B) { benchAddConst(AddConst, 5, t) } +func BenchmarkAddConst10(t *testing.B) { benchAddConst(AddConst, 10, t) } +func BenchmarkAddConst100(t *testing.B) { benchAddConst(AddConst, 100, t) } +func BenchmarkAddConst1000(t *testing.B) { benchAddConst(AddConst, 1000, t) } +func BenchmarkAddConst10000(t *testing.B) { benchAddConst(AddConst, 10000, t) } +func BenchmarkAddConst100000(t *testing.B) { benchAddConst(AddConst, 100000, t) } +func BenchmarkAddConst500000(t *testing.B) { benchAddConst(AddConst, 500000, t) } + +func BenchmarkLAddConst1(t *testing.B) { benchAddConst(naiveAddConst, 1, t) } +func BenchmarkLAddConst2(t *testing.B) { benchAddConst(naiveAddConst, 2, t) } +func BenchmarkLAddConst3(t *testing.B) { benchAddConst(naiveAddConst, 3, t) } +func BenchmarkLAddConst4(t *testing.B) { benchAddConst(naiveAddConst, 4, t) } +func BenchmarkLAddConst5(t *testing.B) { benchAddConst(naiveAddConst, 5, t) } +func BenchmarkLAddConst10(t *testing.B) { benchAddConst(naiveAddConst, 10, t) } +func BenchmarkLAddConst100(t *testing.B) { benchAddConst(naiveAddConst, 100, t) } +func BenchmarkLAddConst1000(t *testing.B) { benchAddConst(naiveAddConst, 1000, t) } +func BenchmarkLAddConst10000(t *testing.B) { benchAddConst(naiveAddConst, 10000, t) } +func BenchmarkLAddConst100000(t *testing.B) { benchAddConst(naiveAddConst, 100000, t) } +func BenchmarkLAddConst500000(t *testing.B) { benchAddConst(naiveAddConst, 500000, t) } + +func benchCumSum(f func(a, b []float64) []float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveCumSum = func(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +func BenchmarkCumSum1(t *testing.B) { benchCumSum(CumSum, 1, t) } +func BenchmarkCumSum2(t *testing.B) { benchCumSum(CumSum, 2, t) } +func BenchmarkCumSum3(t *testing.B) { benchCumSum(CumSum, 3, t) } +func BenchmarkCumSum4(t *testing.B) { benchCumSum(CumSum, 4, t) } +func BenchmarkCumSum5(t *testing.B) { benchCumSum(CumSum, 5, t) } +func BenchmarkCumSum10(t *testing.B) { benchCumSum(CumSum, 10, t) } +func BenchmarkCumSum100(t *testing.B) { benchCumSum(CumSum, 100, t) } +func BenchmarkCumSum1000(t *testing.B) { benchCumSum(CumSum, 1000, t) } +func BenchmarkCumSum10000(t *testing.B) { benchCumSum(CumSum, 10000, t) } +func BenchmarkCumSum100000(t *testing.B) { benchCumSum(CumSum, 100000, t) } +func BenchmarkCumSum500000(t *testing.B) { benchCumSum(CumSum, 500000, t) } + +func BenchmarkLCumSum1(t *testing.B) { benchCumSum(naiveCumSum, 1, t) } +func BenchmarkLCumSum2(t *testing.B) { benchCumSum(naiveCumSum, 2, t) } +func BenchmarkLCumSum3(t *testing.B) { benchCumSum(naiveCumSum, 3, t) } +func BenchmarkLCumSum4(t *testing.B) { benchCumSum(naiveCumSum, 4, t) } +func BenchmarkLCumSum5(t *testing.B) { benchCumSum(naiveCumSum, 5, t) } +func BenchmarkLCumSum10(t *testing.B) { benchCumSum(naiveCumSum, 10, t) } +func BenchmarkLCumSum100(t *testing.B) { benchCumSum(naiveCumSum, 100, t) } +func BenchmarkLCumSum1000(t *testing.B) { benchCumSum(naiveCumSum, 1000, t) } +func BenchmarkLCumSum10000(t *testing.B) { benchCumSum(naiveCumSum, 10000, t) } +func BenchmarkLCumSum100000(t *testing.B) { benchCumSum(naiveCumSum, 100000, t) } +func BenchmarkLCumSum500000(t *testing.B) { benchCumSum(naiveCumSum, 500000, t) } + +func benchCumProd(f func(a, b []float64) []float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveCumProd = func(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +func BenchmarkCumProd1(t *testing.B) { benchCumProd(CumProd, 1, t) } +func BenchmarkCumProd2(t *testing.B) { benchCumProd(CumProd, 2, t) } +func BenchmarkCumProd3(t *testing.B) { benchCumProd(CumProd, 3, t) } +func BenchmarkCumProd4(t *testing.B) { benchCumProd(CumProd, 4, t) } +func BenchmarkCumProd5(t *testing.B) { benchCumProd(CumProd, 5, t) } +func BenchmarkCumProd10(t *testing.B) { benchCumProd(CumProd, 10, t) } +func BenchmarkCumProd100(t *testing.B) { benchCumProd(CumProd, 100, t) } +func BenchmarkCumProd1000(t *testing.B) { benchCumProd(CumProd, 1000, t) } +func BenchmarkCumProd10000(t *testing.B) { benchCumProd(CumProd, 10000, t) } +func BenchmarkCumProd100000(t *testing.B) { benchCumProd(CumProd, 100000, t) } +func BenchmarkCumProd500000(t *testing.B) { benchCumProd(CumProd, 500000, t) } + +func BenchmarkLCumProd1(t *testing.B) { benchCumProd(naiveCumProd, 1, t) } +func BenchmarkLCumProd2(t *testing.B) { benchCumProd(naiveCumProd, 2, t) } +func BenchmarkLCumProd3(t *testing.B) { benchCumProd(naiveCumProd, 3, t) } +func BenchmarkLCumProd4(t *testing.B) { benchCumProd(naiveCumProd, 4, t) } +func BenchmarkLCumProd5(t *testing.B) { benchCumProd(naiveCumProd, 5, t) } +func BenchmarkLCumProd10(t *testing.B) { benchCumProd(naiveCumProd, 10, t) } +func BenchmarkLCumProd100(t *testing.B) { benchCumProd(naiveCumProd, 100, t) } +func BenchmarkLCumProd1000(t *testing.B) { benchCumProd(naiveCumProd, 1000, t) } +func BenchmarkLCumProd10000(t *testing.B) { benchCumProd(naiveCumProd, 10000, t) } +func BenchmarkLCumProd100000(t *testing.B) { benchCumProd(naiveCumProd, 100000, t) } +func BenchmarkLCumProd500000(t *testing.B) { benchCumProd(naiveCumProd, 500000, t) } + +func benchDiv(f func(a, b []float64), sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveDiv = func(a, b []float64) { + for i, v := range b { + a[i] /= v + } +} + +func BenchmarkDiv1(t *testing.B) { benchDiv(Div, 1, t) } +func BenchmarkDiv2(t *testing.B) { benchDiv(Div, 2, t) } +func BenchmarkDiv3(t *testing.B) { benchDiv(Div, 3, t) } +func BenchmarkDiv4(t *testing.B) { benchDiv(Div, 4, t) } +func BenchmarkDiv5(t *testing.B) { benchDiv(Div, 5, t) } +func BenchmarkDiv10(t *testing.B) { benchDiv(Div, 10, t) } +func BenchmarkDiv100(t *testing.B) { benchDiv(Div, 100, t) } +func BenchmarkDiv1000(t *testing.B) { benchDiv(Div, 1000, t) } +func BenchmarkDiv10000(t *testing.B) { benchDiv(Div, 10000, t) } +func BenchmarkDiv100000(t *testing.B) { benchDiv(Div, 100000, t) } +func BenchmarkDiv500000(t *testing.B) { benchDiv(Div, 500000, t) } + +func BenchmarkLDiv1(t *testing.B) { benchDiv(naiveDiv, 1, t) } +func BenchmarkLDiv2(t *testing.B) { benchDiv(naiveDiv, 2, t) } +func BenchmarkLDiv3(t *testing.B) { benchDiv(naiveDiv, 3, t) } +func BenchmarkLDiv4(t *testing.B) { benchDiv(naiveDiv, 4, t) } +func BenchmarkLDiv5(t *testing.B) { benchDiv(naiveDiv, 5, t) } +func BenchmarkLDiv10(t *testing.B) { benchDiv(naiveDiv, 10, t) } +func BenchmarkLDiv100(t *testing.B) { benchDiv(naiveDiv, 100, t) } +func BenchmarkLDiv1000(t *testing.B) { benchDiv(naiveDiv, 1000, t) } +func BenchmarkLDiv10000(t *testing.B) { benchDiv(naiveDiv, 10000, t) } +func BenchmarkLDiv100000(t *testing.B) { benchDiv(naiveDiv, 100000, t) } +func BenchmarkLDiv500000(t *testing.B) { benchDiv(naiveDiv, 500000, t) } + +func benchDivTo(f func(dst, a, b []float64) []float64, sz int, t *testing.B) { + dst, a, b := z[:sz], x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(dst, a, b) + } +} + +var naiveDivTo = func(dst, s, t []float64) []float64 { + for i, v := range s { + dst[i] = v / t[i] + } + return dst +} + +func BenchmarkDivTo1(t *testing.B) { benchDivTo(DivTo, 1, t) } +func BenchmarkDivTo2(t *testing.B) { benchDivTo(DivTo, 2, t) } +func BenchmarkDivTo3(t *testing.B) { benchDivTo(DivTo, 3, t) } +func BenchmarkDivTo4(t *testing.B) { benchDivTo(DivTo, 4, t) } +func BenchmarkDivTo5(t *testing.B) { benchDivTo(DivTo, 5, t) } +func BenchmarkDivTo10(t *testing.B) { benchDivTo(DivTo, 10, t) } +func BenchmarkDivTo100(t *testing.B) { benchDivTo(DivTo, 100, t) } +func BenchmarkDivTo1000(t *testing.B) { benchDivTo(DivTo, 1000, t) } +func BenchmarkDivTo10000(t *testing.B) { benchDivTo(DivTo, 10000, t) } +func BenchmarkDivTo100000(t *testing.B) { benchDivTo(DivTo, 100000, t) } +func BenchmarkDivTo500000(t *testing.B) { benchDivTo(DivTo, 500000, t) } + +func BenchmarkLDivTo1(t *testing.B) { benchDivTo(naiveDivTo, 1, t) } +func BenchmarkLDivTo2(t *testing.B) { benchDivTo(naiveDivTo, 2, t) } +func BenchmarkLDivTo3(t *testing.B) { benchDivTo(naiveDivTo, 3, t) } +func BenchmarkLDivTo4(t *testing.B) { benchDivTo(naiveDivTo, 4, t) } +func BenchmarkLDivTo5(t *testing.B) { benchDivTo(naiveDivTo, 5, t) } +func BenchmarkLDivTo10(t *testing.B) { benchDivTo(naiveDivTo, 10, t) } +func BenchmarkLDivTo100(t *testing.B) { benchDivTo(naiveDivTo, 100, t) } +func BenchmarkLDivTo1000(t *testing.B) { benchDivTo(naiveDivTo, 1000, t) } +func BenchmarkLDivTo10000(t *testing.B) { benchDivTo(naiveDivTo, 10000, t) } +func BenchmarkLDivTo100000(t *testing.B) { benchDivTo(naiveDivTo, 100000, t) } +func BenchmarkLDivTo500000(t *testing.B) { benchDivTo(naiveDivTo, 500000, t) } + +func benchL1Dist(f func(a, b []float64) float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveL1Dist = func(s, t []float64) float64 { + var norm float64 + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm +} + +func BenchmarkL1Dist1(t *testing.B) { benchL1Dist(L1Dist, 1, t) } +func BenchmarkL1Dist2(t *testing.B) { benchL1Dist(L1Dist, 2, t) } +func BenchmarkL1Dist3(t *testing.B) { benchL1Dist(L1Dist, 3, t) } +func BenchmarkL1Dist4(t *testing.B) { benchL1Dist(L1Dist, 4, t) } +func BenchmarkL1Dist5(t *testing.B) { benchL1Dist(L1Dist, 5, t) } +func BenchmarkL1Dist10(t *testing.B) { benchL1Dist(L1Dist, 10, t) } +func BenchmarkL1Dist100(t *testing.B) { benchL1Dist(L1Dist, 100, t) } +func BenchmarkL1Dist1000(t *testing.B) { benchL1Dist(L1Dist, 1000, t) } +func BenchmarkL1Dist10000(t *testing.B) { benchL1Dist(L1Dist, 10000, t) } +func BenchmarkL1Dist100000(t *testing.B) { benchL1Dist(L1Dist, 100000, t) } +func BenchmarkL1Dist500000(t *testing.B) { benchL1Dist(L1Dist, 500000, t) } + +func BenchmarkLL1Dist1(t *testing.B) { benchL1Dist(naiveL1Dist, 1, t) } +func BenchmarkLL1Dist2(t *testing.B) { benchL1Dist(naiveL1Dist, 2, t) } +func BenchmarkLL1Dist3(t *testing.B) { benchL1Dist(naiveL1Dist, 3, t) } +func BenchmarkLL1Dist4(t *testing.B) { benchL1Dist(naiveL1Dist, 4, t) } +func BenchmarkLL1Dist5(t *testing.B) { benchL1Dist(naiveL1Dist, 5, t) } +func BenchmarkLL1Dist10(t *testing.B) { benchL1Dist(naiveL1Dist, 10, t) } +func BenchmarkLL1Dist100(t *testing.B) { benchL1Dist(naiveL1Dist, 100, t) } +func BenchmarkLL1Dist1000(t *testing.B) { benchL1Dist(naiveL1Dist, 1000, t) } +func BenchmarkLL1Dist10000(t *testing.B) { benchL1Dist(naiveL1Dist, 10000, t) } +func BenchmarkLL1Dist100000(t *testing.B) { benchL1Dist(naiveL1Dist, 100000, t) } +func BenchmarkLL1Dist500000(t *testing.B) { benchL1Dist(naiveL1Dist, 500000, t) } + +func benchLinfDist(f func(a, b []float64) float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveLinfDist = func(s, t []float64) float64 { + var norm float64 + if len(s) == 0 { + return 0 + } + norm = math.Abs(t[0] - s[0]) + for i, v := range s[1:] { + absDiff := math.Abs(t[i+1] - v) + if absDiff > norm || math.IsNaN(norm) { + norm = absDiff + } + } + return norm +} + +func BenchmarkLinfDist1(t *testing.B) { benchLinfDist(LinfDist, 1, t) } +func BenchmarkLinfDist2(t *testing.B) { benchLinfDist(LinfDist, 2, t) } +func BenchmarkLinfDist3(t *testing.B) { benchLinfDist(LinfDist, 3, t) } +func BenchmarkLinfDist4(t *testing.B) { benchLinfDist(LinfDist, 4, t) } +func BenchmarkLinfDist5(t *testing.B) { benchLinfDist(LinfDist, 5, t) } +func BenchmarkLinfDist10(t *testing.B) { benchLinfDist(LinfDist, 10, t) } +func BenchmarkLinfDist100(t *testing.B) { benchLinfDist(LinfDist, 100, t) } +func BenchmarkLinfDist1000(t *testing.B) { benchLinfDist(LinfDist, 1000, t) } +func BenchmarkLinfDist10000(t *testing.B) { benchLinfDist(LinfDist, 10000, t) } +func BenchmarkLinfDist100000(t *testing.B) { benchLinfDist(LinfDist, 100000, t) } +func BenchmarkLinfDist500000(t *testing.B) { benchLinfDist(LinfDist, 500000, t) } + +func BenchmarkLLinfDist1(t *testing.B) { benchLinfDist(naiveLinfDist, 1, t) } +func BenchmarkLLinfDist2(t *testing.B) { benchLinfDist(naiveLinfDist, 2, t) } +func BenchmarkLLinfDist3(t *testing.B) { benchLinfDist(naiveLinfDist, 3, t) } +func BenchmarkLLinfDist4(t *testing.B) { benchLinfDist(naiveLinfDist, 4, t) } +func BenchmarkLLinfDist5(t *testing.B) { benchLinfDist(naiveLinfDist, 5, t) } +func BenchmarkLLinfDist10(t *testing.B) { benchLinfDist(naiveLinfDist, 10, t) } +func BenchmarkLLinfDist100(t *testing.B) { benchLinfDist(naiveLinfDist, 100, t) } +func BenchmarkLLinfDist1000(t *testing.B) { benchLinfDist(naiveLinfDist, 1000, t) } +func BenchmarkLLinfDist10000(t *testing.B) { benchLinfDist(naiveLinfDist, 10000, t) } +func BenchmarkLLinfDist100000(t *testing.B) { benchLinfDist(naiveLinfDist, 100000, t) } +func BenchmarkLLinfDist500000(t *testing.B) { benchLinfDist(naiveLinfDist, 500000, t) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_test.go new file mode 100644 index 00000000..78d26d77 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/bench_test.go @@ -0,0 +1,438 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +package f64 + +import ( + "math/rand" + "testing" +) + +var ( + a = float64(2) + x = make([]float64, 1000000) + y = make([]float64, 1000000) + z = make([]float64, 1000000) +) + +func init() { + for n := range x { + x[n] = float64(n) + y[n] = float64(n) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a float64, x, y []float64)) { + x, y := x[:n], y[:n] + + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a float64, x, y []float64) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkF64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkF64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkF64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkF64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkF64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkF64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkF64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkF64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLF64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []float64, a float64, x, y []float64)) { + x, y, z := x[:n], y[:n], z[:n] + + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []float64, a float64, x, y []float64) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkF64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLF64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + + for i := 0; i < t.N; i++ { + f(1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkF64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkF64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLF64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkF64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLF64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } + +// Scal* benchmarks +func BenchmarkDscalUnitaryN1(b *testing.B) { benchmarkDscalUnitary(b, 1) } +func BenchmarkDscalUnitaryN2(b *testing.B) { benchmarkDscalUnitary(b, 2) } +func BenchmarkDscalUnitaryN3(b *testing.B) { benchmarkDscalUnitary(b, 3) } +func BenchmarkDscalUnitaryN4(b *testing.B) { benchmarkDscalUnitary(b, 4) } +func BenchmarkDscalUnitaryN10(b *testing.B) { benchmarkDscalUnitary(b, 10) } +func BenchmarkDscalUnitaryN100(b *testing.B) { benchmarkDscalUnitary(b, 100) } +func BenchmarkDscalUnitaryN1000(b *testing.B) { benchmarkDscalUnitary(b, 1000) } +func BenchmarkDscalUnitaryN10000(b *testing.B) { benchmarkDscalUnitary(b, 10000) } +func BenchmarkDscalUnitaryN100000(b *testing.B) { benchmarkDscalUnitary(b, 100000) } + +func benchmarkDscalUnitary(b *testing.B, n int) { + x := randomSlice(n, 1) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalUnitary(2, x) + ScalUnitary(0.5, x) + } + benchSink = x +} + +func BenchmarkDscalUnitaryToN1(b *testing.B) { benchmarkDscalUnitaryTo(b, 1) } +func BenchmarkDscalUnitaryToN2(b *testing.B) { benchmarkDscalUnitaryTo(b, 2) } +func BenchmarkDscalUnitaryToN3(b *testing.B) { benchmarkDscalUnitaryTo(b, 3) } +func BenchmarkDscalUnitaryToN4(b *testing.B) { benchmarkDscalUnitaryTo(b, 4) } +func BenchmarkDscalUnitaryToN10(b *testing.B) { benchmarkDscalUnitaryTo(b, 10) } +func BenchmarkDscalUnitaryToN100(b *testing.B) { benchmarkDscalUnitaryTo(b, 100) } +func BenchmarkDscalUnitaryToN1000(b *testing.B) { benchmarkDscalUnitaryTo(b, 1000) } +func BenchmarkDscalUnitaryToN10000(b *testing.B) { benchmarkDscalUnitaryTo(b, 10000) } +func BenchmarkDscalUnitaryToN100000(b *testing.B) { benchmarkDscalUnitaryTo(b, 100000) } + +func benchmarkDscalUnitaryTo(b *testing.B, n int) { + x := randomSlice(n, 1) + dst := randomSlice(n, 1) + a := rand.Float64() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitaryTo(dst, a, x) + } + benchSink = dst +} + +func BenchmarkDscalUnitaryToXN1(b *testing.B) { benchmarkDscalUnitaryToX(b, 1) } +func BenchmarkDscalUnitaryToXN2(b *testing.B) { benchmarkDscalUnitaryToX(b, 2) } +func BenchmarkDscalUnitaryToXN3(b *testing.B) { benchmarkDscalUnitaryToX(b, 3) } +func BenchmarkDscalUnitaryToXN4(b *testing.B) { benchmarkDscalUnitaryToX(b, 4) } +func BenchmarkDscalUnitaryToXN10(b *testing.B) { benchmarkDscalUnitaryToX(b, 10) } +func BenchmarkDscalUnitaryToXN100(b *testing.B) { benchmarkDscalUnitaryToX(b, 100) } +func BenchmarkDscalUnitaryToXN1000(b *testing.B) { benchmarkDscalUnitaryToX(b, 1000) } +func BenchmarkDscalUnitaryToXN10000(b *testing.B) { benchmarkDscalUnitaryToX(b, 10000) } +func BenchmarkDscalUnitaryToXN100000(b *testing.B) { benchmarkDscalUnitaryToX(b, 100000) } + +func benchmarkDscalUnitaryToX(b *testing.B, n int) { + x := randomSlice(n, 1) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalUnitaryTo(x, 2, x) + ScalUnitaryTo(x, 0.5, x) + } + benchSink = x +} + +func BenchmarkDscalIncN1Inc1(b *testing.B) { benchmarkDscalInc(b, 1, 1) } + +func BenchmarkDscalIncN2Inc1(b *testing.B) { benchmarkDscalInc(b, 2, 1) } +func BenchmarkDscalIncN2Inc2(b *testing.B) { benchmarkDscalInc(b, 2, 2) } +func BenchmarkDscalIncN2Inc4(b *testing.B) { benchmarkDscalInc(b, 2, 4) } +func BenchmarkDscalIncN2Inc10(b *testing.B) { benchmarkDscalInc(b, 2, 10) } + +func BenchmarkDscalIncN3Inc1(b *testing.B) { benchmarkDscalInc(b, 3, 1) } +func BenchmarkDscalIncN3Inc2(b *testing.B) { benchmarkDscalInc(b, 3, 2) } +func BenchmarkDscalIncN3Inc4(b *testing.B) { benchmarkDscalInc(b, 3, 4) } +func BenchmarkDscalIncN3Inc10(b *testing.B) { benchmarkDscalInc(b, 3, 10) } + +func BenchmarkDscalIncN4Inc1(b *testing.B) { benchmarkDscalInc(b, 4, 1) } +func BenchmarkDscalIncN4Inc2(b *testing.B) { benchmarkDscalInc(b, 4, 2) } +func BenchmarkDscalIncN4Inc4(b *testing.B) { benchmarkDscalInc(b, 4, 4) } +func BenchmarkDscalIncN4Inc10(b *testing.B) { benchmarkDscalInc(b, 4, 10) } + +func BenchmarkDscalIncN10Inc1(b *testing.B) { benchmarkDscalInc(b, 10, 1) } +func BenchmarkDscalIncN10Inc2(b *testing.B) { benchmarkDscalInc(b, 10, 2) } +func BenchmarkDscalIncN10Inc4(b *testing.B) { benchmarkDscalInc(b, 10, 4) } +func BenchmarkDscalIncN10Inc10(b *testing.B) { benchmarkDscalInc(b, 10, 10) } + +func BenchmarkDscalIncN1000Inc1(b *testing.B) { benchmarkDscalInc(b, 1000, 1) } +func BenchmarkDscalIncN1000Inc2(b *testing.B) { benchmarkDscalInc(b, 1000, 2) } +func BenchmarkDscalIncN1000Inc4(b *testing.B) { benchmarkDscalInc(b, 1000, 4) } +func BenchmarkDscalIncN1000Inc10(b *testing.B) { benchmarkDscalInc(b, 1000, 10) } + +func BenchmarkDscalIncN100000Inc1(b *testing.B) { benchmarkDscalInc(b, 100000, 1) } +func BenchmarkDscalIncN100000Inc2(b *testing.B) { benchmarkDscalInc(b, 100000, 2) } +func BenchmarkDscalIncN100000Inc4(b *testing.B) { benchmarkDscalInc(b, 100000, 4) } +func BenchmarkDscalIncN100000Inc10(b *testing.B) { benchmarkDscalInc(b, 100000, 10) } + +func benchmarkDscalInc(b *testing.B, n, inc int) { + x := randomSlice(n, inc) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalInc(2, x, uintptr(n), uintptr(inc)) + ScalInc(0.5, x, uintptr(n), uintptr(inc)) + } + benchSink = x +} + +func BenchmarkDscalIncToN1Inc1(b *testing.B) { benchmarkDscalIncTo(b, 1, 1) } + +func BenchmarkDscalIncToN2Inc1(b *testing.B) { benchmarkDscalIncTo(b, 2, 1) } +func BenchmarkDscalIncToN2Inc2(b *testing.B) { benchmarkDscalIncTo(b, 2, 2) } +func BenchmarkDscalIncToN2Inc4(b *testing.B) { benchmarkDscalIncTo(b, 2, 4) } +func BenchmarkDscalIncToN2Inc10(b *testing.B) { benchmarkDscalIncTo(b, 2, 10) } + +func BenchmarkDscalIncToN3Inc1(b *testing.B) { benchmarkDscalIncTo(b, 3, 1) } +func BenchmarkDscalIncToN3Inc2(b *testing.B) { benchmarkDscalIncTo(b, 3, 2) } +func BenchmarkDscalIncToN3Inc4(b *testing.B) { benchmarkDscalIncTo(b, 3, 4) } +func BenchmarkDscalIncToN3Inc10(b *testing.B) { benchmarkDscalIncTo(b, 3, 10) } + +func BenchmarkDscalIncToN4Inc1(b *testing.B) { benchmarkDscalIncTo(b, 4, 1) } +func BenchmarkDscalIncToN4Inc2(b *testing.B) { benchmarkDscalIncTo(b, 4, 2) } +func BenchmarkDscalIncToN4Inc4(b *testing.B) { benchmarkDscalIncTo(b, 4, 4) } +func BenchmarkDscalIncToN4Inc10(b *testing.B) { benchmarkDscalIncTo(b, 4, 10) } + +func BenchmarkDscalIncToN10Inc1(b *testing.B) { benchmarkDscalIncTo(b, 10, 1) } +func BenchmarkDscalIncToN10Inc2(b *testing.B) { benchmarkDscalIncTo(b, 10, 2) } +func BenchmarkDscalIncToN10Inc4(b *testing.B) { benchmarkDscalIncTo(b, 10, 4) } +func BenchmarkDscalIncToN10Inc10(b *testing.B) { benchmarkDscalIncTo(b, 10, 10) } + +func BenchmarkDscalIncToN1000Inc1(b *testing.B) { benchmarkDscalIncTo(b, 1000, 1) } +func BenchmarkDscalIncToN1000Inc2(b *testing.B) { benchmarkDscalIncTo(b, 1000, 2) } +func BenchmarkDscalIncToN1000Inc4(b *testing.B) { benchmarkDscalIncTo(b, 1000, 4) } +func BenchmarkDscalIncToN1000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 1000, 10) } + +func BenchmarkDscalIncToN100000Inc1(b *testing.B) { benchmarkDscalIncTo(b, 100000, 1) } +func BenchmarkDscalIncToN100000Inc2(b *testing.B) { benchmarkDscalIncTo(b, 100000, 2) } +func BenchmarkDscalIncToN100000Inc4(b *testing.B) { benchmarkDscalIncTo(b, 100000, 4) } +func BenchmarkDscalIncToN100000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 100000, 10) } + +func benchmarkDscalIncTo(b *testing.B, n, inc int) { + x := randomSlice(n, inc) + dst := randomSlice(n, inc) + a := rand.Float64() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalIncTo(dst, uintptr(inc), a, x, uintptr(n), uintptr(inc)) + } + benchSink = dst +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s new file mode 100644 index 00000000..3d438093 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s @@ -0,0 +1,71 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +TEXT ·CumProd(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + MOVQ CX, ret_len+56(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE cp_end + XORQ AX, AX // i = 0 + + MOVSD (SI), X5 // p_prod = { s[0], s[0] } + SHUFPD $0, X5, X5 + MOVSD X5, (DI) // dst[0] = s[0] + INCQ AX // ++i + DECQ CX // -- CX + JZ cp_end // if CX == 0 { return } + + MOVQ CX, BX + ANDQ $3, BX // BX = CX % 4 + SHRQ $2, CX // CX = floor( CX / 4 ) + JZ cp_tail_start // if CX == 0 { goto cp_tail_start } + +cp_loop: // Loop unrolled 4x do { + MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] + MOVUPS 16(SI)(AX*8), X2 + MOVAPS X0, X1 // X1 = X0 + MOVAPS X2, X3 + SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } + SHUFPD $1, X3, X3 + MULPD X0, X1 // X1 *= X0 + MULPD X2, X3 + SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } + SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } + SHUFPD $2, X3, X2 + SHUFPD $3, X3, X3 + MULPD X5, X0 // X0 *= p_prod + MULPD X1, X5 // p_prod *= X1 + MULPD X5, X2 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X2, 16(DI)(AX*8) + MULPD X3, X5 + ADDQ $4, AX // i += 4 + LOOP cp_loop // } while --CX > 0 + + // if BX == 0 { return } + CMPQ BX, $0 + JE cp_end + +cp_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +cp_tail: // do { + MULSD (SI)(AX*8), X5 // p_prod *= s[i] + MOVSD X5, (DI)(AX*8) // dst[i] = p_prod + INCQ AX // ++i + LOOP cp_tail // } while --CX > 0 + +cp_end: + MOVQ DI, ret_base+48(FP) // &ret = &dst + MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) + MOVQ SI, ret_cap+64(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s new file mode 100644 index 00000000..eecfbbe1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s @@ -0,0 +1,64 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +TEXT ·CumSum(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + MOVQ CX, ret_len+56(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE cs_end + XORQ AX, AX // i = 0 + PXOR X5, X5 // p_sum = 0 + MOVQ CX, BX + ANDQ $3, BX // BX = CX % 4 + SHRQ $2, CX // CX = floor( CX / 4 ) + JZ cs_tail_start // if CX == 0 { goto cs_tail_start } + +cs_loop: // Loop unrolled 4x do { + MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] + MOVUPS 16(SI)(AX*8), X2 + MOVAPS X0, X1 // X1 = X0 + MOVAPS X2, X3 + SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } + SHUFPD $1, X3, X3 + ADDPD X0, X1 // X1 += X0 + ADDPD X2, X3 + SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } + SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } + SHUFPD $2, X3, X2 + SHUFPD $3, X3, X3 + ADDPD X5, X0 // X0 += p_sum + ADDPD X1, X5 // p_sum += X1 + ADDPD X5, X2 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X2, 16(DI)(AX*8) + ADDPD X3, X5 + ADDQ $4, AX // i += 4 + LOOP cs_loop // } while --CX > 0 + + // if BX == 0 { return } + CMPQ BX, $0 + JE cs_end + +cs_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +cs_tail: // do { + ADDSD (SI)(AX*8), X5 // p_sum *= s[i] + MOVSD X5, (DI)(AX*8) // dst[i] = p_sum + INCQ AX // ++i + LOOP cs_tail // } while --CX > 0 + +cs_end: + MOVQ DI, ret_base+48(FP) // &ret = &dst + MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) + MOVQ SI, ret_cap+64(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s new file mode 100644 index 00000000..da417708 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s @@ -0,0 +1,67 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Div(dst, s []float64) +TEXT ·Div(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE div_end + XORQ AX, AX // i = 0 + MOVQ SI, BX + ANDQ $15, BX // BX = &s & 15 + JZ div_no_trim // if BX == 0 { goto div_no_trim } + + // Align on 16-bit boundary + MOVSD (DI)(AX*8), X0 // X0 = dst[i] + DIVSD (SI)(AX*8), X0 // X0 /= s[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + DECQ CX // --CX + JZ div_end // if CX == 0 { return } + +div_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ div_tail_start // if CX == 0 { goto div_tail_start } + +div_loop: // Loop unrolled 8x do { + MOVUPS (DI)(AX*8), X0 // X0 = dst[i:i+1] + MOVUPS 16(DI)(AX*8), X1 + MOVUPS 32(DI)(AX*8), X2 + MOVUPS 48(DI)(AX*8), X3 + DIVPD (SI)(AX*8), X0 // X0 /= s[i:i+1] + DIVPD 16(SI)(AX*8), X1 + DIVPD 32(SI)(AX*8), X2 + DIVPD 48(SI)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP div_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE div_end + +div_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +div_tail: // do { + MOVSD (DI)(AX*8), X0 // X0 = dst[i] + DIVSD (SI)(AX*8), X0 // X0 /= s[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + LOOP div_tail // } while --CX > 0 + +div_end: + RET + diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s new file mode 100644 index 00000000..6280aab4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func DivTo(dst, x, y []float64) +TEXT ·DivTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ x_base+24(FP), SI // SI = &x + MOVQ y_base+48(FP), DX // DX = &y + CMPQ x_len+32(FP), CX // CX = max( len(dst), len(x), len(y) ) + CMOVQLE x_len+32(FP), CX + CMPQ y_len+56(FP), CX + CMOVQLE y_len+56(FP), CX + MOVQ CX, ret_len+80(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE div_end + XORQ AX, AX // i = 0 + MOVQ DX, BX + ANDQ $15, BX // BX = &y & OxF + JZ div_no_trim // if BX == 0 { goto div_no_trim } + + // Align on 16-bit boundary + MOVSD (SI)(AX*8), X0 // X0 = s[i] + DIVSD (DX)(AX*8), X0 // X0 /= t[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + DECQ CX // --CX + JZ div_end // if CX == 0 { return } + +div_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ div_tail_start // if CX == 0 { goto div_tail_start } + +div_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X0 = x[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + DIVPD (DX)(AX*8), X0 // X0 /= y[i:i+1] + DIVPD 16(DX)(AX*8), X1 + DIVPD 32(DX)(AX*8), X2 + DIVPD 48(DX)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X0 + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP div_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE div_end + +div_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +div_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = x[i] + DIVSD (DX)(AX*8), X0 // X0 /= y[i] + MOVSD X0, (DI)(AX*8) + INCQ AX // ++i + LOOP div_tail // } while --CX > 0 + +div_end: + MOVQ DI, ret_base+72(FP) // &ret = &dst + MOVQ dst_cap+16(FP), DI // cap(ret) = cap(dst) + MOVQ DI, ret_cap+88(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go new file mode 100644 index 00000000..5b562b57 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 f64 provides float64 vector primitives. +package f64 // import "gonum.org/v1/gonum/internal/asm/f64" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go new file mode 100644 index 00000000..7b86b5b4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go @@ -0,0 +1,35 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float64) (sum float64) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s new file mode 100644 index 00000000..02e654d5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s @@ -0,0 +1,145 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func DdotUnitary(x, y []float64) (sum float64) +// This function assumes len(y) >= len(x). +TEXT ·DotUnitary(SB), NOSPLIT, $0 + MOVQ x+0(FP), R8 + MOVQ x_len+8(FP), DI // n = len(x) + MOVQ y+24(FP), R9 + + MOVSD $(0.0), X7 // sum = 0 + MOVSD $(0.0), X8 // sum = 0 + + MOVQ $0, SI // i = 0 + SUBQ $4, DI // n -= 4 + JL tail_uni // if n < 0 goto tail_uni + +loop_uni: + // sum += x[i] * y[i] unrolled 4x. + MOVUPD 0(R8)(SI*8), X0 + MOVUPD 0(R9)(SI*8), X1 + MOVUPD 16(R8)(SI*8), X2 + MOVUPD 16(R9)(SI*8), X3 + MULPD X1, X0 + MULPD X3, X2 + ADDPD X0, X7 + ADDPD X2, X8 + + ADDQ $4, SI // i += 4 + SUBQ $4, DI // n -= 4 + JGE loop_uni // if n >= 0 goto loop_uni + +tail_uni: + ADDQ $4, DI // n += 4 + JLE end_uni // if n <= 0 goto end_uni + +onemore_uni: + // sum += x[i] * y[i] for the remaining 1-3 elements. + MOVSD 0(R8)(SI*8), X0 + MOVSD 0(R9)(SI*8), X1 + MULSD X1, X0 + ADDSD X0, X7 + + ADDQ $1, SI // i++ + SUBQ $1, DI // n-- + JNZ onemore_uni // if n != 0 goto onemore_uni + +end_uni: + // Add the four sums together. + ADDPD X8, X7 + MOVSD X7, X0 + UNPCKHPD X7, X7 + ADDSD X0, X7 + MOVSD X7, sum+48(FP) // Return final sum. + RET + +// func DdotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) +TEXT ·DotInc(SB), NOSPLIT, $0 + MOVQ x+0(FP), R8 + MOVQ y+24(FP), R9 + MOVQ n+48(FP), CX + MOVQ incX+56(FP), R11 + MOVQ incY+64(FP), R12 + MOVQ ix+72(FP), R13 + MOVQ iy+80(FP), R14 + + MOVSD $(0.0), X7 // sum = 0 + LEAQ (R8)(R13*8), SI // p = &x[ix] + LEAQ (R9)(R14*8), DI // q = &y[ix] + SHLQ $3, R11 // incX *= sizeof(float64) + SHLQ $3, R12 // indY *= sizeof(float64) + + SUBQ $2, CX // n -= 2 + JL tail_inc // if n < 0 goto tail_inc + +loop_inc: + // sum += *p * *q unrolled 2x. + MOVHPD (SI), X0 + MOVHPD (DI), X1 + ADDQ R11, SI // p += incX + ADDQ R12, DI // q += incY + MOVLPD (SI), X0 + MOVLPD (DI), X1 + ADDQ R11, SI // p += incX + ADDQ R12, DI // q += incY + + MULPD X1, X0 + ADDPD X0, X7 + + SUBQ $2, CX // n -= 2 + JGE loop_inc // if n >= 0 goto loop_inc + +tail_inc: + ADDQ $2, CX // n += 2 + JLE end_inc // if n <= 0 goto end_inc + + // sum += *p * *q for the last iteration if n is odd. + MOVSD (SI), X0 + MULSD (DI), X0 + ADDSD X0, X7 + +end_inc: + // Add the two sums together. + MOVSD X7, X0 + UNPCKHPD X7, X7 + ADDSD X0, X7 + MOVSD X7, sum+88(FP) // Return final sum. + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_test.go new file mode 100644 index 00000000..5ca88b8b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_test.go @@ -0,0 +1,280 @@ +// Copyright ©2015 The gonum 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 f64 + +import ( + "fmt" + "math" + "math/rand" + "testing" +) + +func TestDotUnitary(t *testing.T) { + for i, test := range []struct { + xData []float64 + yData []float64 + + want float64 + }{ + { + xData: []float64{2}, + yData: []float64{-3}, + want: -6, + }, + { + xData: []float64{2, 3}, + yData: []float64{-3, 4}, + want: 6, + }, + { + xData: []float64{2, 3, -4}, + yData: []float64{-3, 4, 5}, + want: -14, + }, + { + xData: []float64{2, 3, -4, -5}, + yData: []float64{-3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 2, 3, -4, -5}, + yData: []float64{0, -3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 0, 2, 3, -4, -5}, + yData: []float64{0, 1, -3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4}, + yData: []float64{0, 1, 0, 3, -4, 5, -6}, + want: 4, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, + yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, + want: 39, + }, + } { + const msgGuard = "test %v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" + + x, xFront, xBack := newGuardedVector(test.xData, 1) + y, yFront, yBack := newGuardedVector(test.yData, 1) + got := DotUnitary(x, y) + + if !allNaN(xFront) || !allNaN(xBack) { + t.Errorf(msgGuard, i, "x", xFront, xBack) + } + if !allNaN(yFront) || !allNaN(yBack) { + t.Errorf(msgGuard, i, "y", yFront, yBack) + } + if !equalStrided(test.xData, x, 1) { + t.Errorf("test %v: modified read-only x argument", i) + } + if !equalStrided(test.yData, y, 1) { + t.Errorf("test %v: modified read-only y argument", i) + } + if math.IsNaN(got) { + t.Errorf("test %v: invalid memory read", i) + continue + } + + if got != test.want { + t.Errorf("test %v: unexpected result. want %v, got %v", i, test.want, got) + } + } +} + +func TestDotInc(t *testing.T) { + for i, test := range []struct { + xData []float64 + yData []float64 + + want float64 + wantRev float64 // Result when one of the vectors is reversed. + }{ + { + xData: []float64{2}, + yData: []float64{-3}, + want: -6, + wantRev: -6, + }, + { + xData: []float64{2, 3}, + yData: []float64{-3, 4}, + want: 6, + wantRev: -1, + }, + { + xData: []float64{2, 3, -4}, + yData: []float64{-3, 4, 5}, + want: -14, + wantRev: 34, + }, + { + xData: []float64{2, 3, -4, -5}, + yData: []float64{-3, 4, 5, -6}, + want: 16, + wantRev: 2, + }, + { + xData: []float64{0, 2, 3, -4, -5}, + yData: []float64{0, -3, 4, 5, -6}, + want: 16, + wantRev: 34, + }, + { + xData: []float64{0, 0, 2, 3, -4, -5}, + yData: []float64{0, 1, -3, 4, 5, -6}, + want: 16, + wantRev: -5, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4}, + yData: []float64{0, 1, 0, 3, -4, 5, -6}, + want: 4, + wantRev: -4, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, + yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, + want: 39, + wantRev: 3, + }, + } { + const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" + + for _, incX := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { + for _, incY := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { + n := len(test.xData) + x, xFront, xBack := newGuardedVector(test.xData, incX) + y, yFront, yBack := newGuardedVector(test.yData, incY) + + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + got := DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) + + prefix := fmt.Sprintf("test %v, incX = %v, incY = %v", i, incX, incY) + if !allNaN(xFront) || !allNaN(xBack) { + t.Errorf(msgGuard, prefix, "x", xFront, xBack) + } + if !allNaN(yFront) || !allNaN(yBack) { + t.Errorf(msgGuard, prefix, "y", yFront, yBack) + } + if nonStridedWrite(x, incX) || !equalStrided(test.xData, x, incX) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if nonStridedWrite(y, incY) || !equalStrided(test.yData, y, incY) { + t.Errorf("%v: modified read-only y argument", prefix) + } + if math.IsNaN(got) { + t.Errorf("%v: invalid memory read", prefix) + continue + } + + want := test.want + if incX*incY < 0 { + want = test.wantRev + } + if got != want { + t.Errorf("%v: unexpected result. want %v, got %v", prefix, want, got) + } + } + } + } +} + +func BenchmarkDotUnitaryN1(b *testing.B) { dotUnitaryBenchmark(b, 1) } +func BenchmarkDotUnitaryN2(b *testing.B) { dotUnitaryBenchmark(b, 2) } +func BenchmarkDotUnitaryN3(b *testing.B) { dotUnitaryBenchmark(b, 3) } +func BenchmarkDotUnitaryN4(b *testing.B) { dotUnitaryBenchmark(b, 4) } +func BenchmarkDotUnitaryN10(b *testing.B) { dotUnitaryBenchmark(b, 10) } +func BenchmarkDotUnitaryN100(b *testing.B) { dotUnitaryBenchmark(b, 100) } +func BenchmarkDotUnitaryN1000(b *testing.B) { dotUnitaryBenchmark(b, 1000) } +func BenchmarkDotUnitaryN10000(b *testing.B) { dotUnitaryBenchmark(b, 10000) } +func BenchmarkDotUnitaryN100000(b *testing.B) { dotUnitaryBenchmark(b, 100000) } + +var r float64 + +func dotUnitaryBenchmark(b *testing.B, n int) { + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + y := make([]float64, n) + for i := range y { + y[i] = rand.Float64() + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + r = DotUnitary(x, y) + } +} + +func BenchmarkDotIncN1Inc1(b *testing.B) { dotIncBenchmark(b, 1, 1) } + +func BenchmarkDotIncN2Inc1(b *testing.B) { dotIncBenchmark(b, 2, 1) } +func BenchmarkDotIncN2Inc2(b *testing.B) { dotIncBenchmark(b, 2, 2) } +func BenchmarkDotIncN2Inc4(b *testing.B) { dotIncBenchmark(b, 2, 4) } +func BenchmarkDotIncN2Inc10(b *testing.B) { dotIncBenchmark(b, 2, 10) } + +func BenchmarkDotIncN3Inc1(b *testing.B) { dotIncBenchmark(b, 3, 1) } +func BenchmarkDotIncN3Inc2(b *testing.B) { dotIncBenchmark(b, 3, 2) } +func BenchmarkDotIncN3Inc4(b *testing.B) { dotIncBenchmark(b, 3, 4) } +func BenchmarkDotIncN3Inc10(b *testing.B) { dotIncBenchmark(b, 3, 10) } + +func BenchmarkDotIncN4Inc1(b *testing.B) { dotIncBenchmark(b, 4, 1) } +func BenchmarkDotIncN4Inc2(b *testing.B) { dotIncBenchmark(b, 4, 2) } +func BenchmarkDotIncN4Inc4(b *testing.B) { dotIncBenchmark(b, 4, 4) } +func BenchmarkDotIncN4Inc10(b *testing.B) { dotIncBenchmark(b, 4, 10) } + +func BenchmarkDotIncN10Inc1(b *testing.B) { dotIncBenchmark(b, 10, 1) } +func BenchmarkDotIncN10Inc2(b *testing.B) { dotIncBenchmark(b, 10, 2) } +func BenchmarkDotIncN10Inc4(b *testing.B) { dotIncBenchmark(b, 10, 4) } +func BenchmarkDotIncN10Inc10(b *testing.B) { dotIncBenchmark(b, 10, 10) } + +func BenchmarkDotIncN1000Inc1(b *testing.B) { dotIncBenchmark(b, 1000, 1) } +func BenchmarkDotIncN1000Inc2(b *testing.B) { dotIncBenchmark(b, 1000, 2) } +func BenchmarkDotIncN1000Inc4(b *testing.B) { dotIncBenchmark(b, 1000, 4) } +func BenchmarkDotIncN1000Inc10(b *testing.B) { dotIncBenchmark(b, 1000, 10) } + +func BenchmarkDotIncN100000Inc1(b *testing.B) { dotIncBenchmark(b, 100000, 1) } +func BenchmarkDotIncN100000Inc2(b *testing.B) { dotIncBenchmark(b, 100000, 2) } +func BenchmarkDotIncN100000Inc4(b *testing.B) { dotIncBenchmark(b, 100000, 4) } +func BenchmarkDotIncN100000Inc10(b *testing.B) { dotIncBenchmark(b, 100000, 10) } + +func BenchmarkDotIncN100000IncM1(b *testing.B) { dotIncBenchmark(b, 100000, -1) } +func BenchmarkDotIncN100000IncM2(b *testing.B) { dotIncBenchmark(b, 100000, -2) } +func BenchmarkDotIncN100000IncM4(b *testing.B) { dotIncBenchmark(b, 100000, -4) } +func BenchmarkDotIncN100000IncM10(b *testing.B) { dotIncBenchmark(b, 100000, -10) } + +func dotIncBenchmark(b *testing.B, n, inc int) { + absInc := inc + if inc < 0 { + absInc = -inc + } + x := make([]float64, (n-1)*absInc+1) + for i := range x { + x[i] = rand.Float64() + } + y := make([]float64, (n-1)*absInc+1) + for i := range y { + y[i] = rand.Float64() + } + var ini int + if inc < 0 { + ini = (-n + 1) * inc + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + r = DotInc(x, y, uintptr(n), uintptr(inc), uintptr(inc), uintptr(ini), uintptr(ini)) + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s new file mode 100644 index 00000000..2a8c5a38 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s @@ -0,0 +1,58 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1Dist(s, t []float64) float64 +TEXT ·L1Dist(SB), NOSPLIT, $0 + MOVQ s_base+0(FP), DI // DI = &s + MOVQ t_base+24(FP), SI // SI = &t + MOVQ s_len+8(FP), CX // CX = len(s) + CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) + CMOVQLE t_len+32(FP), CX + PXOR X3, X3 // norm = 0 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE l1_end + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $1, BX // BX = CX % 2 + SHRQ $1, CX // CX = floor( CX / 2 ) + JZ l1_tail_start // if CX == 0 { return 0 } + +l1_loop: // Loop unrolled 2x do { + MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] + MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] + MOVAPS X0, X2 + SUBPD X1, X0 + SUBPD X2, X1 + MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + ADDPD X0, X3 // norm += X0 + ADDQ $2, AX // i += 2 + LOOP l1_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE l1_end + +l1_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + PXOR X0, X0 // reset X0, X1 to break dependencies + PXOR X1, X1 + +l1_tail: + MOVSD (SI)(AX*8), X0 // X0 = t[i] + MOVSD (DI)(AX*8), X1 // x1 = s[i] + MOVAPD X0, X2 + SUBSD X1, X0 + SUBSD X2, X1 + MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + ADDSD X0, X3 // norm += X0 + +l1_end: + MOVAPS X3, X2 + SHUFPD $1, X2, X2 + ADDSD X3, X2 // X2 = X3[1] + X3[0] + MOVSD X2, ret+48(FP) // return X2 + RET + diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s new file mode 100644 index 00000000..fb6ef8d2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func LinfDist(s, t []float64) float64 +TEXT ·LinfDist(SB), NOSPLIT, $0 + MOVQ s_base+0(FP), DI // DI = &s + MOVQ t_base+24(FP), SI // SI = &t + MOVQ s_len+8(FP), CX // CX = len(s) + CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) + CMOVQLE t_len+32(FP), CX + PXOR X3, X3 // norm = 0 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE l1_end + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $1, BX // BX = CX % 2 + SHRQ $1, CX // CX = floor( CX / 2 ) + JZ l1_tail_start // if CX == 0 { return 0 } + +l1_loop: // Loop unrolled 2x do { + MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] + MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] + MOVAPS X0, X2 + SUBPD X1, X0 + SUBPD X2, X1 + MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + MAXPD X0, X3 // norm = max( norm, X0 ) + ADDQ $2, AX // i += 2 + LOOP l1_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE l1_end + +l1_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + PXOR X0, X0 // reset X0, X1 to break dependencies + PXOR X1, X1 + +l1_tail: + MOVSD (SI)(AX*8), X0 // X0 = t[i] + MOVSD (DI)(AX*8), X1 // X1 = s[i] + MOVAPD X0, X2 + SUBSD X1, X0 + SUBSD X2, X1 + MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + MAXSD X0, X3 // norm = max( norm, X0 ) + +l1_end: + MOVAPS X3, X2 + SHUFPD $1, X2, X2 + MAXSD X3, X2 // X2 = max( X3[1], X3[0] ) + MOVSD X2, ret+48(FP) // return X2 + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go new file mode 100644 index 00000000..357e6c4a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float64, x []float64) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float64, alpha float64, x []float64) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float64, x []float64, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scal_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/scal_test.go new file mode 100644 index 00000000..d88b7d10 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scal_test.go @@ -0,0 +1,179 @@ +// Copyright ©2016 The gonum 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 f64 + +import ( + "fmt" + "math/rand" + "testing" +) + +var scalTests = []struct { + alpha float64 + x []float64 + want []float64 +}{ + { + alpha: 0, + x: []float64{}, + want: []float64{}, + }, + { + alpha: 0, + x: []float64{1}, + want: []float64{0}, + }, + { + alpha: 1, + x: []float64{1}, + want: []float64{1}, + }, + { + alpha: 2, + x: []float64{1, -2}, + want: []float64{2, -4}, + }, + { + alpha: 2, + x: []float64{1, -2, 3}, + want: []float64{2, -4, 6}, + }, + { + alpha: 2, + x: []float64{1, -2, 3, 4}, + want: []float64{2, -4, 6, 8}, + }, + { + alpha: 2, + x: []float64{1, -2, 3, 4, -5}, + want: []float64{2, -4, 6, 8, -10}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14, 16}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14, 16, 18}, + }, + { + alpha: 3, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9, 12}, + want: []float64{0, 3, -6, 9, 12, -15, 18, -21, 24, 27, 36}, + }, +} + +func TestScalUnitary(t *testing.T) { + const xGdVal = -0.5 + for i, test := range scalTests { + for _, align := range align1 { + prefix := fmt.Sprintf("Test %v (x:%v)", i, align) + xgLn := 4 + align + xg := guardVector(test.x, xGdVal, xgLn) + x := xg[xgLn : len(xg)-xgLn] + + ScalUnitary(test.alpha, x) + + for i := range test.want { + if !same(x[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + } + } +} + +func TestScalUnitaryTo(t *testing.T) { + const xGdVal, dstGdVal = -1, 0.5 + rng := rand.New(rand.NewSource(42)) + for i, test := range scalTests { + n := len(test.x) + for _, align := range align2 { + prefix := fmt.Sprintf("Test %v (x:%v dst:%v)", i, align.x, align.y) + xgLn, dgLn := 4+align.x, 4+align.y + xg := guardVector(test.x, xGdVal, xgLn) + dg := guardVector(randSlice(n, 1, rng), dstGdVal, dgLn) + x, dst := xg[xgLn:len(xg)-xgLn], dg[dgLn:len(dg)-dgLn] + + ScalUnitaryTo(dst, test.alpha, x) + + for i := range test.want { + if !same(dst[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(dg, dstGdVal, dgLn) { + t.Errorf(msgGuard, prefix, "y", dg[:dgLn], dg[len(dg)-dgLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + } + } +} + +func TestScalInc(t *testing.T) { + const xGdVal = -0.5 + gdLn := 4 + for i, test := range scalTests { + n := len(test.x) + for _, incX := range []int{1, 2, 3, 4, 7, 10} { + prefix := fmt.Sprintf("Test %v (x:%v)", i, incX) + xg := guardIncVector(test.x, xGdVal, incX, gdLn) + x := xg[gdLn : len(xg)-gdLn] + + ScalInc(test.alpha, x, uintptr(n), uintptr(incX)) + + for i := range test.want { + if !same(x[i*incX], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i*incX], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, incX, gdLn) + } + } +} + +func TestScalIncTo(t *testing.T) { + const xGdVal, dstGdVal = -1, 0.5 + gdLn := 4 + rng := rand.New(rand.NewSource(42)) + for i, test := range scalTests { + n := len(test.x) + for _, inc := range newIncSet(1, 2, 3, 4, 7, 10) { + prefix := fmt.Sprintf("test %v (x:%v dst:%v)", i, inc.x, inc.y) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + dg := guardIncVector(randSlice(n, 1, rng), dstGdVal, inc.y, gdLn) + x, dst := xg[gdLn:len(xg)-gdLn], dg[gdLn:len(dg)-gdLn] + + ScalIncTo(dst, uintptr(inc.y), test.alpha, x, uintptr(n), uintptr(inc.x)) + + for i := range test.want { + if !same(dst[i*inc.y], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i*inc.y], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, dg, dstGdVal, inc.y, gdLn) + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s new file mode 100644 index 00000000..55a5758e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R9 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalInc(alpha float64, x []float64, n, incX uintptr) +TEXT ·ScalInc(SB), NOSPLIT, $0 + MOVSD alpha+0(FP), ALPHA // ALPHA = alpha + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ incX+40(FP), INC_X // INC_X = incX + SHLQ $3, INC_X // INC_X *= sizeof(float64) + MOVQ n+32(FP), LEN // LEN = n + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + +loop: // do { // x[i] *= alpha unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + MOVSD X2, (X_PTR) // x[i] = X_i + MOVSD X3, (X_PTR)(INC_X*1) + MOVSD X4, (X_PTR)(INC_X*2) + MOVSD X5, (X_PTR)(INCx3_X*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: // do { + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + MOVSD X2, (X_PTR) // x[i] = X_i + MOVSD X3, (X_PTR)(INC_X*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + + ANDQ $1, TAIL + JZ end + +tail_one: + MOVSD (X_PTR), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (X_PTR) // x[i] = X_i + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s new file mode 100644 index 00000000..57c90a2a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s @@ -0,0 +1,122 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define DST_PTR DI +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R9 +#define INC_DST R10 +#define INCx3_DST R11 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) +TEXT ·ScalIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst + MOVQ incDst+24(FP), INC_DST // INC_DST = incDst + SHLQ $3, INC_DST // INC_DST *= sizeof(float64) + MOVSD alpha+32(FP), ALPHA // ALPHA = alpha + MOVQ x_base+40(FP), X_PTR // X_PTR = &x + MOVQ n+64(FP), LEN // LEN = n + MOVQ incX+72(FP), INC_X // INC_X = incX + SHLQ $3, INC_X // INC_X *= sizeof(float64) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 + +loop: // do { // x[i] *= alpha unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + MOVSD X2, (DST_PTR) // dst[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + MOVSD X2, (DST_PTR) // dst[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incDst*2]) + + ANDQ $1, TAIL + JZ end + +tail_one: + MOVSD (X_PTR), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (DST_PTR) // x[i] = X_i + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s new file mode 100644 index 00000000..da23af77 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s @@ -0,0 +1,112 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // @ MOVDDUP XMM0, 8[RSP] + +#define X_PTR SI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalUnitary(alpha float64, x []float64) +TEXT ·ScalUnitary(SB), NOSPLIT, $0 + MOVDDUP_ALPHA // ALPHA = { alpha, alpha } + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ x_len+16(FP), LEN // LEN = len(x) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + XORQ IDX, IDX // IDX = 0 + + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 + +loop: // do { // x[i] *= alpha unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i + MOVUPS X3, 16(X_PTR)(IDX*8) + MOVUPS X4, 32(X_PTR)(IDX*8) + MOVUPS X5, 48(X_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if n == 0 goto end + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { return } + +tail_one: + // x[i] *= alpha for the remaining element. + MOVSD (X_PTR)(IDX*8), X2 + MULSD ALPHA, X2 + MOVSD X2, (X_PTR)(IDX*8) + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s new file mode 100644 index 00000000..3685d5b5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. 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 Google Inc. 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 +// OWNER 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. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x2024 // @ MOVDDUP 32(SP), X0 /*XMM0, 32[RSP]*/ + +#define X_PTR SI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalUnitaryTo(dst []float64, alpha float64, x []float64) +// This function assumes len(dst) >= len(x). +TEXT ·ScalUnitaryTo(SB), NOSPLIT, $0 + MOVQ x_base+32(FP), X_PTR // X_PTR = &x + MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst + MOVDDUP_ALPHA // ALPHA = { alpha, alpha } + MOVQ x_len+40(FP), LEN // LEN = len(x) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + XORQ IDX, IDX // IDX = 0 + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + +loop: // do { // dst[i] = alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop counters + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if LEN == 0 { goto tail_one } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { return } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (DST_PTR)(IDX*8) // dst[i] = X_i + +end: + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go new file mode 100644 index 00000000..d4de1919 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go @@ -0,0 +1,165 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package f64 + +// L1Norm is +// for _, v := range x { +// sum += math.Abs(v) +// } +// return sum +func L1Norm(x []float64) (sum float64) + +// L1NormInc is +// for i := 0; i < n*incX; i += incX { +// sum += math.Abs(x[i]) +// } +// return sum +func L1NormInc(x []float64, n, incX int) (sum float64) + +// AddConst is +// for i := range x { +// x[i] += alpha +// } +func AddConst(alpha float64, x []float64) + +// Add is +// for i, v := range s { +// dst[i] += v +// } +func Add(dst, s []float64) + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float64, x, y []float64) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + +// CumSum is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] + v +// } +// return dst +func CumSum(dst, s []float64) []float64 + +// CumProd is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] * v +// } +// return dst +func CumProd(dst, s []float64) []float64 + +// Div is +// for i, v := range s { +// dst[i] /= v +// } +func Div(dst, s []float64) + +// DivTo is +// for i, v := range s { +// dst[i] = v / t[i] +// } +// return dst +func DivTo(dst, x, y []float64) []float64 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float64) (sum float64) + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) + +// L1Dist is +// var norm float64 +// for i, v := range s { +// norm += math.Abs(t[i] - v) +// } +// return norm +func L1Dist(s, t []float64) float64 + +// LinfDist is +// var norm float64 +// if len(s) == 0 { +// return 0 +// } +// norm = math.Abs(t[0] - s[0]) +// for i, v := range s[1:] { +// absDiff := math.Abs(t[i+1] - v) +// if absDiff > norm || math.IsNaN(norm) { +// norm = absDiff +// } +// } +// return norm +func LinfDist(s, t []float64) float64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float64, x []float64) + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float64, alpha float64, x []float64) + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float64, x []float64, n, incX uintptr) + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go new file mode 100644 index 00000000..5e4ae69c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go @@ -0,0 +1,157 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +import "math" + +// L1Norm is +// for _, v := range x { +// sum += math.Abs(v) +// } +// return sum +func L1Norm(x []float64) (sum float64) { + for _, v := range x { + sum += math.Abs(v) + } + return sum +} + +// L1NormInc is +// for i := 0; i < n*incX; i += incX { +// sum += math.Abs(x[i]) +// } +// return sum +func L1NormInc(x []float64, n, incX int) (sum float64) { + for i := 0; i < n*incX; i += incX { + sum += math.Abs(x[i]) + } + return sum +} + +// Add is +// for i, v := range s { +// dst[i] += v +// } +func Add(dst, s []float64) { + for i, v := range s { + dst[i] += v + } +} + +// AddConst is +// for i := range x { +// x[i] += alpha +// } +func AddConst(alpha float64, x []float64) { + for i := range x { + x[i] += alpha + } +} + +// CumSum is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] + v +// } +// return dst +func CumSum(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +// CumProd is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] * v +// } +// return dst +func CumProd(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] * v + } + return dst +} + +// Div is +// for i, v := range s { +// dst[i] /= v +// } +func Div(dst, s []float64) { + for i, v := range s { + dst[i] /= v + } +} + +// DivTo is +// for i, v := range s { +// dst[i] = v / t[i] +// } +// return dst +func DivTo(dst, s, t []float64) []float64 { + for i, v := range s { + dst[i] = v / t[i] + } + return dst +} + +// L1Dist is +// var norm float64 +// for i, v := range s { +// norm += math.Abs(t[i] - v) +// } +// return norm +func L1Dist(s, t []float64) float64 { + var norm float64 + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm +} + +// LinfDist is +// var norm float64 +// if len(s) == 0 { +// return 0 +// } +// norm = math.Abs(t[0] - s[0]) +// for i, v := range s[1:] { +// absDiff := math.Abs(t[i+1] - v) +// if absDiff > norm || math.IsNaN(norm) { +// norm = absDiff +// } +// } +// return norm +func LinfDist(s, t []float64) float64 { + var norm float64 + if len(s) == 0 { + return 0 + } + norm = math.Abs(t[0] - s[0]) + for i, v := range s[1:] { + absDiff := math.Abs(t[i+1] - v) + if absDiff > norm || math.IsNaN(norm) { + norm = absDiff + } + } + return norm +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_test.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_test.go new file mode 100644 index 00000000..6dd949fc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_test.go @@ -0,0 +1,574 @@ +// Copyright ©2016 The gonum 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 f64 + +import "testing" + +func TestL1Norm(t *testing.T) { + var src_gd float64 = 1 + for j, v := range []struct { + want float64 + x []float64 + }{ + {want: 0, x: []float64{}}, + {want: 2, x: []float64{2}}, + {want: 6, x: []float64{1, 2, 3}}, + {want: 6, x: []float64{-1, -2, -3}}, + {want: nan, x: []float64{nan}}, + {want: 40, x: []float64{8, -8, 8, -8, 8}}, + {want: 5, x: []float64{0, 1, 0, -1, 0, 1, 0, -1, 0, 1}}, + } { + g_ln := 4 + j%2 + v.x = guardVector(v.x, src_gd, g_ln) + src := v.x[g_ln : len(v.x)-g_ln] + ret := L1Norm(src) + if !same(ret, v.want) { + t.Errorf("Test %d L1Norm error Got: %f Expected: %f", j, ret, v.want) + } + if !isValidGuard(v.x, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.x[:g_ln], v.x[len(v.x)-g_ln:]) + } + } +} + +func TestL1NormInc(t *testing.T) { + var src_gd float64 = 1 + for j, v := range []struct { + inc int + want float64 + x []float64 + }{ + {inc: 2, want: 0, x: []float64{}}, + {inc: 3, want: 2, x: []float64{2}}, + {inc: 10, want: 6, x: []float64{1, 2, 3}}, + {inc: 5, want: 6, x: []float64{-1, -2, -3}}, + {inc: 3, want: nan, x: []float64{nan}}, + {inc: 15, want: 40, x: []float64{8, -8, 8, -8, 8}}, + {inc: 1, want: 5, x: []float64{0, 1, 0, -1, 0, 1, 0, -1, 0, 1}}, + } { + g_ln, ln := 4+j%2, len(v.x) + v.x = guardIncVector(v.x, src_gd, v.inc, g_ln) + src := v.x[g_ln : len(v.x)-g_ln] + ret := L1NormInc(src, ln, v.inc) + if !same(ret, v.want) { + t.Errorf("Test %d L1NormInc error Got: %f Expected: %f", j, ret, v.want) + } + checkValidIncGuard(t, v.x, src_gd, v.inc, g_ln) + } +} + +func TestAdd(t *testing.T) { + var src_gd, dst_gd float64 = 1, 0 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{1}, + src: []float64{0}, + expect: []float64{1}, + }, + { + dst: []float64{1, 2, 3}, + src: []float64{1}, + expect: []float64{2, 2, 3}, + }, + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{1}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{8, 8, 8, 8, 8}, + src: []float64{2, 4, nan, 8, 9}, + expect: []float64{10, 12, nan, 16, 17}, + }, + { + dst: []float64{0, 1, 2, 3, 4}, + src: []float64{-inf, 4, nan, 8, 9}, + expect: []float64{-inf, 5, nan, 11, 13}, + }, + { + dst: make([]float64, 50)[1:49], + src: make([]float64, 50)[1:49], + expect: make([]float64, 50)[1:49], + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + Add(dst, src) + for i := range v.expect { + if !same(dst[i], v.expect[i]) { + t.Errorf("Test %d Add error at %d Got: %v Expected: %v", j, i, dst[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestAddConst(t *testing.T) { + var src_gd float64 = 0 + for j, v := range []struct { + alpha float64 + src, expect []float64 + }{ + { + alpha: 1, + src: []float64{0}, + expect: []float64{1}, + }, + { + alpha: 5, + src: []float64{}, + expect: []float64{}, + }, + { + alpha: 1, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + alpha: 8, + src: []float64{2, 4, nan, 8, 9}, + expect: []float64{10, 12, nan, 16, 17}, + }, + { + alpha: inf, + src: []float64{-inf, 4, nan, 8, 9}, + expect: []float64{nan, inf, nan, inf, inf}, + }, + } { + g_ln := 4 + j%2 + v.src = guardVector(v.src, src_gd, g_ln) + src := v.src[g_ln : len(v.src)-g_ln] + AddConst(v.alpha, src) + for i := range v.expect { + if !same(src[i], v.expect[i]) { + t.Errorf("Test %d AddConst error at %d Got: %v Expected: %v", j, i, src[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:g_ln], v.src[len(v.src)-g_ln:]) + } + } +} + +func TestCumSum(t *testing.T) { + var src_gd, dst_gd float64 = -1, 0 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{0}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 3, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 3, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 3, 6, 10}, + }, + { + dst: []float64{1, nan, nan, 1, 1}, + src: []float64{1, 1, nan, 1, 1}, + expect: []float64{1, 2, nan, nan, nan}, + }, + { + dst: []float64{nan, 4, inf, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 9}, + expect: []float64{inf, inf, nan, nan, nan}, + }, + { + dst: make([]float64, 16), + src: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + expect: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + }, + } { + g_ln := 4 + j%2 + v.src, v.dst = guardVector(v.src, src_gd, g_ln), guardVector(v.dst, dst_gd, g_ln) + src, dst := v.src[g_ln:len(v.src)-g_ln], v.dst[g_ln:len(v.dst)-g_ln] + ret := CumSum(dst, src) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d CumSum error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d CumSum ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.src, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:g_ln], v.src[len(v.src)-g_ln:]) + } + if !isValidGuard(v.dst, dst_gd, g_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:g_ln], v.dst[len(v.dst)-g_ln:]) + } + } +} + +func TestCumProd(t *testing.T) { + var src_gd, dst_gd float64 = -1, 1 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{1}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 2, 6, 24}, + }, + { + dst: []float64{0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 2, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 2, 6}, + }, + { + dst: []float64{nan, 1, nan, 1, 0}, + src: []float64{1, 1, nan, 1, 1}, + expect: []float64{1, 1, nan, nan, nan}, + }, + { + dst: []float64{nan, 4, nan, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 9}, + expect: []float64{inf, inf, nan, nan, nan}, + }, + { + dst: make([]float64, 18), + src: []float64{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + expect: []float64{2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}, + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + ret := CumProd(dst, src) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d CumProd error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d CumProd ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestDiv(t *testing.T) { + var src_gd, dst_gd float64 = -1, 0.5 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{1}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{1, 2, 3, 4}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 1, 1, 1}, + }, + { + dst: []float64{1, 2, 3, 4, 2, 4, 6, 8}, + src: []float64{1, 2, 3, 4, 1, 2, 3, 4}, + expect: []float64{1, 1, 1, 1, 2, 2, 2, 2}, + }, + { + dst: []float64{2, 4, 6}, + src: []float64{1, 2, 3}, + expect: []float64{2, 2, 2}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{0, 0, 0}, + }, + { + dst: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + src: []float64{1, 1, nan, 1, 1, 1, 1, nan, 1, 1}, + expect: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + }, + { + dst: []float64{inf, 4, nan, -inf, 9, inf, 4, nan, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 3, inf, 4, nan, -inf, 3}, + expect: []float64{nan, 1, nan, nan, 3, nan, 1, nan, nan, 3}, + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + Div(dst, src) + for i := range v.expect { + if !same(dst[i], v.expect[i]) { + t.Errorf("Test %d Div error at %d Got: %v Expected: %v", j, i, dst[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestDivTo(t *testing.T) { + var dst_gd, x_gd, y_gd float64 = -1, 0.5, 0.25 + for j, v := range []struct { + dst, x, y, expect []float64 + }{ + { + dst: []float64{1}, + x: []float64{1}, + y: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{1}, + x: []float64{nan}, + y: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{-2, -2, -2}, + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + expect: []float64{1, 1, 1}, + }, + { + dst: []float64{0, 0, 0}, + x: []float64{2, 4, 6}, + y: []float64{1, 2, 3, 4}, + expect: []float64{2, 2, 2}, + }, + { + dst: []float64{-1, -1, -1}, + x: []float64{0, 0, 0}, + y: []float64{1, 2, 3}, + expect: []float64{0, 0, 0}, + }, + { + dst: []float64{inf, inf, inf, inf, inf, inf, inf, inf, inf, inf}, + x: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + y: []float64{1, 1, nan, 1, 1, 1, 1, nan, 1, 1}, + expect: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + }, + { + dst: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + x: []float64{inf, 4, nan, -inf, 9, inf, 4, nan, -inf, 9}, + y: []float64{inf, 4, nan, -inf, 3, inf, 4, nan, -inf, 3}, + expect: []float64{nan, 1, nan, nan, 3, nan, 1, nan, nan, 3}, + }, + } { + xg_ln, yg_ln := 4+j%2, 4+j%3 + v.y, v.x = guardVector(v.y, y_gd, yg_ln), guardVector(v.x, x_gd, xg_ln) + y, x := v.y[yg_ln:len(v.y)-yg_ln], v.x[xg_ln:len(v.x)-xg_ln] + v.dst = guardVector(v.dst, dst_gd, xg_ln) + dst := v.dst[xg_ln : len(v.dst)-xg_ln] + ret := DivTo(dst, x, y) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d DivTo error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d DivTo ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", j, v.y[:yg_ln], v.y[len(v.y)-yg_ln:]) + } + if !isValidGuard(v.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", j, v.x[:xg_ln], v.x[len(v.x)-xg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:xg_ln], v.dst[len(v.dst)-xg_ln:]) + } + } +} + +func TestL1Dist(t *testing.T) { + var t_gd, s_gd float64 = -inf, inf + for j, v := range []struct { + s, t []float64 + expect float64 + }{ + { + s: []float64{1}, + t: []float64{1}, + expect: 0, + }, + { + s: []float64{nan}, + t: []float64{nan}, + expect: nan, + }, + { + s: []float64{1, 2, 3, 4}, + t: []float64{1, 2, 3, 4}, + expect: 0, + }, + { + s: []float64{2, 4, 6}, + t: []float64{1, 2, 3, 4}, + expect: 6, + }, + { + s: []float64{0, 0, 0}, + t: []float64{1, 2, 3}, + expect: 6, + }, + { + s: []float64{0, -4, -10}, + t: []float64{1, 2, 3}, + expect: 20, + }, + { + s: []float64{0, 1, 0, 1, 0}, + t: []float64{1, 1, inf, 1, 1}, + expect: inf, + }, + { + s: []float64{inf, 4, nan, -inf, 9}, + t: []float64{inf, 4, nan, -inf, 3}, + expect: nan, + }, + } { + sg_ln, tg_ln := 4+j%2, 4+j%3 + v.s, v.t = guardVector(v.s, s_gd, sg_ln), guardVector(v.t, t_gd, tg_ln) + s_lc, t_lc := v.s[sg_ln:len(v.s)-sg_ln], v.t[tg_ln:len(v.t)-tg_ln] + ret := L1Dist(s_lc, t_lc) + if !same(ret, v.expect) { + t.Errorf("Test %d L1Dist error Got: %f Expected: %f", j, ret, v.expect) + } + if !isValidGuard(v.s, s_gd, sg_ln) { + t.Errorf("Test %d Guard violated in s vector %v %v", j, v.s[:sg_ln], v.s[len(v.s)-sg_ln:]) + } + if !isValidGuard(v.t, t_gd, tg_ln) { + t.Errorf("Test %d Guard violated in t vector %v %v", j, v.t[:tg_ln], v.t[len(v.t)-tg_ln:]) + } + } +} + +func TestLinfDist(t *testing.T) { + var t_gd, s_gd float64 = 0, inf + for j, v := range []struct { + s, t []float64 + expect float64 + }{ + { + s: []float64{}, + t: []float64{}, + expect: 0, + }, + { + s: []float64{1}, + t: []float64{1}, + expect: 0, + }, + { + s: []float64{nan}, + t: []float64{nan}, + expect: nan, + }, + { + s: []float64{1, 2, 3, 4}, + t: []float64{1, 2, 3, 4}, + expect: 0, + }, + { + s: []float64{2, 4, 6}, + t: []float64{1, 2, 3, 4}, + expect: 3, + }, + { + s: []float64{0, 0, 0}, + t: []float64{1, 2, 3}, + expect: 3, + }, + { + s: []float64{0, 1, 0, 1, 0}, + t: []float64{1, 1, inf, 1, 1}, + expect: inf, + }, + { + s: []float64{inf, 4, nan, -inf, 9}, + t: []float64{inf, 4, nan, -inf, 3}, + expect: 6, + }, + } { + sg_ln, tg_ln := 4+j%2, 4+j%3 + v.s, v.t = guardVector(v.s, s_gd, sg_ln), guardVector(v.t, t_gd, tg_ln) + s_lc, t_lc := v.s[sg_ln:len(v.s)-sg_ln], v.t[tg_ln:len(v.t)-tg_ln] + ret := LinfDist(s_lc, t_lc) + if !same(ret, v.expect) { + t.Errorf("Test %d LinfDist error Got: %f Expected: %f", j, ret, v.expect) + } + if !isValidGuard(v.s, s_gd, sg_ln) { + t.Errorf("Test %d Guard violated in s vector %v %v", j, v.s[:sg_ln], v.s[len(v.s)-sg_ln:]) + } + if !isValidGuard(v.t, t_gd, tg_ln) { + t.Errorf("Test %d Guard violated in t vector %v %v", j, v.t[:tg_ln], v.t[len(v.t)-tg_ln:]) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go new file mode 100644 index 00000000..65b8c985 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go @@ -0,0 +1,14 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// Abs returns the absolute value (also called the modulus) of x. +func Abs(x complex64) float32 { return math.Hypot(real(x), imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/cmath_test.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/cmath_test.go new file mode 100644 index 00000000..39cd5d1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/cmath_test.go @@ -0,0 +1,240 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +import ( + "testing" + + math "gonum.org/v1/gonum/internal/math32" +) + +// The higher-precision values in vc26 were used to derive the +// input arguments vc (see also comment below). For reference +// only (do not delete). +var vc26 = []complex64{ + (4.97901192488367350108546816 + 7.73887247457810456552351752i), + (7.73887247457810456552351752 - 0.27688005719200159404635997i), + (-0.27688005719200159404635997 - 5.01060361827107492160848778i), + (-5.01060361827107492160848778 + 9.63629370719841737980004837i), + (9.63629370719841737980004837 + 2.92637723924396464525443662i), + (2.92637723924396464525443662 + 5.22908343145930665230025625i), + (5.22908343145930665230025625 + 2.72793991043601025126008608i), + (2.72793991043601025126008608 + 1.82530809168085506044576505i), + (1.82530809168085506044576505 - 8.68592476857560136238589621i), + (-8.68592476857560136238589621 + 4.97901192488367350108546816i), +} + +var vc = []complex64{ + (4.9790119248836735e+00 + 7.7388724745781045e+00i), + (7.7388724745781045e+00 - 2.7688005719200159e-01i), + (-2.7688005719200159e-01 - 5.0106036182710749e+00i), + (-5.0106036182710749e+00 + 9.6362937071984173e+00i), + (9.6362937071984173e+00 + 2.9263772392439646e+00i), + (2.9263772392439646e+00 + 5.2290834314593066e+00i), + (5.2290834314593066e+00 + 2.7279399104360102e+00i), + (2.7279399104360102e+00 + 1.8253080916808550e+00i), + (1.8253080916808550e+00 - 8.6859247685756013e+00i), + (-8.6859247685756013e+00 + 4.9790119248836735e+00i), +} + +// The expected results below were computed by the high precision calculators +// at http://keisan.casio.com/. More exact input values (array vc[], above) +// were obtained by printing them with "%.26f". The answers were calculated +// to 26 digits (by using the "Digit number" drop-down control of each +// calculator). + +var abs = []float32{ + 9.2022120669932650313380972e+00, + 7.7438239742296106616261394e+00, + 5.0182478202557746902556648e+00, + 1.0861137372799545160704002e+01, + 1.0070841084922199607011905e+01, + 5.9922447613166942183705192e+00, + 5.8978784056736762299945176e+00, + 3.2822866700678709020367184e+00, + 8.8756430028990417290744307e+00, + 1.0011785496777731986390856e+01, +} + +var conj = []complex64{ + (4.9790119248836735e+00 - 7.7388724745781045e+00i), + (7.7388724745781045e+00 + 2.7688005719200159e-01i), + (-2.7688005719200159e-01 + 5.0106036182710749e+00i), + (-5.0106036182710749e+00 - 9.6362937071984173e+00i), + (9.6362937071984173e+00 - 2.9263772392439646e+00i), + (2.9263772392439646e+00 - 5.2290834314593066e+00i), + (5.2290834314593066e+00 - 2.7279399104360102e+00i), + (2.7279399104360102e+00 - 1.8253080916808550e+00i), + (1.8253080916808550e+00 + 8.6859247685756013e+00i), + (-8.6859247685756013e+00 - 4.9790119248836735e+00i), +} + +var sqrt = []complex64{ + (2.6628203086086130543813948e+00 + 1.4531345674282185229796902e+00i), + (2.7823278427251986247149295e+00 - 4.9756907317005224529115567e-02i), + (1.5397025302089642757361015e+00 - 1.6271336573016637535695727e+00i), + (1.7103411581506875260277898e+00 + 2.8170677122737589676157029e+00i), + (3.1390392472953103383607947e+00 + 4.6612625849858653248980849e-01i), + (2.1117080764822417640789287e+00 + 1.2381170223514273234967850e+00i), + (2.3587032281672256703926939e+00 + 5.7827111903257349935720172e-01i), + (1.7335262588873410476661577e+00 + 5.2647258220721269141550382e-01i), + (2.3131094974708716531499282e+00 - 1.8775429304303785570775490e+00i), + (8.1420535745048086240947359e-01 + 3.0575897587277248522656113e+00i), +} + +// special cases +var vcAbsSC = []complex64{ + NaN(), +} +var absSC = []float32{ + math.NaN(), +} +var vcConjSC = []complex64{ + NaN(), +} +var conjSC = []complex64{ + NaN(), +} +var vcIsNaNSC = []complex64{ + complex(math.Inf(-1), math.Inf(-1)), + complex(math.Inf(-1), math.NaN()), + complex(math.NaN(), math.Inf(-1)), + complex(0, math.NaN()), + complex(math.NaN(), 0), + complex(math.Inf(1), math.Inf(1)), + complex(math.Inf(1), math.NaN()), + complex(math.NaN(), math.Inf(1)), + complex(math.NaN(), math.NaN()), +} +var isNaNSC = []bool{ + false, + false, + false, + true, + true, + false, + false, + false, + true, +} +var vcSqrtSC = []complex64{ + NaN(), +} +var sqrtSC = []complex64{ + NaN(), +} + +// functions borrowed from pkg/math/all_test.go +func tolerance(a, b, e float32) bool { + d := a - b + if d < 0 { + d = -d + } + + // note: b is correct (expected) value, a is actual value. + // make error tolerance a fraction of b, not a. + if b != 0 { + e = e * b + if e < 0 { + e = -e + } + } + return d < e +} +func veryclose(a, b float32) bool { return tolerance(a, b, 1e-7) } +func alike(a, b float32) bool { + switch { + case a != a && b != b: // math.IsNaN(a) && math.IsNaN(b): + return true + case a == b: + return math.Signbit(a) == math.Signbit(b) + } + return false +} + +func cTolerance(a, b complex64, e float32) bool { + d := Abs(a - b) + if b != 0 { + e = e * Abs(b) + if e < 0 { + e = -e + } + } + return d < e +} +func cVeryclose(a, b complex64) bool { return cTolerance(a, b, 1e-7) } +func cAlike(a, b complex64) bool { + switch { + case IsNaN(a) && IsNaN(b): + return true + case a == b: + return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b)) + } + return false +} + +func TestAbs(t *testing.T) { + for i := 0; i < len(vc); i++ { + if f := Abs(vc[i]); !veryclose(abs[i], f) { + t.Errorf("Abs(%g) = %g, want %g", vc[i], f, abs[i]) + } + } + for i := 0; i < len(vcAbsSC); i++ { + if f := Abs(vcAbsSC[i]); !alike(absSC[i], f) { + t.Errorf("Abs(%g) = %g, want %g", vcAbsSC[i], f, absSC[i]) + } + } +} +func TestConj(t *testing.T) { + for i := 0; i < len(vc); i++ { + if f := Conj(vc[i]); !cVeryclose(conj[i], f) { + t.Errorf("Conj(%g) = %g, want %g", vc[i], f, conj[i]) + } + } + for i := 0; i < len(vcConjSC); i++ { + if f := Conj(vcConjSC[i]); !cAlike(conjSC[i], f) { + t.Errorf("Conj(%g) = %g, want %g", vcConjSC[i], f, conjSC[i]) + } + } +} +func TestIsNaN(t *testing.T) { + for i := 0; i < len(vcIsNaNSC); i++ { + if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f { + t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i]) + } + } +} +func TestSqrt(t *testing.T) { + for i := 0; i < len(vc); i++ { + if f := Sqrt(vc[i]); !cVeryclose(sqrt[i], f) { + t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i]) + } + } + for i := 0; i < len(vcSqrtSC); i++ { + if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) { + t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i]) + } + } +} + +func BenchmarkAbs(b *testing.B) { + for i := 0; i < b.N; i++ { + Abs(complex(2.5, 3.5)) + } +} +func BenchmarkConj(b *testing.B) { + for i := 0; i < b.N; i++ { + Conj(complex(2.5, 3.5)) + } +} +func BenchmarkSqrt(b *testing.B) { + for i := 0; i < b.N; i++ { + Sqrt(complex(2.5, 3.5)) + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go new file mode 100644 index 00000000..84b7b556 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go @@ -0,0 +1,12 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +// Conj returns the complex conjugate of x. +func Conj(x complex64) complex64 { return complex(real(x), -imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go new file mode 100644 index 00000000..40f808a9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 cmplx64 provides complex64 versions of standard library math/cmplx +// package routines used by gonum/blas. +package cmplx64 // import "gonum.org/v1/gonum/internal/cmplx64" diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go new file mode 100644 index 00000000..e674e52b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go @@ -0,0 +1,25 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// IsInf returns true if either real(x) or imag(x) is an infinity. +func IsInf(x complex64) bool { + if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) { + return true + } + return false +} + +// Inf returns a complex infinity, complex(+Inf, +Inf). +func Inf() complex64 { + inf := math.Inf(1) + return complex(inf, inf) +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go new file mode 100644 index 00000000..2630ef86 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go @@ -0,0 +1,29 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// IsNaN returns true if either real(x) or imag(x) is NaN +// and neither is an infinity. +func IsNaN(x complex64) bool { + switch { + case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0): + return false + case math.IsNaN(real(x)) || math.IsNaN(imag(x)): + return true + } + return false +} + +// NaN returns a complex ``not-a-number'' value. +func NaN() complex64 { + nan := math.NaN() + return complex(nan, nan) +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go new file mode 100644 index 00000000..313fd11f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go @@ -0,0 +1,108 @@ +// Copyright 2010 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. + +// Copyright ©2017 The gonum 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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// The original C code, the long comment, and the constants +// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. +// The go code is a simplified version of the original C. +// +// Cephes Math Library Release 2.8: June, 2000 +// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier +// +// The readme file at http://netlib.sandia.gov/cephes/ says: +// Some software in this archive may be from the book _Methods and +// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster +// International, 1989) or from the Cephes Mathematical Library, a +// commercial product. In either event, it is copyrighted by the author. +// What you see here may be used freely but it comes with no support or +// guarantee. +// +// The two known misprints in the book are repaired here in the +// source listings for the gamma function and the incomplete beta +// integral. +// +// Stephen L. Moshier +// moshier@na-net.ornl.gov + +// Complex square root +// +// DESCRIPTION: +// +// If z = x + iy, r = |z|, then +// +// 1/2 +// Re w = [ (r + x)/2 ] , +// +// 1/2 +// Im w = [ (r - x)/2 ] . +// +// Cancelation error in r-x or r+x is avoided by using the +// identity 2 Re w Im w = y. +// +// Note that -w is also a square root of z. The root chosen +// is always in the right half plane and Im w has the same sign as y. +// +// ACCURACY: +// +// Relative error: +// arithmetic domain # trials peak rms +// DEC -10,+10 25000 3.2e-17 9.6e-18 +// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17 + +// Sqrt returns the square root of x. +// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x). +func Sqrt(x complex64) complex64 { + if imag(x) == 0 { + if real(x) == 0 { + return complex(0, 0) + } + if real(x) < 0 { + return complex(0, math.Sqrt(-real(x))) + } + return complex(math.Sqrt(real(x)), 0) + } + if real(x) == 0 { + if imag(x) < 0 { + r := math.Sqrt(-0.5 * imag(x)) + return complex(r, -r) + } + r := math.Sqrt(0.5 * imag(x)) + return complex(r, r) + } + a := real(x) + b := imag(x) + var scale float32 + // Rescale to avoid internal overflow or underflow. + if math.Abs(a) > 4 || math.Abs(b) > 4 { + a *= 0.25 + b *= 0.25 + scale = 2 + } else { + a *= 1.8014398509481984e16 // 2**54 + b *= 1.8014398509481984e16 + scale = 7.450580596923828125e-9 // 2**-27 + } + r := math.Hypot(a, b) + var t float32 + if a > 0 { + t = math.Sqrt(0.5*r + 0.5*a) + r = scale * math.Abs((0.5*b)/t) + t *= scale + } else { + r = math.Sqrt(0.5*r - 0.5*a) + t = scale * math.Abs((0.5*b)/r) + r *= scale + } + if b < 0 { + return complex(t, -r) + } + return complex(t, r) +} diff --git a/vendor/gonum.org/v1/gonum/internal/math32/doc.go b/vendor/gonum.org/v1/gonum/internal/math32/doc.go new file mode 100644 index 00000000..2368fcd9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/math32/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 math32 provides float32 versions of standard library math package +// routines used by gonum/blas/native. +package math32 // import "gonum.org/v1/gonum/internal/math32" diff --git a/vendor/gonum.org/v1/gonum/internal/math32/math.go b/vendor/gonum.org/v1/gonum/internal/math32/math.go new file mode 100644 index 00000000..3e466611 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/math32/math.go @@ -0,0 +1,111 @@ +// Copyright 2009 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. + +// Copyright ©2015 The gonum 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 math32 + +import ( + "math" +) + +const ( + unan = 0x7fc00000 + uinf = 0x7f800000 + uneginf = 0xff800000 + mask = 0x7f8 >> 3 + shift = 32 - 8 - 1 + bias = 127 +) + +// Abs returns the absolute value of x. +// +// Special cases are: +// Abs(±Inf) = +Inf +// Abs(NaN) = NaN +func Abs(x float32) float32 { + switch { + case x < 0: + return -x + case x == 0: + return 0 // return correctly abs(-0) + } + return x +} + +// Copysign returns a value with the magnitude +// of x and the sign of y. +func Copysign(x, y float32) float32 { + const sign = 1 << 31 + return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign) +} + +// Hypot returns Sqrt(p*p + q*q), taking care to avoid +// unnecessary overflow and underflow. +// +// Special cases are: +// Hypot(±Inf, q) = +Inf +// Hypot(p, ±Inf) = +Inf +// Hypot(NaN, q) = NaN +// Hypot(p, NaN) = NaN +func Hypot(p, q float32) float32 { + // special cases + switch { + case IsInf(p, 0) || IsInf(q, 0): + return Inf(1) + case IsNaN(p) || IsNaN(q): + return NaN() + } + if p < 0 { + p = -p + } + if q < 0 { + q = -q + } + if p < q { + p, q = q, p + } + if p == 0 { + return 0 + } + q = q / p + return p * Sqrt(1+q*q) +} + +// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. +func Inf(sign int) float32 { + var v uint32 + if sign >= 0 { + v = uinf + } else { + v = uneginf + } + return math.Float32frombits(v) +} + +// IsInf reports whether f is an infinity, according to sign. +// If sign > 0, IsInf reports whether f is positive infinity. +// If sign < 0, IsInf reports whether f is negative infinity. +// If sign == 0, IsInf reports whether f is either infinity. +func IsInf(f float32, sign int) bool { + // Test for infinity by comparing against maximum float. + // To avoid the floating-point hardware, could use: + // x := math.Float32bits(f); + // return sign >= 0 && x == uinf || sign <= 0 && x == uneginf; + return sign >= 0 && f > math.MaxFloat32 || sign <= 0 && f < -math.MaxFloat32 +} + +// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value. +func IsNaN(f float32) (is bool) { + // IEEE 754 says that only NaNs satisfy f != f. + // To avoid the floating-point hardware, could use: + // x := math.Float32bits(f); + // return uint32(x>>shift)&mask == mask && x != uinf && x != uneginf + return f != f +} + +// NaN returns an IEEE 754 ``not-a-number'' value. +func NaN() float32 { return math.Float32frombits(unan) } diff --git a/vendor/gonum.org/v1/gonum/internal/math32/math_test.go b/vendor/gonum.org/v1/gonum/internal/math32/math_test.go new file mode 100644 index 00000000..aa29ea37 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/math32/math_test.go @@ -0,0 +1,238 @@ +// Copyright ©2015 The gonum 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 math32 + +import ( + "math" + "testing" + "testing/quick" + + "gonum.org/v1/gonum/floats" +) + +const tol = 1e-7 + +func TestAbs(t *testing.T) { + f := func(x float32) bool { + y := Abs(x) + return y == float32(math.Abs(float64(x))) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestCopySign(t *testing.T) { + f := func(x struct{ X, Y float32 }) bool { + y := Copysign(x.X, x.Y) + return y == float32(math.Copysign(float64(x.X), float64(x.Y))) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestHypot(t *testing.T) { + // tol is increased for Hypot to avoid failures + // related to https://github.com/gonum/gonum/issues/110. + const tol = 1e-6 + f := func(x struct{ X, Y float32 }) bool { + y := Hypot(x.X, x.Y) + if math.Hypot(float64(x.X), float64(x.Y)) > math.MaxFloat32 { + return true + } + return floats.EqualWithinRel(float64(y), math.Hypot(float64(x.X), float64(x.Y)), tol) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestInf(t *testing.T) { + if float64(Inf(1)) != math.Inf(1) || float64(Inf(-1)) != math.Inf(-1) { + t.Error("float32(inf) not infinite") + } +} + +func TestIsInf(t *testing.T) { + posInf := float32(math.Inf(1)) + negInf := float32(math.Inf(-1)) + if !IsInf(posInf, 0) || !IsInf(negInf, 0) || !IsInf(posInf, 1) || !IsInf(negInf, -1) || IsInf(posInf, -1) || IsInf(negInf, 1) { + t.Error("unexpected isInf value") + } + f := func(x struct { + F float32 + Sign int + }) bool { + y := IsInf(x.F, x.Sign) + return y == math.IsInf(float64(x.F), x.Sign) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestIsNaN(t *testing.T) { + f := func(x float32) bool { + y := IsNaN(x) + return y == math.IsNaN(float64(x)) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestNaN(t *testing.T) { + if !math.IsNaN(float64(NaN())) { + t.Errorf("float32(nan) is a number: %f", NaN()) + } +} + +func TestSignbit(t *testing.T) { + f := func(x float32) bool { + return Signbit(x) == math.Signbit(float64(x)) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestSqrt(t *testing.T) { + f := func(x float32) bool { + y := Sqrt(x) + if IsNaN(y) && IsNaN(sqrt(x)) { + return true + } + return floats.EqualWithinRel(float64(y), float64(sqrt(x)), tol) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +// Copyright 2009 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. + +// The original C code and the long comment below are +// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and +// came with this notice. The go code is a simplified +// version of the original C. +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// __ieee754_sqrt(x) +// Return correctly rounded sqrt. +// ----------------------------------------- +// | Use the hardware sqrt if you have one | +// ----------------------------------------- +// Method: +// Bit by bit method using integer arithmetic. (Slow, but portable) +// 1. Normalization +// Scale x to y in [1,4) with even powers of 2: +// find an integer k such that 1 <= (y=x*2**(2k)) < 4, then +// sqrt(x) = 2**k * sqrt(y) +// 2. Bit by bit computation +// Let q = sqrt(y) truncated to i bit after binary point (q = 1), +// i 0 +// i+1 2 +// s = 2*q , and y = 2 * ( y - q ). (1) +// i i i i +// +// To compute q from q , one checks whether +// i+1 i +// +// -(i+1) 2 +// (q + 2 ) <= y. (2) +// i +// -(i+1) +// If (2) is false, then q = q ; otherwise q = q + 2 . +// i+1 i i+1 i +// +// With some algebraic manipulation, it is not difficult to see +// that (2) is equivalent to +// -(i+1) +// s + 2 <= y (3) +// i i +// +// The advantage of (3) is that s and y can be computed by +// i i +// the following recurrence formula: +// if (3) is false +// +// s = s , y = y ; (4) +// i+1 i i+1 i +// +// otherwise, +// -i -(i+1) +// s = s + 2 , y = y - s - 2 (5) +// i+1 i i+1 i i +// +// One may easily use induction to prove (4) and (5). +// Note. Since the left hand side of (3) contain only i+2 bits, +// it does not necessary to do a full (53-bit) comparison +// in (3). +// 3. Final rounding +// After generating the 53 bits result, we compute one more bit. +// Together with the remainder, we can decide whether the +// result is exact, bigger than 1/2ulp, or less than 1/2ulp +// (it will never equal to 1/2ulp). +// The rounding mode can be detected by checking whether +// huge + tiny is equal to huge, and whether huge - tiny is +// equal to huge for some floating point number "huge" and "tiny". +// +func sqrt(x float32) float32 { + // special cases + switch { + case x == 0 || IsNaN(x) || IsInf(x, 1): + return x + case x < 0: + return NaN() + } + ix := math.Float32bits(x) + // normalize x + exp := int((ix >> shift) & mask) + if exp == 0 { // subnormal x + for ix&1<>= 1 // exp = exp/2, exponent of square root + // generate sqrt(x) bit by bit + ix <<= 1 + var q, s uint32 // q = sqrt(x) + r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB + for r != 0 { + t := s + r + if t <= ix { + s = t + r + ix -= t + q += r + } + ix <<= 1 + r >>= 1 + } + // final rounding + if ix != 0 { // remainder, result not exact + q += q & 1 // round according to extra bit + } + ix = q>>1 + uint32(exp-1+bias)< 0 || nru > 0 || ncc > 0) { + info = impl.Dlasq1(n, d, e, work) + // If info is 2 dqds didn't finish, and so try to. + if info != 2 { + return info == 0 + } + info = 0 + } + nm1 := n - 1 + nm12 := nm1 + nm1 + nm13 := nm12 + nm1 + idir := 0 + + eps := dlamchE + unfl := dlamchS + lower := uplo == blas.Lower + var cs, sn, r float64 + if lower { + for i := 0; i < n-1; i++ { + cs, sn, r = impl.Dlartg(d[i], e[i]) + d[i] = r + e[i] = sn * d[i+1] + d[i+1] *= cs + work[i] = cs + work[nm1+i] = sn + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, n, work, work[n-1:], u, ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, n, ncc, work, work[n-1:], c, ldc) + } + } + // Compute singular values to a relative accuracy of tol. If tol is negative + // the values will be computed to an absolute accuracy of math.Abs(tol) * norm(b) + tolmul := math.Max(10, math.Min(100, math.Pow(eps, -1.0/8))) + tol := tolmul * eps + var smax float64 + for i := 0; i < n; i++ { + smax = math.Max(smax, math.Abs(d[i])) + } + for i := 0; i < n-1; i++ { + smax = math.Max(smax, math.Abs(e[i])) + } + + var sminl float64 + var thresh float64 + if tol >= 0 { + sminoa := math.Abs(d[0]) + if sminoa != 0 { + mu := sminoa + for i := 1; i < n; i++ { + mu = math.Abs(d[i]) * (mu / (mu + math.Abs(e[i-1]))) + sminoa = math.Min(sminoa, mu) + if sminoa == 0 { + break + } + } + } + sminoa = sminoa / math.Sqrt(float64(n)) + thresh = math.Max(tol*sminoa, float64(maxIter*n*n)*unfl) + } else { + thresh = math.Max(math.Abs(tol)*smax, float64(maxIter*n*n)*unfl) + } + // Prepare for the main iteration loop for the singular values. + maxIt := maxIter * n * n + iter := 0 + oldl2 := -1 + oldm := -1 + // m points to the last element of unconverged part of matrix. + m := n + + Outer: + for m > 1 { + if iter > maxIt { + info = 0 + for i := 0; i < n-1; i++ { + if e[i] != 0 { + info++ + } + } + return info == 0 + } + // Find diagonal block of matrix to work on. + if tol < 0 && math.Abs(d[m-1]) <= thresh { + d[m-1] = 0 + } + smax = math.Abs(d[m-1]) + smin := smax + var l2 int + var broke bool + for l3 := 0; l3 < m-1; l3++ { + l2 = m - l3 - 2 + abss := math.Abs(d[l2]) + abse := math.Abs(e[l2]) + if tol < 0 && abss <= thresh { + d[l2] = 0 + } + if abse <= thresh { + broke = true + break + } + smin = math.Min(smin, abss) + smax = math.Max(math.Max(smax, abss), abse) + } + if broke { + e[l2] = 0 + if l2 == m-2 { + // Convergence of bottom singular value, return to top. + m-- + continue + } + l2++ + } else { + l2 = 0 + } + // e[ll] through e[m-2] are nonzero, e[ll-1] is zero + if l2 == m-2 { + // Handle 2×2 block separately. + var sinr, cosr, sinl, cosl float64 + d[m-1], d[m-2], sinr, cosr, sinl, cosl = impl.Dlasv2(d[m-2], e[m-2], d[m-1]) + e[m-2] = 0 + if ncvt > 0 { + bi.Drot(ncvt, vt[(m-2)*ldvt:], 1, vt[(m-1)*ldvt:], 1, cosr, sinr) + } + if nru > 0 { + bi.Drot(nru, u[m-2:], ldu, u[m-1:], ldu, cosl, sinl) + } + if ncc > 0 { + bi.Drot(ncc, c[(m-2)*ldc:], 1, c[(m-1)*ldc:], 1, cosl, sinl) + } + m -= 2 + continue + } + // If working on a new submatrix, choose shift direction from larger end + // diagonal element toward smaller. + if l2 > oldm-1 || m-1 < oldl2 { + if math.Abs(d[l2]) >= math.Abs(d[m-1]) { + idir = 1 + } else { + idir = 2 + } + } + // Apply convergence tests. + // TODO(btracey): There is a lot of similar looking code here. See + // if there is a better way to de-duplicate. + if idir == 1 { + // Run convergence test in forward direction. + // First apply standard test to bottom of matrix. + if math.Abs(e[m-2]) <= math.Abs(tol)*math.Abs(d[m-1]) || (tol < 0 && math.Abs(e[m-2]) <= thresh) { + e[m-2] = 0 + continue + } + if tol >= 0 { + // If relative accuracy desired, apply convergence criterion forward. + mu := math.Abs(d[l2]) + sminl = mu + for l3 := l2; l3 < m-1; l3++ { + if math.Abs(e[l3]) <= tol*mu { + e[l3] = 0 + continue Outer + } + mu = math.Abs(d[l3+1]) * (mu / (mu + math.Abs(e[l3]))) + sminl = math.Min(sminl, mu) + } + } + } else { + // Run convergence test in backward direction. + // First apply standard test to top of matrix. + if math.Abs(e[l2]) <= math.Abs(tol)*math.Abs(d[l2]) || (tol < 0 && math.Abs(e[l2]) <= thresh) { + e[l2] = 0 + continue + } + if tol >= 0 { + // If relative accuracy desired, apply convergence criterion backward. + mu := math.Abs(d[m-1]) + sminl = mu + for l3 := m - 2; l3 >= l2; l3-- { + if math.Abs(e[l3]) <= tol*mu { + e[l3] = 0 + continue Outer + } + mu = math.Abs(d[l3]) * (mu / (mu + math.Abs(e[l3]))) + sminl = math.Min(sminl, mu) + } + } + } + oldl2 = l2 + oldm = m + // Compute shift. First, test if shifting would ruin relative accuracy, + // and if so set the shift to zero. + var shift float64 + if tol >= 0 && float64(n)*tol*(sminl/smax) <= math.Max(eps, (1.0/100)*tol) { + shift = 0 + } else { + var sl2 float64 + if idir == 1 { + sl2 = math.Abs(d[l2]) + shift, _ = impl.Dlas2(d[m-2], e[m-2], d[m-1]) + } else { + sl2 = math.Abs(d[m-1]) + shift, _ = impl.Dlas2(d[l2], e[l2], d[l2+1]) + } + // Test if shift is negligible + if sl2 > 0 { + if (shift/sl2)*(shift/sl2) < eps { + shift = 0 + } + } + } + iter += m - l2 + 1 + // If no shift, do simplified QR iteration. + if shift == 0 { + if idir == 1 { + cs := 1.0 + oldcs := 1.0 + var sn, r, oldsn float64 + for i := l2; i < m-1; i++ { + cs, sn, r = impl.Dlartg(d[i]*cs, e[i]) + if i > l2 { + e[i-1] = oldsn * r + } + oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i+1]*sn) + work[i-l2] = cs + work[i-l2+nm1] = sn + work[i-l2+nm12] = oldcs + work[i-l2+nm13] = oldsn + } + h := d[m-1] * cs + d[m-1] = h * oldcs + e[m-2] = h * oldsn + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) + } + if math.Abs(e[m-2]) < thresh { + e[m-2] = 0 + } + } else { + cs := 1.0 + oldcs := 1.0 + var sn, r, oldsn float64 + for i := m - 1; i >= l2+1; i-- { + cs, sn, r = impl.Dlartg(d[i]*cs, e[i-1]) + if i < m-1 { + e[i] = oldsn * r + } + oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i-1]*sn) + work[i-l2-1] = cs + work[i-l2+nm1-1] = -sn + work[i-l2+nm12-1] = oldcs + work[i-l2+nm13-1] = -oldsn + } + h := d[l2] * cs + d[l2] = h * oldcs + e[l2] = h * oldsn + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) + } + if math.Abs(e[l2]) <= thresh { + e[l2] = 0 + } + } + } else { + // Use nonzero shift. + if idir == 1 { + // Chase bulge from top to bottom. Save cosines and sines for + // later singular vector updates. + f := (math.Abs(d[l2]) - shift) * (math.Copysign(1, d[l2]) + shift/d[l2]) + g := e[l2] + var cosl, sinl float64 + for i := l2; i < m-1; i++ { + cosr, sinr, r := impl.Dlartg(f, g) + if i > l2 { + e[i-1] = r + } + f = cosr*d[i] + sinr*e[i] + e[i] = cosr*e[i] - sinr*d[i] + g = sinr * d[i+1] + d[i+1] *= cosr + cosl, sinl, r = impl.Dlartg(f, g) + d[i] = r + f = cosl*e[i] + sinl*d[i+1] + d[i+1] = cosl*d[i+1] - sinl*e[i] + if i < m-2 { + g = sinl * e[i+1] + e[i+1] = cosl * e[i+1] + } + work[i-l2] = cosr + work[i-l2+nm1] = sinr + work[i-l2+nm12] = cosl + work[i-l2+nm13] = sinl + } + e[m-2] = f + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) + } + if math.Abs(e[m-2]) <= thresh { + e[m-2] = 0 + } + } else { + // Chase bulge from top to bottom. Save cosines and sines for + // later singular vector updates. + f := (math.Abs(d[m-1]) - shift) * (math.Copysign(1, d[m-1]) + shift/d[m-1]) + g := e[m-2] + for i := m - 1; i > l2; i-- { + cosr, sinr, r := impl.Dlartg(f, g) + if i < m-1 { + e[i] = r + } + f = cosr*d[i] + sinr*e[i-1] + e[i-1] = cosr*e[i-1] - sinr*d[i] + g = sinr * d[i-1] + d[i-1] *= cosr + cosl, sinl, r := impl.Dlartg(f, g) + d[i] = r + f = cosl*e[i-1] + sinl*d[i-1] + d[i-1] = cosl*d[i-1] - sinl*e[i-1] + if i > l2+1 { + g = sinl * e[i-2] + e[i-2] *= cosl + } + work[i-l2-1] = cosr + work[i-l2+nm1-1] = -sinr + work[i-l2+nm12-1] = cosl + work[i-l2+nm13-1] = -sinl + } + e[l2] = f + if math.Abs(e[l2]) <= thresh { + e[l2] = 0 + } + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) + } + } + } + } + } + + // All singular values converged, make them positive. + for i := 0; i < n; i++ { + if d[i] < 0 { + d[i] *= -1 + if ncvt > 0 { + bi.Dscal(ncvt, -1, vt[i*ldvt:], 1) + } + } + } + + // Sort the singular values in decreasing order. + for i := 0; i < n-1; i++ { + isub := 0 + smin := d[0] + for j := 1; j < n-i; j++ { + if d[j] <= smin { + isub = j + smin = d[j] + } + } + if isub != n-i { + // Swap singular values and vectors. + d[isub] = d[n-i-1] + d[n-i-1] = smin + if ncvt > 0 { + bi.Dswap(ncvt, vt[isub*ldvt:], 1, vt[(n-i-1)*ldvt:], 1) + } + if nru > 0 { + bi.Dswap(nru, u[isub:], ldu, u[n-i-1:], ldu) + } + if ncc > 0 { + bi.Dswap(ncc, c[isub*ldc:], 1, c[(n-i-1)*ldc:], 1) + } + } + } + info = 0 + for i := 0; i < n-1; i++ { + if e[i] != 0 { + info++ + } + } + return info == 0 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go new file mode 100644 index 00000000..e271c99d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgebak updates an n×m matrix V as +// V = P D V, if side == lapack.RightEV, +// V = P D^{-1} V, if side == lapack.LeftEV, +// where P and D are n×n permutation and scaling matrices, respectively, +// implicitly represented by job, scale, ilo and ihi as returned by Dgebal. +// +// Typically, columns of the matrix V contain the right or left (determined by +// side) eigenvectors of the balanced matrix output by Dgebal, and Dgebak forms +// the eigenvectors of the original matrix. +// +// Dgebak is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + switch side { + default: + panic(badEVSide) + case lapack.LeftEV, lapack.RightEV: + } + checkMatrix(n, m, v, ldv) + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + } + + // Quick return if possible. + if n == 0 || m == 0 || job == lapack.None { + return + } + + bi := blas64.Implementation() + if ilo != ihi && job != lapack.Permute { + // Backward balance. + if side == lapack.RightEV { + for i := ilo; i <= ihi; i++ { + bi.Dscal(m, scale[i], v[i*ldv:], 1) + } + } else { + for i := ilo; i <= ihi; i++ { + bi.Dscal(m, 1/scale[i], v[i*ldv:], 1) + } + } + } + if job == lapack.Scale { + return + } + // Backward permutation. + for i := ilo - 1; i >= 0; i-- { + k := int(scale[i]) + if k == i { + continue + } + bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) + } + for i := ihi + 1; i < n; i++ { + k := int(scale[i]) + if k == i { + continue + } + bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go new file mode 100644 index 00000000..ee57ead1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go @@ -0,0 +1,228 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgebal balances an n×n matrix A. Balancing consists of two stages, permuting +// and scaling. Both steps are optional and depend on the value of job. +// +// Permuting consists of applying a permutation matrix P such that the matrix +// that results from P^T*A*P takes the upper block triangular form +// [ T1 X Y ] +// P^T A P = [ 0 B Z ], +// [ 0 0 T2 ] +// where T1 and T2 are upper triangular matrices and B contains at least one +// nonzero off-diagonal element in each row and column. The indices ilo and ihi +// mark the starting and ending columns of the submatrix B. The eigenvalues of A +// isolated in the first 0 to ilo-1 and last ihi+1 to n-1 elements on the +// diagonal can be read off without any roundoff error. +// +// Scaling consists of applying a diagonal similarity transformation D such that +// D^{-1}*B*D has the 1-norm of each row and its corresponding column nearly +// equal. The output matrix is +// [ T1 X*D Y ] +// [ 0 inv(D)*B*D inv(D)*Z ]. +// [ 0 0 T2 ] +// Scaling may reduce the 1-norm of the matrix, and improve the accuracy of +// the computed eigenvalues and/or eigenvectors. +// +// job specifies the operations that will be performed on A. +// If job is lapack.None, Dgebal sets scale[i] = 1 for all i and returns ilo=0, ihi=n-1. +// If job is lapack.Permute, only permuting will be done. +// If job is lapack.Scale, only scaling will be done. +// If job is lapack.PermuteScale, both permuting and scaling will be done. +// +// On return, if job is lapack.Permute or lapack.PermuteScale, it will hold that +// A[i,j] == 0, for i > j and j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}. +// If job is lapack.None or lapack.Scale, or if n == 0, it will hold that +// ilo == 0 and ihi == n-1. +// +// On return, scale will contain information about the permutations and scaling +// factors applied to A. If π(j) denotes the index of the column interchanged +// with column j, and D[j,j] denotes the scaling factor applied to column j, +// then +// scale[j] == π(j), for j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}, +// == D[j,j], for j ∈ {ilo, ..., ihi}. +// scale must have length equal to n, otherwise Dgebal will panic. +// +// Dgebal is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebal(job lapack.Job, n int, a []float64, lda int, scale []float64) (ilo, ihi int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + checkMatrix(n, n, a, lda) + if len(scale) != n { + panic("lapack: bad length of scale") + } + + ilo = 0 + ihi = n - 1 + + if n == 0 || job == lapack.None { + for i := range scale { + scale[i] = 1 + } + return ilo, ihi + } + + bi := blas64.Implementation() + swapped := true + + if job == lapack.Scale { + goto scaling + } + + // Permutation to isolate eigenvalues if possible. + // + // Search for rows isolating an eigenvalue and push them down. + for swapped { + swapped = false + rows: + for i := ihi; i >= 0; i-- { + for j := 0; j <= ihi; j++ { + if i == j { + continue + } + if a[i*lda+j] != 0 { + continue rows + } + } + // Row i has only zero off-diagonal elements in the + // block A[ilo:ihi+1,ilo:ihi+1]. + scale[ihi] = float64(i) + if i != ihi { + bi.Dswap(ihi+1, a[i:], lda, a[ihi:], lda) + bi.Dswap(n, a[i*lda:], 1, a[ihi*lda:], 1) + } + if ihi == 0 { + scale[0] = 1 + return ilo, ihi + } + ihi-- + swapped = true + break + } + } + // Search for columns isolating an eigenvalue and push them left. + swapped = true + for swapped { + swapped = false + columns: + for j := ilo; j <= ihi; j++ { + for i := ilo; i <= ihi; i++ { + if i == j { + continue + } + if a[i*lda+j] != 0 { + continue columns + } + } + // Column j has only zero off-diagonal elements in the + // block A[ilo:ihi+1,ilo:ihi+1]. + scale[ilo] = float64(j) + if j != ilo { + bi.Dswap(ihi+1, a[j:], lda, a[ilo:], lda) + bi.Dswap(n-ilo, a[j*lda+ilo:], 1, a[ilo*lda+ilo:], 1) + } + swapped = true + ilo++ + break + } + } + +scaling: + for i := ilo; i <= ihi; i++ { + scale[i] = 1 + } + + if job == lapack.Permute { + return ilo, ihi + } + + // Balance the submatrix in rows ilo to ihi. + + const ( + // sclfac should be a power of 2 to avoid roundoff errors. + // Elements of scale are restricted to powers of sclfac, + // therefore the matrix will be only nearly balanced. + sclfac = 2 + // factor determines the minimum reduction of the row and column + // norms that is considered non-negligible. It must be less than 1. + factor = 0.95 + ) + sfmin1 := dlamchS / dlamchP + sfmax1 := 1 / sfmin1 + sfmin2 := sfmin1 * sclfac + sfmax2 := 1 / sfmin2 + + // Iterative loop for norm reduction. + var conv bool + for !conv { + conv = true + for i := ilo; i <= ihi; i++ { + c := bi.Dnrm2(ihi-ilo+1, a[ilo*lda+i:], lda) + r := bi.Dnrm2(ihi-ilo+1, a[i*lda+ilo:], 1) + ica := bi.Idamax(ihi+1, a[i:], lda) + ca := math.Abs(a[ica*lda+i]) + ira := bi.Idamax(n-ilo, a[i*lda+ilo:], 1) + ra := math.Abs(a[i*lda+ilo+ira]) + + // Guard against zero c or r due to underflow. + if c == 0 || r == 0 { + continue + } + g := r / sclfac + f := 1.0 + s := c + r + for c < g && math.Max(f, math.Max(c, ca)) < sfmax2 && math.Min(r, math.Min(g, ra)) > sfmin2 { + if math.IsNaN(c + f + ca + r + g + ra) { + // Panic if NaN to avoid infinite loop. + panic("lapack: NaN") + } + f *= sclfac + c *= sclfac + ca *= sclfac + g /= sclfac + r /= sclfac + ra /= sclfac + } + g = c / sclfac + for r <= g && math.Max(r, ra) < sfmax2 && math.Min(math.Min(f, c), math.Min(g, ca)) > sfmin2 { + f /= sclfac + c /= sclfac + ca /= sclfac + g /= sclfac + r *= sclfac + ra *= sclfac + } + + if c+r >= factor*s { + // Reduction would be negligible. + continue + } + if f < 1 && scale[i] < 1 && f*scale[i] <= sfmin1 { + continue + } + if f > 1 && scale[i] > 1 && scale[i] >= sfmax1/f { + continue + } + + // Now balance. + scale[i] *= f + bi.Dscal(n-ilo, 1/f, a[i*lda+ilo:], 1) + bi.Dscal(ihi+1, f, a[i:], lda) + conv = false + } + } + return ilo, ihi +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go new file mode 100644 index 00000000..7f7f61c1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go @@ -0,0 +1,74 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgebd2 reduces an m×n matrix A to upper or lower bidiagonal form by an orthogonal +// transformation. +// Q^T * A * P = B +// if m >= n, B is upper diagonal, otherwise B is lower bidiagonal. +// d is the diagonal, len = min(m,n) +// e is the off-diagonal len = min(m,n)-1 +// +// Dgebd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) { + checkMatrix(m, n, a, lda) + if len(d) < min(m, n) { + panic(badD) + } + if len(e) < min(m, n)-1 { + panic(badE) + } + if len(tauQ) < min(m, n) { + panic(badTauQ) + } + if len(tauP) < min(m, n) { + panic(badTauP) + } + if len(work) < max(m, n) { + panic(badWork) + } + if m >= n { + for i := 0; i < n; i++ { + a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) + d[i] = a[i*lda+i] + a[i*lda+i] = 1 + // Apply H_i to A[i:m, i+1:n] from the left. + if i < n-1 { + impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tauQ[i], a[i*lda+i+1:], lda, work) + } + a[i*lda+i] = d[i] + if i < n-1 { + a[i*lda+i+1], tauP[i] = impl.Dlarfg(n-i-1, a[i*lda+i+1], a[i*lda+min(i+2, n-1):], 1) + e[i] = a[i*lda+i+1] + a[i*lda+i+1] = 1 + impl.Dlarf(blas.Right, m-i-1, n-i-1, a[i*lda+i+1:], 1, tauP[i], a[(i+1)*lda+i+1:], lda, work) + a[i*lda+i+1] = e[i] + } else { + tauP[i] = 0 + } + } + return + } + for i := 0; i < m; i++ { + a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + d[i] = a[i*lda+i] + a[i*lda+i] = 1 + if i < m-1 { + impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tauP[i], a[(i+1)*lda+i:], lda, work) + } + a[i*lda+i] = d[i] + if i < m-1 { + a[(i+1)*lda+i], tauQ[i] = impl.Dlarfg(m-i-1, a[(i+1)*lda+i], a[min(i+2, m-1)*lda+i:], lda) + e[i] = a[(i+1)*lda+i] + a[(i+1)*lda+i] = 1 + impl.Dlarf(blas.Left, m-i-1, n-i-1, a[(i+1)*lda+i:], lda, tauQ[i], a[(i+1)*lda+i+1:], lda, work) + a[(i+1)*lda+i] = e[i] + } else { + tauQ[i] = 0 + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go new file mode 100644 index 00000000..f0c041cc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by +// an orthogonal transformation: +// Q^T * A * P = B. +// The diagonal elements of B are stored in d and the off-diagonal elements are stored +// in e. These are additionally stored along the diagonal of A and the off-diagonal +// of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B is a +// lower-bidiagonal matrix. +// +// The remaining elements of A store the data needed to construct Q and P. +// The matrices Q and P are products of elementary reflectors +// if m >= n, Q = H_0 * H_1 * ... * H_{n-1}, +// P = G_0 * G_1 * ... * G_{n-2}, +// if m < n, Q = H_0 * H_1 * ... * H_{m-2}, +// P = G_0 * G_1 * ... * G_{m-1}, +// where +// H_i = I - tauQ[i] * v_i * v_i^T, +// G_i = I - tauP[i] * u_i * u_i^T. +// +// As an example, on exit the entries of A when m = 6, and n = 5 +// [ d e u1 u1 u1] +// [v1 d e u2 u2] +// [v1 v2 d e u3] +// [v1 v2 v3 d e] +// [v1 v2 v3 v4 d] +// [v1 v2 v3 v4 v5] +// and when m = 5, n = 6 +// [ d u1 u1 u1 u1 u1] +// [ e d u2 u2 u2 u2] +// [v1 e d u3 u3 u3] +// [v1 v2 e d u4 u4] +// [v1 v2 v3 e d u5] +// +// d, tauQ, and tauP must all have length at least min(m,n), and e must have +// length min(m,n) - 1, unless lwork is -1 when there is no check except for +// work which must have a length of at least one. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise. +// Dgebrd is blocked decomposition, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgebrd, +// the optimal work length will be stored into work[0]. +// +// Dgebrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + // Calculate optimal work. + nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1) + var lworkOpt int + if lwork == -1 { + if len(work) < 1 { + panic(badWork) + } + lworkOpt = ((m + n) * nb) + work[0] = float64(max(1, lworkOpt)) + return + } + minmn := min(m, n) + if len(d) < minmn { + panic(badD) + } + if len(e) < minmn-1 { + panic(badE) + } + if len(tauQ) < minmn { + panic(badTauQ) + } + if len(tauP) < minmn { + panic(badTauP) + } + ws := max(m, n) + if lwork < max(1, ws) { + panic(badWork) + } + if len(work) < lwork { + panic(badWork) + } + var nx int + if nb > 1 && nb < minmn { + nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1)) + if nx < minmn { + ws = (m + n) * nb + if lwork < ws { + nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1) + if lwork >= (m+n)*nbmin { + nb = lwork / (m + n) + } else { + nb = minmn + nx = minmn + } + } + } + } else { + nx = minmn + } + bi := blas64.Implementation() + ldworkx := nb + ldworky := nb + var i int + // Netlib lapack has minmn - nx, but this makes the last nx rows (which by + // default is large) be unblocked. As written here, the blocking is more + // consistent. + for i = 0; i < minmn-nb; i += nb { + // Reduce rows and columns i:i+nb to bidiagonal form and return + // the matrices X and Y which are needed to update the unreduced + // part of the matrix. + // X is stored in the first m rows of work, y in the next rows. + x := work[:m*ldworkx] + y := work[m*ldworkx:] + impl.Dlabrd(m-i, n-i, nb, a[i*lda+i:], lda, + d[i:], e[i:], tauQ[i:], tauP[i:], + x, ldworkx, y, ldworky) + + // Update the trailing submatrix A[i+nb:m,i+nb:n], using an update + // of the form A := A - V*Y**T - X*U**T + bi.Dgemm(blas.NoTrans, blas.Trans, m-i-nb, n-i-nb, nb, + -1, a[(i+nb)*lda+i:], lda, y[nb*ldworky:], ldworky, + 1, a[(i+nb)*lda+i+nb:], lda) + + bi.Dgemm(blas.NoTrans, blas.NoTrans, m-i-nb, n-i-nb, nb, + -1, x[nb*ldworkx:], ldworkx, a[i*lda+i+nb:], lda, + 1, a[(i+nb)*lda+i+nb:], lda) + + // Copy diagonal and off-diagonal elements of B back into A. + if m >= n { + for j := i; j < i+nb; j++ { + a[j*lda+j] = d[j] + a[j*lda+j+1] = e[j] + } + } else { + for j := i; j < i+nb; j++ { + a[j*lda+j] = d[j] + a[(j+1)*lda+j] = e[j] + } + } + } + // Use unblocked code to reduce the remainder of the matrix. + impl.Dgebd2(m-i, n-i, a[i*lda+i:], lda, d[i:], e[i:], tauQ[i:], tauP[i:], work) + work[0] = float64(lworkOpt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go new file mode 100644 index 00000000..20bafce4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go @@ -0,0 +1,81 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgecon estimates the reciprocal of the condition number of the n×n matrix A +// given the LU decomposition of the matrix. The condition number computed may +// be based on the 1-norm or the ∞-norm. +// +// The slice a contains the result of the LU decomposition of A as computed by Dgetrf. +// +// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 4*n and Dgecon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dgecon will panic otherwise. +func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic(badNorm) + } + if len(work) < 4*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + + if n == 0 { + return 1 + } else if anorm == 0 { + return 0 + } + + bi := blas64.Implementation() + var rcond, ainvnm float64 + var kase int + var normin bool + isave := new([3]int) + onenrm := norm == lapack.MaxColumnSum + smlnum := dlamchS + kase1 := 2 + if onenrm { + kase1 = 1 + } + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / ainvnm) / anorm + } + return rcond + } + var sl, su float64 + if kase == kase1 { + sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) + su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) + } else { + su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) + sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) + } + scale := sl * su + normin = true + if scale != 1 { + ix := bi.Idamax(n, work, 1) + if scale == 0 || scale < math.Abs(work[ix])*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go new file mode 100644 index 00000000..7c2d9a29 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go @@ -0,0 +1,284 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgeev computes the eigenvalues and, optionally, the left and/or right +// eigenvectors for an n×n real nonsymmetric matrix A. +// +// The right eigenvector v_j of A corresponding to an eigenvalue λ_j +// is defined by +// A v_j = λ_j v_j, +// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by +// u_j^H A = λ_j u_j^H, +// where u_j^H is the conjugate transpose of u_j. +// +// On return, A will be overwritten and the left and right eigenvectors will be +// stored, respectively, in the columns of the n×n matrices VL and VR in the +// same order as their eigenvalues. If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV, +// otherwise jobvl must be lapack.None. Right eigenvectors will be computed +// only if jobvr == lapack.ComputeRightEV, otherwise jobvr must be lapack.None. +// For other values of jobvl and jobvr Dgeev will panic. +// +// wr and wi contain the real and imaginary parts, respectively, of the computed +// eigenvalues. Complex conjugate pairs of eigenvalues appear consecutively with +// the eigenvalue having the positive imaginary part first. +// wr and wi must have length n, and Dgeev will panic otherwise. +// +// work must have length at least lwork and lwork must be at least max(1,4*n) if +// the left or right eigenvectors are computed, and at least max(1,3*n) if no +// eigenvectors are computed. For good performance, lwork must generally be +// larger. On return, optimal value of lwork will be stored in work[0]. +// +// If lwork == -1, instead of performing Dgeev, the function only calculates the +// optimal vaule of lwork and stores it into work[0]. +// +// On return, first is the index of the first valid eigenvalue. If first == 0, +// all eigenvalues and eigenvectors have been computed. If first is positive, +// Dgeev failed to compute all the eigenvalues, no eigenvectors have been +// computed and wr[first:] and wi[first:] contain those eigenvalues which have +// converged. +func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) { + var wantvl bool + switch jobvl { + default: + panic("lapack: invalid LeftEVJob") + case lapack.ComputeLeftEV: + wantvl = true + case lapack.None: + } + var wantvr bool + switch jobvr { + default: + panic("lapack: invalid RightEVJob") + case lapack.ComputeRightEV: + wantvr = true + case lapack.None: + } + switch { + case n < 0: + panic(nLT0) + case len(work) < lwork: + panic(shortWork) + } + var minwrk int + if wantvl || wantvr { + minwrk = max(1, 4*n) + } else { + minwrk = max(1, 3*n) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if wantvl { + checkMatrix(n, n, vl, ldvl) + } + if wantvr { + checkMatrix(n, n, vr, ldvr) + } + switch { + case len(wr) != n: + panic("lapack: bad length of wr") + case len(wi) != n: + panic("lapack: bad length of wi") + case lwork < minwrk: + panic(badWork) + } + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return 0 + } + + maxwrk := 2*n + n*impl.Ilaenv(1, "DGEHRD", " ", n, 1, n, 0) + if wantvl || wantvr { + maxwrk = max(maxwrk, 2*n+(n-1)*impl.Ilaenv(1, "DORGHR", " ", n, 1, n, -1)) + impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, 0, n-1, + nil, 1, nil, nil, nil, 1, work, -1) + maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) + side := lapack.LeftEV + if wantvr { + side = lapack.RightEV + } + impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, nil, 1, nil, 1, nil, 1, + n, work, -1) + maxwrk = max(maxwrk, n+int(work[0])) + maxwrk = max(maxwrk, 4*n) + } else { + impl.Dhseqr(lapack.EigenvaluesOnly, lapack.None, n, 0, n-1, + nil, 1, nil, nil, nil, 1, work, -1) + maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) + } + maxwrk = max(maxwrk, minwrk) + + if lwork == -1 { + work[0] = float64(maxwrk) + return 0 + } + + // Get machine constants. + smlnum := math.Sqrt(dlamchS) / dlamchP + bignum := 1 / smlnum + + // Scale A if max element outside range [smlnum,bignum]. + anrm := impl.Dlange(lapack.MaxAbs, n, n, a, lda, nil) + var scalea bool + var cscale float64 + if 0 < anrm && anrm < smlnum { + scalea = true + cscale = smlnum + } else if anrm > bignum { + scalea = true + cscale = bignum + } + if scalea { + impl.Dlascl(lapack.General, 0, 0, anrm, cscale, n, n, a, lda) + } + + // Balance the matrix. + workbal := work[:n] + ilo, ihi := impl.Dgebal(lapack.PermuteScale, n, a, lda, workbal) + + // Reduce to upper Hessenberg form. + iwrk := 2 * n + tau := work[n : iwrk-1] + impl.Dgehrd(n, ilo, ihi, a, lda, tau, work[iwrk:], lwork-iwrk) + + var side lapack.EVSide + if wantvl { + side = lapack.LeftEV + // Copy Householder vectors to VL. + impl.Dlacpy(blas.Lower, n, n, a, lda, vl, ldvl) + // Generate orthogonal matrix in VL. + impl.Dorghr(n, ilo, ihi, vl, ldvl, tau, work[iwrk:], lwork-iwrk) + // Perform QR iteration, accumulating Schur vectors in VL. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, ilo, ihi, + a, lda, wr, wi, vl, ldvl, work[iwrk:], lwork-iwrk) + if wantvr { + // Want left and right eigenvectors. + // Copy Schur vectors to VR. + side = lapack.RightLeftEV + impl.Dlacpy(blas.All, n, n, vl, ldvl, vr, ldvr) + } + } else if wantvr { + side = lapack.RightEV + // Copy Householder vectors to VR. + impl.Dlacpy(blas.Lower, n, n, a, lda, vr, ldvr) + // Generate orthogonal matrix in VR. + impl.Dorghr(n, ilo, ihi, vr, ldvr, tau, work[iwrk:], lwork-iwrk) + // Perform QR iteration, accumulating Schur vectors in VR. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, ilo, ihi, + a, lda, wr, wi, vr, ldvr, work[iwrk:], lwork-iwrk) + } else { + // Compute eigenvalues only. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesOnly, lapack.None, n, ilo, ihi, + a, lda, wr, wi, nil, 1, work[iwrk:], lwork-iwrk) + } + + if first > 0 { + if scalea { + // Undo scaling. + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wr, 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wi, 1) + } + work[0] = float64(maxwrk) + return first + } + + if wantvl || wantvr { + // Compute left and/or right eigenvectors. + impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, + a, lda, vl, ldvl, vr, ldvr, n, work[iwrk:], lwork-iwrk) + } + bi := blas64.Implementation() + if wantvl { + // Undo balancing of left eigenvectors. + impl.Dgebak(lapack.PermuteScale, lapack.LeftEV, n, ilo, ihi, workbal, n, vl, ldvl) + // Normalize left eigenvectors and make largest component real. + for i, wii := range wi { + if wii < 0 { + continue + } + if wii == 0 { + scl := 1 / bi.Dnrm2(n, vl[i:], ldvl) + bi.Dscal(n, scl, vl[i:], ldvl) + continue + } + scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vl[i:], ldvl), bi.Dnrm2(n, vl[i+1:], ldvl)) + bi.Dscal(n, scl, vl[i:], ldvl) + bi.Dscal(n, scl, vl[i+1:], ldvl) + for k := 0; k < n; k++ { + vi := vl[k*ldvl+i] + vi1 := vl[k*ldvl+i+1] + work[iwrk+k] = vi*vi + vi1*vi1 + } + k := bi.Idamax(n, work[iwrk:iwrk+n], 1) + cs, sn, _ := impl.Dlartg(vl[k*ldvl+i], vl[k*ldvl+i+1]) + bi.Drot(n, vl[i:], ldvl, vl[i+1:], ldvl, cs, sn) + vl[k*ldvl+i+1] = 0 + } + } + if wantvr { + // Undo balancing of right eigenvectors. + impl.Dgebak(lapack.PermuteScale, lapack.RightEV, n, ilo, ihi, workbal, n, vr, ldvr) + // Normalize right eigenvectors and make largest component real. + for i, wii := range wi { + if wii < 0 { + continue + } + if wii == 0 { + scl := 1 / bi.Dnrm2(n, vr[i:], ldvr) + bi.Dscal(n, scl, vr[i:], ldvr) + continue + } + scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vr[i:], ldvr), bi.Dnrm2(n, vr[i+1:], ldvr)) + bi.Dscal(n, scl, vr[i:], ldvr) + bi.Dscal(n, scl, vr[i+1:], ldvr) + for k := 0; k < n; k++ { + vi := vr[k*ldvr+i] + vi1 := vr[k*ldvr+i+1] + work[iwrk+k] = vi*vi + vi1*vi1 + } + k := bi.Idamax(n, work[iwrk:iwrk+n], 1) + cs, sn, _ := impl.Dlartg(vr[k*ldvr+i], vr[k*ldvr+i+1]) + bi.Drot(n, vr[i:], ldvr, vr[i+1:], ldvr, cs, sn) + vr[k*ldvr+i+1] = 0 + } + } + + if scalea { + // Undo scaling. + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) + } + + work[0] = float64(maxwrk) + return first +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go new file mode 100644 index 00000000..776f8421 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go @@ -0,0 +1,84 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgehd2 reduces a block of a general n×n matrix A to upper Hessenberg form H +// by an orthogonal similarity transformation Q^T * A * Q = H. +// +// The matrix Q is represented as a product of (ihi-ilo) elementary +// reflectors +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T +// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. +// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. +// +// On entry, a contains the n×n general matrix to be reduced. On return, the +// upper triangle and the first subdiagonal of A are overwritten with the upper +// Hessenberg matrix H, and the elements below the first subdiagonal, with the +// slice tau, represent the orthogonal matrix Q as a product of elementary +// reflectors. +// +// The contents of A are illustrated by the following example, with n = 7, ilo = +// 1 and ihi = 5. +// On entry, +// [ a a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a ] +// on return, +// [ a a h h h h a ] +// [ a h h h h a ] +// [ h h h h h h ] +// [ v1 h h h h h ] +// [ v1 v2 h h h h ] +// [ v1 v2 v3 h h h ] +// [ a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// ilo and ihi determine the block of A that will be reduced to upper Hessenberg +// form. It must hold that 0 <= ilo <= ihi <= max(0, n-1), otherwise Dgehd2 will +// panic. +// +// On return, tau will contain the scalar factors of the elementary reflectors. +// It must have length equal to n-1, otherwise Dgehd2 will panic. +// +// work must have length at least n, otherwise Dgehd2 will panic. +// +// Dgehd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) { + checkMatrix(n, n, a, lda) + switch { + case ilo < 0 || ilo > max(0, n-1): + panic(badIlo) + case ihi < min(ilo, n-1) || ihi >= n: + panic(badIhi) + case len(tau) != n-1: + panic(badTau) + case len(work) < n: + panic(badWork) + } + + for i := ilo; i < ihi; i++ { + // Compute elementary reflector H_i to annihilate A[i+2:ihi+1,i]. + var aii float64 + aii, tau[i] = impl.Dlarfg(ihi-i, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + a[(i+1)*lda+i] = 1 + + // Apply H_i to A[0:ihi+1,i+1:ihi+1] from the right. + impl.Dlarf(blas.Right, ihi+1, ihi-i, a[(i+1)*lda+i:], lda, tau[i], a[i+1:], lda, work) + + // Apply H_i to A[i+1:ihi+1,i+1:n] from the left. + impl.Dlarf(blas.Left, ihi-i, n-i-1, a[(i+1)*lda+i:], lda, tau[i], a[(i+1)*lda+i+1:], lda, work) + a[(i+1)*lda+i] = aii + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go new file mode 100644 index 00000000..0dd90fa5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go @@ -0,0 +1,183 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgehrd reduces a block of a real n×n general matrix A to upper Hessenberg +// form H by an orthogonal similarity transformation Q^T * A * Q = H. +// +// The matrix Q is represented as a product of (ihi-ilo) elementary +// reflectors +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T +// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. +// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. +// +// On entry, a contains the n×n general matrix to be reduced. On return, the +// upper triangle and the first subdiagonal of A will be overwritten with the +// upper Hessenberg matrix H, and the elements below the first subdiagonal, with +// the slice tau, represent the orthogonal matrix Q as a product of elementary +// reflectors. +// +// The contents of a are illustrated by the following example, with n = 7, ilo = +// 1 and ihi = 5. +// On entry, +// [ a a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a ] +// on return, +// [ a a h h h h a ] +// [ a h h h h a ] +// [ h h h h h h ] +// [ v1 h h h h h ] +// [ v1 v2 h h h h ] +// [ v1 v2 v3 h h h ] +// [ a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// ilo and ihi determine the block of A that will be reduced to upper Hessenberg +// form. It must hold that 0 <= ilo <= ihi < n if n > 0, and ilo == 0 and ihi == +// -1 if n == 0, otherwise Dgehrd will panic. +// +// On return, tau will contain the scalar factors of the elementary reflectors. +// Elements tau[:ilo] and tau[ihi:] will be set to zero. tau must have length +// equal to n-1 if n > 0, otherwise Dgehrd will panic. +// +// work must have length at least lwork and lwork must be at least max(1,n), +// otherwise Dgehrd will panic. On return, work[0] contains the optimal value of +// lwork. +// +// If lwork == -1, instead of performing Dgehrd, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgehrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if len(tau) != n-1 && n > 0 { + panic(badTau) + } + } + + const ( + nbmax = 64 + ldt = nbmax + 1 + tsize = ldt * nbmax + ) + // Compute the workspace requirements. + nb := min(nbmax, impl.Ilaenv(1, "DGEHRD", " ", n, ilo, ihi, -1)) + lwkopt := n*nb + tsize + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + // Set tau[:ilo] and tau[ihi:] to zero. + for i := 0; i < ilo; i++ { + tau[i] = 0 + } + for i := ihi; i < n-1; i++ { + tau[i] = 0 + } + + // Quick return if possible. + nh := ihi - ilo + 1 + if nh <= 1 { + work[0] = 1 + return + } + + // Determine the block size. + nbmin := 2 + var nx int + if 1 < nb && nb < nh { + // Determine when to cross over from blocked to unblocked code + // (last block is always handled by unblocked code). + nx = max(nb, impl.Ilaenv(3, "DGEHRD", " ", n, ilo, ihi, -1)) + if nx < nh { + // Determine if workspace is large enough for blocked code. + if lwork < n*nb+tsize { + // Not enough workspace to use optimal nb: + // determine the minimum value of nb, and reduce + // nb or force use of unblocked code. + nbmin = max(2, impl.Ilaenv(2, "DGEHRD", " ", n, ilo, ihi, -1)) + if lwork >= n*nbmin+tsize { + nb = (lwork - tsize) / n + } else { + nb = 1 + } + } + } + } + ldwork := nb // work is used as an n×nb matrix. + + var i int + if nb < nbmin || nh <= nb { + // Use unblocked code below. + i = ilo + } else { + // Use blocked code. + bi := blas64.Implementation() + iwt := n * nb // Size of the matrix Y and index where the matrix T starts in work. + for i = ilo; i < ihi-nx; i += nb { + ib := min(nb, ihi-i) + + // Reduce columns [i:i+ib] to Hessenberg form, returning the + // matrices V and T of the block reflector H = I - V*T*V^T + // which performs the reduction, and also the matrix Y = A*V*T. + impl.Dlahr2(ihi+1, i+1, ib, a[i:], lda, tau[i:], work[iwt:], ldt, work, ldwork) + + // Apply the block reflector H to A[:ihi+1,i+ib:ihi+1] from the + // right, computing A := A - Y * V^T. V[i+ib,i+ib-1] must be set + // to 1. + ei := a[(i+ib)*lda+i+ib-1] + a[(i+ib)*lda+i+ib-1] = 1 + bi.Dgemm(blas.NoTrans, blas.Trans, ihi+1, ihi-i-ib+1, ib, + -1, work, ldwork, + a[(i+ib)*lda+i:], lda, + 1, a[i+ib:], lda) + a[(i+ib)*lda+i+ib-1] = ei + + // Apply the block reflector H to A[0:i+1,i+1:i+ib-1] from the + // right. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, i+1, ib-1, + 1, a[(i+1)*lda+i:], lda, work, ldwork) + for j := 0; j <= ib-2; j++ { + bi.Daxpy(i+1, -1, work[j:], ldwork, a[i+j+1:], lda) + } + + // Apply the block reflector H to A[i+1:ihi+1,i+ib:n] from the + // left. + impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, + ihi-i, n-i-ib, ib, + a[(i+1)*lda+i:], lda, work[iwt:], ldt, a[(i+1)*lda+i+ib:], lda, work, ldwork) + } + } + // Use unblocked code to reduce the rest of the matrix. + impl.Dgehd2(n, i, ihi, a, lda, tau, work) + work[0] = float64(lwkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go new file mode 100644 index 00000000..2e4fd692 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgelq2 computes the LQ factorization of the m×n matrix A. +// +// In an LQ factorization, L is a lower triangular m×n matrix, and Q is an n×n +// orthonormal matrix. +// +// a is modified to contain the information to construct L and Q. +// The lower triangle of a contains the matrix L. The upper triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length of at least k = min(m,n) +// and this function will panic otherwise. +// +// See Dgeqr2 for a description of the elementary reflectors and orthonormal +// matrix Q. Q is constructed as a product of these elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0. +// +// work is temporary storage of length at least m and this function will panic otherwise. +// +// Dgelq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgelq2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if len(work) < m { + panic(badWork) + } + for i := 0; i < k; i++ { + a[i*lda+i], tau[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + if i < m-1 { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(blas.Right, m-i-1, n-i, + a[i*lda+i:], 1, + tau[i], + a[(i+1)*lda+i:], lda, + work) + a[i*lda+i] = aii + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go new file mode 100644 index 00000000..13485012 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgelqf computes the LQ factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgelq2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m, and this function will panic otherwise. +// Dgelqf is a blocked LQ factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgelqf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) + lworkopt := m * max(nb, 1) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + checkMatrix(m, n, a, lda) + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if k == 0 { + return + } + // Find the optimal blocking size based on the size of available memory + // and optimal machine parameters. + nbmin := 2 + var nx int + iws := m + ldwork := nb + if nb > 1 && k > nb { + nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1)) + if nx < k { + iws = m * nb + if lwork < iws { + nb = lwork / m + nbmin = max(2, impl.Ilaenv(2, "DGELQF", " ", m, n, -1, -1)) + } + } + } + // Computed blocked LQ factorization. + var i int + if nb >= nbmin && nb < k && nx < k { + for i = 0; i < k-nx; i += nb { + ib := min(k-i, nb) + impl.Dgelq2(ib, n-i, a[i*lda+i:], lda, tau[i:], work) + if i+ib < m { + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Forward, lapack.RowWise, + m-i-ib, n-i, ib, + a[i*lda+i:], lda, + work, ldwork, + a[(i+ib)*lda+i:], lda, + work[ib*ldwork:], ldwork) + } + } + } + // Perform unblocked LQ factorization on the remainder. + if i < k { + impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go new file mode 100644 index 00000000..b1d71823 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go @@ -0,0 +1,200 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgels finds a minimum-norm solution based on the matrices A and B using the +// QR or LQ factorization. Dgels returns false if the matrix +// A is singular, and true if this solution was successfully found. +// +// The minimization problem solved depends on the input parameters. +// +// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of +// A * X = B. +// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of +// A^T * X = B. +// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// Note that the least-squares solutions (cases 1 and 3) perform the minimization +// per column of B. This is not the same as finding the minimum-norm matrix. +// +// The matrix A is a general matrix of size m×n and is modified during this call. +// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, +// the elements of b specify the input matrix B. B has size m×nrhs if +// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the +// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, +// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic +// otherwise. A longer work will enable blocked algorithms to be called. +// In the special case that lwork == -1, work[0] will be set to the optimal working +// length. +func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool { + notran := trans == blas.NoTrans + checkMatrix(m, n, a, lda) + mn := min(m, n) + checkMatrix(max(m, n), nrhs, b, ldb) + + // Find optimal block size. + tpsd := true + if notran { + tpsd = false + } + var nb int + if m >= n { + nb = impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) + if tpsd { + nb = max(nb, impl.Ilaenv(1, "DORMQR", "LN", m, nrhs, n, -1)) + } else { + nb = max(nb, impl.Ilaenv(1, "DORMQR", "LT", m, nrhs, n, -1)) + } + } else { + nb = impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) + if tpsd { + nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LT", n, nrhs, m, -1)) + } else { + nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LN", n, nrhs, m, -1)) + } + } + if lwork == -1 { + work[0] = float64(max(1, mn+max(mn, nrhs)*nb)) + return true + } + + if len(work) < lwork { + panic(shortWork) + } + if lwork < mn+max(mn, nrhs) { + panic(badWork) + } + if m == 0 || n == 0 || nrhs == 0 { + impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) + return true + } + + // Scale the input matrices if they contain extreme values. + smlnum := dlamchS / dlamchP + bignum := 1 / smlnum + anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) + var iascl int + if anrm > 0 && anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) + iascl = 1 + } else if anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) + } else if anrm == 0 { + // Matrix is all zeros. + impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) + return true + } + brow := m + if tpsd { + brow = n + } + bnrm := impl.Dlange(lapack.MaxAbs, brow, nrhs, b, ldb, nil) + ibscl := 0 + if bnrm > 0 && bnrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, bnrm, smlnum, brow, nrhs, b, ldb) + ibscl = 1 + } else if bnrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bnrm, bignum, brow, nrhs, b, ldb) + ibscl = 2 + } + + // Solve the minimization problem using a QR or an LQ decomposition. + var scllen int + if m >= n { + impl.Dgeqrf(m, n, a, lda, work, work[mn:], lwork-mn) + if !tpsd { + impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n, + a, lda, + work[:n], + b, ldb, + work[mn:], lwork-mn) + ok := impl.Dtrtrs(blas.Upper, blas.NoTrans, blas.NonUnit, n, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + scllen = n + } else { + ok := impl.Dtrtrs(blas.Upper, blas.Trans, blas.NonUnit, n, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + for i := n; i < m; i++ { + for j := 0; j < nrhs; j++ { + b[i*ldb+j] = 0 + } + } + impl.Dormqr(blas.Left, blas.NoTrans, m, nrhs, n, + a, lda, + work[:n], + b, ldb, + work[mn:], lwork-mn) + scllen = m + } + } else { + impl.Dgelqf(m, n, a, lda, work, work[mn:], lwork-mn) + if !tpsd { + ok := impl.Dtrtrs(blas.Lower, blas.NoTrans, blas.NonUnit, + m, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + for i := m; i < n; i++ { + for j := 0; j < nrhs; j++ { + b[i*ldb+j] = 0 + } + } + impl.Dormlq(blas.Left, blas.Trans, n, nrhs, m, + a, lda, + work, + b, ldb, + work[mn:], lwork-mn) + scllen = n + } else { + impl.Dormlq(blas.Left, blas.NoTrans, n, nrhs, m, + a, lda, + work, + b, ldb, + work[mn:], lwork-mn) + ok := impl.Dtrtrs(blas.Lower, blas.Trans, blas.NonUnit, + m, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + } + } + + // Adjust answer vector based on scaling. + if iascl == 1 { + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, scllen, nrhs, b, ldb) + } + if iascl == 2 { + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, scllen, nrhs, b, ldb) + } + if ibscl == 1 { + impl.Dlascl(lapack.General, 0, 0, smlnum, bnrm, scllen, nrhs, b, ldb) + } + if ibscl == 2 { + impl.Dlascl(lapack.General, 0, 0, bignum, bnrm, scllen, nrhs, b, ldb) + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go new file mode 100644 index 00000000..19040cfa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go @@ -0,0 +1,45 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgeql2 computes the QL factorization of the m×n matrix A. That is, Dgeql2 +// computes Q and L such that +// A = Q * L +// where Q is an m×m orthonormal matrix and L is a lower trapezoidal matrix. +// +// Q is represented as a product of elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0 +// where k = min(m,n) and each H_i has the form +// H_i = I - tau[i] * v_i * v_i^T +// Vector v_i has v[m-k+i+1:m] = 0, v[m-k+i] = 1, and v[:m-k+i+1] is stored on +// exit in A[0:m-k+i-1, n-k+i]. +// +// tau must have length at least min(m,n), and Dgeql2 will panic otherwise. +// +// work is temporary memory storage and must have length at least n. +// +// Dgeql2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeql2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < min(m, n) { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + k := min(m, n) + var aii float64 + for i := k - 1; i >= 0; i-- { + // Generate elementary reflector H_i to annihilate A[0:m-k+i-1, n-k+i]. + aii, tau[i] = impl.Dlarfg(m-k+i+1, a[(m-k+i)*lda+n-k+i], a[n-k+i:], lda) + + // Apply H_i to A[0:m-k+i, 0:n-k+i-1] from the left. + a[(m-k+i)*lda+n-k+i] = 1 + impl.Dlarf(blas.Left, m-k+i+1, n-k+i, a[n-k+i:], lda, tau[i], a, lda, work) + a[(m-k+i)*lda+n-k+i] = aii + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go new file mode 100644 index 00000000..50529cac --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go @@ -0,0 +1,174 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgeqp3 computes a QR factorization with column pivoting of the +// m×n matrix A: A*P = Q*R using Level 3 BLAS. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{k-1}, where k = min(m,n). +// Each H_i has the form +// H_i = I - tau * v * v^T +// where tau and v are real vectors with v[0:i-1] = 0 and v[i] = 1; +// v[i:m] is stored on exit in A[i:m, i], and tau in tau[i]. +// +// jpvt specifies a column pivot to be applied to A. If +// jpvt[j] is at least zero, the jth column of A is permuted +// to the front of A*P (a leading column), if jpvt[j] is -1 +// the jth column of A is a free column. If jpvt[j] < -1, Dgeqp3 +// will panic. On return, jpvt holds the permutation that was +// applied; the jth column of A*P was the jpvt[j] column of A. +// jpvt must have length n or Dgeqp3 will panic. +// +// tau holds the scalar factors of the elementary reflectors. +// It must have length min(m, n), otherwise Dgeqp3 will panic. +// +// work must have length at least max(1,lwork), and lwork must be at least +// 3*n+1, otherwise Dgeqp3 will panic. For optimal performance lwork must +// be at least 2*n+(n+1)*nb, where nb is the optimal blocksize. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dgeqp3, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgeqp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) { + const ( + inb = 1 + inbmin = 2 + ixover = 3 + ) + checkMatrix(m, n, a, lda) + + if len(jpvt) != n { + panic(badIpiv) + } + for _, v := range jpvt { + if v < -1 || n <= v { + panic("lapack: jpvt element out of range") + } + } + minmn := min(m, n) + if len(work) < max(1, lwork) { + panic(badWork) + } + + var iws, lwkopt, nb int + if minmn == 0 { + iws = 1 + lwkopt = 1 + } else { + iws = 3*n + 1 + nb = impl.Ilaenv(inb, "DGEQRF", " ", m, n, -1, -1) + lwkopt = 2*n + (n+1)*nb + } + work[0] = float64(lwkopt) + + if lwork == -1 { + return + } + + if len(tau) < minmn { + panic(badTau) + } + + bi := blas64.Implementation() + + // Move initial columns up front. + var nfxd int + for j := 0; j < n; j++ { + if jpvt[j] == -1 { + jpvt[j] = j + continue + } + if j != nfxd { + bi.Dswap(m, a[j:], lda, a[nfxd:], lda) + jpvt[j], jpvt[nfxd] = jpvt[nfxd], j + } else { + jpvt[j] = j + } + nfxd++ + } + + // Factorize nfxd columns. + // + // Compute the QR factorization of nfxd columns and update remaining columns. + if nfxd > 0 { + na := min(m, nfxd) + impl.Dgeqrf(m, na, a, lda, tau, work, lwork) + iws = max(iws, int(work[0])) + if na < n { + impl.Dormqr(blas.Left, blas.Trans, m, n-na, na, a, lda, tau[:na], a[na:], lda, + work, lwork) + iws = max(iws, int(work[0])) + } + } + + if nfxd >= minmn { + work[0] = float64(iws) + return + } + + // Factorize free columns. + sm := m - nfxd + sn := n - nfxd + sminmn := minmn - nfxd + + // Determine the block size. + nb = impl.Ilaenv(inb, "DGEQRF", " ", sm, sn, -1, -1) + nbmin := 2 + nx := 0 + + if 1 < nb && nb < sminmn { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(ixover, "DGEQRF", " ", sm, sn, -1, -1)) + + if nx < sminmn { + // Determine if workspace is large enough for blocked code. + minws := 2*sn + (sn+1)*nb + iws = max(iws, minws) + if lwork < minws { + // Not enough workspace to use optimal nb. Reduce + // nb and determine the minimum value of nb. + nb = (lwork - 2*sn) / (sn + 1) + nbmin = max(2, impl.Ilaenv(inbmin, "DGEQRF", " ", sm, sn, -1, -1)) + } + } + } + + // Initialize partial column norms. + // The first n elements of work store the exact column norms. + for j := nfxd; j < n; j++ { + work[j] = bi.Dnrm2(sm, a[nfxd*lda+j:], lda) + work[n+j] = work[j] + } + j := nfxd + if nbmin <= nb && nb < sminmn && nx < sminmn { + // Use blocked code initially. + + // Compute factorization. + var fjb int + for topbmn := minmn - nx; j < topbmn; j += fjb { + jb := min(nb, topbmn-j) + + // Factorize jb columns among columns j:n. + fjb = impl.Dlaqps(m, n-j, j, jb, a[j:], lda, jpvt[j:], tau[j:], + work[j:n], work[j+n:2*n], work[2*n:2*n+jb], work[2*n+jb:], jb) + } + } + + // Use unblocked code to factor the last or only block. + if j < minmn { + impl.Dlaqp2(m, n-j, j, a[j:], lda, jpvt[j:], tau[j:], + work[j:n], work[j+n:2*n], work[2*n:]) + } + + work[0] = float64(iws) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go new file mode 100644 index 00000000..6b032063 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go @@ -0,0 +1,59 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgeqr2 computes a QR factorization of the m×n matrix A. +// +// In a QR factorization, Q is an m×m orthonormal matrix, and R is an +// upper triangular m×n matrix. +// +// A is modified to contain the information to construct Q and R. +// The upper triangle of a contains the matrix R. The lower triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length at least min(m,n), and +// this function will panic otherwise. +// +// The ith elementary reflector can be explicitly constructed by first extracting +// the +// v[j] = 0 j < i +// v[j] = 1 j == i +// v[j] = a[j*lda+i] j > i +// and computing H_i = I - tau[i] * v * v^T. +// +// The orthonormal matrix Q can be constructed from a product of these elementary +// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). +// +// work is temporary storage of length at least n and this function will panic otherwise. +// +// Dgeqr2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) { + // TODO(btracey): This is oriented such that columns of a are eliminated. + // This likely could be re-arranged to take better advantage of row-major + // storage. + checkMatrix(m, n, a, lda) + if len(work) < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + for i := 0; i < k; i++ { + // Generate elementary reflector H_i. + a[i*lda+i], tau[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min((i+1), m-1)*lda+i:], lda) + if i < n-1 { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(blas.Left, m-i, n-i-1, + a[i*lda+i:], lda, + tau[i], + a[i*lda+i+1:], lda, + work) + a[i*lda+i] = aii + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go new file mode 100644 index 00000000..c5662c91 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go @@ -0,0 +1,99 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgeqrf computes the QR factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgeqr2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// The length of work must be at least max(1, lwork) and lwork must be -1 +// or at least n, otherwise this function will panic. +// Dgeqrf is a blocked QR factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgeqrf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + if len(work) < max(1, lwork) { + panic(shortWork) + } + // nb is the optimal blocksize, i.e. the number of columns transformed at a time. + nb := impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) + lworkopt := n * max(nb, 1) + lworkopt = max(n, lworkopt) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + checkMatrix(m, n, a, lda) + if lwork < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if k == 0 { + work[0] = float64(lworkopt) + return + } + nbmin := 2 // Minimal block size. + var nx int // Use unblocked (unless changed in the next for loop) + iws := n + ldwork := nb + // Only consider blocked if the suggested block size is > 1 and the + // number of rows or columns is sufficiently large. + if 1 < nb && nb < k { + // nx is the block size at which the code switches from blocked + // to unblocked. + nx = max(0, impl.Ilaenv(3, "DGEQRF", " ", m, n, -1, -1)) + if k > nx { + iws = ldwork * n + if lwork < iws { + // Not enough workspace to use the optimal block + // size. Get the minimum block size instead. + nb = lwork / n + nbmin = max(2, impl.Ilaenv(2, "DGEQRF", " ", m, n, -1, -1)) + } + } + } + for i := range work { + work[i] = 0 + } + // Compute QR using a blocked algorithm. + var i int + if nbmin <= nb && nb < k && nx < k { + for i = 0; i < k-nx; i += nb { + ib := min(k-i, nb) + // Compute the QR factorization of the current block. + impl.Dgeqr2(m-i, ib, a[i*lda+i:], lda, tau[i:], work) + if i+ib < n { + // Form the triangular factor of the block reflector and apply H^T + // In Dlarft, work becomes the T matrix. + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, + m-i, n-i-ib, ib, + a[i*lda+i:], lda, + work, ldwork, + a[i*lda+i+ib:], lda, + work[ib*ldwork:], ldwork) + } + } + } + // Call unblocked code on the remaining columns. + if i < k { + impl.Dgeqr2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go new file mode 100644 index 00000000..ef20a022 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go @@ -0,0 +1,53 @@ +// Copyright ©2017 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dgerq2 computes an RQ factorization of the m×n matrix A, +// A = R * Q. +// On exit, if m <= n, the upper triangle of the subarray +// A[0:m, n-m:n] contains the m×m upper triangular matrix R. +// If m >= n, the elements on and above the (m-n)-th subdiagonal +// contain the m×n upper trapezoidal matrix R. +// The remaining elements, with tau, represent the +// orthogonal matrix Q as a product of min(m,n) elementary +// reflectors. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{min(m,n)-1}. +// Each H(i) has the form +// H_i = I - tau_i * v * v^T +// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], +// v[n-k+i:n] = 0 and v[n-k+i] = 1. +// +// tau must have length min(m,n) and work must have length m, otherwise +// Dgerq2 will panic. +// +// Dgerq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgerq2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if len(work) < m { + panic(badWork) + } + + for i := k - 1; i >= 0; i-- { + // Generate elementary reflector H[i] to annihilate + // A[m-k+i, 0:n-k+i-1]. + mki := m - k + i + nki := n - k + i + var aii float64 + aii, tau[i] = impl.Dlarfg(nki+1, a[mki*lda+nki], a[mki*lda:], 1) + + // Apply H[i] to A[0:m-k+i-1, 0:n-k+i] from the right. + a[mki*lda+nki] = 1 + impl.Dlarf(blas.Right, mki, nki+1, a[mki*lda:], 1, tau[i], a, lda, work) + a[mki*lda+nki] = aii + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go new file mode 100644 index 00000000..daf8f0d0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go @@ -0,0 +1,128 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgerqf computes an RQ factorization of the m×n matrix A, +// A = R * Q. +// On exit, if m <= n, the upper triangle of the subarray +// A[0:m, n-m:n] contains the m×m upper triangular matrix R. +// If m >= n, the elements on and above the (m-n)-th subdiagonal +// contain the m×n upper trapezoidal matrix R. +// The remaining elements, with tau, represent the +// orthogonal matrix Q as a product of min(m,n) elementary +// reflectors. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{min(m,n)-1}. +// Each H(i) has the form +// H_i = I - tau_i * v * v^T +// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], +// v[n-k+i:n] = 0 and v[n-k+i] = 1. +// +// tau must have length min(m,n), work must have length max(1, lwork), +// and lwork must be -1 or at least max(1, m), otherwise Dgerqf will panic. +// On exit, work[0] will contain the optimal length for work. +// +// Dgerqf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + + if len(work) < max(1, lwork) { + panic(shortWork) + } + if lwork != -1 && lwork < max(1, m) { + panic(badWork) + } + + k := min(m, n) + if len(tau) != k { + panic(badTau) + } + + var nb, lwkopt int + if k == 0 { + lwkopt = 1 + } else { + nb = impl.Ilaenv(1, "DGERQF", " ", m, n, -1, -1) + lwkopt = m * nb + } + work[0] = float64(lwkopt) + + if lwork == -1 { + return + } + + // Return quickly if possible. + if k == 0 { + return + } + + nbmin := 2 + nx := 1 + iws := m + var ldwork int + if 1 < nb && nb < k { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(3, "DGERQF", " ", m, n, -1, -1)) + if nx < k { + // Determine whether workspace is large enough for blocked code. + iws = m * nb + if lwork < iws { + // Not enough workspace to use optimal nb. Reduce + // nb and determine the minimum value of nb. + nb = lwork / m + nbmin = max(2, impl.Ilaenv(2, "DGERQF", " ", m, n, -1, -1)) + } + ldwork = nb + } + } + + var mu, nu int + if nbmin <= nb && nb < k && nx < k { + // Use blocked code initially. + // The last kk rows are handled by the block method. + ki := ((k - nx - 1) / nb) * nb + kk := min(k, ki+nb) + + var i int + for i = k - kk + ki; i >= k-kk; i -= nb { + ib := min(k-i, nb) + + // Compute the RQ factorization of the current block + // A[m-k+i:m-k+i+ib-1, 0:n-k+i+ib-1]. + impl.Dgerq2(ib, n-k+i+ib, a[(m-k+i)*lda:], lda, tau[i:], work) + if m-k+i > 0 { + // Form the triangular factor of the block reflector + // H = H_{i+ib-1} . . . H_{i+1} H_i. + impl.Dlarft(lapack.Backward, lapack.RowWise, + n-k+i+ib, ib, a[(m-k+i)*lda:], lda, tau[i:], + work, ldwork) + + // Apply H to A[0:m-k+i-1, 0:n-k+i+ib-1] from the right. + impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Backward, lapack.RowWise, + m-k+i, n-k+i+ib, ib, a[(m-k+i)*lda:], lda, + work, ldwork, + a, lda, + work[ib*ldwork:], ldwork) + } + } + mu = m - k + i + nb + nu = n - k + i + nb + } else { + mu = m + nu = n + } + + // Use unblocked code to factor the last or only block. + if mu > 0 && nu > 0 { + impl.Dgerq2(mu, nu, a, lda, tau, work) + } + work[0] = float64(iws) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go new file mode 100644 index 00000000..82a151c7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go @@ -0,0 +1,1356 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +const noSVDO = "dgesvd: not coded for overwrite" + +// Dgesvd computes the singular value decomposition of the input matrix A. +// +// The singular value decomposition is +// A = U * Sigma * V^T +// where Sigma is an m×n diagonal matrix containing the singular values of A, +// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first +// min(m,n) columns of U and V are the left and right singular vectors of A +// respectively. +// +// jobU and jobVT are options for computing the singular vectors. The behavior +// is as follows +// jobU == lapack.SVDAll All m columns of U are returned in u +// jobU == lapack.SVDInPlace The first min(m,n) columns are returned in u +// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a +// jobU == lapack.SVDNone The columns of U are not computed. +// The behavior is the same for jobVT and the rows of V^T. At most one of jobU +// and jobVT can equal lapack.SVDOverwrite, and Dgesvd will panic otherwise. +// +// On entry, a contains the data for the m×n matrix A. During the call to Dgesvd +// the data is overwritten. On exit, A contains the appropriate singular vectors +// if either job is lapack.SVDOverwrite. +// +// s is a slice of length at least min(m,n) and on exit contains the singular +// values in decreasing order. +// +// u contains the left singular vectors on exit, stored column-wise. If +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is +// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is +// not used. +// +// vt contains the left singular vectors on exit, stored row-wise. If +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is +// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is +// not used. +// +// work is a slice for storing temporary memory, and lwork is the usable size of +// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). +// If lwork == -1, instead of performing Dgesvd, the optimal work length will be +// stored into work[0]. Dgesvd will panic if the working memory has insufficient +// storage. +// +// Dgesvd returns whether the decomposition successfully completed. +func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) { + minmn := min(m, n) + checkMatrix(m, n, a, lda) + if jobU == lapack.SVDAll { + checkMatrix(m, m, u, ldu) + } else if jobU == lapack.SVDInPlace { + checkMatrix(m, minmn, u, ldu) + } + if jobVT == lapack.SVDAll { + checkMatrix(n, n, vt, ldvt) + } else if jobVT == lapack.SVDInPlace { + checkMatrix(minmn, n, vt, ldvt) + } + if jobU == lapack.SVDOverwrite && jobVT == lapack.SVDOverwrite { + panic("lapack: both jobU and jobVT are lapack.SVDOverwrite") + } + if len(s) < minmn { + panic(badS) + } + if jobU == lapack.SVDOverwrite || jobVT == lapack.SVDOverwrite { + panic(noSVDO) + } + if m == 0 || n == 0 { + return true + } + + wantua := jobU == lapack.SVDAll + wantus := jobU == lapack.SVDInPlace + wantuas := wantua || wantus + wantuo := jobU == lapack.SVDOverwrite + wantun := jobU == lapack.None + + wantva := jobVT == lapack.SVDAll + wantvs := jobVT == lapack.SVDInPlace + wantvas := wantva || wantvs + wantvo := jobVT == lapack.SVDOverwrite + wantvn := jobVT == lapack.None + + bi := blas64.Implementation() + var mnthr int + + // Compute optimal space for subroutines. + maxwrk := 1 + opts := string(jobU) + string(jobVT) + var wrkbl, bdspac int + if m >= n { + mnthr = impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) + bdspac = 5 * n + impl.Dgeqrf(m, n, a, lda, nil, work, -1) + lwork_dgeqrf := int(work[0]) + impl.Dorgqr(m, n, n, a, lda, nil, work, -1) + lwork_dorgqr_n := int(work[0]) + impl.Dorgqr(m, m, n, a, lda, nil, work, -1) + lwork_dorgqr_m := int(work[0]) + impl.Dgebrd(n, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + impl.Dorgbr(lapack.ApplyP, n, n, n, a, lda, nil, work, -1) + lwork_dorgbr_p := int(work[0]) + impl.Dorgbr(lapack.ApplyQ, n, n, n, a, lda, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + + if m >= mnthr { + // m >> n + if wantun { + // Path 1 + maxwrk = n + lwork_dgeqrf + maxwrk = max(maxwrk, 3*n+lwork_dgebrd) + if wantvo || wantvas { + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) + } + maxwrk = max(maxwrk, bdspac) + } else if wantuo && wantvn { + // Path 2 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(n*n+wrkbl, n*n+m*n+n) + } else if wantuo && wantvs { + // Path 3 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(n*n+wrkbl, n*n+m*n+n) + } else if wantus && wantvn { + // Path 4 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantus && wantvo { + // Path 5 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*n*n + wrkbl + } else if wantus && wantvas { + // Path 6 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantua && wantvn { + // Path 7 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantua && wantvo { + // Path 8 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*n*n + wrkbl + } else if wantua && wantvas { + // Path 9 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } + } else { + // Path 10: m > n + impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + maxwrk = 3*n + lwork_dgebrd + if wantus || wantuo { + impl.Dorgbr(lapack.ApplyQ, m, n, n, a, lda, nil, work, -1) + lwork_dorgbr_q = int(work[0]) + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) + } + if wantua { + impl.Dorgbr(lapack.ApplyQ, m, m, n, a, lda, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) + } + if !wantvn { + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) + } + maxwrk = max(maxwrk, bdspac) + } + } else { + mnthr = impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) + + bdspac = 5 * m + impl.Dgelqf(m, n, a, lda, nil, work, -1) + lwork_dgelqf := int(work[0]) + impl.Dorglq(n, n, m, nil, n, nil, work, -1) + lwork_dorglq_n := int(work[0]) + impl.Dorglq(m, n, m, a, lda, nil, work, -1) + lwork_dorglq_m := int(work[0]) + impl.Dgebrd(m, m, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + impl.Dorgbr(lapack.ApplyP, m, m, m, a, n, nil, work, -1) + lwork_dorgbr_p := int(work[0]) + impl.Dorgbr(lapack.ApplyQ, m, m, m, a, n, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + if n >= mnthr { + // n >> m + if wantvn { + // Path 1t + maxwrk = m + lwork_dgelqf + maxwrk = max(maxwrk, 3*m+lwork_dgebrd) + if wantuo || wantuas { + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) + } + maxwrk = max(maxwrk, bdspac) + } else if wantvo && wantun { + // Path 2t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(m*m+wrkbl, m*m+m*n+m) + } else if wantvo && wantuas { + // Path 3t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(m*m+wrkbl, m*m+m*n+m) + } else if wantvs && wantun { + // Path 4t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantvs && wantuo { + // Path 5t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*m*m + wrkbl + } else if wantvs && wantuas { + // Path 6t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantva && wantun { + // Path 7t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantva && wantuo { + // Path 8t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*m*m + wrkbl + } else if wantva && wantuas { + // Path 9t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } + } else { + // Path 10t, n > m + impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd = int(work[0]) + maxwrk = 3*m + lwork_dgebrd + if wantvs || wantvo { + impl.Dorgbr(lapack.ApplyP, m, n, m, a, n, nil, work, -1) + lwork_dorgbr_p = int(work[0]) + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) + } + if wantva { + impl.Dorgbr(lapack.ApplyP, n, n, m, a, n, nil, work, -1) + lwork_dorgbr_p = int(work[0]) + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) + } + if !wantun { + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) + } + maxwrk = max(maxwrk, bdspac) + } + } + + minWork := max(1, 5*minmn) + if !((wantun && m >= mnthr) || (wantvn && n >= mnthr)) { + minWork = max(minWork, 3*minmn+max(m, n)) + } + + if lwork != -1 { + if len(work) < lwork { + panic(badWork) + } + if lwork < minWork { + panic(badWork) + } + } + if m == 0 || n == 0 { + return true + } + + maxwrk = max(maxwrk, minWork) + work[0] = float64(maxwrk) + if lwork == -1 { + return true + } + + // Perform decomposition. + eps := dlamchE + smlnum := math.Sqrt(dlamchS) / eps + bignum := 1 / smlnum + + // Scale A if max element outside range [smlnum, bignum]. + anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) + var iscl bool + if anrm > 0 && anrm < smlnum { + iscl = true + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) + } else if anrm > bignum { + iscl = true + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) + } + + var ie int + if m >= n { + // If A has sufficiently more rows than columns, use the QR decomposition. + if m >= mnthr { + // m >> n + if wantun { + // Path 1. + itau := 0 + iwork := itau + n + + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Zero out below R. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + ie = 0 + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + ncvt := 0 + if wantvo || wantvas { + // Generate P^T. + impl.Dorgbr(lapack.ApplyP, n, n, n, a, lda, work[itaup:], + work[iwork:], lwork-iwork) + ncvt = n + } + iwork = ie + n + + // Perform bidiagonal QR iteration computing right singular vectors + // of A in A if desired. + ok = impl.Dbdsqr(blas.Upper, n, ncvt, 0, 0, s, work[ie:], + a, lda, work, 1, work, 1, work[iwork:]) + + // If right singular vectors desired in VT, copy them there. + if wantvas { + impl.Dlacpy(blas.All, n, n, a, lda, vt, ldvt) + } + } else if wantuo && wantvn { + // Path 2 + panic(noSVDO) + } else if wantuo && wantvas { + // Path 3 + panic(noSVDO) + } else if wantus { + if wantvn { + // Path 4 + if lwork >= n*n+max(4*n, bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*n { + ldworkr = lda + } else { + ldworkr = n + } + itau := ir + ldworkr*n + iwork := itau + n + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to work[ir:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) + + // Generate Q in A. + impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[ir:]. + impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate left vectors bidiagonalizing R in work[ir:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[ir:], ldworkr, + work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, compuing left singular + // vectors of R in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, + work[ir:], ldworkr, work, 1, work[iwork:]) + + // Multiply Q in A by left singular vectors of R in + // work[ir:], storing result in U. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, + work[ir:], ldworkr, 0, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Zero out below R in A. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left vectors bidiagonalizing R. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left + // singular vectors of A in U. + ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], work, 1, + u, ldu, work, 1, work[iwork:]) + } + } else if wantvo { + // Path 5 + panic(noSVDO) + } else if wantvas { + // Path 6 + if lwork >= n*n+max(4*n, bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*n { + ldworku = lda + } else { + ldworku = n + } + itau := iu + ldworku*n + iwork := itau + n + + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + // Copy R to work[iu:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) + + // Generate Q in A. + impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[iu:], copying result to VT. + impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) + + // Generate left bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[iu:], ldworku, + work[itauq:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[iu:], and computing right singular + // vectors of R in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], + vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) + + // Multiply Q in A by left singular vectors of R in + // work[iu:], storing result in U. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, + work[iu:], ldworku, 0, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q * R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to VT, zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } else if wantua { + if wantvn { + // Path 7 + if lwork >= n*n+max(max(n+m, 4*n), bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*n { + ldworkr = lda + } else { + ldworkr = n + } + itau := ir + ldworkr*n + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Copy R to work[ir:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[ir:]. + impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in work[ir:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[ir:], ldworkr, + work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, + work[ir:], ldworkr, work, 1, work[iwork:]) + + // Multiply Q in U by left singular vectors of R in + // work[ir:], storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, u, ldu, + work[ir:], ldworkr, 0, a, lda) + + // Copy left singular vectors of A from A to U. + impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Zero out below R in A. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in A. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left + // singular vectors of A in U. + ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], + work, 1, u, ldu, work, 1, work[iwork:]) + } + } else if wantvo { + // Path 8. + panic(noSVDO) + } else if wantvas { + // Path 9. + if lwork >= n*n+max(max(n+m, 4*n), bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*n { + ldworku = lda + } else { + ldworku = n + } + itau := iu + ldworku*n + iwork := itau + n + + // Compute A = Q * R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to work[iu:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) + + ie = itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[iu:], copying result to VT. + impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) + + // Generate left bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[iu:], ldworku, + work[itauq:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[iu:] and computing right + // singular vectors of R in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], + vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) + + // Multiply Q in U by left singular vectors of R in + // work[iu:], storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, + u, ldu, work[iu:], ldworku, 0, a, lda) + + // Copy left singular vectors of A from A to U. + impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) + + /* + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, + m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + */ + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R from A to VT, zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, + m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } + } else { + // Path 10. + // M at least N, but not much larger. + ie = 0 + itauq := ie + n + itaup := itauq + n + iwork := itaup + n + + // Bidiagonalize A. + impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + if wantuas { + // Left singular vectors are desired in U. Copy result to U and + // generate left biadiagonalizing vectors in U. + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + var ncu int + if wantus { + ncu = n + } + if wantua { + ncu = m + } + impl.Dorgbr(lapack.ApplyQ, m, ncu, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + } + if wantvas { + // Right singular vectors are desired in VT. Copy result to VT and + // generate left biadiagonalizing vectors in VT. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) + } + if wantuo { + panic(noSVDO) + } + if wantvo { + panic(noSVDO) + } + iwork = ie + n + var nru, ncvt int + if wantuas || wantuo { + nru = m + } + if wantun { + nru = 0 + } + if wantvas || wantvo { + ncvt = n + } + if wantvn { + ncvt = 0 + } + if !wantuo && !wantvo { + // Perform bidiagonal QR iteration, if desired, computing left + // singular vectors in U and right singular vectors in VT. + ok = impl.Dbdsqr(blas.Upper, n, ncvt, nru, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } else { + // There will be two branches when the implementation is complete. + panic(noSVDO) + } + } + } else { + // A has more columns than rows. If A has sufficiently more columns than + // rows, first reduce using the LQ decomposition. + if n >= mnthr { + // n >> m. + if wantvn { + // Path 1t. + itau := 0 + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Zero out above L. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + ie := 0 + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:itauq], + work[itauq:itaup], work[itaup:iwork], work[iwork:], lwork-iwork) + if wantuo || wantuas { + impl.Dorgbr(lapack.ApplyQ, m, m, m, a, lda, + work[itauq:], work[iwork:], lwork-iwork) + } + iwork = ie + m + nru := 0 + if wantuo || wantuas { + nru = m + } + + // Perform bidiagonal QR iteration, computing left singular vectors + // of A in A if desired. + ok = impl.Dbdsqr(blas.Upper, m, 0, nru, 0, s, work[ie:], + work, 1, a, lda, work, 1, work[iwork:]) + + // If left singular vectors desired in U, copy them there. + if wantuas { + impl.Dlacpy(blas.All, m, m, a, lda, u, ldu) + } + } else if wantvo && wantun { + // Path 2t. + panic(noSVDO) + } else if wantvo && wantuas { + // Path 3t. + panic(noSVDO) + } else if wantvs { + if wantun { + // Path 4t. + if lwork >= m*m+max(4*m, bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*m { + ldworkr = lda + } else { + ldworkr = m + } + itau := ir + ldworkr*m + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[ir:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) + + // Generate Q in A. + impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[ir:]. + impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate right vectors bidiagonalizing L in work[ir:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[ir:], ldworkr, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right singular + // vectors of L in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], + work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[ir:] by + // Q in A, storing result in VT. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[ir:], ldworkr, a, lda, 0, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy result to VT. + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Zero out above L in A. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right vectors bidiagonalizing L by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right + // singular vectors of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], + vt, ldvt, work, 1, work, 1, work[iwork:]) + } + } else if wantuo { + // Path 5t. + panic(noSVDO) + } else if wantuas { + // Path 6t. + if lwork >= m*m+max(4*m, bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*m { + ldworku = lda + } else { + ldworku = m + } + itau := iu + ldworku*m + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[iu:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) + + // Generate Q in A. + impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[iu:], copying result to U. + impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) + + // Generate right bidiagionalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[iu:], ldworku, + work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of L in U and computing right singular vectors of + // L in work[iu:]. + ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], + work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[iu:] by + // Q in A, storing result in VT. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[iu:], ldworku, a, lda, 0, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L*Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to U, zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in U. + impl.Dgebrd(m, m, u, ldu, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in U by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], vt, ldvt, + u, ldu, work, 1, work[iwork:]) + } + } + } else if wantva { + if wantun { + // Path 7t. + if lwork >= m*m+max(max(n+m, 4*m), bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*m { + ldworkr = lda + } else { + ldworkr = m + } + itau := ir + ldworkr*m + iwork := itau + m + + // Compute A = L*Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Copy L to work[ir:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[ir:]. + impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in work[ir:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[ir:], ldworkr, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right + // singular vectors of L in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], + work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[ir:] by + // Q in VT, storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[ir:], ldworkr, vt, ldvt, 0, a, lda) + + // Copy right singular vectors of A from A to VT. + impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + // Compute A = L * Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Zero out above L in A. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in A by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right singular + // vectors of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], + vt, ldvt, work, 1, work, 1, work[iwork:]) + } + } else if wantuo { + panic(noSVDO) + } else if wantuas { + // Path 9t. + if lwork >= m*m+max(max(m+n, 4*m), bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + + var ldworku int + if lwork >= wrkbl+lda*m { + ldworku = lda + } else { + ldworku = m + } + itau := iu + ldworku*m + iwork := itau + m + + // Generate A = L * Q copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[iu:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) + ie = itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[iu:], copying result to U. + impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) + + // Generate right bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[iu:], ldworku, + work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of L in U and computing right singular vectors + // of L in work[iu:]. + ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], + work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[iu:] + // Q in VT, storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[iu:], ldworku, vt, ldvt, 0, a, lda) + + // Copy right singular vectors of A from A to VT. + impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L * Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to U, zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) + + ie = itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in U. + impl.Dgebrd(m, m, u, ldu, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in U by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } + } else { + // Path 10t. + // N at least M, but not much larger. + ie = 0 + itauq := ie + m + itaup := itauq + m + iwork := itaup + m + + // Bidiagonalize A. + impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + if wantuas { + // If left singular vectors desired in U, copy result to U and + // generate left bidiagonalizing vectors in U. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dorgbr(lapack.ApplyQ, m, m, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + } + if wantvas { + // If right singular vectors desired in VT, copy result to VT + // and generate right bidiagonalizing vectors in VT. + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + var nrvt int + if wantva { + nrvt = n + } else { + nrvt = m + } + impl.Dorgbr(lapack.ApplyP, nrvt, n, m, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) + } + if wantuo { + panic(noSVDO) + } + if wantvo { + panic(noSVDO) + } + iwork = ie + m + var nru, ncvt int + if wantuas || wantuo { + nru = m + } + if wantvas || wantvo { + ncvt = n + } + if !wantuo && !wantvo { + // Perform bidiagonal QR iteration, if desired, computing left + // singular vectors in U and computing right singular vectors in + // VT. + ok = impl.Dbdsqr(blas.Lower, m, ncvt, nru, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } else { + // There will be two branches when the implementation is complete. + panic(noSVDO) + } + } + } + if !ok { + if ie > 1 { + for i := 0; i < minmn-1; i++ { + work[i+1] = work[i+ie] + } + } + if ie < 1 { + for i := minmn - 2; i >= 0; i-- { + work[i+1] = work[i+ie] + } + } + } + // Undo scaling if necessary. + if iscl { + if anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn, 1, s, minmn) + } + if !ok && anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn-1, 1, work[minmn:], minmn) + } + if anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn, 1, s, minmn) + } + if !ok && anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn-1, 1, work[minmn:], minmn) + } + } + work[0] = float64(maxwrk) + return ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go new file mode 100644 index 00000000..3167d160 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go @@ -0,0 +1,69 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetf2 computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of a into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetf2 returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +// +// Dgetf2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + if m == 0 || n == 0 { + return true + } + bi := blas64.Implementation() + sfmin := dlamchS + ok = true + for j := 0; j < mn; j++ { + // Find a pivot and test for singularity. + jp := j + bi.Idamax(m-j, a[j*lda+j:], lda) + ipiv[j] = jp + if a[jp*lda+j] == 0 { + ok = false + } else { + // Swap the rows if necessary. + if jp != j { + bi.Dswap(n, a[j*lda:], 1, a[jp*lda:], 1) + } + if j < m-1 { + aj := a[j*lda+j] + if math.Abs(aj) >= sfmin { + bi.Dscal(m-j-1, 1/aj, a[(j+1)*lda+j:], lda) + } else { + for i := 0; i < m-j-1; i++ { + a[(j+1)*lda+j] = a[(j+1)*lda+j] / a[lda*j+j] + } + } + } + } + if j < mn-1 { + bi.Dger(m-j-1, n-j-1, -1, a[(j+1)*lda+j:], lda, a[j*lda+j+1:], 1, a[(j+1)*lda+j+1:], lda) + } + } + return ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go new file mode 100644 index 00000000..2b95668c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go @@ -0,0 +1,70 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetrf computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of A into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetrf is the blocked version of the algorithm. +// +// Dgetrf returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func (impl Implementation) Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + if m == 0 || n == 0 { + return false + } + bi := blas64.Implementation() + nb := impl.Ilaenv(1, "DGETRF", " ", m, n, -1, -1) + if nb <= 1 || nb >= min(m, n) { + // Use the unblocked algorithm. + return impl.Dgetf2(m, n, a, lda, ipiv) + } + ok = true + for j := 0; j < mn; j += nb { + jb := min(mn-j, nb) + blockOk := impl.Dgetf2(m-j, jb, a[j*lda+j:], lda, ipiv[j:]) + if !blockOk { + ok = false + } + for i := j; i <= min(m-1, j+jb-1); i++ { + ipiv[i] = j + ipiv[i] + } + impl.Dlaswp(j, a, lda, j, j+jb-1, ipiv[:j+jb], 1) + if j+jb < n { + impl.Dlaswp(n-j-jb, a[j+jb:], lda, j, j+jb-1, ipiv[:j+jb], 1) + bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, + jb, n-j-jb, 1, + a[j*lda+j:], lda, + a[j*lda+j+jb:], lda) + if j+jb < m { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m-j-jb, n-j-jb, jb, -1, + a[(j+jb)*lda+j:], lda, + a[j*lda+j+jb:], lda, + 1, a[(j+jb)*lda+j+jb:], lda) + } + } + } + return ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go new file mode 100644 index 00000000..993d6c02 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go @@ -0,0 +1,92 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetri computes the inverse of the matrix A using the LU factorization computed +// by Dgetrf. On entry, a contains the PLU decomposition of A as computed by +// Dgetrf and on exit contains the reciprocal of the original matrix. +// +// Dgetri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= n and this function will panic otherwise. +// Dgetri is a blocked inversion, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgetri, +// the optimal work length will be stored into work[0]. +func (impl Implementation) Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + if len(ipiv) < n { + panic(badIpiv) + } + nb := impl.Ilaenv(1, "DGETRI", " ", n, -1, -1, -1) + if lwork == -1 { + work[0] = float64(n * nb) + return true + } + if lwork < n { + panic(badWork) + } + if len(work) < lwork { + panic(badWork) + } + if n == 0 { + return true + } + ok = impl.Dtrtri(blas.Upper, blas.NonUnit, n, a, lda) + if !ok { + return false + } + nbmin := 2 + ldwork := nb + if nb > 1 && nb < n { + iws := max(ldwork*n, 1) + if lwork < iws { + nb = lwork / ldwork + nbmin = max(2, impl.Ilaenv(2, "DGETRI", " ", n, -1, -1, -1)) + } + } + bi := blas64.Implementation() + // TODO(btracey): Replace this with a more row-major oriented algorithm. + if nb < nbmin || nb >= n { + // Unblocked code. + for j := n - 1; j >= 0; j-- { + for i := j + 1; i < n; i++ { + work[i*ldwork] = a[i*lda+j] + a[i*lda+j] = 0 + } + if j < n { + bi.Dgemv(blas.NoTrans, n, n-j-1, -1, a[(j+1):], lda, work[(j+1)*ldwork:], ldwork, 1, a[j:], lda) + } + } + } else { + nn := ((n - 1) / nb) * nb + for j := nn; j >= 0; j -= nb { + jb := min(nb, n-j) + for jj := j; jj < j+jb-1; jj++ { + for i := jj + 1; i < n; i++ { + work[i*ldwork+(jj-j)] = a[i*lda+jj] + a[i*lda+jj] = 0 + } + } + if j+jb < n { + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, jb, n-j-jb, -1, a[(j+jb):], lda, work[(j+jb)*ldwork:], ldwork, 1, a[j:], lda) + bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, jb, 1, work[j*ldwork:], ldwork, a[j:], lda) + } + } + } + for j := n - 2; j >= 0; j-- { + jp := ipiv[j] + if jp != j { + bi.Dswap(n, a[j:], lda, a[jp:], lda) + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go new file mode 100644 index 00000000..ca5a9b2a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go @@ -0,0 +1,55 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetrs solves a system of equations using an LU factorization. +// The system of equations solved is +// A * X = B if trans == blas.Trans +// A^T * X = B if trans == blas.NoTrans +// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. +// +// On entry b contains the elements of the matrix B. On exit, b contains the +// elements of X, the solution to the system of equations. +// +// a and ipiv contain the LU factorization of A and the permutation indices as +// computed by Dgetrf. ipiv is zero-indexed. +func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) { + checkMatrix(n, n, a, lda) + checkMatrix(n, nrhs, b, ldb) + if len(ipiv) < n { + panic(badIpiv) + } + if n == 0 || nrhs == 0 { + return + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + bi := blas64.Implementation() + if trans == blas.NoTrans { + // Solve A * X = B. + impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, 1) + // Solve L * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, + n, nrhs, 1, a, lda, b, ldb) + // Solve U * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, + n, nrhs, 1, a, lda, b, ldb) + return + } + // Solve A^T * X = B. + // Solve U^T * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, + n, nrhs, 1, a, lda, b, ldb) + // Solve L^T * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.Unit, + n, nrhs, 1, a, lda, b, ldb) + impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, -1) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go new file mode 100644 index 00000000..cf3635d9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go @@ -0,0 +1,230 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dggsvd3 computes the generalized singular value decomposition (GSVD) +// of an m×n matrix A and p×n matrix B: +// U^T*A*Q = D1*[ 0 R ] +// +// V^T*B*Q = D2*[ 0 R ] +// where U, V and Q are orthogonal matrices. +// +// Dggsvd3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and +// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following +// structures, respectively: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// Dggsvd3 computes C, S, R, and optionally the orthogonal transformation +// matrices U, V and Q. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// alpha and beta must have length n or Dggsvd3 will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, iwork contains the permutation required to sort alpha descending. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than n, otherwise Dggsvd3 will panic. If +// lwork is -1, work[0] holds the optimal lwork on return, but Dggsvd3 does +// not perform the GSVD. +func (impl Implementation) Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) { + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + wantu := jobU == lapack.GSVDU + if wantu { + checkMatrix(m, m, u, ldu) + } else if jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + wantv := jobV == lapack.GSVDV + if wantv { + checkMatrix(p, p, v, ldv) + } else if jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + wantq := jobQ == lapack.GSVDQ + if wantq { + checkMatrix(n, n, q, ldq) + } else if jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + if lwork != -1 && lwork <= n { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(shortWork) + } + if len(iwork) < n { + panic(badWork) + } + + // Determine optimal work length. + impl.Dggsvp3(jobU, jobV, jobQ, + m, p, n, + a, lda, + b, ldb, + 0, 0, + u, ldu, + v, ldv, + q, ldq, + iwork, + work, work, -1) + lwkopt := n + int(work[0]) + lwkopt = max(lwkopt, 2*n) + lwkopt = max(lwkopt, 1) + work[0] = float64(lwkopt) + if lwork == -1 { + return 0, 0, true + } + + // Compute the Frobenius norm of matrices A and B. + anorm := impl.Dlange(lapack.NormFrob, m, n, a, lda, nil) + bnorm := impl.Dlange(lapack.NormFrob, p, n, b, ldb, nil) + + // Get machine precision and set up threshold for determining + // the effective numerical rank of the matrices A and B. + tola := float64(max(m, n)) * math.Max(anorm, dlamchS) * dlamchP + tolb := float64(max(p, n)) * math.Max(bnorm, dlamchS) * dlamchP + + // Preprocessing. + k, l = impl.Dggsvp3(jobU, jobV, jobQ, + m, p, n, + a, lda, + b, ldb, + tola, tolb, + u, ldu, + v, ldv, + q, ldq, + iwork, + work[:n], work[n:], lwork-n) + + // Compute the GSVD of two upper "triangular" matrices. + _, ok = impl.Dtgsja(jobU, jobV, jobQ, + m, p, n, + k, l, + a, lda, + b, ldb, + tola, tolb, + alpha, beta, + u, ldu, + v, ldv, + q, ldq, + work) + + // Sort the singular values and store the pivot indices in iwork + // Copy alpha to work, then sort alpha in work. + bi := blas64.Implementation() + bi.Dcopy(n, alpha, 1, work[:n], 1) + ibnd := min(l, m-k) + for i := 0; i < ibnd; i++ { + // Scan for largest alpha_{k+i}. + isub := i + smax := work[k+i] + for j := i + 1; j < ibnd; j++ { + if v := work[k+j]; v > smax { + isub = j + smax = v + } + } + if isub != i { + work[k+isub] = work[k+i] + work[k+i] = smax + iwork[k+i] = k + isub + } else { + iwork[k+i] = k + i + } + } + + work[0] = float64(lwkopt) + + return k, l, ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go new file mode 100644 index 00000000..bd068ff1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go @@ -0,0 +1,273 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dggsvp3 computes orthogonal matrices U, V and Q such that +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// V^T*B*Q = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// Dggsvp3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps. +// Where eps is the machine epsilon. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than zero, otherwise Dggsvp3 will panic. +// +// Dggsvp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) { + const forward = true + + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + wantu := jobU == lapack.GSVDU + if !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + wantv := jobV == lapack.GSVDV + if !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + wantq := jobQ == lapack.GSVDQ + if !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(iwork) != n { + panic(badWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(badWork) + } + + var lwkopt int + impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, -1) + lwkopt = int(work[0]) + if wantv { + lwkopt = max(lwkopt, p) + } + lwkopt = max(lwkopt, min(n, p)) + lwkopt = max(lwkopt, m) + if wantq { + lwkopt = max(lwkopt, n) + } + impl.Dgeqp3(m, n, a, lda, iwork, tau, work, -1) + lwkopt = max(lwkopt, int(work[0])) + lwkopt = max(1, lwkopt) + if lwork == -1 { + work[0] = float64(lwkopt) + return 0, 0 + } + + // tau check must come after lwkopt query since + // the Dggsvd3 call for lwkopt query may have + // lwork == -1, and tau is provided by work. + if len(tau) < n { + panic(badTau) + } + + // QR with column pivoting of B: B*P = V*[ S11 S12 ]. + // [ 0 0 ] + for i := range iwork[:n] { + iwork[i] = 0 + } + impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, lwork) + + // Update A := A*P. + impl.Dlapmt(forward, m, n, a, lda, iwork) + + // Determine the effective rank of matrix B. + for i := 0; i < min(p, n); i++ { + if math.Abs(b[i*ldb+i]) > tolb { + l++ + } + } + + if wantv { + // Copy the details of V, and form V. + impl.Dlaset(blas.All, p, p, 0, 0, v, ldv) + if p > 1 { + impl.Dlacpy(blas.Lower, p-1, min(p, n), b[ldb:], ldb, v[ldv:], ldv) + } + impl.Dorg2r(p, p, min(p, n), v, ldv, tau, work) + } + + // Clean up B. + for i := 1; i < l; i++ { + r := b[i*ldb : i*ldb+i] + for j := range r { + r[j] = 0 + } + } + if p > l { + impl.Dlaset(blas.All, p-l, n, 0, 0, b[l*ldb:], ldb) + } + + if wantq { + // Set Q = I and update Q := Q*P. + impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) + impl.Dlapmt(forward, n, n, q, ldq, iwork) + } + + if p >= l && n != l { + // RQ factorization of [ S11 S12 ]: [ S11 S12 ] = [ 0 S12 ]*Z. + impl.Dgerq2(l, n, b, ldb, tau, work) + + // Update A := A*Z^T. + impl.Dormr2(blas.Right, blas.Trans, m, n, l, b, ldb, tau, a, lda, work) + + if wantq { + // Update Q := Q*Z^T. + impl.Dormr2(blas.Right, blas.Trans, n, n, l, b, ldb, tau, q, ldq, work) + } + + // Clean up B. + impl.Dlaset(blas.All, l, n-l, 0, 0, b, ldb) + for i := 1; i < l; i++ { + r := b[i*ldb+n-l : i*ldb+i+n-l] + for j := range r { + r[j] = 0 + } + } + } + + // Let N-L L + // A = [ A11 A12 ] M, + // + // then the following does the complete QR decomposition of A11: + // + // A11 = U*[ 0 T12 ]*P1^T. + // [ 0 0 ] + for i := range iwork[:n-l] { + iwork[i] = 0 + } + impl.Dgeqp3(m, n-l, a, lda, iwork[:n-l], tau, work, lwork) + + // Determine the effective rank of A11. + for i := 0; i < min(m, n-l); i++ { + if math.Abs(a[i*lda+i]) > tola { + k++ + } + } + + // Update A12 := U^T*A12, where A12 = A[0:m, n-l:n]. + impl.Dorm2r(blas.Left, blas.Trans, m, l, min(m, n-l), a, lda, tau, a[n-l:], lda, work) + + if wantu { + // Copy the details of U, and form U. + impl.Dlaset(blas.All, m, m, 0, 0, u, ldu) + if m > 1 { + impl.Dlacpy(blas.Lower, m-1, min(m, n-l), a[lda:], lda, u[ldu:], ldu) + } + impl.Dorg2r(m, m, min(m, n-l), u, ldu, tau, work) + } + + if wantq { + // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*P1. + impl.Dlapmt(forward, n, n-l, q, ldq, iwork[:n-l]) + } + + // Clean up A: set the strictly lower triangular part of + // A[0:k, 0:k] = 0, and A[k:m, 0:n-l] = 0. + for i := 1; i < k; i++ { + r := a[i*lda : i*lda+i] + for j := range r { + r[j] = 0 + } + } + if m > k { + impl.Dlaset(blas.All, m-k, n-l, 0, 0, a[k*lda:], lda) + } + + if n-l > k { + // RQ factorization of [ T11 T12 ] = [ 0 T12 ]*Z1. + impl.Dgerq2(k, n-l, a, lda, tau, work) + + if wantq { + // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*Z1^T. + impl.Dorm2r(blas.Right, blas.Trans, n, n-l, k, a, lda, tau, q, ldq, work) + } + + // Clean up A. + impl.Dlaset(blas.All, k, n-l-k, 0, 0, a, lda) + for i := 1; i < k; i++ { + r := a[i*lda+n-k-l : i*lda+i+n-k-l] + for j := range r { + a[j] = 0 + } + } + } + + if m > k { + // QR factorization of A[k:m, n-l:n]. + impl.Dgeqr2(m-k, l, a[k*lda+n-l:], lda, tau, work) + if wantu { + // Update U[:, k:m) := U[:, k:m]*U1. + impl.Dorm2r(blas.Right, blas.NoTrans, m, m-k, min(m-k, l), a[k*lda+n-l:], lda, tau, u[k:], ldu, work) + } + + // Clean up A. + for i := k + 1; i < m; i++ { + r := a[i*lda+n-l : i*lda+min(n-l+i-k, n)] + for j := range r { + r[j] = 0 + } + } + } + + work[0] = float64(lwkopt) + return k, l +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go new file mode 100644 index 00000000..a8c81888 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go @@ -0,0 +1,257 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dhseqr computes the eigenvalues of an n×n Hessenberg matrix H and, +// optionally, the matrices T and Z from the Schur decomposition +// H = Z T Z^T, +// where T is an n×n upper quasi-triangular matrix (the Schur form), and Z is +// the n×n orthogonal matrix of Schur vectors. +// +// Optionally Z may be postmultiplied into an input orthogonal matrix Q so that +// this routine can give the Schur factorization of a matrix A which has been +// reduced to the Hessenberg form H by the orthogonal matrix Q: +// A = Q H Q^T = (QZ) T (QZ)^T. +// +// If job == lapack.EigenvaluesOnly, only the eigenvalues will be computed. +// If job == lapack.EigenvaluesAndSchur, the eigenvalues and the Schur form T will +// be computed. +// For other values of job Dhseqr will panic. +// +// If compz == lapack.None, no Schur vectors will be computed and Z will not be +// referenced. +// If compz == lapack.HessEV, on return Z will contain the matrix of Schur +// vectors of H. +// If compz == lapack.OriginalEV, on entry z is assumed to contain the orthogonal +// matrix Q that is the identity except for the submatrix +// Q[ilo:ihi+1,ilo:ihi+1]. On return z will be updated to the product Q*Z. +// +// ilo and ihi determine the block of H on which Dhseqr operates. It is assumed +// that H is already upper triangular in rows and columns [0:ilo] and [ihi+1:n], +// although it will be only checked that the block is isolated, that is, +// ilo == 0 or H[ilo,ilo-1] == 0, +// ihi == n-1 or H[ihi+1,ihi] == 0, +// and Dhseqr will panic otherwise. ilo and ihi are typically set by a previous +// call to Dgebal, otherwise they should be set to 0 and n-1, respectively. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0. +// +// wr and wi must have length n. +// +// work must have length at least lwork and lwork must be at least max(1,n) +// otherwise Dhseqr will panic. The minimum lwork delivers very good and +// sometimes optimal performance, although lwork as large as 11*n may be +// required. On return, work[0] will contain the optimal value of lwork. +// +// If lwork is -1, instead of performing Dhseqr, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// unconverged indicates whether Dhseqr computed all the eigenvalues. +// +// If unconverged == 0, all the eigenvalues have been computed and their real +// and imaginary parts will be stored on return in wr and wi, respectively. If +// two eigenvalues are computed as a complex conjugate pair, they are stored in +// consecutive elements of wr and wi, say the i-th and (i+1)th, with wi[i] > 0 +// and wi[i+1] < 0. +// +// If unconverged == 0 and job == lapack.EigenvaluesAndSchur, on return H will +// contain the upper quasi-triangular matrix T from the Schur decomposition (the +// Schur form). 2×2 diagonal blocks (corresponding to complex conjugate pairs of +// eigenvalues) will be returned in standard form, with +// H[i,i] == H[i+1,i+1], +// and +// H[i+1,i]*H[i,i+1] < 0. +// The eigenvalues will be stored in wr and wi in the same order as on the +// diagonal of the Schur form returned in H, with +// wr[i] = H[i,i], +// and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, +// wi[i] = sqrt(-H[i+1,i]*H[i,i+1]), +// wi[i+1] = -wi[i]. +// +// If unconverged == 0 and job == lapack.EigenvaluesOnly, the contents of h +// on return is unspecified. +// +// If unconverged > 0, some eigenvalues have not converged, and the blocks +// [0:ilo] and [unconverged:n] of wr and wi will contain those eigenvalues which +// have been successfully computed. Failures are rare. +// +// If unconverged > 0 and job == lapack.EigenvaluesOnly, on return the +// remaining unconverged eigenvalues are the eigenvalues of the upper Hessenberg +// matrix H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged > 0 and job == lapack.EigenvaluesAndSchur, then on +// return +// (initial H) U = U (final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged > 0 and compz == lapack.OriginalEV, then on return +// (final Z) = (initial Z) U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// If unconverged > 0 and compz == lapack.HessEV, then on return +// (final Z) = U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// References: +// [1] R. Byers. LAPACK 3.1 xHSEQR: Tuning and Implementation Notes on the +// Small Bulge Multi-Shift QR Algorithm with Aggressive Early Deflation. +// LAPACK Working Note 187 (2007) +// URL: http://www.netlib.org/lapack/lawnspdf/lawn187.pdf +// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: +// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix +// Anal. Appl. 23(4) (2002), pp. 929—947 +// URL: http://dx.doi.org/10.1137/S0895479801384573 +// [3] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +// Dhseqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, z []float64, ldz int, work []float64, lwork int) (unconverged int) { + var wantt bool + switch job { + default: + panic(badEVJob) + case lapack.EigenvaluesOnly: + case lapack.EigenvaluesAndSchur: + wantt = true + } + var wantz bool + switch compz { + default: + panic(badEVComp) + case lapack.None: + case lapack.HessEV, lapack.OriginalEV: + wantz = true + } + switch { + case n < 0: + panic(nLT0) + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(n, n, h, ldh) + switch { + case wantz: + checkMatrix(n, n, z, ldz) + case len(wr) < n: + panic("lapack: wr has insufficient length") + case len(wi) < n: + panic("lapack: wi has insufficient length") + } + } + + const ( + // Matrices of order ntiny or smaller must be processed by + // Dlahqr because of insufficient subdiagonal scratch space. + // This is a hard limit. + ntiny = 11 + + // nl is the size of a local workspace to help small matrices + // through a rare Dlahqr failure. nl > ntiny is required and + // nl <= nmin = Ilaenv(ispec=12,...) is recommended (the default + // value of nmin is 75). Using nl = 49 allows up to six + // simultaneous shifts and a 16×16 deflation window. + nl = 49 + ) + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return 0 + } + + // Quick return in case of a workspace query. + if lwork == -1 { + impl.Dlaqr04(wantt, wantz, n, ilo, ihi, nil, 0, nil, nil, ilo, ihi, nil, 0, work, -1, 1) + work[0] = math.Max(float64(n), work[0]) + return 0 + } + + // Copy eigenvalues isolated by Dgebal. + for i := 0; i < ilo; i++ { + wr[i] = h[i*ldh+i] + wi[i] = 0 + } + for i := ihi + 1; i < n; i++ { + wr[i] = h[i*ldh+i] + wi[i] = 0 + } + + // Initialize Z to identity matrix if requested. + if compz == lapack.HessEV { + impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) + } + + // Quick return if possible. + if ilo == ihi { + wr[ilo] = h[ilo*ldh+ilo] + wi[ilo] = 0 + return 0 + } + + // Dlahqr/Dlaqr04 crossover point. + nmin := impl.Ilaenv(12, "DHSEQR", string(job)+string(compz), n, ilo, ihi, lwork) + nmin = max(ntiny, nmin) + + if n > nmin { + // Dlaqr0 for big matrices. + unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], + ilo, ihi, z, ldz, work, lwork, 1) + } else { + // Dlahqr for small matrices. + unconverged = impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], + ilo, ihi, z, ldz) + if unconverged > 0 { + // A rare Dlahqr failure! Dlaqr04 sometimes succeeds + // when Dlahqr fails. + kbot := unconverged + if n >= nl { + // Larger matrices have enough subdiagonal + // scratch space to call Dlaqr04 directly. + unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, kbot, h, ldh, + wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, work, lwork, 1) + } else { + // Tiny matrices don't have enough subdiagonal + // scratch space to benefit from Dlaqr04. Hence, + // tiny matrices must be copied into a larger + // array before calling Dlaqr04. + var hl [nl * nl]float64 + impl.Dlacpy(blas.All, n, n, h, ldh, hl[:], nl) + impl.Dlaset(blas.All, nl, nl-n, 0, 0, hl[n:], nl) + var workl [nl]float64 + unconverged = impl.Dlaqr04(wantt, wantz, nl, ilo, kbot, hl[:], nl, + wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, workl[:], nl, 1) + work[0] = workl[0] + if wantt || unconverged > 0 { + impl.Dlacpy(blas.All, n, n, hl[:], nl, h, ldh) + } + } + } + } + // Zero out under the first subdiagonal, if necessary. + if (wantt || unconverged > 0) && n > 2 { + impl.Dlaset(blas.Lower, n-2, n-2, 0, 0, h[2*ldh:], ldh) + } + + work[0] = math.Max(float64(n), work[0]) + return unconverged +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go new file mode 100644 index 00000000..abe5dae0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlabrd reduces the first NB rows and columns of a real general m×n matrix +// A to upper or lower bidiagonal form by an orthogonal transformation +// Q**T * A * P +// If m >= n, A is reduced to upper bidiagonal form and upon exit the elements +// on and below the diagonal in the first nb columns represent the elementary +// reflectors, and the elements above the diagonal in the first nb rows represent +// the matrix P. If m < n, A is reduced to lower bidiagonal form and the elements +// P is instead stored above the diagonal. +// +// The reduction to bidiagonal form is stored in d and e, where d are the diagonal +// elements, and e are the off-diagonal elements. +// +// The matrices Q and P are products of elementary reflectors +// Q = H_0 * H_1 * ... * H_{nb-1} +// P = G_0 * G_1 * ... * G_{nb-1} +// where +// H_i = I - tauQ[i] * v_i * v_i^T +// G_i = I - tauP[i] * u_i * u_i^T +// +// As an example, on exit the entries of A when m = 6, n = 5, and nb = 2 +// [ 1 1 u1 u1 u1] +// [v1 1 1 u2 u2] +// [v1 v2 a a a] +// [v1 v2 a a a] +// [v1 v2 a a a] +// [v1 v2 a a a] +// and when m = 5, n = 6, and nb = 2 +// [ 1 u1 u1 u1 u1 u1] +// [ 1 1 u2 u2 u2 u2] +// [v1 1 a a a a] +// [v1 v2 a a a a] +// [v1 v2 a a a a] +// +// Dlabrd also returns the matrices X and Y which are used with U and V to +// apply the transformation to the unreduced part of the matrix +// A := A - V*Y^T - X*U^T +// and returns the matrices X and Y which are needed to apply the +// transformation to the unreduced part of A. +// +// X is an m×nb matrix, Y is an n×nb matrix. d, e, taup, and tauq must all have +// length at least nb. Dlabrd will panic if these size constraints are violated. +// +// Dlabrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauQ, tauP, x []float64, ldx int, y []float64, ldy int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, nb, x, ldx) + checkMatrix(n, nb, y, ldy) + if len(d) < nb { + panic(badD) + } + if len(e) < nb { + panic(badE) + } + if len(tauQ) < nb { + panic(badTauQ) + } + if len(tauP) < nb { + panic(badTauP) + } + if m <= 0 || n <= 0 { + return + } + bi := blas64.Implementation() + if m >= n { + // Reduce to upper bidiagonal form. + for i := 0; i < nb; i++ { + bi.Dgemv(blas.NoTrans, m-i, i, -1, a[i*lda:], lda, y[i*ldy:], 1, 1, a[i*lda+i:], lda) + bi.Dgemv(blas.NoTrans, m-i, i, -1, x[i*ldx:], ldx, a[i:], lda, 1, a[i*lda+i:], lda) + + a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) + d[i] = a[i*lda+i] + if i < n-1 { + // Compute Y[i+1:n, i]. + a[i*lda+i] = 1 + bi.Dgemv(blas.Trans, m-i, n-i-1, 1, a[i*lda+i+1:], lda, a[i*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i, i, 1, a[i*lda:], lda, a[i*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i, i, 1, x[i*ldx:], ldx, a[i*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) + + // Update A[i, i+1:n]. + bi.Dgemv(blas.NoTrans, n-i-1, i+1, -1, y[(i+1)*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i+1:], 1) + bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, x[i*ldx:], 1, 1, a[i*lda+i+1:], 1) + + // Generate reflection P[i] to annihilate A[i, i+2:n]. + a[i*lda+i+1], tauP[i] = impl.Dlarfg(n-i-1, a[i*lda+i+1], a[i*lda+min(i+2, n-1):], 1) + e[i] = a[i*lda+i+1] + a[i*lda+i+1] = 1 + + // Compute X[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[i*lda+i+1:], 1, 0, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.Trans, n-i-1, i+1, 1, y[(i+1)*ldy:], ldy, a[i*lda+i+1:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.NoTrans, i, n-i-1, 1, a[i+1:], lda, a[i*lda+i+1:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) + } + } + return + } + // Reduce to lower bidiagonal form. + for i := 0; i < nb; i++ { + // Update A[i,i:n] + bi.Dgemv(blas.NoTrans, n-i, i, -1, y[i*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i:], 1) + bi.Dgemv(blas.Trans, i, n-i, -1, a[i:], lda, x[i*ldx:], 1, 1, a[i*lda+i:], 1) + + // Generate reflection P[i] to annihilate A[i, i+1:n] + a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + d[i] = a[i*lda+i] + if i < m-1 { + a[i*lda+i] = 1 + // Compute X[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, n-i, 1, a[(i+1)*lda+i:], lda, a[i*lda+i:], 1, 0, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.Trans, n-i, i, 1, y[i*ldy:], ldy, a[i*lda+i:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.NoTrans, i, n-i, 1, a[i:], lda, a[i*lda+i:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) + + // Update A[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, y[i*ldy:], 1, 1, a[(i+1)*lda+i:], lda) + bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, x[(i+1)*ldx:], ldx, a[i:], lda, 1, a[(i+1)*lda+i:], lda) + + // Generate reflection Q[i] to annihilate A[i+2:m, i]. + a[(i+1)*lda+i], tauQ[i] = impl.Dlarfg(m-i-1, a[(i+1)*lda+i], a[min(i+2, m-1)*lda+i:], lda) + e[i] = a[(i+1)*lda+i] + a[(i+1)*lda+i] = 1 + + // Compute Y[i+1:n, i]. + bi.Dgemv(blas.Trans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i-1, i, 1, a[(i+1)*lda:], lda, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i-1, i+1, 1, x[(i+1)*ldx:], ldx, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.Trans, i+1, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go new file mode 100644 index 00000000..0f38ac1d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlacn2 estimates the 1-norm of an n×n matrix A using sequential updates with +// matrix-vector products provided externally. +// +// Dlacn2 is called sequentially and it returns the value of est and kase to be +// used on the next call. +// On the initial call, kase must be 0. +// In between calls, x must be overwritten by +// A * X if kase was returned as 1, +// A^T * X if kase was returned as 2, +// and all other parameters must not be changed. +// On the final return, kase is returned as 0, v contains A*W where W is a +// vector, and est = norm(V)/norm(W) is a lower bound for 1-norm of A. +// +// v, x, and isgn must all have length n and n must be at least 1, otherwise +// Dlacn2 will panic. isave is used for temporary storage. +// +// Dlacn2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) { + if n < 1 { + panic("lapack: non-positive n") + } + checkVector(n, x, 1) + checkVector(n, v, 1) + if len(isgn) < n { + panic("lapack: insufficient isgn length") + } + if isave[0] < 0 || isave[0] > 5 { + panic("lapack: bad isave value") + } + if isave[0] == 0 && kase != 0 { + panic("lapack: bad isave value") + } + itmax := 5 + bi := blas64.Implementation() + if kase == 0 { + for i := 0; i < n; i++ { + x[i] = 1 / float64(n) + } + kase = 1 + isave[0] = 1 + return est, kase + } + switch isave[0] { + default: + panic("unreachable") + case 1: + if n == 1 { + v[0] = x[0] + est = math.Abs(v[0]) + kase = 0 + return est, kase + } + est = bi.Dasum(n, x, 1) + for i := 0; i < n; i++ { + x[i] = math.Copysign(1, x[i]) + isgn[i] = int(x[i]) + } + kase = 2 + isave[0] = 2 + return est, kase + case 2: + isave[1] = bi.Idamax(n, x, 1) + isave[2] = 2 + for i := 0; i < n; i++ { + x[i] = 0 + } + x[isave[1]] = 1 + kase = 1 + isave[0] = 3 + return est, kase + case 3: + bi.Dcopy(n, x, 1, v, 1) + estold := est + est = bi.Dasum(n, v, 1) + sameSigns := true + for i := 0; i < n; i++ { + if int(math.Copysign(1, x[i])) != isgn[i] { + sameSigns = false + break + } + } + if !sameSigns && est > estold { + for i := 0; i < n; i++ { + x[i] = math.Copysign(1, x[i]) + isgn[i] = int(x[i]) + } + kase = 2 + isave[0] = 4 + return est, kase + } + case 4: + jlast := isave[1] + isave[1] = bi.Idamax(n, x, 1) + if x[jlast] != math.Abs(x[isave[1]]) && isave[2] < itmax { + isave[2] += 1 + for i := 0; i < n; i++ { + x[i] = 0 + } + x[isave[1]] = 1 + kase = 1 + isave[0] = 3 + return est, kase + } + case 5: + tmp := 2 * (bi.Dasum(n, x, 1)) / float64(3*n) + if tmp > est { + bi.Dcopy(n, x, 1, v, 1) + est = tmp + } + kase = 0 + return est, kase + } + // Iteration complete. Final stage + altsgn := 1.0 + for i := 0; i < n; i++ { + x[i] = altsgn * (1 + float64(i)/float64(n-1)) + altsgn *= -1 + } + kase = 1 + isave[0] = 5 + return est, kase +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go new file mode 100644 index 00000000..f5b90e17 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify +// a triangular portion with blas.Upper or blas.Lower, or can specify all of the +// elemest with blas.All. +// +// Dlacpy is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, n, b, ldb) + switch uplo { + default: + panic(badUplo) + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i+1, n); j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go new file mode 100644 index 00000000..17f356e8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go @@ -0,0 +1,49 @@ +// Copyright ©2016 The gonum 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 gonum + +import "math" + +// Dlae2 computes the eigenvalues of a 2×2 symmetric matrix +// [a b] +// [b c] +// and returns the eigenvalue with the larger absolute value as rt1 and the +// smaller as rt2. +// +// Dlae2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlae2(a, b, c float64) (rt1, rt2 float64) { + sm := a + c + df := a - c + adf := math.Abs(df) + tb := b + b + ab := math.Abs(tb) + acmx := c + acmn := a + if math.Abs(a) > math.Abs(c) { + acmx = a + acmn = c + } + var rt float64 + if adf > ab { + rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) + } else if adf < ab { + rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) + } else { + rt = ab * math.Sqrt2 + } + if sm < 0 { + rt1 = 0.5 * (sm - rt) + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + return rt1, rt2 + } + if sm > 0 { + rt1 = 0.5 * (sm + rt) + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + return rt1, rt2 + } + rt1 = 0.5 * rt + rt2 = -0.5 * rt + return rt1, rt2 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go new file mode 100644 index 00000000..50fd7d0b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go @@ -0,0 +1,82 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlaev2 computes the Eigen decomposition of a symmetric 2×2 matrix. +// The matrix is given by +// [a b] +// [b c] +// Dlaev2 returns rt1 and rt2, the eigenvalues of the matrix where |RT1| > |RT2|, +// and [cs1, sn1] which is the unit right eigenvalue for RT1. +// [ cs1 sn1] [a b] [cs1 -sn1] = [rt1 0] +// [-sn1 cs1] [b c] [sn1 cs1] [ 0 rt2] +// +// Dlaev2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) { + sm := a + c + df := a - c + adf := math.Abs(df) + tb := b + b + ab := math.Abs(tb) + acmx := c + acmn := a + if math.Abs(a) > math.Abs(c) { + acmx = a + acmn = c + } + var rt float64 + if adf > ab { + rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) + } else if adf < ab { + rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) + } else { + rt = ab * math.Sqrt(2) + } + var sgn1 float64 + if sm < 0 { + rt1 = 0.5 * (sm - rt) + sgn1 = -1 + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + } else if sm > 0 { + rt1 = 0.5 * (sm + rt) + sgn1 = 1 + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + } else { + rt1 = 0.5 * rt + rt2 = -0.5 * rt + sgn1 = 1 + } + var cs, sgn2 float64 + if df >= 0 { + cs = df + rt + sgn2 = 1 + } else { + cs = df - rt + sgn2 = -1 + } + acs := math.Abs(cs) + if acs > ab { + ct := -tb / cs + sn1 = 1 / math.Sqrt(1+ct*ct) + cs1 = ct * sn1 + } else { + if ab == 0 { + cs1 = 1 + sn1 = 0 + } else { + tn := -cs / tb + cs1 = 1 / math.Sqrt(1+tn*tn) + sn1 = tn * cs1 + } + } + if sgn1 == sgn2 { + tn := cs1 + cs1 = -sn1 + sn1 = tn + } + return rt1, rt2, cs1, sn1 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go new file mode 100644 index 00000000..470b63a4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go @@ -0,0 +1,261 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlaexc swaps two adjacent diagonal blocks of order 1 or 2 in an n×n upper +// quasi-triangular matrix T by an orthogonal similarity transformation. +// +// T must be in Schur canonical form, that is, block upper triangular with 1×1 +// and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal elements +// equal and its off-diagonal elements of opposite sign. On return, T will +// contain the updated matrix again in Schur canonical form. +// +// If wantq is true, the transformation is accumulated in the n×n matrix Q, +// otherwise Q is not referenced. +// +// j1 is the index of the first row of the first block. n1 and n2 are the order +// of the first and second block, respectively. +// +// work must have length at least n, otherwise Dlaexc will panic. +// +// If ok is false, the transformed matrix T would be too far from Schur form. +// The blocks are not swapped, and T and Q are not modified. +// +// If n1 and n2 are both equal to 1, Dlaexc will always return true. +// +// Dlaexc is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaexc(wantq bool, n int, t []float64, ldt int, q []float64, ldq int, j1, n1, n2 int, work []float64) (ok bool) { + checkMatrix(n, n, t, ldt) + if wantq { + checkMatrix(n, n, q, ldq) + } + if j1 < 0 || n <= j1 { + panic("lapack: index j1 out of range") + } + if len(work) < n { + panic(badWork) + } + if n1 < 0 || 2 < n1 { + panic("lapack: invalid value of n1") + } + if n2 < 0 || 2 < n2 { + panic("lapack: invalid value of n2") + } + + if n == 0 || n1 == 0 || n2 == 0 { + return true + } + if j1+n1 >= n { + // TODO(vladimir-ch): Reference LAPACK does this check whether + // the start of the second block is in the matrix T. It returns + // true if it is not and moreover it does not check whether the + // whole second block fits into T. This does not feel + // satisfactory. The only caller of Dlaexc is Dtrexc, so if the + // caller makes sure that this does not happen, we could be + // stricter here. + return true + } + + j2 := j1 + 1 + j3 := j1 + 2 + + bi := blas64.Implementation() + + if n1 == 1 && n2 == 1 { + // Swap two 1×1 blocks. + t11 := t[j1*ldt+j1] + t22 := t[j2*ldt+j2] + + // Determine the transformation to perform the interchange. + cs, sn, _ := impl.Dlartg(t[j1*ldt+j2], t22-t11) + + // Apply transformation to the matrix T. + if n-j3 > 0 { + bi.Drot(n-j3, t[j1*ldt+j3:], 1, t[j2*ldt+j3:], 1, cs, sn) + } + if j1 > 0 { + bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) + } + + t[j1*ldt+j1] = t22 + t[j2*ldt+j2] = t11 + + if wantq { + // Accumulate transformation in the matrix Q. + bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) + } + + return true + } + + // Swapping involves at least one 2×2 block. + // + // Copy the diagonal block of order n1+n2 to the local array d and + // compute its norm. + nd := n1 + n2 + var d [16]float64 + const ldd = 4 + impl.Dlacpy(blas.All, nd, nd, t[j1*ldt+j1:], ldt, d[:], ldd) + dnorm := impl.Dlange(lapack.MaxAbs, nd, nd, d[:], ldd, work) + + // Compute machine-dependent threshold for test for accepting swap. + eps := dlamchP + thresh := math.Max(10*eps*dnorm, dlamchS/eps) + + // Solve T11*X - X*T22 = scale*T12 for X. + var x [4]float64 + const ldx = 2 + scale, _, _ := impl.Dlasy2(false, false, -1, n1, n2, d[:], ldd, d[n1*ldd+n1:], ldd, d[n1:], ldd, x[:], ldx) + + // Swap the adjacent diagonal blocks. + switch { + case n1 == 1 && n2 == 2: + // Generate elementary reflector H so that + // ( scale, X11, X12 ) H = ( 0, 0, * ) + u := [3]float64{scale, x[0], 1} + _, tau := impl.Dlarfg(3, x[1], u[:2], 1) + t11 := t[j1*ldt+j1] + + // Perform swap provisionally on diagonal block in d. + impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) + impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) + + // Test whether to reject swap. + if math.Max(math.Abs(d[2*ldd]), math.Max(math.Abs(d[2*ldd+1]), math.Abs(d[2*ldd+2]-t11))) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + impl.Dlarfx(blas.Left, 3, n-j1, u[:], tau, t[j1*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j2+1, 3, u[:], tau, t[j1:], ldt, work) + + t[j3*ldt+j1] = 0 + t[j3*ldt+j2] = 0 + t[j3*ldt+j3] = t11 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) + } + + case n1 == 2 && n2 == 1: + // Generate elementary reflector H so that: + // H ( -X11 ) = ( * ) + // ( -X21 ) = ( 0 ) + // ( scale ) = ( 0 ) + u := [3]float64{1, -x[ldx], scale} + _, tau := impl.Dlarfg(3, -x[0], u[1:], 1) + t33 := t[j3*ldt+j3] + + // Perform swap provisionally on diagonal block in D. + impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) + impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) + + // Test whether to reject swap. + if math.Max(math.Abs(d[ldd]), math.Max(math.Abs(d[2*ldd]), math.Abs(d[0]-t33))) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + impl.Dlarfx(blas.Right, j3+1, 3, u[:], tau, t[j1:], ldt, work) + impl.Dlarfx(blas.Left, 3, n-j1-1, u[:], tau, t[j1*ldt+j2:], ldt, work) + + t[j1*ldt+j1] = t33 + t[j2*ldt+j1] = 0 + t[j3*ldt+j1] = 0 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) + } + + default: // n1 == 2 && n2 == 2 + // Generate elementary reflectors H_1 and H_2 so that: + // H_2 H_1 ( -X11 -X12 ) = ( * * ) + // ( -X21 -X22 ) ( 0 * ) + // ( scale 0 ) ( 0 0 ) + // ( 0 scale ) ( 0 0 ) + u1 := [3]float64{1, -x[ldx], scale} + _, tau1 := impl.Dlarfg(3, -x[0], u1[1:], 1) + + temp := -tau1 * (x[1] + u1[1]*x[ldx+1]) + u2 := [3]float64{1, -temp * u1[2], scale} + _, tau2 := impl.Dlarfg(3, -temp*u1[1]-x[ldx+1], u2[1:], 1) + + // Perform swap provisionally on diagonal block in D. + impl.Dlarfx(blas.Left, 3, 4, u1[:], tau1, d[:], ldd, work) + impl.Dlarfx(blas.Right, 4, 3, u1[:], tau1, d[:], ldd, work) + impl.Dlarfx(blas.Left, 3, 4, u2[:], tau2, d[ldd:], ldd, work) + impl.Dlarfx(blas.Right, 4, 3, u2[:], tau2, d[1:], ldd, work) + + // Test whether to reject swap. + m1 := math.Max(math.Abs(d[2*ldd]), math.Abs(d[2*ldd+1])) + m2 := math.Max(math.Abs(d[3*ldd]), math.Abs(d[3*ldd+1])) + if math.Max(m1, m2) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + j4 := j1 + 3 + impl.Dlarfx(blas.Left, 3, n-j1, u1[:], tau1, t[j1*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j4+1, 3, u1[:], tau1, t[j1:], ldt, work) + impl.Dlarfx(blas.Left, 3, n-j1, u2[:], tau2, t[j2*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j4+1, 3, u2[:], tau2, t[j2:], ldt, work) + + t[j3*ldt+j1] = 0 + t[j3*ldt+j2] = 0 + t[j4*ldt+j1] = 0 + t[j4*ldt+j2] = 0 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u1[:], tau1, q[j1:], ldq, work) + impl.Dlarfx(blas.Right, n, 3, u2[:], tau2, q[j2:], ldq, work) + } + } + + if n2 == 2 { + // Standardize new 2×2 block T11. + a, b := t[j1*ldt+j1], t[j1*ldt+j2] + c, d := t[j2*ldt+j1], t[j2*ldt+j2] + var cs, sn float64 + t[j1*ldt+j1], t[j1*ldt+j2], t[j2*ldt+j1], t[j2*ldt+j2], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) + if n-j1-2 > 0 { + bi.Drot(n-j1-2, t[j1*ldt+j1+2:], 1, t[j2*ldt+j1+2:], 1, cs, sn) + } + if j1 > 0 { + bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) + } + if wantq { + bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) + } + } + if n1 == 2 { + // Standardize new 2×2 block T22. + j3 := j1 + n2 + j4 := j3 + 1 + a, b := t[j3*ldt+j3], t[j3*ldt+j4] + c, d := t[j4*ldt+j3], t[j4*ldt+j4] + var cs, sn float64 + t[j3*ldt+j3], t[j3*ldt+j4], t[j4*ldt+j3], t[j4*ldt+j4], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) + if n-j3-2 > 0 { + bi.Drot(n-j3-2, t[j3*ldt+j3+2:], 1, t[j4*ldt+j3+2:], 1, cs, sn) + } + bi.Drot(j3, t[j3:], ldt, t[j4:], ldt, cs, sn) + if wantq { + bi.Drot(n, q[j3:], ldq, q[j4:], ldq, cs, sn) + } + } + + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go new file mode 100644 index 00000000..3b73384f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go @@ -0,0 +1,182 @@ +// Copyright ©2017 The gonum 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 gonum + +import "math" + +// Dlags2 computes 2-by-2 orthogonal matrices U, V and Q with the +// triangles of A and B specified by upper. +// +// If upper is true +// +// U^T*A*Q = U^T*[ a1 a2 ]*Q = [ x 0 ] +// [ 0 a3 ] [ x x ] +// and +// V^T*B*Q = V^T*[ b1 b2 ]*Q = [ x 0 ] +// [ 0 b3 ] [ x x ] +// +// otherwise +// +// U^T*A*Q = U^T*[ a1 0 ]*Q = [ x x ] +// [ a2 a3 ] [ 0 x ] +// and +// V^T*B*Q = V^T*[ b1 0 ]*Q = [ x x ] +// [ b2 b3 ] [ 0 x ]. +// +// The rows of the transformed A and B are parallel, where +// +// U = [ csu snu ], V = [ csv snv ], Q = [ csq snq ] +// [ -snu csu ] [ -snv csv ] [ -snq csq ] +// +// Dlags2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) { + if upper { + // Input matrices A and B are upper triangular matrices. + // + // Form matrix C = A*adj(B) = [ a b ] + // [ 0 d ] + a := a1 * b3 + d := a3 * b1 + b := a2*b1 - a1*b2 + + // The SVD of real 2-by-2 triangular C. + // + // [ csl -snl ]*[ a b ]*[ csr snr ] = [ r 0 ] + // [ snl csl ] [ 0 d ] [ -snr csr ] [ 0 t ] + _, _, snr, csr, snl, csl := impl.Dlasv2(a, b, d) + + if math.Abs(csl) >= math.Abs(snl) || math.Abs(csr) >= math.Abs(snr) { + // Compute the [0, 0] and [0, 1] elements of U^T*A and V^T*B, + // and [0, 1] element of |U|^T*|A| and |V|^T*|B|. + + ua11r := csl * a1 + ua12 := csl*a2 + snl*a3 + + vb11r := csr * b1 + vb12 := csr*b2 + snr*b3 + + aua12 := math.Abs(csl)*math.Abs(a2) + math.Abs(snl)*math.Abs(a3) + avb12 := math.Abs(csr)*math.Abs(b2) + math.Abs(snr)*math.Abs(b3) + + // Zero [0, 1] elements of U^T*A and V^T*B. + if math.Abs(ua11r)+math.Abs(ua12) != 0 { + if aua12/(math.Abs(ua11r)+math.Abs(ua12)) <= avb12/(math.Abs(vb11r)+math.Abs(vb12)) { + csq, snq, _ = impl.Dlartg(-ua11r, ua12) + } else { + csq, snq, _ = impl.Dlartg(-vb11r, vb12) + } + } else { + csq, snq, _ = impl.Dlartg(-vb11r, vb12) + } + + csu = csl + snu = -snl + csv = csr + snv = -snr + } else { + // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B, + // and [1, 1] element of |U|^T*|A| and |V|^T*|B|. + + ua21 := -snl * a1 + ua22 := -snl*a2 + csl*a3 + + vb21 := -snr * b1 + vb22 := -snr*b2 + csr*b3 + + aua22 := math.Abs(snl)*math.Abs(a2) + math.Abs(csl)*math.Abs(a3) + avb22 := math.Abs(snr)*math.Abs(b2) + math.Abs(csr)*math.Abs(b3) + + // Zero [1, 1] elements of U^T*A and V^T*B, and then swap. + if math.Abs(ua21)+math.Abs(ua22) != 0 { + if aua22/(math.Abs(ua21)+math.Abs(ua22)) <= avb22/(math.Abs(vb21)+math.Abs(vb22)) { + csq, snq, _ = impl.Dlartg(-ua21, ua22) + } else { + csq, snq, _ = impl.Dlartg(-vb21, vb22) + } + } else { + csq, snq, _ = impl.Dlartg(-vb21, vb22) + } + + csu = snl + snu = csl + csv = snr + snv = csr + } + } else { + // Input matrices A and B are lower triangular matrices + // + // Form matrix C = A*adj(B) = [ a 0 ] + // [ c d ] + a := a1 * b3 + d := a3 * b1 + c := a2*b3 - a3*b2 + + // The SVD of real 2-by-2 triangular C + // + // [ csl -snl ]*[ a 0 ]*[ csr snr ] = [ r 0 ] + // [ snl csl ] [ c d ] [ -snr csr ] [ 0 t ] + _, _, snr, csr, snl, csl := impl.Dlasv2(a, c, d) + + if math.Abs(csr) >= math.Abs(snr) || math.Abs(csl) >= math.Abs(snl) { + // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B, + // and [1, 0] element of |U|^T*|A| and |V|^T*|B|. + + ua21 := -snr*a1 + csr*a2 + ua22r := csr * a3 + + vb21 := -snl*b1 + csl*b2 + vb22r := csl * b3 + + aua21 := math.Abs(snr)*math.Abs(a1) + math.Abs(csr)*math.Abs(a2) + avb21 := math.Abs(snl)*math.Abs(b1) + math.Abs(csl)*math.Abs(b2) + + // Zero [1, 0] elements of U^T*A and V^T*B. + if (math.Abs(ua21) + math.Abs(ua22r)) != 0 { + if aua21/(math.Abs(ua21)+math.Abs(ua22r)) <= avb21/(math.Abs(vb21)+math.Abs(vb22r)) { + csq, snq, _ = impl.Dlartg(ua22r, ua21) + } else { + csq, snq, _ = impl.Dlartg(vb22r, vb21) + } + } else { + csq, snq, _ = impl.Dlartg(vb22r, vb21) + } + + csu = csr + snu = -snr + csv = csl + snv = -snl + } else { + // Compute the [0, 0] and [0, 1] elements of U^T *A and V^T *B, + // and [0, 0] element of |U|^T*|A| and |V|^T*|B|. + + ua11 := csr*a1 + snr*a2 + ua12 := snr * a3 + + vb11 := csl*b1 + snl*b2 + vb12 := snl * b3 + + aua11 := math.Abs(csr)*math.Abs(a1) + math.Abs(snr)*math.Abs(a2) + avb11 := math.Abs(csl)*math.Abs(b1) + math.Abs(snl)*math.Abs(b2) + + // Zero [0, 0] elements of U^T*A and V^T*B, and then swap. + if (math.Abs(ua11) + math.Abs(ua12)) != 0 { + if aua11/(math.Abs(ua11)+math.Abs(ua12)) <= avb11/(math.Abs(vb11)+math.Abs(vb12)) { + csq, snq, _ = impl.Dlartg(ua12, ua11) + } else { + csq, snq, _ = impl.Dlartg(vb12, vb11) + } + } else { + csq, snq, _ = impl.Dlartg(vb12, vb11) + } + + csu = snr + snu = csr + csv = snl + snv = csl + } + } + + return csu, snu, csv, snv, csq, snq +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go new file mode 100644 index 00000000..bf14a036 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go @@ -0,0 +1,423 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlahqr computes the eigenvalues and Schur factorization of a block of an n×n +// upper Hessenberg matrix H, using the double-shift/single-shift QR algorithm. +// +// h and ldh represent the matrix H. Dlahqr works primarily with the Hessenberg +// submatrix H[ilo:ihi+1,ilo:ihi+1], but applies transformations to all of H if +// wantt is true. It is assumed that H[ihi+1:n,ihi+1:n] is already upper +// quasi-triangular, although this is not checked. +// +// It must hold that +// 0 <= ilo <= max(0,ihi), and ihi < n, +// and that +// H[ilo,ilo-1] == 0, if ilo > 0, +// otherwise Dlahqr will panic. +// +// If unconverged is zero on return, wr[ilo:ihi+1] and wi[ilo:ihi+1] will contain +// respectively the real and imaginary parts of the computed eigenvalues ilo +// to ihi. If two eigenvalues are computed as a complex conjugate pair, they are +// stored in consecutive elements of wr and wi, say the i-th and (i+1)th, with +// wi[i] > 0 and wi[i+1] < 0. If wantt is true, the eigenvalues are stored in +// the same order as on the diagonal of the Schur form returned in H, with +// wr[i] = H[i,i], and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, +// wi[i] = sqrt(abs(H[i+1,i]*H[i,i+1])) and wi[i+1] = -wi[i]. +// +// wr and wi must have length ihi+1. +// +// z and ldz represent an n×n matrix Z. If wantz is true, the transformations +// will be applied to the submatrix Z[iloz:ihiz+1,ilo:ihi+1] and it must hold that +// 0 <= iloz <= ilo, and ihi <= ihiz < n. +// If wantz is false, z is not referenced. +// +// unconverged indicates whether Dlahqr computed all the eigenvalues ilo to ihi +// in a total of 30 iterations per eigenvalue. +// +// If unconverged is zero, all the eigenvalues ilo to ihi have been computed and +// will be stored on return in wr[ilo:ihi+1] and wi[ilo:ihi+1]. +// +// If unconverged is zero and wantt is true, H[ilo:ihi+1,ilo:ihi+1] will be +// overwritten on return by upper quasi-triangular full Schur form with any +// 2×2 diagonal blocks in standard form. +// +// If unconverged is zero and if wantt is false, the contents of h on return is +// unspecified. +// +// If unconverged is positive, some eigenvalues have not converged, and +// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] contain those eigenvalues +// which have been successfully computed. +// +// If unconverged is positive and wantt is true, then on return +// (initial H)*U = U*(final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged is positive and wantt is false, on return the remaining +// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix +// H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged is positive and wantz is true, then on return +// (final Z) = (initial Z)*U, +// where U is the orthogonal matrix in (*) regardless of the value of wantt. +// +// Dlahqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlahqr(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int) (unconverged int) { + checkMatrix(n, n, h, ldh) + switch { + case ilo < 0 || max(0, ihi) < ilo: + panic(badIlo) + case n <= ihi: + panic(badIhi) + case len(wr) != ihi+1: + panic("lapack: bad length of wr") + case len(wi) != ihi+1: + panic("lapack: bad length of wi") + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic("lapack: block is not isolated") + } + if wantz { + checkMatrix(n, n, z, ldz) + switch { + case iloz < 0 || ilo < iloz: + panic("lapack: iloz out of range") + case ihiz < ihi || n <= ihiz: + panic("lapack: ihiz out of range") + } + } + + // Quick return if possible. + if n == 0 { + return 0 + } + if ilo == ihi { + wr[ilo] = h[ilo*ldh+ilo] + wi[ilo] = 0 + return 0 + } + + // Clear out the trash. + for j := ilo; j < ihi-2; j++ { + h[(j+2)*ldh+j] = 0 + h[(j+3)*ldh+j] = 0 + } + if ilo <= ihi-2 { + h[ihi*ldh+ihi-2] = 0 + } + + nh := ihi - ilo + 1 + nz := ihiz - iloz + 1 + + // Set machine-dependent constants for the stopping criterion. + ulp := dlamchP + smlnum := float64(nh) / ulp * dlamchS + + // i1 and i2 are the indices of the first row and last column of H to + // which transformations must be applied. If eigenvalues only are being + // computed, i1 and i2 are set inside the main loop. + var i1, i2 int + if wantt { + i1 = 0 + i2 = n - 1 + } + + itmax := 30 * max(10, nh) // Total number of QR iterations allowed. + + // The main loop begins here. i is the loop index and decreases from ihi + // to ilo in steps of 1 or 2. Each iteration of the loop works with the + // active submatrix in rows and columns l to i. Eigenvalues i+1 to ihi + // have already converged. Either l = ilo or H[l,l-1] is negligible so + // that the matrix splits. + bi := blas64.Implementation() + i := ihi + for i >= ilo { + l := ilo + + // Perform QR iterations on rows and columns ilo to i until a + // submatrix of order 1 or 2 splits off at the bottom because a + // subdiagonal element has become negligible. + converged := false + for its := 0; its <= itmax; its++ { + // Look for a single small subdiagonal element. + var k int + for k = i; k > l; k-- { + if math.Abs(h[k*ldh+k-1]) <= smlnum { + break + } + tst := math.Abs(h[(k-1)*ldh+k-1]) + math.Abs(h[k*ldh+k]) + if tst == 0 { + if k-2 >= ilo { + tst += math.Abs(h[(k-1)*ldh+k-2]) + } + if k+1 <= ihi { + tst += math.Abs(h[(k+1)*ldh+k]) + } + } + // The following is a conservative small + // subdiagonal deflation criterion due to Ahues + // & Tisseur (LAWN 122, 1997). It has better + // mathematical foundation and improves accuracy + // in some cases. + if math.Abs(h[k*ldh+k-1]) <= ulp*tst { + ab := math.Max(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) + ba := math.Min(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) + aa := math.Max(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) + bb := math.Min(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) + s := aa + ab + if ab/s*ba <= math.Max(smlnum, aa/s*bb*ulp) { + break + } + } + } + l = k + if l > ilo { + // H[l,l-1] is negligible. + h[l*ldh+l-1] = 0 + } + if l >= i-1 { + // Break the loop because a submatrix of order 1 + // or 2 has split off. + converged = true + break + } + + // Now the active submatrix is in rows and columns l to + // i. If eigenvalues only are being computed, only the + // active submatrix need be transformed. + if !wantt { + i1 = l + i2 = i + } + + const ( + dat1 = 3.0 + dat2 = -0.4375 + ) + var h11, h21, h12, h22 float64 + switch its { + case 10: // Exceptional shift. + s := math.Abs(h[(l+1)*ldh+l]) + math.Abs(h[(l+2)*ldh+l+1]) + h11 = dat1*s + h[l*ldh+l] + h12 = dat2 * s + h21 = s + h22 = h11 + case 20: // Exceptional shift. + s := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) + h11 = dat1*s + h[i*ldh+i] + h12 = dat2 * s + h21 = s + h22 = h11 + default: // Prepare to use Francis' double shift (i.e., + // 2nd degree generalized Rayleigh quotient). + h11 = h[(i-1)*ldh+i-1] + h21 = h[i*ldh+i-1] + h12 = h[(i-1)*ldh+i] + h22 = h[i*ldh+i] + } + s := math.Abs(h11) + math.Abs(h12) + math.Abs(h21) + math.Abs(h22) + var ( + rt1r, rt1i float64 + rt2r, rt2i float64 + ) + if s != 0 { + h11 /= s + h21 /= s + h12 /= s + h22 /= s + tr := (h11 + h22) / 2 + det := (h11-tr)*(h22-tr) - h12*h21 + rtdisc := math.Sqrt(math.Abs(det)) + if det >= 0 { + // Complex conjugate shifts. + rt1r = tr * s + rt2r = rt1r + rt1i = rtdisc * s + rt2i = -rt1i + } else { + // Real shifts (use only one of them). + rt1r = tr + rtdisc + rt2r = tr - rtdisc + if math.Abs(rt1r-h22) <= math.Abs(rt2r-h22) { + rt1r *= s + rt2r = rt1r + } else { + rt2r *= s + rt1r = rt2r + } + rt1i = 0 + rt2i = 0 + } + } + + // Look for two consecutive small subdiagonal elements. + var m int + var v [3]float64 + for m = i - 2; m >= l; m-- { + // Determine the effect of starting the + // double-shift QR iteration at row m, and see + // if this would make H[m,m-1] negligible. The + // following uses scaling to avoid overflows and + // most underflows. + h21s := h[(m+1)*ldh+m] + s := math.Abs(h[m*ldh+m]-rt2r) + math.Abs(rt2i) + math.Abs(h21s) + h21s /= s + v[0] = h21s*h[m*ldh+m+1] + (h[m*ldh+m]-rt1r)*((h[m*ldh+m]-rt2r)/s) - rt2i/s*rt1i + v[1] = h21s * (h[m*ldh+m] + h[(m+1)*ldh+m+1] - rt1r - rt2r) + v[2] = h21s * h[(m+2)*ldh+m+1] + s = math.Abs(v[0]) + math.Abs(v[1]) + math.Abs(v[2]) + v[0] /= s + v[1] /= s + v[2] /= s + if m == l { + break + } + dsum := math.Abs(h[(m-1)*ldh+m-1]) + math.Abs(h[m*ldh+m]) + math.Abs(h[(m+1)*ldh+m+1]) + if math.Abs(h[m*ldh+m-1])*(math.Abs(v[1])+math.Abs(v[2])) <= ulp*math.Abs(v[0])*dsum { + break + } + } + + // Double-shift QR step. + for k := m; k < i; k++ { + // The first iteration of this loop determines a + // reflection G from the vector V and applies it + // from left and right to H, thus creating a + // non-zero bulge below the subdiagonal. + // + // Each subsequent iteration determines a + // reflection G to restore the Hessenberg form + // in the (k-1)th column, and thus chases the + // bulge one step toward the bottom of the + // active submatrix. nr is the order of G. + + nr := min(3, i-k+1) + if k > m { + bi.Dcopy(nr, h[k*ldh+k-1:], ldh, v[:], 1) + } + var t0 float64 + v[0], t0 = impl.Dlarfg(nr, v[0], v[1:], 1) + if k > m { + h[k*ldh+k-1] = v[0] + h[(k+1)*ldh+k-1] = 0 + if k < i-1 { + h[(k+2)*ldh+k-1] = 0 + } + } else if m > l { + // Use the following instead of H[k,k-1] = -H[k,k-1] + // to avoid a bug when v[1] and v[2] underflow. + h[k*ldh+k-1] *= 1 - t0 + } + t1 := t0 * v[1] + if nr == 3 { + t2 := t0 * v[2] + + // Apply G from the left to transform + // the rows of the matrix in columns k + // to i2. + for j := k; j <= i2; j++ { + sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] + v[2]*h[(k+2)*ldh+j] + h[k*ldh+j] -= sum * t0 + h[(k+1)*ldh+j] -= sum * t1 + h[(k+2)*ldh+j] -= sum * t2 + } + + // Apply G from the right to transform + // the columns of the matrix in rows i1 + // to min(k+3,i). + for j := i1; j <= min(k+3, i); j++ { + sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] + v[2]*h[j*ldh+k+2] + h[j*ldh+k] -= sum * t0 + h[j*ldh+k+1] -= sum * t1 + h[j*ldh+k+2] -= sum * t2 + } + + if wantz { + // Accumulate transformations in the matrix Z. + for j := iloz; j <= ihiz; j++ { + sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] + v[2]*z[j*ldz+k+2] + z[j*ldz+k] -= sum * t0 + z[j*ldz+k+1] -= sum * t1 + z[j*ldz+k+2] -= sum * t2 + } + } + } else if nr == 2 { + // Apply G from the left to transform + // the rows of the matrix in columns k + // to i2. + for j := k; j <= i2; j++ { + sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] + h[k*ldh+j] -= sum * t0 + h[(k+1)*ldh+j] -= sum * t1 + } + + // Apply G from the right to transform + // the columns of the matrix in rows i1 + // to min(k+3,i). + for j := i1; j <= i; j++ { + sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] + h[j*ldh+k] -= sum * t0 + h[j*ldh+k+1] -= sum * t1 + } + + if wantz { + // Accumulate transformations in the matrix Z. + for j := iloz; j <= ihiz; j++ { + sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] + z[j*ldz+k] -= sum * t0 + z[j*ldz+k+1] -= sum * t1 + } + } + } + } + } + + if !converged { + // The QR iteration finished without splitting off a + // submatrix of order 1 or 2. + return i + 1 + } + + if l == i { + // H[i,i-1] is negligible: one eigenvalue has converged. + wr[i] = h[i*ldh+i] + wi[i] = 0 + } else if l == i-1 { + // H[i-1,i-2] is negligible: a pair of eigenvalues have converged. + + // Transform the 2×2 submatrix to standard Schur form, + // and compute and store the eigenvalues. + var cs, sn float64 + a, b := h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] + c, d := h[i*ldh+i-1], h[i*ldh+i] + a, b, c, d, wr[i-1], wi[i-1], wr[i], wi[i], cs, sn = impl.Dlanv2(a, b, c, d) + h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] = a, b + h[i*ldh+i-1], h[i*ldh+i] = c, d + + if wantt { + // Apply the transformation to the rest of H. + if i2 > i { + bi.Drot(i2-i, h[(i-1)*ldh+i+1:], 1, h[i*ldh+i+1:], 1, cs, sn) + } + bi.Drot(i-i1-1, h[i1*ldh+i-1:], ldh, h[i1*ldh+i:], ldh, cs, sn) + } + + if wantz { + // Apply the transformation to Z. + bi.Drot(nz, z[iloz*ldz+i-1:], ldz, z[iloz*ldz+i:], ldz, cs, sn) + } + } + + // Return to start of the main loop with new value of i. + i = l - 1 + } + return 0 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go new file mode 100644 index 00000000..607810f0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go @@ -0,0 +1,169 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlahr2 reduces the first nb columns of a real general n×(n-k+1) matrix A so +// that elements below the k-th subdiagonal are zero. The reduction is performed +// by an orthogonal similarity transformation Q^T * A * Q. Dlahr2 returns the +// matrices V and T which determine Q as a block reflector I - V*T*V^T, and +// also the matrix Y = A * V * T. +// +// The matrix Q is represented as a product of nb elementary reflectors +// Q = H_0 * H_1 * ... * H_{nb-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T, +// where v is a real vector with v[0:i+k-1] = 0 and v[i+k-1] = 1. v[i+k:n] is +// stored on exit in A[i+k+1:n,i]. +// +// The elements of the vectors v together form the (n-k+1)×nb matrix +// V which is needed, with T and Y, to apply the transformation to the +// unreduced part of the matrix, using an update of the form +// A = (I - V*T*V^T) * (A - Y*V^T). +// +// On entry, a contains the n×(n-k+1) general matrix A. On return, the elements +// on and above the k-th subdiagonal in the first nb columns are overwritten +// with the corresponding elements of the reduced matrix; the elements below the +// k-th subdiagonal, with the slice tau, represent the matrix Q as a product of +// elementary reflectors. The other columns of A are unchanged. +// +// The contents of A on exit are illustrated by the following example +// with n = 7, k = 3 and nb = 2: +// [ a a a a a ] +// [ a a a a a ] +// [ a a a a a ] +// [ h h a a a ] +// [ v0 h a a a ] +// [ v0 v1 a a a ] +// [ v0 v1 a a a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// k is the offset for the reduction. Elements below the k-th subdiagonal in the +// first nb columns are reduced to zero. +// +// nb is the number of columns to be reduced. +// +// On entry, a represents the n×(n-k+1) matrix A. On return, the elements on and +// above the k-th subdiagonal in the first nb columns are overwritten with the +// corresponding elements of the reduced matrix. The elements below the k-th +// subdiagonal, with the slice tau, represent the matrix Q as a product of +// elementary reflectors. The other columns of A are unchanged. +// +// tau will contain the scalar factors of the elementary reflectors. It must +// have length at least nb. +// +// t and ldt represent the nb×nb upper triangular matrix T, and y and ldy +// represent the n×nb matrix Y. +// +// Dlahr2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { + checkMatrix(n, n-k+1, a, lda) + if len(tau) < nb { + panic(badTau) + } + checkMatrix(nb, nb, t, ldt) + checkMatrix(n, nb, y, ldy) + + // Quick return if possible. + if n <= 1 { + return + } + + bi := blas64.Implementation() + var ei float64 + for i := 0; i < nb; i++ { + if i > 0 { + // Update A[k:n,i]. + + // Update i-th column of A - Y * V^T. + bi.Dgemv(blas.NoTrans, n-k, i, + -1, y[k*ldy:], ldy, + a[(k+i-1)*lda:], 1, + 1, a[k*lda+i:], lda) + + // Apply I - V * T^T * V^T to this column (call it b) + // from the left, using the last column of T as + // workspace. + // Let V = [ V1 ] and b = [ b1 ] (first i rows) + // [ V2 ] [ b2 ] + // where V1 is unit lower triangular. + // + // w := V1^T * b1. + bi.Dcopy(i, a[k*lda+i:], lda, t[nb-1:], ldt) + bi.Dtrmv(blas.Lower, blas.Trans, blas.Unit, i, + a[k*lda:], lda, t[nb-1:], ldt) + + // w := w + V2^T * b2. + bi.Dgemv(blas.Trans, n-k-i, i, + 1, a[(k+i)*lda:], lda, + a[(k+i)*lda+i:], lda, + 1, t[nb-1:], ldt) + + // w := T^T * w. + bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, i, + t, ldt, t[nb-1:], ldt) + + // b2 := b2 - V2*w. + bi.Dgemv(blas.NoTrans, n-k-i, i, + -1, a[(k+i)*lda:], lda, + t[nb-1:], ldt, + 1, a[(k+i)*lda+i:], lda) + + // b1 := b1 - V1*w. + bi.Dtrmv(blas.Lower, blas.NoTrans, blas.Unit, i, + a[k*lda:], lda, t[nb-1:], ldt) + bi.Daxpy(i, -1, t[nb-1:], ldt, a[k*lda+i:], lda) + + a[(k+i-1)*lda+i-1] = ei + } + + // Generate the elementary reflector H_i to annihilate + // A[k+i+1:n,i]. + ei, tau[i] = impl.Dlarfg(n-k-i, a[(k+i)*lda+i], a[min(k+i+1, n-1)*lda+i:], lda) + a[(k+i)*lda+i] = 1 + + // Compute Y[k:n,i]. + bi.Dgemv(blas.NoTrans, n-k, n-k-i, + 1, a[k*lda+i+1:], lda, + a[(k+i)*lda+i:], lda, + 0, y[k*ldy+i:], ldy) + bi.Dgemv(blas.Trans, n-k-i, i, + 1, a[(k+i)*lda:], lda, + a[(k+i)*lda+i:], lda, + 0, t[i:], ldt) + bi.Dgemv(blas.NoTrans, n-k, i, + -1, y[k*ldy:], ldy, + t[i:], ldt, + 1, y[k*ldy+i:], ldy) + bi.Dscal(n-k, tau[i], y[k*ldy+i:], ldy) + + // Compute T[0:i,i]. + bi.Dscal(i, -tau[i], t[i:], ldt) + bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, + t, ldt, t[i:], ldt) + + t[i*ldt+i] = tau[i] + } + a[(k+nb-1)*lda+nb-1] = ei + + // Compute Y[0:k,0:nb]. + impl.Dlacpy(blas.All, k, nb, a[1:], lda, y, ldy) + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, k, nb, + 1, a[k*lda:], lda, y, ldy) + if n > k+nb { + bi.Dgemm(blas.NoTrans, blas.NoTrans, k, nb, n-k-nb, + 1, a[1+nb:], lda, + a[(k+nb)*lda:], lda, + 1, y, ldy) + } + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, k, nb, + 1, t, ldt, y, ldy) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go new file mode 100644 index 00000000..fb1873f7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go @@ -0,0 +1,396 @@ +// Copyright ©2016 The gonum 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 gonum + +import "math" + +// Dlaln2 solves a linear equation or a system of 2 linear equations of the form +// (ca A - w D) X = scale B, if trans == false, +// (ca A^T - w D) X = scale B, if trans == true, +// where A is a na×na real matrix, ca is a real scalar, D is a na×na diagonal +// real matrix, w is a scalar, real if nw == 1, complex if nw == 2, and X and B +// are na×1 matrices, real if w is real, complex if w is complex. +// +// If w is complex, X and B are represented as na×2 matrices, the first column +// of each being the real part and the second being the imaginary part. +// +// na and nw must be 1 or 2, otherwise Dlaln2 will panic. +// +// d1 and d2 are the diagonal elements of D. d2 is not used if na == 1. +// +// wr and wi represent the real and imaginary part, respectively, of the scalar +// w. wi is not used if nw == 1. +// +// smin is the desired lower bound on the singular values of A. This should be +// a safe distance away from underflow or overflow, say, between +// (underflow/machine precision) and (overflow*machine precision). +// +// If both singular values of (ca A - w D) are less than smin, smin*identity +// will be used instead of (ca A - w D). If only one singular value is less than +// smin, one element of (ca A - w D) will be perturbed enough to make the +// smallest singular value roughly smin. If both singular values are at least +// smin, (ca A - w D) will not be perturbed. In any case, the perturbation will +// be at most some small multiple of max(smin, ulp*norm(ca A - w D)). The +// singular values are computed by infinity-norm approximations, and thus will +// only be correct to a factor of 2 or so. +// +// All input quantities are assumed to be smaller than overflow by a reasonable +// factor. +// +// scale is a scaling factor less than or equal to 1 which is chosen so that X +// can be computed without overflow. X is further scaled if necessary to assure +// that norm(ca A - w D)*norm(X) is less than overflow. +// +// xnorm contains the infinity-norm of X when X is regarded as a na×nw real +// matrix. +// +// ok will be false if (ca A - w D) had to be perturbed to make its smallest +// singular value greater than smin, otherwise ok will be true. +// +// Dlaln2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool) { + // TODO(vladimir-ch): Consider splitting this function into two, one + // handling the real case (nw == 1) and the other handling the complex + // case (nw == 2). Given that Go has complex types, their signatures + // would be simpler and more natural, and the implementation not as + // convoluted. + + if na != 1 && na != 2 { + panic("lapack: invalid value of na") + } + if nw != 1 && nw != 2 { + panic("lapack: invalid value of nw") + } + checkMatrix(na, na, a, lda) + checkMatrix(na, nw, b, ldb) + checkMatrix(na, nw, x, ldx) + + smlnum := 2 * dlamchS + bignum := 1 / smlnum + smini := math.Max(smin, smlnum) + + ok = true + scale = 1 + + if na == 1 { + // 1×1 (i.e., scalar) system C X = B. + + if nw == 1 { + // Real 1×1 system. + + // C = ca A - w D. + csr := ca*a[0] - wr*d1 + cnorm := math.Abs(csr) + + // If |C| < smini, use C = smini. + if cnorm < smini { + csr = smini + cnorm = smini + ok = false + } + + // Check scaling for X = B / C. + bnorm := math.Abs(b[0]) + if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { + scale = 1 / bnorm + } + + // Compute X. + x[0] = b[0] * scale / csr + xnorm = math.Abs(x[0]) + + return scale, xnorm, ok + } + + // Complex 1×1 system (w is complex). + + // C = ca A - w D. + csr := ca*a[0] - wr*d1 + csi := -wi * d1 + cnorm := math.Abs(csr) + math.Abs(csi) + + // If |C| < smini, use C = smini. + if cnorm < smini { + csr = smini + csi = 0 + cnorm = smini + ok = false + } + + // Check scaling for X = B / C. + bnorm := math.Abs(b[0]) + math.Abs(b[1]) + if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { + scale = 1 / bnorm + } + + // Compute X. + cx := complex(scale*b[0], scale*b[1]) / complex(csr, csi) + x[0], x[1] = real(cx), imag(cx) + xnorm = math.Abs(x[0]) + math.Abs(x[1]) + + return scale, xnorm, ok + } + + // 2×2 system. + + // Compute the real part of + // C = ca A - w D + // or + // C = ca A^T - w D. + crv := [4]float64{ + ca*a[0] - wr*d1, + ca * a[1], + ca * a[lda], + ca*a[lda+1] - wr*d2, + } + if trans { + crv[1] = ca * a[lda] + crv[2] = ca * a[1] + } + + pivot := [4][4]int{ + {0, 1, 2, 3}, + {1, 0, 3, 2}, + {2, 3, 0, 1}, + {3, 2, 1, 0}, + } + + if nw == 1 { + // Real 2×2 system (w is real). + + // Find the largest element in C. + var cmax float64 + var icmax int + for j, v := range crv { + v = math.Abs(v) + if v > cmax { + cmax = v + icmax = j + } + } + + // If norm(C) < smini, use smini*identity. + if cmax < smini { + bnorm := math.Max(math.Abs(b[0]), math.Abs(b[ldb])) + if smini < 1 && bnorm > math.Max(1, bignum*smini) { + scale = 1 / bnorm + } + temp := scale / smini + x[0] = temp * b[0] + x[ldx] = temp * b[ldb] + xnorm = temp * bnorm + ok = false + + return scale, xnorm, ok + } + + // Gaussian elimination with complete pivoting. + // Form upper triangular matrix + // [ur11 ur12] + // [ 0 ur22] + ur11 := crv[icmax] + ur12 := crv[pivot[icmax][1]] + cr21 := crv[pivot[icmax][2]] + cr22 := crv[pivot[icmax][3]] + ur11r := 1 / ur11 + lr21 := ur11r * cr21 + ur22 := cr22 - ur12*lr21 + + // If smaller pivot < smini, use smini. + if math.Abs(ur22) < smini { + ur22 = smini + ok = false + } + + var br1, br2 float64 + if icmax > 1 { + // If the pivot lies in the second row, swap the rows. + br1 = b[ldb] + br2 = b[0] + } else { + br1 = b[0] + br2 = b[ldb] + } + br2 -= lr21 * br1 // Apply the Gaussian elimination step to the right-hand side. + + bbnd := math.Max(math.Abs(ur22*ur11r*br1), math.Abs(br2)) + if bbnd > 1 && math.Abs(ur22) < 1 && bbnd >= bignum*math.Abs(ur22) { + scale = 1 / bbnd + } + + // Solve the linear system ur*xr=br. + xr2 := br2 * scale / ur22 + xr1 := scale*br1*ur11r - ur11r*ur12*xr2 + if icmax&0x1 != 0 { + // If the pivot lies in the second column, swap the components of the solution. + x[0] = xr2 + x[ldx] = xr1 + } else { + x[0] = xr1 + x[ldx] = xr2 + } + xnorm = math.Max(math.Abs(xr1), math.Abs(xr2)) + + // Further scaling if norm(A)*norm(X) > overflow. + if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { + temp := cmax / bignum + x[0] *= temp + x[ldx] *= temp + xnorm *= temp + scale *= temp + } + + return scale, xnorm, ok + } + + // Complex 2×2 system (w is complex). + + // Find the largest element in C. + civ := [4]float64{ + -wi * d1, + 0, + 0, + -wi * d2, + } + var cmax float64 + var icmax int + for j, v := range crv { + v := math.Abs(v) + if v+math.Abs(civ[j]) > cmax { + cmax = v + math.Abs(civ[j]) + icmax = j + } + } + + // If norm(C) < smini, use smini*identity. + if cmax < smini { + br1 := math.Abs(b[0]) + math.Abs(b[1]) + br2 := math.Abs(b[ldb]) + math.Abs(b[ldb+1]) + bnorm := math.Max(br1, br2) + if smini < 1 && bnorm > 1 && bnorm > bignum*smini { + scale = 1 / bnorm + } + temp := scale / smini + x[0] = temp * b[0] + x[1] = temp * b[1] + x[ldb] = temp * b[ldb] + x[ldb+1] = temp * b[ldb+1] + xnorm = temp * bnorm + ok = false + + return scale, xnorm, ok + } + + // Gaussian elimination with complete pivoting. + ur11 := crv[icmax] + ui11 := civ[icmax] + ur12 := crv[pivot[icmax][1]] + ui12 := civ[pivot[icmax][1]] + cr21 := crv[pivot[icmax][2]] + ci21 := civ[pivot[icmax][2]] + cr22 := crv[pivot[icmax][3]] + ci22 := civ[pivot[icmax][3]] + var ( + ur11r, ui11r float64 + lr21, li21 float64 + ur12s, ui12s float64 + ur22, ui22 float64 + ) + if icmax == 0 || icmax == 3 { + // Off-diagonals of pivoted C are real. + if math.Abs(ur11) > math.Abs(ui11) { + temp := ui11 / ur11 + ur11r = 1 / (ur11 * (1 + temp*temp)) + ui11r = -temp * ur11r + } else { + temp := ur11 / ui11 + ui11r = -1 / (ui11 * (1 + temp*temp)) + ur11r = -temp * ui11r + } + lr21 = cr21 * ur11r + li21 = cr21 * ui11r + ur12s = ur12 * ur11r + ui12s = ur12 * ui11r + ur22 = cr22 - ur12*lr21 + ui22 = ci22 - ur12*li21 + } else { + // Diagonals of pivoted C are real. + ur11r = 1 / ur11 + // ui11r is already 0. + lr21 = cr21 * ur11r + li21 = ci21 * ur11r + ur12s = ur12 * ur11r + ui12s = ui12 * ur11r + ur22 = cr22 - ur12*lr21 + ui12*li21 + ui22 = -ur12*li21 - ui12*lr21 + } + u22abs := math.Abs(ur22) + math.Abs(ui22) + + // If smaller pivot < smini, use smini. + if u22abs < smini { + ur22 = smini + ui22 = 0 + ok = false + } + + var br1, bi1 float64 + var br2, bi2 float64 + if icmax > 1 { + // If the pivot lies in the second row, swap the rows. + br1 = b[ldb] + bi1 = b[ldb+1] + br2 = b[0] + bi2 = b[1] + } else { + br1 = b[0] + bi1 = b[1] + br2 = b[ldb] + bi2 = b[ldb+1] + } + br2 += -lr21*br1 + li21*bi1 + bi2 += -li21*br1 - lr21*bi1 + + bbnd1 := u22abs * (math.Abs(ur11r) + math.Abs(ui11r)) * (math.Abs(br1) + math.Abs(bi1)) + bbnd2 := math.Abs(br2) + math.Abs(bi2) + bbnd := math.Max(bbnd1, bbnd2) + if bbnd > 1 && u22abs < 1 && bbnd >= bignum*u22abs { + scale = 1 / bbnd + br1 *= scale + bi1 *= scale + br2 *= scale + bi2 *= scale + } + + cx2 := complex(br2, bi2) / complex(ur22, ui22) + xr2, xi2 := real(cx2), imag(cx2) + xr1 := ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 + xi1 := ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 + if icmax&0x1 != 0 { + // If the pivot lies in the second column, swap the components of the solution. + x[0] = xr2 + x[1] = xi2 + x[ldx] = xr1 + x[ldx+1] = xi1 + } else { + x[0] = xr1 + x[1] = xi1 + x[ldx] = xr2 + x[ldx+1] = xi2 + } + xnorm = math.Max(math.Abs(xr1)+math.Abs(xi1), math.Abs(xr2)+math.Abs(xi2)) + + // Further scaling if norm(A)*norm(X) > overflow. + if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { + temp := cmax / bignum + x[0] *= temp + x[1] *= temp + x[ldx] *= temp + x[ldx+1] *= temp + xnorm *= temp + scale *= temp + } + + return scale, xnorm, ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go new file mode 100644 index 00000000..66b46aab --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlange computes the matrix norm of the general m×n matrix a. The input norm +// specifies the norm computed. +// lapack.MaxAbs: the maximum absolute value of an element. +// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. +// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. +// lapack.NormFrob: the square root of the sum of the squares of the entries. +// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 { + // TODO(btracey): These should probably be refactored to use BLAS calls. + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + if m == 0 && n == 0 { + return 0 + } + if norm == lapack.MaxAbs { + var value float64 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + value = math.Max(value, math.Abs(a[i*lda+j])) + } + } + return value + } + if norm == lapack.MaxColumnSum { + if len(work) < n { + panic(badWork) + } + for i := 0; i < n; i++ { + work[i] = 0 + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + var value float64 + for i := 0; i < n; i++ { + value = math.Max(value, work[i]) + } + return value + } + if norm == lapack.MaxRowSum { + var value float64 + for i := 0; i < m; i++ { + var sum float64 + for j := 0; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + value = math.Max(value, sum) + } + return value + } + if norm == lapack.NormFrob { + var value float64 + scale := 0.0 + sum := 1.0 + for i := 0; i < m; i++ { + scale, sum = impl.Dlassq(n, a[i*lda:], 1, scale, sum) + } + value = scale * math.Sqrt(sum) + return value + } + panic("lapack: bad matrix norm") +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go new file mode 100644 index 00000000..7adb7aad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlanst computes the specified norm of a symmetric tridiagonal matrix A. +// The diagonal elements of A are stored in d and the off-diagonal elements +// are stored in e. +func (impl Implementation) Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 { + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if n <= 0 { + return 0 + } + switch norm { + default: + panic(badNorm) + case lapack.MaxAbs: + anorm := math.Abs(d[n-1]) + for i := 0; i < n-1; i++ { + sum := math.Abs(d[i]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + sum = math.Abs(e[i]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + } + return anorm + case lapack.MaxColumnSum, lapack.MaxRowSum: + if n == 1 { + return math.Abs(d[0]) + } + anorm := math.Abs(d[0]) + math.Abs(e[0]) + sum := math.Abs(e[n-2]) + math.Abs(d[n-1]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + for i := 1; i < n-1; i++ { + sum := math.Abs(d[i]) + math.Abs(e[i]) + math.Abs(e[i-1]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + } + return anorm + case lapack.NormFrob: + var scale float64 + sum := 1.0 + if n > 1 { + scale, sum = impl.Dlassq(n-1, e, 1, scale, sum) + sum = 2 * sum + } + scale, sum = impl.Dlassq(n, d, 1, scale, sum) + return scale * math.Sqrt(sum) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go new file mode 100644 index 00000000..03a7585b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go @@ -0,0 +1,125 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlansy computes the specified norm of an n×n symmetric matrix. If +// norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length +// at least n, otherwise work is unused. +func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(n, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n { + panic(badWork) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + + if n == 0 { + return 0 + } + switch norm { + default: + panic("unreachable") + case lapack.MaxAbs: + if uplo == blas.Upper { + var max float64 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := math.Abs(a[i*lda+j]) + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + } + return max + } + var max float64 + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := math.Abs(a[i*lda+j]) + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + } + return max + case lapack.MaxRowSum, lapack.MaxColumnSum: + // A symmetric matrix has the same 1-norm and ∞-norm. + for i := 0; i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + work[i] += math.Abs(a[i*lda+i]) + for j := i + 1; j < n; j++ { + v := math.Abs(a[i*lda+j]) + work[i] += v + work[j] += v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + v := math.Abs(a[i*lda+j]) + work[i] += v + work[j] += v + } + work[i] += math.Abs(a[i*lda+i]) + } + } + var max float64 + for i := 0; i < n; i++ { + v := work[i] + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + return max + case lapack.NormFrob: + if uplo == blas.Upper { + var sum float64 + for i := 0; i < n; i++ { + v := a[i*lda+i] + sum += v * v + for j := i + 1; j < n; j++ { + v := a[i*lda+j] + sum += 2 * v * v + } + } + return math.Sqrt(sum) + } + var sum float64 + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + v := a[i*lda+j] + sum += 2 * v * v + } + v := a[i*lda+i] + sum += v * v + } + return math.Sqrt(sum) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go new file mode 100644 index 00000000..43cf6fd2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go @@ -0,0 +1,252 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlantr computes the specified norm of an m×n trapezoidal matrix A. If +// norm == lapack.MaxColumnSum work must have length at least n, otherwise work +// is unused. +func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.Unit && diag != blas.NonUnit { + panic(badDiag) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + if min(m, n) == 0 { + return 0 + } + switch norm { + default: + panic("unreachable") + case lapack.MaxAbs: + if diag == blas.Unit { + value := 1.0 + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + var value float64 + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + case lapack.MaxColumnSum: + if diag == blas.Unit { + for i := 0; i < min(m, n); i++ { + work[i] = 1 + } + for i := min(m, n); i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } + } else { + for i := 0; i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } + } + var max float64 + for _, v := range work[:n] { + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + return max + case lapack.MaxRowSum: + var maxsum float64 + if diag == blas.Unit { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + var sum float64 + if i < min(m, n) { + sum = 1 + } + for j := i + 1; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return math.NaN() + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } else { + for i := 1; i < m; i++ { + var sum float64 + if i < min(m, n) { + sum = 1 + } + for j := 0; j < min(i, n); j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return math.NaN() + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } + } else { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + var sum float64 + for j := i; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return sum + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } else { + for i := 0; i < m; i++ { + var sum float64 + for j := 0; j <= min(i, n-1); j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return sum + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } + } + case lapack.NormFrob: + var nrm float64 + if diag == blas.Unit { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + tmp := a[i*lda+j] + nrm += tmp * tmp + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + tmp := a[i*lda+j] + nrm += tmp * tmp + } + } + } + nrm += float64(min(m, n)) + } else { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + nrm += tmp * tmp + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + tmp := math.Abs(a[i*lda+j]) + nrm += tmp * tmp + } + } + } + } + return math.Sqrt(nrm) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go new file mode 100644 index 00000000..1faeba32 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go @@ -0,0 +1,132 @@ +// Copyright ©2016 The gonum 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 gonum + +import "math" + +// Dlanv2 computes the Schur factorization of a real 2×2 matrix: +// [ a b ] = [ cs -sn ] * [ aa bb ] * [ cs sn ] +// [ c d ] [ sn cs ] [ cc dd ] * [-sn cs ] +// If cc is zero, aa and dd are real eigenvalues of the matrix. Otherwise it +// holds that aa = dd and bb*cc < 0, and aa ± sqrt(bb*cc) are complex conjugate +// eigenvalues. The real and imaginary parts of the eigenvalues are returned in +// (rt1r,rt1i) and (rt2r,rt2i). +func (impl Implementation) Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) { + switch { + case c == 0: // Matrix is already upper triangular. + aa = a + bb = b + cc = 0 + dd = d + cs = 1 + sn = 0 + case b == 0: // Matrix is lower triangular, swap rows and columns. + aa = d + bb = -c + cc = 0 + dd = a + cs = 0 + sn = 1 + case a == d && math.Signbit(b) != math.Signbit(c): // Matrix is already in the standard Schur form. + aa = a + bb = b + cc = c + dd = d + cs = 1 + sn = 0 + default: + temp := a - d + p := temp / 2 + bcmax := math.Max(math.Abs(b), math.Abs(c)) + bcmis := math.Min(math.Abs(b), math.Abs(c)) + if b*c < 0 { + bcmis *= -1 + } + scale := math.Max(math.Abs(p), bcmax) + z := p/scale*p + bcmax/scale*bcmis + eps := dlamchP + + if z >= 4*eps { + // Real eigenvalues. Compute aa and dd. + if p > 0 { + z = p + math.Sqrt(scale)*math.Sqrt(z) + } else { + z = p - math.Sqrt(scale)*math.Sqrt(z) + } + aa = d + z + dd = d - bcmax/z*bcmis + // Compute bb and the rotation matrix. + tau := impl.Dlapy2(c, z) + cs = z / tau + sn = c / tau + bb = b - c + cc = 0 + } else { + // Complex eigenvalues, or real (almost) equal eigenvalues. + // Make diagonal elements equal. + sigma := b + c + tau := impl.Dlapy2(sigma, temp) + cs = math.Sqrt((1 + math.Abs(sigma)/tau) / 2) + sn = -p / (tau * cs) + if sigma < 0 { + sn *= -1 + } + // Compute [ aa bb ] = [ a b ] [ cs -sn ] + // [ cc dd ] [ c d ] [ sn cs ] + aa = a*cs + b*sn + bb = -a*sn + b*cs + cc = c*cs + d*sn + dd = -c*sn + d*cs + // Compute [ a b ] = [ cs sn ] [ aa bb ] + // [ c d ] [-sn cs ] [ cc dd ] + a = aa*cs + cc*sn + b = bb*cs + dd*sn + c = -aa*sn + cc*cs + d = -bb*sn + dd*cs + + temp = (a + d) / 2 + aa = temp + bb = b + cc = c + dd = temp + + if cc != 0 { + if bb != 0 { + if math.Signbit(bb) == math.Signbit(cc) { + // Real eigenvalues, reduce to + // upper triangular form. + sab := math.Sqrt(math.Abs(bb)) + sac := math.Sqrt(math.Abs(cc)) + p = sab * sac + if cc < 0 { + p *= -1 + } + tau = 1 / math.Sqrt(math.Abs(bb+cc)) + aa = temp + p + bb = bb - cc + cc = 0 + dd = temp - p + cs1 := sab * tau + sn1 := sac * tau + cs, sn = cs*cs1-sn*sn1, cs*sn1+sn+cs1 + } + } else { + bb = -cc + cc = 0 + cs, sn = -sn, cs + } + } + } + } + + // Store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). + rt1r = aa + rt2r = dd + if cc != 0 { + rt1i = math.Sqrt(math.Abs(bb)) * math.Sqrt(math.Abs(cc)) + rt2i = -rt1i + } + return +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go new file mode 100644 index 00000000..990e90d2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go @@ -0,0 +1,36 @@ +// Copyright ©2017 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlapll returns the smallest singular value of the n×2 matrix A = [ x y ]. +// The function first computes the QR factorization of A = Q*R, and then computes +// the SVD of the 2-by-2 upper triangular matrix r. +// +// The contents of x and y are overwritten during the call. +// +// Dlapll is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 { + checkVector(n, x, incX) + checkVector(n, y, incY) + + if n <= 1 { + return 0 + } + + // Compute the QR factorization of the N-by-2 matrix [ X Y ]. + a00, tau := impl.Dlarfg(n, x[0], x[incX:], incX) + x[0] = 1 + + bi := blas64.Implementation() + c := -tau * bi.Ddot(n, x, incX, y, incY) + bi.Daxpy(n, c, x, incX, y, incY) + a11, _ := impl.Dlarfg(n-1, y[incY], y[2*incY:], incY) + + // Compute the SVD of 2-by-2 upper triangular matrix. + ssmin, _ := impl.Dlas2(a00, y[0], a11) + return ssmin +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go new file mode 100644 index 00000000..98331f5b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go @@ -0,0 +1,72 @@ +// Copyright ©2017 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlapmt rearranges the columns of the m×n matrix X as specified by the +// permutation k_0, k_1, ..., k_n-1 of the integers 0, ..., n-1. +// +// If forward is true a forward permutation is performed: +// +// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. +// +// otherwise a backward permutation is performed: +// +// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. +// +// k must have length n, otherwise Dlapmt will panic. k is zero-indexed. +func (impl Implementation) Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) { + checkMatrix(m, n, x, ldx) + if len(k) != n { + panic(badKperm) + } + + if n <= 1 { + return + } + + for i, v := range k { + v++ + k[i] = -v + } + + bi := blas64.Implementation() + + if forward { + for j, v := range k { + if v >= 0 { + continue + } + k[j] = -v + i := -v - 1 + for k[i] < 0 { + bi.Dswap(m, x[j:], ldx, x[i:], ldx) + + k[i] = -k[i] + j = i + i = k[i] - 1 + } + } + } else { + for i, v := range k { + if v >= 0 { + continue + } + k[i] = -v + j := -v - 1 + for j != i { + bi.Dswap(m, x[j:], ldx, x[i:], ldx) + + k[j] = -k[j] + j = k[j] - 1 + } + } + } + + for i := range k { + k[i]-- + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go new file mode 100644 index 00000000..cbc63210 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go @@ -0,0 +1,14 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlapy2 is the LAPACK version of math.Hypot. +// +// Dlapy2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dlapy2(x, y float64) float64 { + return math.Hypot(x, y) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go new file mode 100644 index 00000000..8b2118b1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go @@ -0,0 +1,111 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqp2 computes a QR factorization with column pivoting of the block A[offset:m, 0:n] +// of the m×n matrix A. The block A[0:offset, 0:n] is accordingly pivoted, but not factorized. +// +// On exit, the upper triangle of block A[offset:m, 0:n] is the triangular factor obtained. +// The elements in block A[offset:m, 0:n] below the diagonal, together with tau, represent +// the orthogonal matrix Q as a product of elementary reflectors. +// +// offset is number of rows of the matrix A that must be pivoted but not factorized. +// offset must not be negative otherwise Dlaqp2 will panic. +// +// On exit, jpvt holds the permutation that was applied; the jth column of A*P was the +// jpvt[j] column of A. jpvt must have length n, otherwise Dlaqp2 will panic. +// +// On exit tau holds the scalar factors of the elementary reflectors. It must have length +// at least min(m-offset, n) otherwise Dlaqp2 will panic. +// +// vn1 and vn2 hold the partial and complete column norms respectively. They must have length n, +// otherwise Dlaqp2 will panic. +// +// work must have length n, otherwise Dlaqp2 will panic. +// +// Dlaqp2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) { + checkMatrix(m, n, a, lda) + if len(jpvt) != n { + panic(badIpiv) + } + mn := min(m-offset, n) + if len(tau) < mn { + panic(badTau) + } + if len(vn1) < n { + panic(badVn1) + } + if len(vn2) < n { + panic(badVn2) + } + if len(work) < n { + panic(badWork) + } + + tol3z := math.Sqrt(dlamchE) + + bi := blas64.Implementation() + + // Compute factorization. + for i := 0; i < mn; i++ { + offpi := offset + i + + // Determine ith pivot column and swap if necessary. + p := i + bi.Idamax(n-i, vn1[i:], 1) + if p != i { + bi.Dswap(m, a[p:], lda, a[i:], lda) + jpvt[p], jpvt[i] = jpvt[i], jpvt[p] + vn1[p] = vn1[i] + vn2[p] = vn2[i] + } + + // Generate elementary reflector H_i. + if offpi < m-1 { + a[offpi*lda+i], tau[i] = impl.Dlarfg(m-offpi, a[offpi*lda+i], a[(offpi+1)*lda+i:], lda) + } else { + tau[i] = 0 + } + + if i < n-1 { + // Apply H_i^T to A[offset+i:m, i:n] from the left. + aii := a[offpi*lda+i] + a[offpi*lda+i] = 1 + impl.Dlarf(blas.Left, m-offpi, n-i-1, a[offpi*lda+i:], lda, tau[i], a[offpi*lda+i+1:], lda, work) + a[offpi*lda+i] = aii + } + + // Update partial column norms. + for j := i + 1; j < n; j++ { + if vn1[j] == 0 { + continue + } + + // The following marked lines follow from the + // analysis in Lapack Working Note 176. + r := math.Abs(a[offpi*lda+j]) / vn1[j] // * + temp := math.Max(0, 1-r*r) // * + r = vn1[j] / vn2[j] // * + temp2 := temp * r * r // * + if temp2 < tol3z { + var v float64 + if offpi < m-1 { + v = bi.Dnrm2(m-offpi-1, a[(offpi+1)*lda+j:], lda) + } + vn1[j] = v + vn2[j] = v + } else { + vn1[j] *= math.Sqrt(temp) // * + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go new file mode 100644 index 00000000..d5883c5c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go @@ -0,0 +1,217 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqps computes a step of QR factorization with column pivoting +// of an m×n matrix A by using Blas-3. It tries to factorize nb +// columns from A starting from the row offset, and updates all +// of the matrix with Dgemm. +// +// In some cases, due to catastrophic cancellations, it cannot +// factorize nb columns. Hence, the actual number of factorized +// columns is returned in kb. +// +// Dlaqps computes a QR factorization with column pivoting of the +// block A[offset:m, 0:nb] of the m×n matrix A. The block +// A[0:offset, 0:n] is accordingly pivoted, but not factorized. +// +// On exit, the upper triangle of block A[offset:m, 0:kb] is the +// triangular factor obtained. The elements in block A[offset:m, 0:n] +// below the diagonal, together with tau, represent the orthogonal +// matrix Q as a product of elementary reflectors. +// +// offset is number of rows of the matrix A that must be pivoted but +// not factorized. offset must not be negative otherwise Dlaqps will panic. +// +// On exit, jpvt holds the permutation that was applied; the jth column +// of A*P was the jpvt[j] column of A. jpvt must have length n, +// otherwise Dlapqs will panic. +// +// On exit tau holds the scalar factors of the elementary reflectors. +// It must have length nb, otherwise Dlapqs will panic. +// +// vn1 and vn2 hold the partial and complete column norms respectively. +// They must have length n, otherwise Dlapqs will panic. +// +// auxv must have length nb, otherwise Dlaqps will panic. +// +// f and ldf represent an n×nb matrix F that is overwritten during the +// call. +// +// Dlaqps is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqps(m, n, offset, nb int, a []float64, lda int, jpvt []int, tau, vn1, vn2, auxv, f []float64, ldf int) (kb int) { + checkMatrix(m, n, a, lda) + checkMatrix(n, nb, f, ldf) + if offset > m { + panic(offsetGTM) + } + if n < 0 || nb > n { + panic(badNb) + } + if len(jpvt) != n { + panic(badIpiv) + } + if len(tau) < nb { + panic(badTau) + } + if len(vn1) < n { + panic(badVn1) + } + if len(vn2) < n { + panic(badVn2) + } + if len(auxv) < nb { + panic(badAuxv) + } + + lastrk := min(m, n+offset) + lsticc := -1 + tol3z := math.Sqrt(dlamchE) + + bi := blas64.Implementation() + + var k, rk int + for ; k < nb && lsticc == -1; k++ { + rk = offset + k + + // Determine kth pivot column and swap if necessary. + p := k + bi.Idamax(n-k, vn1[k:], 1) + if p != k { + bi.Dswap(m, a[p:], lda, a[k:], lda) + bi.Dswap(k, f[p*ldf:], 1, f[k*ldf:], 1) + jpvt[p], jpvt[k] = jpvt[k], jpvt[p] + vn1[p] = vn1[k] + vn2[p] = vn2[k] + } + + // Apply previous Householder reflectors to column K: + // + // A[rk:m, k] = A[rk:m, k] - A[rk:m, 0:k-1]*F[k, 0:k-1]^T. + if k > 0 { + bi.Dgemv(blas.NoTrans, m-rk, k, -1, + a[rk*lda:], lda, + f[k*ldf:], 1, + 1, + a[rk*lda+k:], lda) + } + + // Generate elementary reflector H_k. + if rk < m-1 { + a[rk*lda+k], tau[k] = impl.Dlarfg(m-rk, a[rk*lda+k], a[(rk+1)*lda+k:], lda) + } else { + tau[k] = 0 + } + + akk := a[rk*lda+k] + a[rk*lda+k] = 1 + + // Compute kth column of F: + // + // Compute F[k+1:n, k] = tau[k]*A[rk:m, k+1:n]^T*A[rk:m, k]. + if k < n-1 { + bi.Dgemv(blas.Trans, m-rk, n-k-1, tau[k], + a[rk*lda+k+1:], lda, + a[rk*lda+k:], lda, + 0, + f[(k+1)*ldf+k:], ldf) + } + + // Padding F[0:k, k] with zeros. + for j := 0; j < k; j++ { + f[j*ldf+k] = 0 + } + + // Incremental updating of F: + // + // F[0:n, k] := F[0:n, k] - tau[k]*F[0:n, 0:k-1]*A[rk:m, 0:k-1]^T*A[rk:m,k]. + if k > 0 { + bi.Dgemv(blas.Trans, m-rk, k, -tau[k], + a[rk*lda:], lda, + a[rk*lda+k:], lda, + 0, + auxv, 1) + bi.Dgemv(blas.NoTrans, n, k, 1, + f, ldf, + auxv, 1, + 1, + f[k:], ldf) + } + + // Update the current row of A: + // + // A[rk, k+1:n] = A[rk, k+1:n] - A[rk, 0:k]*F[k+1:n, 0:k]^T. + if k < n-1 { + bi.Dgemv(blas.NoTrans, n-k-1, k+1, -1, + f[(k+1)*ldf:], ldf, + a[rk*lda:], 1, + 1, + a[rk*lda+k+1:], 1) + } + + // Update partial column norms. + if rk < lastrk-1 { + for j := k + 1; j < n; j++ { + if vn1[j] == 0 { + continue + } + + // The following marked lines follow from the + // analysis in Lapack Working Note 176. + r := math.Abs(a[rk*lda+j]) / vn1[j] // * + temp := math.Max(0, 1-r*r) // * + r = vn1[j] / vn2[j] // * + temp2 := temp * r * r // * + if temp2 < tol3z { + // vn2 is used here as a collection of + // indices into vn2 and also a collection + // of column norms. + vn2[j] = float64(lsticc) + lsticc = j + } else { + vn1[j] *= math.Sqrt(temp) // * + } + } + } + + a[rk*lda+k] = akk + } + kb = k + rk = offset + kb + + // Apply the block reflector to the rest of the matrix: + // + // A[offset+kb+1:m, kb+1:n] := A[offset+kb+1:m, kb+1:n] - A[offset+kb+1:m, 1:kb]*F[kb+1:n, 1:kb]^T. + if kb < min(n, m-offset) { + bi.Dgemm(blas.NoTrans, blas.Trans, + m-rk, n-kb, kb, -1, + a[rk*lda:], lda, + f[kb*ldf:], ldf, + 1, + a[rk*lda+kb:], lda) + } + + // Recomputation of difficult columns. + for lsticc >= 0 { + itemp := int(vn2[lsticc]) + + // NOTE: The computation of vn1[lsticc] relies on the fact that + // Dnrm2 does not fail on vectors with norm below the value of + // sqrt(dlamchS) + v := bi.Dnrm2(m-rk, a[rk*lda+lsticc:], lda) + vn1[lsticc] = v + vn2[lsticc] = v + + lsticc = itemp + } + + return kb +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go new file mode 100644 index 00000000..6db4d98d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go @@ -0,0 +1,475 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" +) + +// Dlaqr04 computes the eigenvalues of a block of an n×n upper Hessenberg matrix +// H, and optionally the matrices T and Z from the Schur decomposition +// H = Z T Z^T +// where T is an upper quasi-triangular matrix (the Schur form), and Z is the +// orthogonal matrix of Schur vectors. +// +// wantt indicates whether the full Schur form T is required. If wantt is false, +// then only enough of H will be updated to preserve the eigenvalues. +// +// wantz indicates whether the n×n matrix of Schur vectors Z is required. If it +// is true, the orthogonal similarity transformation will be accumulated into +// Z[iloz:ihiz+1,ilo:ihi+1], otherwise Z will not be referenced. +// +// ilo and ihi determine the block of H on which Dlaqr04 operates. It must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0, +// and the block must be isolated, that is, +// ilo == 0 or H[ilo,ilo-1] == 0, +// ihi == n-1 or H[ihi+1,ihi] == 0, +// otherwise Dlaqr04 will panic. +// +// wr and wi must have length ihi+1. +// +// iloz and ihiz specify the rows of Z to which transformations will be applied +// if wantz is true. It must hold that +// 0 <= iloz <= ilo, and ihi <= ihiz < n, +// otherwise Dlaqr04 will panic. +// +// work must have length at least lwork and lwork must be +// lwork >= 1, if n <= 11, +// lwork >= n, if n > 11, +// otherwise Dlaqr04 will panic. lwork as large as 6*n may be required for +// optimal performance. On return, work[0] will contain the optimal value of +// lwork. +// +// If lwork is -1, instead of performing Dlaqr04, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// recur is the non-negative recursion depth. For recur > 0, Dlaqr04 behaves +// as DLAQR0, for recur == 0 it behaves as DLAQR4. +// +// unconverged indicates whether Dlaqr04 computed all the eigenvalues of H[ilo:ihi+1,ilo:ihi+1]. +// +// If unconverged is zero and wantt is true, H will contain on return the upper +// quasi-triangular matrix T from the Schur decomposition. 2×2 diagonal blocks +// (corresponding to complex conjugate pairs of eigenvalues) will be returned in +// standard form, with H[i,i] == H[i+1,i+1] and H[i+1,i]*H[i,i+1] < 0. +// +// If unconverged is zero and if wantt is false, the contents of h on return is +// unspecified. +// +// If unconverged is zero, all the eigenvalues have been computed and their real +// and imaginary parts will be stored on return in wr[ilo:ihi+1] and +// wi[ilo:ihi+1], respectively. If two eigenvalues are computed as a complex +// conjugate pair, they are stored in consecutive elements of wr and wi, say the +// i-th and (i+1)th, with wi[i] > 0 and wi[i+1] < 0. If wantt is true, then the +// eigenvalues are stored in the same order as on the diagonal of the Schur form +// returned in H, with wr[i] = H[i,i] and, if H[i:i+2,i:i+2] is a 2×2 diagonal +// block, wi[i] = sqrt(-H[i+1,i]*H[i,i+1]) and wi[i+1] = -wi[i]. +// +// If unconverged is positive, some eigenvalues have not converged, and +// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] will contain those +// eigenvalues which have been successfully computed. Failures are rare. +// +// If unconverged is positive and wantt is true, then on return +// (initial H)*U = U*(final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged is positive and wantt is false, on return the remaining +// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix +// H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged is positive and wantz is true, then on return +// (final Z) = (initial Z)*U, +// where U is the orthogonal matrix in (*) regardless of the value of wantt. +// +// References: +// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: +// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix +// Anal. Appl. 23(4) (2002), pp. 929—947 +// URL: http://dx.doi.org/10.1137/S0895479801384573 +// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +// Dlaqr04 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int, work []float64, lwork int, recur int) (unconverged int) { + const ( + // Matrices of order ntiny or smaller must be processed by + // Dlahqr because of insufficient subdiagonal scratch space. + // This is a hard limit. + ntiny = 11 + // Exceptional deflation windows: try to cure rare slow + // convergence by varying the size of the deflation window after + // kexnw iterations. + kexnw = 5 + // Exceptional shifts: try to cure rare slow convergence with + // ad-hoc exceptional shifts every kexsh iterations. + kexsh = 6 + + // See https://github.com/gonum/lapack/pull/151#discussion_r68162802 + // and the surrounding discussion for an explanation where these + // constants come from. + // TODO(vladimir-ch): Similar constants for exceptional shifts + // are used also in dlahqr.go. The first constant is different + // there, it is equal to 3. Why? And does it matter? + wilk1 = 0.75 + wilk2 = -0.4375 + ) + + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < 1 && n <= ntiny && lwork != -1: + panic(badWork) + // TODO(vladimir-ch): Enable if and when we figure out what the minimum + // necessary lwork value is. Dlaqr04 says that the minimum is n which + // clashes with Dlaqr23's opinion about optimal work when nw <= 2 + // (independent of n). + // case lwork < n && n > ntiny && lwork != -1: + // panic(badWork) + case len(work) < lwork: + panic(shortWork) + case recur < 0: + panic("lapack: recur is negative") + } + if wantz { + if iloz < 0 || ilo < iloz { + panic("lapack: invalid value of iloz") + } + if ihiz < ihi || n <= ihiz { + panic("lapack: invalid value of ihiz") + } + } + if lwork != -1 { + checkMatrix(n, n, h, ldh) + if wantz { + checkMatrix(n, n, z, ldz) + } + switch { + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic("lapack: block not isolated") + case ihi+1 < n && h[(ihi+1)*ldh+ihi] != 0: + panic("lapack: block not isolated") + case len(wr) != ihi+1: + panic("lapack: bad length of wr") + case len(wi) != ihi+1: + panic("lapack: bad length of wi") + } + } + + // Quick return. + if n == 0 { + work[0] = 1 + return 0 + } + + if n <= ntiny { + // Tiny matrices must use Dlahqr. + work[0] = 1 + if lwork == -1 { + return 0 + } + return impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, iloz, ihiz, z, ldz) + } + + // Use small bulge multi-shift QR with aggressive early deflation on + // larger-than-tiny matrices. + var jbcmpz string + if wantt { + jbcmpz = "S" + } else { + jbcmpz = "E" + } + if wantz { + jbcmpz += "V" + } else { + jbcmpz += "N" + } + + var fname string + if recur > 0 { + fname = "DLAQR0" + } else { + fname = "DLAQR4" + } + // nwr is the recommended deflation window size. n is greater than 11, + // so there is enough subdiagonal workspace for nwr >= 2 as required. + // (In fact, there is enough subdiagonal space for nwr >= 3.) + // TODO(vladimir-ch): If there is enough space for nwr >= 3, should we + // use it? + nwr := impl.Ilaenv(13, fname, jbcmpz, n, ilo, ihi, lwork) + nwr = max(2, nwr) + nwr = min(ihi-ilo+1, min((n-1)/3, nwr)) + + // nsr is the recommended number of simultaneous shifts. n is greater + // than 11, so there is enough subdiagonal workspace for nsr to be even + // and greater than or equal to two as required. + nsr := impl.Ilaenv(15, fname, jbcmpz, n, ilo, ihi, lwork) + nsr = min(nsr, min((n+6)/9, ihi-ilo)) + nsr = max(2, nsr&^1) + + // Workspace query call to Dlaqr23. + impl.Dlaqr23(wantt, wantz, n, ilo, ihi, nwr+1, nil, 0, iloz, ihiz, nil, 0, + nil, nil, nil, 0, n, nil, 0, n, nil, 0, work, -1, recur) + // Optimal workspace is max(Dlaqr5, Dlaqr23). + lwkopt := max(3*nsr/2, int(work[0])) + // Quick return in case of workspace query. + if lwork == -1 { + work[0] = float64(lwkopt) + return 0 + } + + // Dlahqr/Dlaqr04 crossover point. + nmin := impl.Ilaenv(12, fname, jbcmpz, n, ilo, ihi, lwork) + nmin = max(ntiny, nmin) + + // Nibble determines when to skip a multi-shift QR sweep (Dlaqr5). + nibble := impl.Ilaenv(14, fname, jbcmpz, n, ilo, ihi, lwork) + nibble = max(0, nibble) + + // Computation mode of far-from-diagonal orthogonal updates in Dlaqr5. + kacc22 := impl.Ilaenv(16, fname, jbcmpz, n, ilo, ihi, lwork) + kacc22 = max(0, min(kacc22, 2)) + + // nwmax is the largest possible deflation window for which there is + // sufficient workspace. + nwmax := min((n-1)/3, lwork/2) + nw := nwmax // Start with maximum deflation window size. + + // nsmax is the largest number of simultaneous shifts for which there is + // sufficient workspace. + nsmax := min((n+6)/9, 2*lwork/3) &^ 1 + + ndfl := 1 // Number of iterations since last deflation. + ndec := 0 // Deflation window size decrement. + + // Main loop. + var ( + itmax = max(30, 2*kexsh) * max(10, (ihi-ilo+1)) + it = 0 + ) + for kbot := ihi; kbot >= ilo; { + if it == itmax { + unconverged = kbot + 1 + break + } + it++ + + // Locate active block. + ktop := ilo + for k := kbot; k >= ilo+1; k-- { + if h[k*ldh+k-1] == 0 { + ktop = k + break + } + } + + // Select deflation window size nw. + // + // Typical Case: + // If possible and advisable, nibble the entire active block. + // If not, use size min(nwr,nwmax) or min(nwr+1,nwmax) + // depending upon which has the smaller corresponding + // subdiagonal entry (a heuristic). + // + // Exceptional Case: + // If there have been no deflations in kexnw or more + // iterations, then vary the deflation window size. At first, + // because larger windows are, in general, more powerful than + // smaller ones, rapidly increase the window to the maximum + // possible. Then, gradually reduce the window size. + nh := kbot - ktop + 1 + nwupbd := min(nh, nwmax) + if ndfl < kexnw { + nw = min(nwupbd, nwr) + } else { + nw = min(nwupbd, 2*nw) + } + if nw < nwmax { + if nw >= nh-1 { + nw = nh + } else { + kwtop := kbot - nw + 1 + if math.Abs(h[kwtop*ldh+kwtop-1]) > math.Abs(h[(kwtop-1)*ldh+kwtop-2]) { + nw++ + } + } + } + if ndfl < kexnw { + ndec = -1 + } else if ndec >= 0 || nw >= nwupbd { + ndec++ + if nw-ndec < 2 { + ndec = 0 + } + nw -= ndec + } + + // Split workspace under the subdiagonal of H into: + // - an nw×nw work array V in the lower left-hand corner, + // - an nw×nhv horizontal work array along the bottom edge (nhv + // must be at least nw but more is better), + // - an nve×nw vertical work array along the left-hand-edge + // (nhv can be any positive integer but more is better). + kv := n - nw + kt := nw + kwv := nw + 1 + nhv := n - kwv - kt + // Aggressive early deflation. + ls, ld := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, + h, ldh, iloz, ihiz, z, ldz, wr[:kbot+1], wi[:kbot+1], + h[kv*ldh:], ldh, nhv, h[kv*ldh+kt:], ldh, nhv, h[kwv*ldh:], ldh, work, lwork, recur) + + // Adjust kbot accounting for new deflations. + kbot -= ld + // ks points to the shifts. + ks := kbot - ls + 1 + + // Skip an expensive QR sweep if there is a (partly heuristic) + // reason to expect that many eigenvalues will deflate without + // it. Here, the QR sweep is skipped if many eigenvalues have + // just been deflated or if the remaining active block is small. + if ld > 0 && (100*ld > nw*nibble || kbot-ktop+1 <= min(nmin, nwmax)) { + // ld is positive, note progress. + ndfl = 1 + continue + } + + // ns is the nominal number of simultaneous shifts. This may be + // lowered (slightly) if Dlaqr23 did not provide that many + // shifts. + ns := min(min(nsmax, nsr), max(2, kbot-ktop)) &^ 1 + + // If there have been no deflations in a multiple of kexsh + // iterations, then try exceptional shifts. Otherwise use shifts + // provided by Dlaqr23 above or from the eigenvalues of a + // trailing principal submatrix. + if ndfl%kexsh == 0 { + ks = kbot - ns + 1 + for i := kbot; i > max(ks, ktop+1); i -= 2 { + ss := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) + aa := wilk1*ss + h[i*ldh+i] + _, _, _, _, wr[i-1], wi[i-1], wr[i], wi[i], _, _ = + impl.Dlanv2(aa, ss, wilk2*ss, aa) + } + if ks == ktop { + wr[ks+1] = h[(ks+1)*ldh+ks+1] + wi[ks+1] = 0 + wr[ks] = wr[ks+1] + wi[ks] = wi[ks+1] + } + } else { + // If we got ns/2 or fewer shifts, use Dlahqr or recur + // into Dlaqr04 on a trailing principal submatrix to get + // more. Since ns <= nsmax <=(n+6)/9, there is enough + // space below the subdiagonal to fit an ns×ns scratch + // array. + if kbot-ks+1 <= ns/2 { + ks = kbot - ns + 1 + kt = n - ns + impl.Dlacpy(blas.All, ns, ns, h[ks*ldh+ks:], ldh, h[kt*ldh:], ldh) + if ns > nmin && recur > 0 { + ks += impl.Dlaqr04(false, false, ns, 1, ns-1, h[kt*ldh:], ldh, + wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 0, work, lwork, recur-1) + } else { + ks += impl.Dlahqr(false, false, ns, 0, ns-1, h[kt*ldh:], ldh, + wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 0) + } + // In case of a rare QR failure use eigenvalues + // of the trailing 2×2 principal submatrix. + if ks >= kbot { + aa := h[(kbot-1)*ldh+kbot-1] + bb := h[(kbot-1)*ldh+kbot] + cc := h[kbot*ldh+kbot-1] + dd := h[kbot*ldh+kbot] + _, _, _, _, wr[kbot-1], wi[kbot-1], wr[kbot], wi[kbot], _, _ = + impl.Dlanv2(aa, bb, cc, dd) + ks = kbot - 1 + } + } + + if kbot-ks+1 > ns { + // Sorting the shifts helps a little. Bubble + // sort keeps complex conjugate pairs together. + sorted := false + for k := kbot; k > ks; k-- { + if sorted { + break + } + sorted = true + for i := ks; i < k; i++ { + if math.Abs(wr[i])+math.Abs(wi[i]) >= math.Abs(wr[i+1])+math.Abs(wi[i+1]) { + continue + } + sorted = false + wr[i], wr[i+1] = wr[i+1], wr[i] + wi[i], wi[i+1] = wi[i+1], wi[i] + } + } + } + + // Shuffle shifts into pairs of real shifts and pairs of + // complex conjugate shifts using the fact that complex + // conjugate shifts are already adjacent to one another. + // TODO(vladimir-ch): The shuffling here could probably + // be removed but I'm not sure right now and it's safer + // to leave it. + for i := kbot; i > ks+1; i -= 2 { + if wi[i] == -wi[i-1] { + continue + } + wr[i], wr[i-1], wr[i-2] = wr[i-1], wr[i-2], wr[i] + wi[i], wi[i-1], wi[i-2] = wi[i-1], wi[i-2], wi[i] + } + } + + // If there are only two shifts and both are real, then use only one. + if kbot-ks+1 == 2 && wi[kbot] == 0 { + if math.Abs(wr[kbot]-h[kbot*ldh+kbot]) < math.Abs(wr[kbot-1]-h[kbot*ldh+kbot]) { + wr[kbot-1] = wr[kbot] + } else { + wr[kbot] = wr[kbot-1] + } + } + + // Use up to ns of the the smallest magnitude shifts. If there + // aren't ns shifts available, then use them all, possibly + // dropping one to make the number of shifts even. + ns = min(ns, kbot-ks+1) &^ 1 + ks = kbot - ns + 1 + + // Split workspace under the subdiagonal into: + // - a kdu×kdu work array U in the lower left-hand-corner, + // - a kdu×nhv horizontal work array WH along the bottom edge + // (nhv must be at least kdu but more is better), + // - an nhv×kdu vertical work array WV along the left-hand-edge + // (nhv must be at least kdu but more is better). + kdu := 3*ns - 3 + ku := n - kdu + kwh := kdu + kwv = kdu + 3 + nhv = n - kwv - kdu + // Small-bulge multi-shift QR sweep. + impl.Dlaqr5(wantt, wantz, kacc22, n, ktop, kbot, ns, + wr[ks:ks+ns], wi[ks:ks+ns], h, ldh, iloz, ihiz, z, ldz, + work, 3, h[ku*ldh:], ldh, nhv, h[kwv*ldh:], ldh, nhv, h[ku*ldh+kwh:], ldh) + + // Note progress (or the lack of it). + if ld > 0 { + ndfl = 1 + } else { + ndfl++ + } + } + + work[0] = float64(lwkopt) + return unconverged +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go new file mode 100644 index 00000000..9efd774a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum 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 gonum + +import "math" + +// Dlaqr1 sets v to a scalar multiple of the first column of the product +// (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) +// where H is a 2×2 or 3×3 matrix, I is the identity matrix of the same size, +// and i is the imaginary unit. Scaling is done to avoid overflows and most +// underflows. +// +// n is the order of H and must be either 2 or 3. It must hold that either sr1 = +// sr2 and si1 = -si2, or si1 = si2 = 0. The length of v must be equal to n. If +// any of these conditions is not met, Dlaqr1 will panic. +// +// Dlaqr1 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) { + if n != 2 && n != 3 { + panic(badDims) + } + checkMatrix(n, n, h, ldh) + if len(v) != n { + panic(badSlice) + } + if !((sr1 == sr2 && si1 == -si2) || (si1 == 0 && si2 == 0)) { + panic(badShifts) + } + + if n == 2 { + s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + if s == 0 { + v[0] = 0 + v[1] = 0 + } else { + h21s := h[ldh] / s + v[0] = h21s*h[1] + (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + v[1] = h21s * (h[0] + h[ldh+1] - sr1 - sr2) + } + return + } + + s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + math.Abs(h[2*ldh]) + if s == 0 { + v[0] = 0 + v[1] = 0 + v[2] = 0 + } else { + h21s := h[ldh] / s + h31s := h[2*ldh] / s + v[0] = (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + h[1]*h21s + h[2]*h31s + v[1] = h21s*(h[0]+h[ldh+1]-sr1-sr2) + h[ldh+2]*h31s + v[2] = h31s*(h[0]+h[2*ldh+2]-sr1-sr2) + h21s*h[2*ldh+1] + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go new file mode 100644 index 00000000..1a59e4b9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go @@ -0,0 +1,403 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlaqr23 performs the orthogonal similarity transformation of an n×n upper +// Hessenberg matrix to detect and deflate fully converged eigenvalues from a +// trailing principal submatrix using aggressive early deflation [1]. +// +// On return, H will be overwritten by a new Hessenberg matrix that is a +// perturbation of an orthogonal similarity transformation of H. It is hoped +// that on output H will have many zero subdiagonal entries. +// +// If wantt is true, the matrix H will be fully updated so that the +// quasi-triangular Schur factor can be computed. If wantt is false, then only +// enough of H will be updated to preserve the eigenvalues. +// +// If wantz is true, the orthogonal similarity transformation will be +// accumulated into Z[iloz:ihiz+1,ktop:kbot+1], otherwise Z is not referenced. +// +// ktop and kbot determine a block [ktop:kbot+1,ktop:kbot+1] along the diagonal +// of H. It must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0, +// and the block must be isolated, that is, it must hold that +// ktop == 0 or H[ktop,ktop-1] == 0, +// kbot == n-1 or H[kbot+1,kbot] == 0, +// otherwise Dlaqr23 will panic. +// +// nw is the deflation window size. It must hold that +// 0 <= nw <= kbot-ktop+1, +// otherwise Dlaqr23 will panic. +// +// iloz and ihiz specify the rows of the n×n matrix Z to which transformations +// will be applied if wantz is true. It must hold that +// 0 <= iloz <= ktop, and kbot <= ihiz < n, +// otherwise Dlaqr23 will panic. +// +// sr and si must have length kbot+1, otherwise Dlaqr23 will panic. +// +// v and ldv represent an nw×nw work matrix. +// t and ldt represent an nw×nh work matrix, and nh must be at least nw. +// wv and ldwv represent an nv×nw work matrix. +// +// work must have length at least lwork and lwork must be at least max(1,2*nw), +// otherwise Dlaqr23 will panic. Larger values of lwork may result in greater +// efficiency. On return, work[0] will contain the optimal value of lwork. +// +// If lwork is -1, instead of performing Dlaqr23, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// recur is the non-negative recursion depth. For recur > 0, Dlaqr23 behaves +// as DLAQR3, for recur == 0 it behaves as DLAQR2. +// +// On return, ns and nd will contain respectively the number of unconverged +// (i.e., approximate) eigenvalues and converged eigenvalues that are stored in +// sr and si. +// +// On return, the real and imaginary parts of approximate eigenvalues that may +// be used for shifts will be stored respectively in sr[kbot-nd-ns+1:kbot-nd+1] +// and si[kbot-nd-ns+1:kbot-nd+1]. +// +// On return, the real and imaginary parts of converged eigenvalues will be +// stored respectively in sr[kbot-nd+1:kbot+1] and si[kbot-nd+1:kbot+1]. +// +// References: +// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +func (impl Implementation) Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int) { + switch { + case ktop < 0 || max(0, n-1) < ktop: + panic("lapack: invalid value of ktop") + case kbot < min(ktop, n-1) || n <= kbot: + panic("lapack: invalid value of kbot") + case (nw < 0 || kbot-ktop+1 < nw) && lwork != -1: + panic("lapack: invalid value of nw") + case nh < nw: + panic("lapack: invalid value of nh") + case lwork < max(1, 2*nw) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + case recur < 0: + panic("lapack: recur is negative") + } + if wantz { + switch { + case iloz < 0 || ktop < iloz: + panic("lapack: invalid value of iloz") + case ihiz < kbot || n <= ihiz: + panic("lapack: invalid value of ihiz") + } + } + if lwork != -1 { + // Check input slices only if not doing workspace query. + checkMatrix(n, n, h, ldh) + checkMatrix(nw, nw, v, ldv) + checkMatrix(nw, nh, t, ldt) + checkMatrix(nv, nw, wv, ldwv) + if wantz { + checkMatrix(n, n, z, ldz) + } + switch { + case ktop > 0 && h[ktop*ldh+ktop-1] != 0: + panic("lapack: block not isolated") + case kbot+1 < n && h[(kbot+1)*ldh+kbot] != 0: + panic("lapack: block not isolated") + case len(sr) != kbot+1: + panic("lapack: bad length of sr") + case len(si) != kbot+1: + panic("lapack: bad length of si") + } + } + + // Quick return for zero window size. + if nw == 0 { + work[0] = 1 + return 0, 0 + } + + // LAPACK code does not enforce the documented behavior + // nw <= kbot-ktop+1 + // but we do (we panic above). + jw := nw + lwkopt := max(1, 2*nw) + if jw > 2 { + // Workspace query call to Dgehrd. + impl.Dgehrd(jw, 0, jw-2, nil, 0, nil, work, -1) + lwk1 := int(work[0]) + // Workspace query call to Dormhr. + impl.Dormhr(blas.Right, blas.NoTrans, jw, jw, 0, jw-2, nil, 0, nil, nil, 0, work, -1) + lwk2 := int(work[0]) + if recur > 0 { + // Workspace query call to Dlaqr04. + impl.Dlaqr04(true, true, jw, 0, jw-1, nil, 0, nil, nil, 0, jw-1, nil, 0, work, -1, recur-1) + lwk3 := int(work[0]) + // Optimal workspace. + lwkopt = max(jw+max(lwk1, lwk2), lwk3) + } else { + // Optimal workspace. + lwkopt = jw + max(lwk1, lwk2) + } + } + // Quick return in case of workspace query. + if lwork == -1 { + work[0] = float64(lwkopt) + return 0, 0 + } + + // Machine constants. + ulp := dlamchP + smlnum := float64(n) / ulp * dlamchS + + // Setup deflation window. + var s float64 + kwtop := kbot - jw + 1 + if kwtop != ktop { + s = h[kwtop*ldh+kwtop-1] + } + if kwtop == kbot { + // 1×1 deflation window. + sr[kwtop] = h[kwtop*ldh+kwtop] + si[kwtop] = 0 + ns = 1 + nd = 0 + if math.Abs(s) <= math.Max(smlnum, ulp*math.Abs(h[kwtop*ldh+kwtop])) { + ns = 0 + nd = 1 + if kwtop > ktop { + h[kwtop*ldh+kwtop-1] = 0 + } + } + work[0] = 1 + return ns, nd + } + + // Convert to spike-triangular form. In case of a rare QR failure, this + // routine continues to do aggressive early deflation using that part of + // the deflation window that converged using infqr here and there to + // keep track. + impl.Dlacpy(blas.Upper, jw, jw, h[kwtop*ldh+kwtop:], ldh, t, ldt) + bi := blas64.Implementation() + bi.Dcopy(jw-1, h[(kwtop+1)*ldh+kwtop:], ldh+1, t[ldt:], ldt+1) + impl.Dlaset(blas.All, jw, jw, 0, 1, v, ldv) + nmin := impl.Ilaenv(12, "DLAQR3", "SV", jw, 0, jw-1, lwork) + var infqr int + if recur > 0 && jw > nmin { + infqr = impl.Dlaqr04(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv, work, lwork, recur-1) + } else { + infqr = impl.Dlahqr(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv) + } + // Note that ilo == 0 which conveniently coincides with the success + // value of infqr, that is, infqr as an index always points to the first + // converged eigenvalue. + + // Dtrexc needs a clean margin near the diagonal. + for j := 0; j < jw-3; j++ { + t[(j+2)*ldt+j] = 0 + t[(j+3)*ldt+j] = 0 + } + if jw >= 3 { + t[(jw-1)*ldt+jw-3] = 0 + } + + ns = jw + ilst := infqr + // Deflation detection loop. + for ilst < ns { + bulge := false + if ns >= 2 { + bulge = t[(ns-1)*ldt+ns-2] != 0 + } + if !bulge { + // Real eigenvalue. + abst := math.Abs(t[(ns-1)*ldt+ns-1]) + if abst == 0 { + abst = math.Abs(s) + } + if math.Abs(s*v[ns-1]) <= math.Max(smlnum, ulp*abst) { + // Deflatable. + ns-- + } else { + // Undeflatable, move it up out of the way. + // Dtrexc can not fail in this case. + _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) + ilst++ + } + continue + } + // Complex conjugate pair. + abst := math.Abs(t[(ns-1)*ldt+ns-1]) + math.Sqrt(math.Abs(t[(ns-1)*ldt+ns-2]))*math.Sqrt(math.Abs(t[(ns-2)*ldt+ns-1])) + if abst == 0 { + abst = math.Abs(s) + } + if math.Max(math.Abs(s*v[ns-1]), math.Abs(s*v[ns-2])) <= math.Max(smlnum, ulp*abst) { + // Deflatable. + ns -= 2 + } else { + // Undeflatable, move them up out of the way. + // Dtrexc does the right thing with ilst in case of a + // rare exchange failure. + _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) + ilst += 2 + } + } + + // Return to Hessenberg form. + if ns == 0 { + s = 0 + } + if ns < jw { + // Sorting diagonal blocks of T improves accuracy for graded + // matrices. Bubble sort deals well with exchange failures. + sorted := false + i := ns + for !sorted { + sorted = true + kend := i - 1 + i = infqr + var k int + if i == ns-1 || t[(i+1)*ldt+i] == 0 { + k = i + 1 + } else { + k = i + 2 + } + for k <= kend { + var evi float64 + if k == i+1 { + evi = math.Abs(t[i*ldt+i]) + } else { + evi = math.Abs(t[i*ldt+i]) + math.Sqrt(math.Abs(t[(i+1)*ldt+i]))*math.Sqrt(math.Abs(t[i*ldt+i+1])) + } + + var evk float64 + if k == kend || t[(k+1)*ldt+k] == 0 { + evk = math.Abs(t[k*ldt+k]) + } else { + evk = math.Abs(t[k*ldt+k]) + math.Sqrt(math.Abs(t[(k+1)*ldt+k]))*math.Sqrt(math.Abs(t[k*ldt+k+1])) + } + + if evi >= evk { + i = k + } else { + sorted = false + _, ilst, ok := impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, i, k, work) + if ok { + i = ilst + } else { + i = k + } + } + if i == kend || t[(i+1)*ldt+i] == 0 { + k = i + 1 + } else { + k = i + 2 + } + } + } + } + + // Restore shift/eigenvalue array from T. + for i := jw - 1; i >= infqr; { + if i == infqr || t[i*ldt+i-1] == 0 { + sr[kwtop+i] = t[i*ldt+i] + si[kwtop+i] = 0 + i-- + continue + } + aa := t[(i-1)*ldt+i-1] + bb := t[(i-1)*ldt+i] + cc := t[i*ldt+i-1] + dd := t[i*ldt+i] + _, _, _, _, sr[kwtop+i-1], si[kwtop+i-1], sr[kwtop+i], si[kwtop+i], _, _ = impl.Dlanv2(aa, bb, cc, dd) + i -= 2 + } + + if ns < jw || s == 0 { + if ns > 1 && s != 0 { + // Reflect spike back into lower triangle. + bi.Dcopy(ns, v[:ns], 1, work[:ns], 1) + _, tau := impl.Dlarfg(ns, work[0], work[1:ns], 1) + work[0] = 1 + impl.Dlaset(blas.Lower, jw-2, jw-2, 0, 0, t[2*ldt:], ldt) + impl.Dlarf(blas.Left, ns, jw, work[:ns], 1, tau, t, ldt, work[jw:]) + impl.Dlarf(blas.Right, ns, ns, work[:ns], 1, tau, t, ldt, work[jw:]) + impl.Dlarf(blas.Right, jw, ns, work[:ns], 1, tau, v, ldv, work[jw:]) + impl.Dgehrd(jw, 0, ns-1, t, ldt, work[:jw-1], work[jw:], lwork-jw) + } + + // Copy updated reduced window into place. + if kwtop > 0 { + h[kwtop*ldh+kwtop-1] = s * v[0] + } + impl.Dlacpy(blas.Upper, jw, jw, t, ldt, h[kwtop*ldh+kwtop:], ldh) + bi.Dcopy(jw-1, t[ldt:], ldt+1, h[(kwtop+1)*ldh+kwtop:], ldh+1) + + // Accumulate orthogonal matrix in order to update H and Z, if + // requested. + if ns > 1 && s != 0 { + // work[:ns-1] contains the elementary reflectors stored + // by a call to Dgehrd above. + impl.Dormhr(blas.Right, blas.NoTrans, jw, ns, 0, ns-1, + t, ldt, work[:ns-1], v, ldv, work[jw:], lwork-jw) + } + + // Update vertical slab in H. + var ltop int + if !wantt { + ltop = ktop + } + for krow := ltop; krow < kwtop; krow += nv { + kln := min(nv, kwtop-krow) + bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, + 1, h[krow*ldh+kwtop:], ldh, v, ldv, + 0, wv, ldwv) + impl.Dlacpy(blas.All, kln, jw, wv, ldwv, h[krow*ldh+kwtop:], ldh) + } + + // Update horizontal slab in H. + if wantt { + for kcol := kbot + 1; kcol < n; kcol += nh { + kln := min(nh, n-kcol) + bi.Dgemm(blas.Trans, blas.NoTrans, jw, kln, jw, + 1, v, ldv, h[kwtop*ldh+kcol:], ldh, + 0, t, ldt) + impl.Dlacpy(blas.All, jw, kln, t, ldt, h[kwtop*ldh+kcol:], ldh) + } + } + + // Update vertical slab in Z. + if wantz { + for krow := iloz; krow <= ihiz; krow += nv { + kln := min(nv, ihiz-krow+1) + bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, + 1, z[krow*ldz+kwtop:], ldz, v, ldv, + 0, wv, ldwv) + impl.Dlacpy(blas.All, kln, jw, wv, ldwv, z[krow*ldz+kwtop:], ldz) + } + } + } + + // The number of deflations. + nd = jw - ns + // Shifts are converged eigenvalues that could not be deflated. + // Subtracting infqr from the spike length takes care of the case of a + // rare QR failure while calculating eigenvalues of the deflation + // window. + ns -= infqr + work[0] = float64(lwkopt) + return ns, nd +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go new file mode 100644 index 00000000..0b6959dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go @@ -0,0 +1,616 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqr5 performs a single small-bulge multi-shift QR sweep on an isolated +// block of a Hessenberg matrix. +// +// wantt and wantz determine whether the quasi-triangular Schur factor and the +// orthogonal Schur factor, respectively, will be computed. +// +// kacc22 specifies the computation mode of far-from-diagonal orthogonal +// updates. Permitted values are: +// 0: Dlaqr5 will not accumulate reflections and will not use matrix-matrix +// multiply to update far-from-diagonal matrix entries. +// 1: Dlaqr5 will accumulate reflections and use matrix-matrix multiply to +// update far-from-diagonal matrix entries. +// 2: Dlaqr5 will accumulate reflections, use matrix-matrix multiply to update +// far-from-diagonal matrix entries, and take advantage of 2×2 block +// structure during matrix multiplies. +// For other values of kacc2 Dlaqr5 will panic. +// +// n is the order of the Hessenberg matrix H. +// +// ktop and kbot are indices of the first and last row and column of an isolated +// diagonal block upon which the QR sweep will be applied. It must hold that +// ktop == 0, or 0 < ktop <= n-1 and H[ktop, ktop-1] == 0, and +// kbot == n-1, or 0 <= kbot < n-1 and H[kbot+1, kbot] == 0, +// otherwise Dlaqr5 will panic. +// +// nshfts is the number of simultaneous shifts. It must be positive and even, +// otherwise Dlaqr5 will panic. +// +// sr and si contain the real and imaginary parts, respectively, of the shifts +// of origin that define the multi-shift QR sweep. On return both slices may be +// reordered by Dlaqr5. Their length must be equal to nshfts, otherwise Dlaqr5 +// will panic. +// +// h and ldh represent the Hessenberg matrix H of size n×n. On return +// multi-shift QR sweep with shifts sr+i*si has been applied to the isolated +// diagonal block in rows and columns ktop through kbot, inclusive. +// +// iloz and ihiz specify the rows of Z to which transformations will be applied +// if wantz is true. It must hold that 0 <= iloz <= ihiz < n, otherwise Dlaqr5 +// will panic. +// +// z and ldz represent the matrix Z of size n×n. If wantz is true, the QR sweep +// orthogonal similarity transformation is accumulated into +// z[iloz:ihiz,iloz:ihiz] from the right, otherwise z not referenced. +// +// v and ldv represent an auxiliary matrix V of size (nshfts/2)×3. Note that V +// is transposed with respect to the reference netlib implementation. +// +// u and ldu represent an auxiliary matrix of size (3*nshfts-3)×(3*nshfts-3). +// +// wh and ldwh represent an auxiliary matrix of size (3*nshfts-3)×nh. +// +// wv and ldwv represent an auxiliary matrix of size nv×(3*nshfts-3). +// +// Dlaqr5 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, nshfts int, sr, si []float64, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, u []float64, ldu int, nv int, wv []float64, ldwv int, nh int, wh []float64, ldwh int) { + checkMatrix(n, n, h, ldh) + if ktop < 0 || n <= ktop { + panic("lapack: invalid value of ktop") + } + if ktop > 0 && h[ktop*ldh+ktop-1] != 0 { + panic("lapack: diagonal block is not isolated") + } + if kbot < 0 || n <= kbot { + panic("lapack: invalid value of kbot") + } + if kbot < n-1 && h[(kbot+1)*ldh+kbot] != 0 { + panic("lapack: diagonal block is not isolated") + } + if nshfts < 0 || nshfts&0x1 != 0 { + panic("lapack: invalid number of shifts") + } + if len(sr) != nshfts || len(si) != nshfts { + panic(badSlice) // TODO(vladimir-ch) Another message? + } + if wantz { + if ihiz >= n { + panic("lapack: invalid value of ihiz") + } + if iloz < 0 || ihiz < iloz { + panic("lapack: invalid value of iloz") + } + checkMatrix(n, n, z, ldz) + } + checkMatrix(nshfts/2, 3, v, ldv) // Transposed w.r.t. lapack. + checkMatrix(3*nshfts-3, 3*nshfts-3, u, ldu) + checkMatrix(nv, 3*nshfts-3, wv, ldwv) + checkMatrix(3*nshfts-3, nh, wh, ldwh) + if kacc22 != 0 && kacc22 != 1 && kacc22 != 2 { + panic("lapack: invalid value of kacc22") + } + + // If there are no shifts, then there is nothing to do. + if nshfts < 2 { + return + } + // If the active block is empty or 1×1, then there is nothing to do. + if ktop >= kbot { + return + } + + // Shuffle shifts into pairs of real shifts and pairs of complex + // conjugate shifts assuming complex conjugate shifts are already + // adjacent to one another. + for i := 0; i < nshfts-2; i += 2 { + if si[i] == -si[i+1] { + continue + } + sr[i], sr[i+1], sr[i+2] = sr[i+1], sr[i+2], sr[i] + si[i], si[i+1], si[i+2] = si[i+1], si[i+2], si[i] + } + + // Note: lapack says that nshfts must be even but allows it to be odd + // anyway. We panic above if nshfts is not even, so reducing it by one + // is unnecessary. The only caller Dlaqr04 uses only even nshfts. + // + // The original comment and code from lapack-3.6.0/SRC/dlaqr5.f:341: + // * ==== NSHFTS is supposed to be even, but if it is odd, + // * . then simply reduce it by one. The shuffle above + // * . ensures that the dropped shift is real and that + // * . the remaining shifts are paired. ==== + // * + // NS = NSHFTS - MOD( NSHFTS, 2 ) + ns := nshfts + + safmin := dlamchS + ulp := dlamchP + smlnum := safmin * float64(n) / ulp + + // Use accumulated reflections to update far-from-diagonal entries? + accum := kacc22 == 1 || kacc22 == 2 + // If so, exploit the 2×2 block structure? + blk22 := ns > 2 && kacc22 == 2 + + // Clear trash. + if ktop+2 <= kbot { + h[(ktop+2)*ldh+ktop] = 0 + } + + // nbmps = number of 2-shift bulges in the chain. + nbmps := ns / 2 + + // kdu = width of slab. + kdu := 6*nbmps - 3 + + // Create and chase chains of nbmps bulges. + for incol := 3*(1-nbmps) + ktop - 1; incol <= kbot-2; incol += 3*nbmps - 2 { + ndcol := incol + kdu + if accum { + impl.Dlaset(blas.All, kdu, kdu, 0, 1, u, ldu) + } + + // Near-the-diagonal bulge chase. The following loop performs + // the near-the-diagonal part of a small bulge multi-shift QR + // sweep. Each 6*nbmps-2 column diagonal chunk extends from + // column incol to column ndcol (including both column incol and + // column ndcol). The following loop chases a 3*nbmps column + // long chain of nbmps bulges 3*nbmps-2 columns to the right. + // (incol may be less than ktop and ndcol may be greater than + // kbot indicating phantom columns from which to chase bulges + // before they are actually introduced or to which to chase + // bulges beyond column kbot.) + for krcol := incol; krcol <= min(incol+3*nbmps-3, kbot-2); krcol++ { + // Bulges number mtop to mbot are active double implicit + // shift bulges. There may or may not also be small 2×2 + // bulge, if there is room. The inactive bulges (if any) + // must wait until the active bulges have moved down the + // diagonal to make room. The phantom matrix paradigm + // described above helps keep track. + + mtop := max(0, ((ktop-1)-krcol+2)/3) + mbot := min(nbmps, (kbot-krcol)/3) - 1 + m22 := mbot + 1 + bmp22 := (mbot < nbmps-1) && (krcol+3*m22 == kbot-2) + + // Generate reflections to chase the chain right one + // column. (The minimum value of k is ktop-1.) + for m := mtop; m <= mbot; m++ { + k := krcol + 3*m + if k == ktop-1 { + impl.Dlaqr1(3, h[ktop*ldh+ktop:], ldh, + sr[2*m], si[2*m], sr[2*m+1], si[2*m+1], + v[m*ldv:m*ldv+3]) + alpha := v[m*ldv] + _, v[m*ldv] = impl.Dlarfg(3, alpha, v[m*ldv+1:m*ldv+3], 1) + continue + } + beta := h[(k+1)*ldh+k] + v[m*ldv+1] = h[(k+2)*ldh+k] + v[m*ldv+2] = h[(k+3)*ldh+k] + beta, v[m*ldv] = impl.Dlarfg(3, beta, v[m*ldv+1:m*ldv+3], 1) + + // A bulge may collapse because of vigilant deflation or + // destructive underflow. In the underflow case, try the + // two-small-subdiagonals trick to try to reinflate the + // bulge. + if h[(k+3)*ldh+k] != 0 || h[(k+3)*ldh+k+1] != 0 || h[(k+3)*ldh+k+2] == 0 { + // Typical case: not collapsed (yet). + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + continue + } + + // Atypical case: collapsed. Attempt to reintroduce + // ignoring H[k+1,k] and H[k+2,k]. If the fill + // resulting from the new reflector is too large, + // then abandon it. Otherwise, use the new one. + var vt [3]float64 + impl.Dlaqr1(3, h[(k+1)*ldh+k+1:], ldh, sr[2*m], + si[2*m], sr[2*m+1], si[2*m+1], vt[:]) + alpha := vt[0] + _, vt[0] = impl.Dlarfg(3, alpha, vt[1:3], 1) + refsum := vt[0] * (h[(k+1)*ldh+k] + vt[1]*h[(k+2)*ldh+k]) + + dsum := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) + math.Abs(h[(k+2)*ldh+k+2]) + if math.Abs(h[(k+2)*ldh+k]-refsum*vt[1])+math.Abs(refsum*vt[2]) > ulp*dsum { + // Starting a new bulge here would create + // non-negligible fill. Use the old one with + // trepidation. + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + continue + } else { + // Starting a new bulge here would create + // only negligible fill. Replace the old + // reflector with the new one. + h[(k+1)*ldh+k] -= refsum + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + v[m*ldv] = vt[0] + v[m*ldv+1] = vt[1] + v[m*ldv+2] = vt[2] + } + } + + // Generate a 2×2 reflection, if needed. + if bmp22 { + k := krcol + 3*m22 + if k == ktop-1 { + impl.Dlaqr1(2, h[(k+1)*ldh+k+1:], ldh, + sr[2*m22], si[2*m22], sr[2*m22+1], si[2*m22+1], + v[m22*ldv:m22*ldv+2]) + beta := v[m22*ldv] + _, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) + } else { + beta := h[(k+1)*ldh+k] + v[m22*ldv+1] = h[(k+2)*ldh+k] + beta, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + } + } + + // Multiply H by reflections from the left. + var jbot int + switch { + case accum: + jbot = min(ndcol, kbot) + case wantt: + jbot = n - 1 + default: + jbot = kbot + } + for j := max(ktop, krcol); j <= jbot; j++ { + mend := min(mbot+1, (j-krcol+2)/3) - 1 + for m := mtop; m <= mend; m++ { + k := krcol + 3*m + refsum := v[m*ldv] * (h[(k+1)*ldh+j] + + v[m*ldv+1]*h[(k+2)*ldh+j] + v[m*ldv+2]*h[(k+3)*ldh+j]) + h[(k+1)*ldh+j] -= refsum + h[(k+2)*ldh+j] -= refsum * v[m*ldv+1] + h[(k+3)*ldh+j] -= refsum * v[m*ldv+2] + } + } + if bmp22 { + k := krcol + 3*m22 + for j := max(k+1, ktop); j <= jbot; j++ { + refsum := v[m22*ldv] * (h[(k+1)*ldh+j] + v[m22*ldv+1]*h[(k+2)*ldh+j]) + h[(k+1)*ldh+j] -= refsum + h[(k+2)*ldh+j] -= refsum * v[m22*ldv+1] + } + } + + // Multiply H by reflections from the right. Delay filling in the last row + // until the vigilant deflation check is complete. + var jtop int + switch { + case accum: + jtop = max(ktop, incol) + case wantt: + jtop = 0 + default: + jtop = ktop + } + for m := mtop; m <= mbot; m++ { + if v[m*ldv] == 0 { + continue + } + k := krcol + 3*m + for j := jtop; j <= min(kbot, k+3); j++ { + refsum := v[m*ldv] * (h[j*ldh+k+1] + + v[m*ldv+1]*h[j*ldh+k+2] + v[m*ldv+2]*h[j*ldh+k+3]) + h[j*ldh+k+1] -= refsum + h[j*ldh+k+2] -= refsum * v[m*ldv+1] + h[j*ldh+k+3] -= refsum * v[m*ldv+2] + } + if accum { + // Accumulate U. (If necessary, update Z later with with an + // efficient matrix-matrix multiply.) + kms := k - incol + for j := max(0, ktop-incol-1); j < kdu; j++ { + refsum := v[m*ldv] * (u[j*ldu+kms] + + v[m*ldv+1]*u[j*ldu+kms+1] + v[m*ldv+2]*u[j*ldu+kms+2]) + u[j*ldu+kms] -= refsum + u[j*ldu+kms+1] -= refsum * v[m*ldv+1] + u[j*ldu+kms+2] -= refsum * v[m*ldv+2] + } + } else if wantz { + // U is not accumulated, so update Z now by multiplying by + // reflections from the right. + for j := iloz; j <= ihiz; j++ { + refsum := v[m*ldv] * (z[j*ldz+k+1] + + v[m*ldv+1]*z[j*ldz+k+2] + v[m*ldv+2]*z[j*ldz+k+3]) + z[j*ldz+k+1] -= refsum + z[j*ldz+k+2] -= refsum * v[m*ldv+1] + z[j*ldz+k+3] -= refsum * v[m*ldv+2] + } + } + } + + // Special case: 2×2 reflection (if needed). + if bmp22 && v[m22*ldv] != 0 { + k := krcol + 3*m22 + for j := jtop; j <= min(kbot, k+3); j++ { + refsum := v[m22*ldv] * (h[j*ldh+k+1] + v[m22*ldv+1]*h[j*ldh+k+2]) + h[j*ldh+k+1] -= refsum + h[j*ldh+k+2] -= refsum * v[m22*ldv+1] + } + if accum { + kms := k - incol + for j := max(0, ktop-incol-1); j < kdu; j++ { + refsum := v[m22*ldv] * (u[j*ldu+kms] + v[m22*ldv+1]*u[j*ldu+kms+1]) + u[j*ldu+kms] -= refsum + u[j*ldu+kms+1] -= refsum * v[m22*ldv+1] + } + } else if wantz { + for j := iloz; j <= ihiz; j++ { + refsum := v[m22*ldv] * (z[j*ldz+k+1] + v[m22*ldv+1]*z[j*ldz+k+2]) + z[j*ldz+k+1] -= refsum + z[j*ldz+k+2] -= refsum * v[m22*ldv+1] + } + } + } + + // Vigilant deflation check. + mstart := mtop + if krcol+3*mstart < ktop { + mstart++ + } + mend := mbot + if bmp22 { + mend++ + } + if krcol == kbot-2 { + mend++ + } + for m := mstart; m <= mend; m++ { + k := min(kbot-1, krcol+3*m) + + // The following convergence test requires that the tradition + // small-compared-to-nearby-diagonals criterion and the Ahues & + // Tisseur (LAWN 122, 1997) criteria both be satisfied. The latter + // improves accuracy in some examples. Falling back on an alternate + // convergence criterion when tst1 or tst2 is zero (as done here) is + // traditional but probably unnecessary. + + if h[(k+1)*ldh+k] == 0 { + continue + } + tst1 := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) + if tst1 == 0 { + if k >= ktop+1 { + tst1 += math.Abs(h[k*ldh+k-1]) + } + if k >= ktop+2 { + tst1 += math.Abs(h[k*ldh+k-2]) + } + if k >= ktop+3 { + tst1 += math.Abs(h[k*ldh+k-3]) + } + if k <= kbot-2 { + tst1 += math.Abs(h[(k+2)*ldh+k+1]) + } + if k <= kbot-3 { + tst1 += math.Abs(h[(k+3)*ldh+k+1]) + } + if k <= kbot-4 { + tst1 += math.Abs(h[(k+4)*ldh+k+1]) + } + } + if math.Abs(h[(k+1)*ldh+k]) <= math.Max(smlnum, ulp*tst1) { + h12 := math.Max(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) + h21 := math.Min(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) + h11 := math.Max(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) + h22 := math.Min(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) + scl := h11 + h12 + tst2 := h22 * (h11 / scl) + if tst2 == 0 || h21*(h12/scl) <= math.Max(smlnum, ulp*tst2) { + h[(k+1)*ldh+k] = 0 + } + } + } + + // Fill in the last row of each bulge. + mend = min(nbmps, (kbot-krcol-1)/3) - 1 + for m := mtop; m <= mend; m++ { + k := krcol + 3*m + refsum := v[m*ldv] * v[m*ldv+2] * h[(k+4)*ldh+k+3] + h[(k+4)*ldh+k+1] = -refsum + h[(k+4)*ldh+k+2] = -refsum * v[m*ldv+1] + h[(k+4)*ldh+k+3] -= refsum * v[m*ldv+2] + } + } + + // Use U (if accumulated) to update far-from-diagonal entries in H. + // If required, use U to update Z as well. + if !accum { + continue + } + var jtop, jbot int + if wantt { + jtop = 0 + jbot = n - 1 + } else { + jtop = ktop + jbot = kbot + } + bi := blas64.Implementation() + if !blk22 || incol < ktop || kbot < ndcol || ns <= 2 { + // Updates not exploiting the 2×2 block structure of U. k0 and nu keep track + // of the location and size of U in the special cases of introducing bulges + // and chasing bulges off the bottom. In these special cases and in case the + // number of shifts is ns = 2, there is no 2×2 block structure to exploit. + + k0 := max(0, ktop-incol-1) + nu := kdu - max(0, ndcol-kbot) - k0 + + // Horizontal multiply. + for jcol := min(ndcol, kbot) + 1; jcol <= jbot; jcol += nh { + jlen := min(nh, jbot-jcol+1) + bi.Dgemm(blas.Trans, blas.NoTrans, nu, jlen, nu, + 1, u[k0*ldu+k0:], ldu, + h[(incol+k0+1)*ldh+jcol:], ldh, + 0, wh, ldwh) + impl.Dlacpy(blas.All, nu, jlen, wh, ldwh, h[(incol+k0+1)*ldh+jcol:], ldh) + } + + // Vertical multiply. + for jrow := jtop; jrow <= max(ktop, incol)-1; jrow += nv { + jlen := min(nv, max(ktop, incol)-jrow) + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, + 1, h[jrow*ldh+incol+k0+1:], ldh, + u[k0*ldu+k0:], ldu, + 0, wv, ldwv) + impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, h[jrow*ldh+incol+k0+1:], ldh) + } + + // Z multiply (also vertical). + if wantz { + for jrow := iloz; jrow <= ihiz; jrow += nv { + jlen := min(nv, ihiz-jrow+1) + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, + 1, z[jrow*ldz+incol+k0+1:], ldz, + u[k0*ldu+k0:], ldu, + 0, wv, ldwv) + impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, z[jrow*ldz+incol+k0+1:], ldz) + } + } + + continue + } + + // Updates exploiting U's 2×2 block structure. + + // i2, i4, j2, j4 are the last rows and columns of the blocks. + i2 := (kdu + 1) / 2 + i4 := kdu + j2 := i4 - i2 + j4 := kdu + + // kzs and knz deal with the band of zeros along the diagonal of one of the + // triangular blocks. + kzs := (j4 - j2) - (ns + 1) + knz := ns + 1 + + // Horizontal multiply. + for jcol := min(ndcol, kbot) + 1; jcol <= jbot; jcol += nh { + jlen := min(nh, jbot-jcol+1) + + // Copy bottom of H to top+kzs of scratch (the first kzs + // rows get multiplied by zero). + impl.Dlacpy(blas.All, knz, jlen, h[(incol+1+j2)*ldh+jcol:], ldh, wh[kzs*ldwh:], ldwh) + + // Multiply by U21^T. + impl.Dlaset(blas.All, kzs, jlen, 0, 0, wh, ldwh) + bi.Dtrmm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, knz, jlen, + 1, u[j2*ldu+kzs:], ldu, wh[kzs*ldwh:], ldwh) + + // Multiply top of H by U11^T. + bi.Dgemm(blas.Trans, blas.NoTrans, i2, jlen, j2, + 1, u, ldu, h[(incol+1)*ldh+jcol:], ldh, + 1, wh, ldwh) + + // Copy top of H to bottom of WH. + impl.Dlacpy(blas.All, j2, jlen, h[(incol+1)*ldh+jcol:], ldh, wh[i2*ldwh:], ldwh) + + // Multiply by U21^T. + bi.Dtrmm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, j2, jlen, + 1, u[i2:], ldu, wh[i2*ldwh:], ldwh) + + // Multiply by U22. + bi.Dgemm(blas.Trans, blas.NoTrans, i4-i2, jlen, j4-j2, + 1, u[j2*ldu+i2:], ldu, h[(incol+1+j2)*ldh+jcol:], ldh, + 1, wh[i2*ldwh:], ldwh) + + // Copy it back. + impl.Dlacpy(blas.All, kdu, jlen, wh, ldwh, h[(incol+1)*ldh+jcol:], ldh) + } + + // Vertical multiply. + for jrow := jtop; jrow <= max(incol, ktop)-1; jrow += nv { + jlen := min(nv, max(incol, ktop)-jrow) + + // Copy right of H to scratch (the first kzs columns get multiplied + // by zero). + impl.Dlacpy(blas.All, jlen, knz, h[jrow*ldh+incol+1+j2:], ldh, wv[kzs:], ldwv) + + // Multiply by U21. + impl.Dlaset(blas.All, jlen, kzs, 0, 0, wv, ldwv) + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, jlen, knz, + 1, u[j2*ldu+kzs:], ldu, wv[kzs:], ldwv) + + // Multiply by U11. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i2, j2, + 1, h[jrow*ldh+incol+1:], ldh, u, ldu, + 1, wv, ldwv) + + // Copy left of H to right of scratch. + impl.Dlacpy(blas.All, jlen, j2, h[jrow*ldh+incol+1:], ldh, wv[i2:], ldwv) + + // Multiply by U21. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.NonUnit, jlen, i4-i2, + 1, u[i2:], ldu, wv[i2:], ldwv) + + // Multiply by U22. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i4-i2, j4-j2, + 1, h[jrow*ldh+incol+1+j2:], ldh, u[j2*ldu+i2:], ldu, + 1, wv[i2:], ldwv) + + // Copy it back. + impl.Dlacpy(blas.All, jlen, kdu, wv, ldwv, h[jrow*ldh+incol+1:], ldh) + } + + if !wantz { + continue + } + // Multiply Z (also vertical). + for jrow := iloz; jrow <= ihiz; jrow += nv { + jlen := min(nv, ihiz-jrow+1) + + // Copy right of Z to left of scratch (first kzs columns get + // multiplied by zero). + impl.Dlacpy(blas.All, jlen, knz, z[jrow*ldz+incol+1+j2:], ldz, wv[kzs:], ldwv) + + // Multiply by U12. + impl.Dlaset(blas.All, jlen, kzs, 0, 0, wv, ldwv) + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, jlen, knz, + 1, u[j2*ldu+kzs:], ldu, wv[kzs:], ldwv) + + // Multiply by U11. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i2, j2, + 1, z[jrow*ldz+incol+1:], ldz, u, ldu, + 1, wv, ldwv) + + // Copy left of Z to right of scratch. + impl.Dlacpy(blas.All, jlen, j2, z[jrow*ldz+incol+1:], ldz, wv[i2:], ldwv) + + // Multiply by U21. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.NonUnit, jlen, i4-i2, + 1, u[i2:], ldu, wv[i2:], ldwv) + + // Multiply by U22. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i4-i2, j4-j2, + 1, z[jrow*ldz+incol+1+j2:], ldz, u[j2*ldu+i2:], ldu, + 1, wv[i2:], ldwv) + + // Copy the result back to Z. + impl.Dlacpy(blas.All, jlen, kdu, wv, ldwv, z[jrow*ldz+incol+1:], ldz) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go new file mode 100644 index 00000000..01f50eae --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlarf applies an elementary reflector to a general rectangular matrix c. +// This computes +// c = h * c if side == Left +// c = c * h if side == right +// where +// h = 1 - tau * v * v^T +// and c is an m * n matrix. +// +// work is temporary storage of length at least m if side == Left and at least +// n if side == Right. This function will panic if this length requirement is not met. +// +// Dlarf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) { + applyleft := side == blas.Left + if (applyleft && len(work) < n) || (!applyleft && len(work) < m) { + panic(badWork) + } + checkMatrix(m, n, c, ldc) + + // v has length m if applyleft and n otherwise. + lenV := n + if applyleft { + lenV = m + } + + checkVector(lenV, v, incv) + + lastv := 0 // last non-zero element of v + lastc := 0 // last non-zero row/column of c + if tau != 0 { + var i int + if applyleft { + lastv = m - 1 + } else { + lastv = n - 1 + } + if incv > 0 { + i = lastv * incv + } + + // Look for the last non-zero row in v. + for lastv >= 0 && v[i] == 0 { + lastv-- + i -= incv + } + if applyleft { + // Scan for the last non-zero column in C[0:lastv, :] + lastc = impl.Iladlc(lastv+1, n, c, ldc) + } else { + // Scan for the last non-zero row in C[:, 0:lastv] + lastc = impl.Iladlr(m, lastv+1, c, ldc) + } + } + if lastv == -1 || lastc == -1 { + return + } + // Sometimes 1-indexing is nicer ... + bi := blas64.Implementation() + if applyleft { + // Form H * C + // w[0:lastc+1] = c[1:lastv+1, 1:lastc+1]^T * v[1:lastv+1,1] + bi.Dgemv(blas.Trans, lastv+1, lastc+1, 1, c, ldc, v, incv, 0, work, 1) + // c[0: lastv, 0: lastc] = c[...] - w[0:lastv, 1] * v[1:lastc, 1]^T + bi.Dger(lastv+1, lastc+1, -tau, v, incv, work, 1, c, ldc) + return + } + // Form C*H + // w[0:lastc+1,1] := c[0:lastc+1,0:lastv+1] * v[0:lastv+1,1] + bi.Dgemv(blas.NoTrans, lastc+1, lastv+1, 1, c, ldc, v, incv, 0, work, 1) + // c[0:lastc+1,0:lastv+1] = c[...] - w[0:lastc+1,0] * v[0:lastv+1,0]^T + bi.Dger(lastc+1, lastv+1, -tau, work, 1, v, incv, c, ldc) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go new file mode 100644 index 00000000..bfafd360 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go @@ -0,0 +1,431 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlarfb applies a block reflector to a matrix. +// +// In the call to Dlarfb, the mxn c is multiplied by the implicitly defined matrix h as follows: +// c = h * c if side == Left and trans == NoTrans +// c = c * h if side == Right and trans == NoTrans +// c = h^T * c if side == Left and trans == Trans +// c = c * h^T if side == Right and trans == Trans +// h is a product of elementary reflectors. direct sets the direction of multiplication +// h = h_1 * h_2 * ... * h_k if direct == Forward +// h = h_k * h_k-1 * ... * h_1 if direct == Backward +// The combination of direct and store defines the orientation of the elementary +// reflectors. In all cases the ones on the diagonal are implicitly represented. +// +// If direct == lapack.Forward and store == lapack.ColumnWise +// V = [ 1 ] +// [v1 1 ] +// [v1 v2 1] +// [v1 v2 v3] +// [v1 v2 v3] +// If direct == lapack.Forward and store == lapack.RowWise +// V = [ 1 v1 v1 v1 v1] +// [ 1 v2 v2 v2] +// [ 1 v3 v3] +// If direct == lapack.Backward and store == lapack.ColumnWise +// V = [v1 v2 v3] +// [v1 v2 v3] +// [ 1 v2 v3] +// [ 1 v3] +// [ 1] +// If direct == lapack.Backward and store == lapack.RowWise +// V = [v1 v1 1 ] +// [v2 v2 v2 1 ] +// [v3 v3 v3 v3 1] +// An elementary reflector can be explicitly constructed by extracting the +// corresponding elements of v, placing a 1 where the diagonal would be, and +// placing zeros in the remaining elements. +// +// t is a k×k matrix containing the block reflector, and this function will panic +// if t is not of sufficient size. See Dlarft for more information. +// +// work is a temporary storage matrix with stride ldwork. +// work must be of size at least n×k side == Left and m×k if side == Right, and +// this function will panic if this size is not met. +// +// Dlarfb is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64, ldwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.ColumnWise && store != lapack.RowWise { + panic(badStore) + } + checkMatrix(m, n, c, ldc) + if k < 0 { + panic(kLT0) + } + checkMatrix(k, k, t, ldt) + nv := m + nw := n + if side == blas.Right { + nv = n + nw = m + } + if store == lapack.ColumnWise { + checkMatrix(nv, k, v, ldv) + } else { + checkMatrix(k, nv, v, ldv) + } + checkMatrix(nw, k, work, ldwork) + + if m == 0 || n == 0 { + return + } + + bi := blas64.Implementation() + + transt := blas.Trans + if trans == blas.Trans { + transt = blas.NoTrans + } + // TODO(btracey): This follows the original Lapack code where the + // elements are copied into the columns of the working array. The + // loops should go in the other direction so the data is written + // into the rows of work so the copy is not strided. A bigger change + // would be to replace work with work^T, but benchmarks would be + // needed to see if the change is merited. + if store == lapack.ColumnWise { + if direct == lapack.Forward { + // V1 is the first k rows of C. V2 is the remaining rows. + if side == blas.Left { + // W = C^T V = C1^T V1 + C2^T V2 (stored in work). + + // W = C1. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) + } + // W = W * V1. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, + n, k, 1, + v, ldv, + work, ldwork) + if m > k { + // W = W + C2^T V2. + bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, + 1, c[k*ldc:], ldc, v[k*ldv:], ldv, + 1, work, ldwork) + } + // W = W * T^T or W * T. + bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V * W^T. + if m > k { + // C2 -= V2 * W^T. + bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, + -1, v[k*ldv:], ldv, work, ldwork, + 1, c[k*ldc:], ldc) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + // C1 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[j*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C = C * H or C * H^T, where C = (C1 C2). + + // W = C1. + for i := 0; i < k; i++ { + bi.Dcopy(m, c[i:], ldc, work[i:], ldwork) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, + 1, c[k:], ldc, v[k*ldv:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, + -1, work, ldwork, v[k*ldv:], ldv, + 1, c[k:], ldc) + } + // C -= W * V^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + // C -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+j] -= work[i*ldwork+j] + } + } + return + } + // V = (V1) + // = (V2) (last k rows) + // Where V2 is unit upper triangular. + if side == blas.Left { + // Form H * C or + // W = C^T V. + + // W = C2^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, + 1, v[(m-k)*ldv:], ldv, + work, ldwork) + if m > k { + // W += C1^T * V1. + bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V * W^T. + if m > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, + -1, v, ldv, work, ldwork, + 1, c, ldc) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, + 1, v[(m-k)*ldv:], ldv, + work, ldwork) + // C2 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[(m-k+j)*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V. + + // W = C2. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) + } + + // W = W * V2. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, + 1, v[(n-k)*ldv:], ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V^T. + if n > k { + // C1 -= W * V1^T. + bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, + -1, work, ldwork, v, ldv, + 1, c, ldc) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, + 1, v[(n-k)*ldv:], ldv, + work, ldwork) + // C2 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+n-k+j] -= work[i*ldwork+j] + } + } + return + } + // Store = Rowwise. + if direct == lapack.Forward { + // V = (V1 V2) where v1 is unit upper triangular. + if side == blas.Left { + // Form H * C or H^T * C where C = (C1; C2). + // W = C^T * V^T. + + // W = C1^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, + 1, c[k*ldc:], ldc, v[k:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V^T * W^T. + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, + -1, v[k:], ldv, work, ldwork, + 1, c[k*ldc:], ldc) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + // C1 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[j*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V^T. + + // W = C1. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[j:], ldc, work[j:], ldwork) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, + 1, c[k:], ldc, v[k:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V. + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, + -1, work, ldwork, v[k:], ldv, + 1, c[k:], ldc) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + // C1 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+j] -= work[i*ldwork+j] + } + } + return + } + // V = (V1 V2) where V2 is the last k columns and is lower unit triangular. + if side == blas.Left { + // Form H * C or H^T C where C = (C1 ; C2). + // W = C^T * V^T. + + // W = C2^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, + 1, v[m-k:], ldv, + work, ldwork) + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V^T * W^T. + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, + -1, v, ldv, work, ldwork, + 1, c, ldc) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, k, + 1, v[m-k:], ldv, + work, ldwork) + // C2 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[(m-k+j)*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V^T. + // W = C2. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, + 1, v[n-k:], ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V. + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, + -1, work, ldwork, v, ldv, + 1, c, ldc) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, + 1, v[n-k:], ldv, + work, ldwork) + // C1 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+n-k+j] -= work[i*ldwork+j] + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go new file mode 100644 index 00000000..09977e50 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go @@ -0,0 +1,62 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlarfg generates an elementary reflector for a Householder matrix. It creates +// a real elementary reflector of order n such that +// H * (alpha) = (beta) +// ( x) ( 0) +// H^T * H = I +// H is represented in the form +// H = 1 - tau * (1; v) * (1 v^T) +// where tau is a real scalar. +// +// On entry, x contains the vector x, on exit it contains v. +// +// Dlarfg is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) { + if n < 0 { + panic(nLT0) + } + if n <= 1 { + return alpha, 0 + } + checkVector(n-1, x, incX) + bi := blas64.Implementation() + xnorm := bi.Dnrm2(n-1, x, incX) + if xnorm == 0 { + return alpha, 0 + } + beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) + safmin := dlamchS / dlamchE + knt := 0 + if math.Abs(beta) < safmin { + // xnorm and beta may be inaccurate, scale x and recompute. + rsafmn := 1 / safmin + for { + knt++ + bi.Dscal(n-1, rsafmn, x, incX) + beta *= rsafmn + alpha *= rsafmn + if math.Abs(beta) >= safmin { + break + } + } + xnorm = bi.Dnrm2(n-1, x, incX) + beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) + } + tau = (beta - alpha) / beta + bi.Dscal(n-1, 1/(alpha-beta), x, incX) + for j := 0; j < knt; j++ { + beta *= safmin + } + return beta, tau +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go new file mode 100644 index 00000000..0a244a48 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlarft forms the triangular factor T of a block reflector H, storing the answer +// in t. +// H = I - V * T * V^T if store == lapack.ColumnWise +// H = I - V^T * T * V if store == lapack.RowWise +// H is defined by a product of the elementary reflectors where +// H = H_0 * H_1 * ... * H_{k-1} if direct == lapack.Forward +// H = H_{k-1} * ... * H_1 * H_0 if direct == lapack.Backward +// +// t is a k×k triangular matrix. t is upper triangular if direct = lapack.Forward +// and lower triangular otherwise. This function will panic if t is not of +// sufficient size. +// +// store describes the storage of the elementary reflectors in v. Please see +// Dlarfb for a description of layout. +// +// tau contains the scalar factors of the elementary reflectors H_i. +// +// Dlarft is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, + v []float64, ldv int, tau []float64, t []float64, ldt int) { + if n == 0 { + return + } + if n < 0 || k < 0 { + panic(negDimension) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.RowWise && store != lapack.ColumnWise { + panic(badStore) + } + if len(tau) < k { + panic(badTau) + } + checkMatrix(k, k, t, ldt) + bi := blas64.Implementation() + // TODO(btracey): There are a number of minor obvious loop optimizations here. + // TODO(btracey): It may be possible to rearrange some of the code so that + // index of 1 is more common in the Dgemv. + if direct == lapack.Forward { + prevlastv := n - 1 + for i := 0; i < k; i++ { + prevlastv = max(i, prevlastv) + if tau[i] == 0 { + for j := 0; j <= i; j++ { + t[j*ldt+i] = 0 + } + continue + } + var lastv int + if store == lapack.ColumnWise { + // skip trailing zeros + for lastv = n - 1; lastv >= i+1; lastv-- { + if v[lastv*ldv+i] != 0 { + break + } + } + for j := 0; j < i; j++ { + t[j*ldt+i] = -tau[i] * v[i*ldv+j] + } + j := min(lastv, prevlastv) + bi.Dgemv(blas.Trans, j-i, i, + -tau[i], v[(i+1)*ldv:], ldv, v[(i+1)*ldv+i:], ldv, + 1, t[i:], ldt) + } else { + for lastv = n - 1; lastv >= i+1; lastv-- { + if v[i*ldv+lastv] != 0 { + break + } + } + for j := 0; j < i; j++ { + t[j*ldt+i] = -tau[i] * v[j*ldv+i] + } + j := min(lastv, prevlastv) + bi.Dgemv(blas.NoTrans, i, j-i, + -tau[i], v[i+1:], ldv, v[i*ldv+i+1:], 1, + 1, t[i:], ldt) + } + bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, t, ldt, t[i:], ldt) + t[i*ldt+i] = tau[i] + if i > 1 { + prevlastv = max(prevlastv, lastv) + } else { + prevlastv = lastv + } + } + return + } + prevlastv := 0 + for i := k - 1; i >= 0; i-- { + if tau[i] == 0 { + for j := i; j < k; j++ { + t[j*ldt+i] = 0 + } + continue + } + var lastv int + if i < k-1 { + if store == lapack.ColumnWise { + for lastv = 0; lastv < i; lastv++ { + if v[lastv*ldv+i] != 0 { + break + } + } + for j := i + 1; j < k; j++ { + t[j*ldt+i] = -tau[i] * v[(n-k+i)*ldv+j] + } + j := max(lastv, prevlastv) + bi.Dgemv(blas.Trans, n-k+i-j, k-i-1, + -tau[i], v[j*ldv+i+1:], ldv, v[j*ldv+i:], ldv, + 1, t[(i+1)*ldt+i:], ldt) + } else { + for lastv = 0; lastv < i; lastv++ { + if v[i*ldv+lastv] != 0 { + break + } + } + for j := i + 1; j < k; j++ { + t[j*ldt+i] = -tau[i] * v[j*ldv+n-k+i] + } + j := max(lastv, prevlastv) + bi.Dgemv(blas.NoTrans, k-i-1, n-k+i-j, + -tau[i], v[(i+1)*ldv+j:], ldv, v[i*ldv+j:], 1, + 1, t[(i+1)*ldt+i:], ldt) + } + bi.Dtrmv(blas.Lower, blas.NoTrans, blas.NonUnit, k-i-1, + t[(i+1)*ldt+i+1:], ldt, + t[(i+1)*ldt+i:], ldt) + if i > 0 { + prevlastv = min(prevlastv, lastv) + } else { + prevlastv = lastv + } + } + t[i*ldt+i] = tau[i] + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go new file mode 100644 index 00000000..5dc00f03 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go @@ -0,0 +1,535 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dlarfx applies an elementary reflector H to a real m×n matrix C, from either +// the left or the right, with loop unrolling when the reflector has order less +// than 11. +// +// H is represented in the form +// H = I - tau * v * v^T, +// where tau is a real scalar and v is a real vector. If tau = 0, then H is +// taken to be the identity matrix. +// +// v must have length equal to m if side == blas.Left, and equal to n if side == +// blas.Right, otherwise Dlarfx will panic. +// +// c and ldc represent the m×n matrix C. On return, C is overwritten by the +// matrix H * C if side == blas.Left, or C * H if side == blas.Right. +// +// work must have length at least n if side == blas.Left, and at least m if side +// == blas.Right, otherwise Dlarfx will panic. work is not referenced if H has +// order < 11. +// +// Dlarfx is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) { + checkMatrix(m, n, c, ldc) + switch side { + case blas.Left: + checkVector(m, v, 1) + if m > 10 && len(work) < n { + panic(badWork) + } + case blas.Right: + checkVector(n, v, 1) + if n > 10 && len(work) < m { + panic(badWork) + } + default: + panic(badSide) + } + + if tau == 0 { + return + } + + if side == blas.Left { + // Form H * C, where H has order m. + switch m { + default: // Code for general m. + impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) + return + + case 0: // No-op for zero size matrix. + return + + case 1: // Special code for 1×1 Householder matrix. + t0 := 1 - tau*v[0]*v[0] + for j := 0; j < n; j++ { + c[j] *= t0 + } + return + + case 2: // Special code for 2×2 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + } + return + + case 3: // Special code for 3×3 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + } + return + + case 4: // Special code for 4×4 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + } + return + + case 5: // Special code for 5×5 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + } + return + + case 6: // Special code for 6×6 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + } + return + + case 7: // Special code for 7×7 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + } + return + + case 8: // Special code for 8×8 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + } + return + + case 9: // Special code for 9×9 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + c[8*ldc+j] -= sum * t8 + } + return + + case 10: // Special code for 10×10 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + v9 := v[9] + t9 := tau * v9 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + v9*c[9*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + c[8*ldc+j] -= sum * t8 + c[9*ldc+j] -= sum * t9 + } + return + } + } + + // Form C * H, where H has order n. + switch n { + default: // Code for general n. + impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) + return + + case 0: // No-op for zero size matrix. + return + + case 1: // Special code for 1×1 Householder matrix. + t0 := 1 - tau*v[0]*v[0] + for j := 0; j < m; j++ { + c[j*ldc] *= t0 + } + return + + case 2: // Special code for 2×2 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + } + return + + case 3: // Special code for 3×3 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + } + return + + case 4: // Special code for 4×4 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + } + return + + case 5: // Special code for 5×5 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + } + return + + case 6: // Special code for 6×6 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + v5*cs[5] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + } + return + + case 7: // Special code for 7×7 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + } + return + + case 8: // Special code for 8×8 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + } + return + + case 9: // Special code for 9×9 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + cs[8] -= sum * t8 + } + return + + case 10: // Special code for 10×10 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + v9 := v[9] + t9 := tau * v9 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + v9*cs[9] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + cs[8] -= sum * t8 + cs[9] -= sum * t9 + } + return + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go new file mode 100644 index 00000000..85aa2064 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go @@ -0,0 +1,80 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlartg generates a plane rotation so that +// [ cs sn] * [f] = [r] +// [-sn cs] [g] = [0] +// This is a more accurate version of BLAS drotg, with the other differences that +// if g = 0, then cs = 1 and sn = 0, and if f = 0 and g != 0, then cs = 0 and sn = 1. +// If abs(f) > abs(g), cs will be positive. +// +// Dlartg is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) { + safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) + safmx2 := 1 / safmn2 + if g == 0 { + cs = 1 + sn = 0 + r = f + return cs, sn, r + } + if f == 0 { + cs = 0 + sn = 1 + r = g + return cs, sn, r + } + f1 := f + g1 := g + scale := math.Max(math.Abs(f1), math.Abs(g1)) + if scale >= safmx2 { + var count int + for { + count++ + f1 *= safmn2 + g1 *= safmn2 + scale = math.Max(math.Abs(f1), math.Abs(g1)) + if scale < safmx2 { + break + } + } + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + for i := 0; i < count; i++ { + r *= safmx2 + } + } else if scale <= safmn2 { + var count int + for { + count++ + f1 *= safmx2 + g1 *= safmx2 + scale = math.Max(math.Abs(f1), math.Abs(g1)) + if scale >= safmn2 { + break + } + } + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + for i := 0; i < count; i++ { + r *= safmn2 + } + } else { + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + } + if math.Abs(f) > math.Abs(g) && cs < 0 { + cs *= -1 + sn *= -1 + r *= -1 + } + return cs, sn, r +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go new file mode 100644 index 00000000..40a4b9c3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go @@ -0,0 +1,43 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlas2 computes the singular values of the 2×2 matrix defined by +// [F G] +// [0 H] +// The smaller and larger singular values are returned in that order. +// +// Dlas2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlas2(f, g, h float64) (ssmin, ssmax float64) { + fa := math.Abs(f) + ga := math.Abs(g) + ha := math.Abs(h) + fhmin := math.Min(fa, ha) + fhmax := math.Max(fa, ha) + if fhmin == 0 { + if fhmax == 0 { + return 0, ga + } + v := math.Min(fhmax, ga) / math.Max(fhmax, ga) + return 0, math.Max(fhmax, ga) * math.Sqrt(1+v*v) + } + if ga < fhmax { + as := 1 + fhmin/fhmax + at := (fhmax - fhmin) / fhmax + au := (ga / fhmax) * (ga / fhmax) + c := 2 / (math.Sqrt(as*as+au) + math.Sqrt(at*at+au)) + return fhmin * c, fhmax / c + } + au := fhmax / ga + if au == 0 { + return fhmin * fhmax / ga, ga + } + as := 1 + fhmin/fhmax + at := (fhmax - fhmin) / fhmax + c := 1 / (math.Sqrt(1+(as*au)*(as*au)) + math.Sqrt(1+(at*au)*(at*au))) + return 2 * (fhmin * c) * au, ga / (c + c) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go new file mode 100644 index 00000000..b25408df --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlascl multiplies an m×n matrix by the scalar cto/cfrom. +// +// cfrom must not be zero, and cto and cfrom must not be NaN, otherwise Dlascl +// will panic. +// +// Dlascl is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if cfrom == 0 { + panic(zeroDiv) + } + if math.IsNaN(cfrom) || math.IsNaN(cto) { + panic(nanScale) + } + if n == 0 || m == 0 { + return + } + smlnum := dlamchS + bignum := 1 / smlnum + cfromc := cfrom + ctoc := cto + cfrom1 := cfromc * smlnum + for { + var done bool + var mul, ctol float64 + if cfrom1 == cfromc { + // cfromc is inf. + mul = ctoc / cfromc + done = true + ctol = ctoc + } else { + ctol = ctoc / bignum + if ctol == ctoc { + // ctoc is either 0 or inf. + mul = ctoc + done = true + cfromc = 1 + } else if math.Abs(cfrom1) > math.Abs(ctoc) && ctoc != 0 { + mul = smlnum + done = false + cfromc = cfrom1 + } else if math.Abs(ctol) > math.Abs(cfromc) { + mul = bignum + done = false + ctoc = ctol + } else { + mul = ctoc / cfromc + done = true + } + } + switch kind { + default: + panic("lapack: not implemented") + case lapack.General: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + case lapack.UpperTri: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + case lapack.LowerTri: + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + } + if done { + break + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go new file mode 100644 index 00000000..79d7edfd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dlaset sets the off-diagonal elements of A to alpha, and the diagonal +// elements to beta. If uplo == blas.Upper, only the elements in the upper +// triangular part are set. If uplo == blas.Lower, only the elements in the +// lower triangular part are set. If uplo is otherwise, all of the elements of A +// are set. +// +// Dlaset is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = alpha + } + } + } else if uplo == blas.Lower { + for i := 0; i < m; i++ { + for j := 0; j < min(i+1, n); j++ { + a[i*lda+j] = alpha + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = alpha + } + } + } + for i := 0; i < min(m, n); i++ { + a[i*lda+i] = beta + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go new file mode 100644 index 00000000..0c91ded4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go @@ -0,0 +1,97 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlasq1 computes the singular values of an n×n bidiagonal matrix with diagonal +// d and off-diagonal e. On exit, d contains the singular values in decreasing +// order, and e is overwritten. d must have length at least n, e must have +// length at least n-1, and the input work must have length at least 4*n. Dlasq1 +// will panic if these conditions are not met. +// +// Dlasq1 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq1(n int, d, e, work []float64) (info int) { + // TODO(btracey): replace info with an error. + if n < 0 { + panic(nLT0) + } + if len(work) < 4*n { + panic(badWork) + } + if len(d) < n { + panic("lapack: length of d less than n") + } + if len(e) < n-1 { + panic("lapack: length of e less than n-1") + } + if n == 0 { + return info + } + if n == 1 { + d[0] = math.Abs(d[0]) + return info + } + if n == 2 { + d[1], d[0] = impl.Dlas2(d[0], e[0], d[1]) + return info + } + // Estimate the largest singular value. + var sigmx float64 + for i := 0; i < n-1; i++ { + d[i] = math.Abs(d[i]) + sigmx = math.Max(sigmx, math.Abs(e[i])) + } + d[n-1] = math.Abs(d[n-1]) + // Early return if sigmx is zero (matrix is already diagonal). + if sigmx == 0 { + impl.Dlasrt(lapack.SortDecreasing, n, d) + return info + } + + for i := 0; i < n; i++ { + sigmx = math.Max(sigmx, d[i]) + } + + // Copy D and E into WORK (in the Z format) and scale (squaring the + // input data makes scaling by a power of the radix pointless). + + eps := dlamchP + safmin := dlamchS + scale := math.Sqrt(eps / safmin) + bi := blas64.Implementation() + bi.Dcopy(n, d, 1, work, 2) + bi.Dcopy(n-1, e, 1, work[1:], 2) + impl.Dlascl(lapack.General, 0, 0, sigmx, scale, 2*n-1, 1, work, 1) + + // Compute the q's and e's. + for i := 0; i < 2*n-1; i++ { + work[i] *= work[i] + } + work[2*n-1] = 0 + + info = impl.Dlasq2(n, work) + if info == 0 { + for i := 0; i < n; i++ { + d[i] = math.Sqrt(work[i]) + } + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) + } else if info == 2 { + // Maximum number of iterations exceeded. Move data from work + // into D and E so the calling subroutine can try to finish. + for i := 0; i < n; i++ { + d[i] = math.Sqrt(work[2*i]) + e[i] = math.Sqrt(work[2*i+1]) + } + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, e, 1) + } + return info +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go new file mode 100644 index 00000000..ebf5863a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go @@ -0,0 +1,368 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlasq2 computes all the eigenvalues of the symmetric positive +// definite tridiagonal matrix associated with the qd array Z. Eigevalues +// are computed to high relative accuracy avoiding denormalization, underflow +// and overflow. +// +// To see the relation of Z to the tridiagonal matrix, let L be a +// unit lower bidiagonal matrix with sub-diagonals Z(2,4,6,,..) and +// let U be an upper bidiagonal matrix with 1's above and diagonal +// Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the +// symmetric tridiagonal to which it is similar. +// +// info returns a status error. The return codes mean as follows: +// 0: The algorithm completed successfully. +// 1: A split was marked by a positive value in e. +// 2: Current block of Z not diagonalized after 100*n iterations (in inner +// while loop). On exit Z holds a qd array with the same eigenvalues as +// the given Z. +// 3: Termination criterion of outer while loop not met (program created more +// than N unreduced blocks). +// +// z must have length at least 4*n, and must not contain any negative elements. +// Dlasq2 will panic otherwise. +// +// Dlasq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq2(n int, z []float64) (info int) { + // TODO(btracey): make info an error. + if len(z) < 4*n { + panic(badZ) + } + const cbias = 1.5 + + eps := dlamchP + safmin := dlamchS + tol := eps * 100 + tol2 := tol * tol + if n < 0 { + panic(nLT0) + } + if n == 0 { + return info + } + if n == 1 { + if z[0] < 0 { + panic(negZ) + } + return info + } + if n == 2 { + if z[1] < 0 || z[2] < 0 { + panic("lapack: bad z value") + } else if z[2] > z[0] { + z[0], z[2] = z[2], z[0] + } + z[4] = z[0] + z[1] + z[2] + if z[1] > z[2]*tol2 { + t := 0.5 * (z[0] - z[2] + z[1]) + s := z[2] * (z[1] / t) + if s <= t { + s = z[2] * (z[1] / (t * (1 + math.Sqrt(1+s/t)))) + } else { + s = z[2] * (z[1] / (t + math.Sqrt(t)*math.Sqrt(t+s))) + } + t = z[0] + s + z[1] + z[2] *= z[0] / t + z[0] = t + } + z[1] = z[2] + z[5] = z[1] + z[0] + return info + } + // Check for negative data and compute sums of q's and e's. + z[2*n-1] = 0 + emin := z[1] + var d, e, qmax float64 + var i1, n1 int + for k := 0; k < 2*(n-1); k += 2 { + if z[k] < 0 || z[k+1] < 0 { + panic("lapack: bad z value") + } + d += z[k] + e += z[k+1] + qmax = math.Max(qmax, z[k]) + emin = math.Min(emin, z[k+1]) + } + if z[2*(n-1)] < 0 { + panic("lapack: bad z value") + } + d += z[2*(n-1)] + qmax = math.Max(qmax, z[2*(n-1)]) + // Check for diagonality. + if e == 0 { + for k := 1; k < n; k++ { + z[k] = z[2*k] + } + impl.Dlasrt(lapack.SortDecreasing, n, z) + z[2*(n-1)] = d + return info + } + trace := d + e + // Check for zero data. + if trace == 0 { + z[2*(n-1)] = 0 + return info + } + // Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). + for k := 2 * n; k >= 2; k -= 2 { + z[2*k-1] = 0 + z[2*k-2] = z[k-1] + z[2*k-3] = 0 + z[2*k-4] = z[k-2] + } + i0 := 0 + n0 := n - 1 + + // Reverse the qd-array, if warranted. + // z[4*i0-3] --> z[4*(i0+1)-3-1] --> z[4*i0] + if cbias*z[4*i0] < z[4*n0] { + ipn4Out := 4 * (i0 + n0 + 2) + for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { + i4 := i4loop - 1 + ipn4 := ipn4Out - 1 + z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] + z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] + } + } + + // Initial split checking via dqd and Li's test. + pp := 0 + for k := 0; k < 2; k++ { + d = z[4*n0+pp] + for i4loop := 4*n0 + pp; i4loop >= 4*(i0+1)+pp; i4loop -= 4 { + i4 := i4loop - 1 + if z[i4-1] <= tol2*d { + z[i4-1] = math.Copysign(0, -1) + d = z[i4-3] + } else { + d = z[i4-3] * (d / (d + z[i4-1])) + } + } + // dqd maps Z to ZZ plus Li's test. + emin = z[4*(i0+1)+pp] + d = z[4*i0+pp] + for i4loop := 4*(i0+1) + pp; i4loop <= 4*n0+pp; i4loop += 4 { + i4 := i4loop - 1 + z[i4-2*pp-2] = d + z[i4-1] + if z[i4-1] <= tol2*d { + z[i4-1] = math.Copysign(0, -1) + z[i4-2*pp-2] = d + z[i4-2*pp] = 0 + d = z[i4+1] + } else if safmin*z[i4+1] < z[i4-2*pp-2] && safmin*z[i4-2*pp-2] < z[i4+1] { + tmp := z[i4+1] / z[i4-2*pp-2] + z[i4-2*pp] = z[i4-1] * tmp + d *= tmp + } else { + z[i4-2*pp] = z[i4+1] * (z[i4-1] / z[i4-2*pp-2]) + d = z[i4+1] * (d / z[i4-2*pp-2]) + } + emin = math.Min(emin, z[i4-2*pp]) + } + z[4*(n0+1)-pp-3] = d + + // Now find qmax. + qmax = z[4*(i0+1)-pp-3] + for i4loop := 4*(i0+1) - pp + 2; i4loop <= 4*(n0+1)+pp-2; i4loop += 4 { + i4 := i4loop - 1 + qmax = math.Max(qmax, z[i4]) + } + // Prepare for the next iteration on K. + pp = 1 - pp + } + + // Initialise variables to pass to DLASQ3. + var ttype int + var dmin1, dmin2, dn, dn1, dn2, g, tau float64 + var tempq float64 + iter := 2 + var nFail int + nDiv := 2 * (n0 - i0) + var i4 int +outer: + for iwhila := 1; iwhila <= n+1; iwhila++ { + // Test for completion. + if n0 < 0 { + // Move q's to the front. + for k := 1; k < n; k++ { + z[k] = z[4*k] + } + // Sort and compute sum of eigenvalues. + impl.Dlasrt(lapack.SortDecreasing, n, z) + e = 0 + for k := n - 1; k >= 0; k-- { + e += z[k] + } + // Store trace, sum(eigenvalues) and information on performance. + z[2*n] = trace + z[2*n+1] = e + z[2*n+2] = float64(iter) + z[2*n+3] = float64(nDiv) / float64(n*n) + z[2*n+4] = 100 * float64(nFail) / float64(iter) + return info + } + + // While array unfinished do + // e[n0] holds the value of sigma when submatrix in i0:n0 + // splits from the rest of the array, but is negated. + var desig float64 + var sigma float64 + if n0 != n-1 { + sigma = -z[4*(n0+1)-2] + } + if sigma < 0 { + info = 1 + return info + } + // Find last unreduced submatrix's top index i0, find qmax and + // emin. Find Gershgorin-type bound if Q's much greater than E's. + var emax float64 + if n0 > i0 { + emin = math.Abs(z[4*(n0+1)-6]) + } else { + emin = 0 + } + qmin := z[4*(n0+1)-4] + qmax = qmin + zSmall := false + for i4loop := 4 * (n0 + 1); i4loop >= 8; i4loop -= 4 { + i4 = i4loop - 1 + if z[i4-5] <= 0 { + zSmall = true + break + } + if qmin >= 4*emax { + qmin = math.Min(qmin, z[i4-3]) + emax = math.Max(emax, z[i4-5]) + } + qmax = math.Max(qmax, z[i4-7]+z[i4-5]) + emin = math.Min(emin, z[i4-5]) + } + if !zSmall { + i4 = 3 + } + i0 = (i4+1)/4 - 1 + pp = 0 + if n0-i0 > 1 { + dee := z[4*i0] + deemin := dee + kmin := i0 + for i4loop := 4*(i0+1) + 1; i4loop <= 4*(n0+1)-3; i4loop += 4 { + i4 := i4loop - 1 + dee = z[i4] * (dee / (dee + z[i4-2])) + if dee <= deemin { + deemin = dee + kmin = (i4+4)/4 - 1 + } + } + if (kmin-i0)*2 < n0-kmin && deemin <= 0.5*z[4*n0] { + ipn4Out := 4 * (i0 + n0 + 2) + pp = 2 + for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { + i4 := i4loop - 1 + ipn4 := ipn4Out - 1 + z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] + z[i4-2], z[ipn4-i4-3] = z[ipn4-i4-3], z[i4-2] + z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] + z[i4], z[ipn4-i4-5] = z[ipn4-i4-5], z[i4] + } + } + } + // Put -(initial shift) into DMIN. + dmin := -math.Max(0, qmin-2*math.Sqrt(qmin)*math.Sqrt(emax)) + + // Now i0:n0 is unreduced. + // PP = 0 for ping, PP = 1 for pong. + // PP = 2 indicates that flipping was applied to the Z array and + // and that the tests for deflation upon entry in Dlasq3 + // should not be performed. + nbig := 100 * (n0 - i0 + 1) + for iwhilb := 0; iwhilb < nbig; iwhilb++ { + if i0 > n0 { + continue outer + } + + // While submatrix unfinished take a good dqds step. + i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau = + impl.Dlasq3(i0, n0, z, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau) + + pp = 1 - pp + // When emin is very small check for splits. + if pp == 0 && n0-i0 >= 3 { + if z[4*(n0+1)-1] <= tol2*qmax || z[4*(n0+1)-2] <= tol2*sigma { + splt := i0 - 1 + qmax = z[4*i0] + emin = z[4*(i0+1)-2] + oldemn := z[4*(i0+1)-1] + for i4loop := 4 * (i0 + 1); i4loop <= 4*(n0-2); i4loop += 4 { + i4 := i4loop - 1 + if z[i4] <= tol2*z[i4-3] || z[i4-1] <= tol2*sigma { + z[i4-1] = -sigma + splt = i4 / 4 + qmax = 0 + emin = z[i4+3] + oldemn = z[i4+4] + } else { + qmax = math.Max(qmax, z[i4+1]) + emin = math.Min(emin, z[i4-1]) + oldemn = math.Min(oldemn, z[i4]) + } + } + z[4*(n0+1)-2] = emin + z[4*(n0+1)-1] = oldemn + i0 = splt + 1 + } + } + } + // Maximum number of iterations exceeded, restore the shift + // sigma and place the new d's and e's in a qd array. + // This might need to be done for several blocks. + info = 2 + i1 = i0 + n1 = n0 + for { + tempq = z[4*i0] + z[4*i0] += sigma + for k := i0 + 1; k <= n0; k++ { + tempe := z[4*(k+1)-6] + z[4*(k+1)-6] *= tempq / z[4*(k+1)-8] + tempq = z[4*k] + z[4*k] += sigma + tempe - z[4*(k+1)-6] + } + // Prepare to do this on the previous block if there is one. + if i1 <= 0 { + break + } + n1 = i1 - 1 + for i1 >= 1 && z[4*(i1+1)-6] >= 0 { + i1 -= 1 + } + sigma = -z[4*(n1+1)-2] + } + for k := 0; k < n; k++ { + z[2*k] = z[4*k] + // Only the block 1..N0 is unfinished. The rest of the e's + // must be essentially zero, although sometimes other data + // has been stored in them. + if k < n0 { + z[2*(k+1)-1] = z[4*(k+1)-1] + } else { + z[2*(k+1)] = 0 + } + } + return info + } + info = 3 + return info +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go new file mode 100644 index 00000000..d547acfb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go @@ -0,0 +1,161 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlasq3 checks for deflation, computes a shift (tau) and calls dqds. +// In case of failure it changes shifts, and tries again until output +// is positive. +// +// Dlasq3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq3(i0, n0 int, z []float64, pp int, dmin, sigma, desig, qmax float64, nFail, iter, nDiv int, ttype int, dmin1, dmin2, dn, dn1, dn2, g, tau float64) ( + i0Out, n0Out, ppOut int, dminOut, sigmaOut, desigOut, qmaxOut float64, nFailOut, iterOut, nDivOut, ttypeOut int, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64) { + const cbias = 1.5 + + n0in := n0 + eps := dlamchP + tol := eps * 100 + tol2 := tol * tol + var nn int + var t float64 + for { + if n0 < i0 { + return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau + } + if n0 == i0 { + z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma + n0-- + continue + } + nn = 4*(n0+1) + pp - 1 + if n0 != i0+1 { + // Check whether e[n0-1] is negligible, 1 eigenvalue. + if z[nn-5] > tol2*(sigma+z[nn-3]) && z[nn-2*pp-4] > tol2*z[nn-7] { + // Check whether e[n0-2] is negligible, 2 eigenvalues. + if z[nn-9] > tol2*sigma && z[nn-2*pp-8] > tol2*z[nn-11] { + break + } + } else { + z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma + n0-- + continue + } + } + if z[nn-3] > z[nn-7] { + z[nn-3], z[nn-7] = z[nn-7], z[nn-3] + } + t = 0.5 * (z[nn-7] - z[nn-3] + z[nn-5]) + if z[nn-5] > z[nn-3]*tol2 && t != 0 { + s := z[nn-3] * (z[nn-5] / t) + if s <= t { + s = z[nn-3] * (z[nn-5] / (t * (1 + math.Sqrt(1+s/t)))) + } else { + s = z[nn-3] * (z[nn-5] / (t + math.Sqrt(t)*math.Sqrt(t+s))) + } + t = z[nn-7] + (s + z[nn-5]) + z[nn-3] *= z[nn-7] / t + z[nn-7] = t + } + z[4*(n0+1)-8] = z[nn-7] + sigma + z[4*(n0+1)-4] = z[nn-3] + sigma + n0 -= 2 + } + if pp == 2 { + pp = 0 + } + + // Reverse the qd-array, if warranted. + if dmin <= 0 || n0 < n0in { + if cbias*z[4*(i0+1)+pp-4] < z[4*(n0+1)+pp-4] { + ipn4Out := 4 * (i0 + n0 + 2) + for j4loop := 4 * (i0 + 1); j4loop <= 2*((i0+1)+(n0+1)-1); j4loop += 4 { + ipn4 := ipn4Out - 1 + j4 := j4loop - 1 + + z[j4-3], z[ipn4-j4-4] = z[ipn4-j4-4], z[j4-3] + z[j4-2], z[ipn4-j4-3] = z[ipn4-j4-3], z[j4-2] + z[j4-1], z[ipn4-j4-6] = z[ipn4-j4-6], z[j4-1] + z[j4], z[ipn4-j4-5] = z[ipn4-j4-5], z[j4] + } + if n0-i0 <= 4 { + z[4*(n0+1)+pp-2] = z[4*(i0+1)+pp-2] + z[4*(n0+1)-pp-1] = z[4*(i0+1)-pp-1] + } + dmin2 = math.Min(dmin2, z[4*(i0+1)-pp-2]) + z[4*(n0+1)+pp-2] = math.Min(math.Min(z[4*(n0+1)+pp-2], z[4*(i0+1)+pp-2]), z[4*(i0+1)+pp+2]) + z[4*(n0+1)-pp-1] = math.Min(math.Min(z[4*(n0+1)-pp-1], z[4*(i0+1)-pp-1]), z[4*(i0+1)-pp+3]) + qmax = math.Max(math.Max(qmax, z[4*(i0+1)+pp-4]), z[4*(i0+1)+pp]) + dmin = math.Copysign(0, -1) // Fortran code has -zero, but -0 in go is 0 + } + } + + // Choose a shift. + tau, ttype, g = impl.Dlasq4(i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn, dn1, dn2, tau, ttype, g) + + // Call dqds until dmin > 0. +loop: + for { + i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq5(i0, n0, z, pp, tau, sigma) + + nDiv += n0 - i0 + 2 + iter++ + switch { + case dmin >= 0 && dmin1 >= 0: + // Success. + goto done + + case dmin < 0 && dmin1 > 0 && z[4*n0-pp-1] < tol*(sigma+dn1) && math.Abs(dn) < tol*sigma: + // Convergence hidden by negative dn. + z[4*n0-pp+1] = 0 + dmin = 0 + goto done + + case dmin < 0: + // Tau too big. Select new Tau and try again. + nFail++ + if ttype < -22 { + // Failed twice. Play it safe. + tau = 0 + } else if dmin1 > 0 { + // Late failure. Gives excellent shift. + tau = (tau + dmin) * (1 - 2*eps) + ttype -= 11 + } else { + // Early failure. Divide by 4. + tau = tau / 4 + ttype -= 12 + } + + case math.IsNaN(dmin): + if tau == 0 { + break loop + } + tau = 0 + + default: + // Possible underflow. Play it safe. + break loop + } + } + + // Risk of underflow. + dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq6(i0, n0, z, pp) + nDiv += n0 - i0 + 2 + iter++ + tau = 0 + +done: + if tau < sigma { + desig += tau + t = sigma + desig + desig -= t - sigma + } else { + t = sigma + tau + desig += sigma - (t - tau) + } + sigma = t + return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go new file mode 100644 index 00000000..e09193b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go @@ -0,0 +1,238 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlasq4 computes an approximation to the smallest eigenvalue using values of d +// from the previous transform. +// i0, n0, and n0in are zero-indexed. +// +// Dlasq4 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq4(i0, n0 int, z []float64, pp int, n0in int, dmin, dmin1, dmin2, dn, dn1, dn2, tau float64, ttype int, g float64) (tauOut float64, ttypeOut int, gOut float64) { + const ( + cnst1 = 0.563 + cnst2 = 1.01 + cnst3 = 1.05 + + cnstthird = 0.333 // TODO(btracey): Fix? + ) + // A negative dmin forces the shift to take that absolute value + // ttype records the type of shift. + if dmin <= 0 { + tau = -dmin + ttype = -1 + return tau, ttype, g + } + nn := 4*(n0+1) + pp - 1 // -1 for zero indexing + s := math.NaN() // Poison s so that failure to take a path below is obvious + if n0in == n0 { + // No eigenvalues deflated. + if dmin == dn || dmin == dn1 { + b1 := math.Sqrt(z[nn-3]) * math.Sqrt(z[nn-5]) + b2 := math.Sqrt(z[nn-7]) * math.Sqrt(z[nn-9]) + a2 := z[nn-7] + z[nn-5] + if dmin == dn && dmin1 == dn1 { + gap2 := dmin2 - a2 - dmin2/4 + var gap1 float64 + if gap2 > 0 && gap2 > b2 { + gap1 = a2 - dn - (b2/gap2)*b2 + } else { + gap1 = a2 - dn - (b1 + b2) + } + if gap1 > 0 && gap1 > b1 { + s = math.Max(dn-(b1/gap1)*b1, 0.5*dmin) + ttype = -2 + } else { + s = 0 + if dn > b1 { + s = dn - b1 + } + if a2 > b1+b2 { + s = math.Min(s, a2-(b1+b2)) + } + s = math.Max(s, cnstthird*dmin) + ttype = -3 + } + } else { + ttype = -4 + s = dmin / 4 + var gam float64 + var np int + if dmin == dn { + gam = dn + a2 = 0 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b2 = z[nn-5] / z[nn-7] + np = nn - 9 + } else { + np = nn - 2*pp + gam = dn1 + if z[np-4] > z[np-2] { + return tau, ttype, g + } + a2 = z[np-4] / z[np-2] + if z[nn-9] > z[nn-11] { + return tau, ttype, g + } + b2 = z[nn-9] / z[nn-11] + np = nn - 13 + } + // Approximate contribution to norm squared from i < nn-1. + a2 += b2 + for i4loop := np + 1; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if b2 == 0 { + break + } + b1 = b2 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b2 *= z[i4] / z[i4-2] + a2 += b2 + if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { + break + } + } + a2 *= cnst3 + // Rayleigh quotient residual bound. + if a2 < cnst1 { + s = gam * (1 - math.Sqrt(a2)) / (1 + a2) + } + } + } else if dmin == dn2 { + ttype = -5 + s = dmin / 4 + // Compute contribution to norm squared from i > nn-2. + np := nn - 2*pp + b1 := z[np-2] + b2 := z[np-6] + gam := dn2 + if z[np-8] > b2 || z[np-4] > b1 { + return tau, ttype, g + } + a2 := (z[np-8] / b2) * (1 + z[np-4]/b1) + // Approximate contribution to norm squared from i < nn-2. + if n0-i0 > 2 { + b2 = z[nn-13] / z[nn-15] + a2 += b2 + for i4loop := (nn + 1) - 17; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if b2 == 0 { + break + } + b1 = b2 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b2 *= z[i4] / z[i4-2] + a2 += b2 + if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { + break + } + } + a2 *= cnst3 + } + if a2 < cnst1 { + s = gam * (1 - math.Sqrt(a2)) / (1 + a2) + } + } else { + // Case 6, no information to guide us. + if ttype == -6 { + g += cnstthird * (1 - g) + } else if ttype == -18 { + g = cnstthird / 4 + } else { + g = 1.0 / 4 + } + s = g * dmin + ttype = -6 + } + } else if n0in == (n0 + 1) { + // One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. + if dmin1 == dn1 && dmin2 == dn2 { + ttype = -7 + s = cnstthird * dmin1 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b1 := z[nn-5] / z[nn-7] + b2 := b1 + if b2 != 0 { + for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + a2 := b1 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b1 *= z[i4] / z[i4-2] + b2 += b1 + if 100*math.Max(b1, a2) < b2 { + break + } + } + } + b2 = math.Sqrt(cnst3 * b2) + a2 := dmin1 / (1 + b2*b2) + gap2 := 0.5*dmin2 - a2 + if gap2 > 0 && gap2 > b2*a2 { + s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) + } else { + s = math.Max(s, a2*(1-cnst2*b2)) + ttype = -8 + } + } else { + s = dmin1 / 4 + if dmin1 == dn1 { + s = 0.5 * dmin1 + } + ttype = -9 + } + } else if n0in == (n0 + 2) { + // Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. + if dmin2 == dn2 && 2*z[nn-5] < z[nn-7] { + ttype = -10 + s = cnstthird * dmin2 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b1 := z[nn-5] / z[nn-7] + b2 := b1 + if b2 != 0 { + for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b1 *= z[i4] / z[i4-2] + b2 += b1 + if 100*b1 < b2 { + break + } + } + } + b2 = math.Sqrt(cnst3 * b2) + a2 := dmin2 / (1 + b2*b2) + gap2 := z[nn-7] + z[nn-9] - math.Sqrt(z[nn-11])*math.Sqrt(z[nn-9]) - a2 + if gap2 > 0 && gap2 > b2*a2 { + s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) + } else { + s = math.Max(s, a2*(1-cnst2*b2)) + } + } else { + s = dmin2 / 4 + ttype = -11 + } + } else if n0in > n0+2 { + // Case 12, more than two eigenvalues deflated. No information. + s = 0 + ttype = -12 + } + tau = s + return tau, ttype, g +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go new file mode 100644 index 00000000..f94f2fb8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go @@ -0,0 +1,127 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlasq5 computes one dqds transform in ping-pong form. +// i0 and n0 are zero-indexed. +// +// Dlasq5 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq5(i0, n0 int, z []float64, pp int, tau, sigma float64) (i0Out, n0Out, ppOut int, tauOut, sigmaOut, dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { + // The lapack function has inputs for ieee and eps, but Go requires ieee so + // these are unnecessary. + if n0-i0-1 <= 0 { + return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 + } + eps := dlamchP + dthresh := eps * (sigma + tau) + if tau < dthresh*0.5 { + tau = 0 + } + var j4 int + var emin float64 + if tau != 0 { + j4 = 4*i0 + pp + emin = z[j4+4] + d := z[j4] - tau + dmin = d + // In the reference there are code paths that actually return this value. + // dmin1 = -z[j4] + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-2] = d + z[j4-1] + tmp := z[j4+1] / z[j4-2] + d = d*tmp - tau + dmin = math.Min(dmin, d) + z[j4] = z[j4-1] * tmp + emin = math.Min(z[j4], emin) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + tmp := z[j4+2] / z[j4-3] + d = d*tmp - tau + dmin = math.Min(dmin, d) + z[j4-1] = z[j4] * tmp + emin = math.Min(z[j4-1], emin) + } + } + // Unroll the last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*((n0+1)-2) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau + dmin = math.Min(dmin, dnm1) + + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau + dmin = math.Min(dmin, dn) + } else { + // This is the version that sets d's to zero if they are small enough. + j4 = 4*(i0+1) + pp - 4 + emin = z[j4+4] + d := z[j4] - tau + dmin = d + // In the reference there are code paths that actually return this value. + // dmin1 = -z[j4] + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-2] = d + z[j4-1] + tmp := z[j4+1] / z[j4-2] + d = d*tmp - tau + if d < dthresh { + d = 0 + } + dmin = math.Min(dmin, d) + z[j4] = z[j4-1] * tmp + emin = math.Min(z[j4], emin) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + tmp := z[j4+2] / z[j4-3] + d = d*tmp - tau + if d < dthresh { + d = 0 + } + dmin = math.Min(dmin, d) + z[j4-1] = z[j4] * tmp + emin = math.Min(z[j4-1], emin) + } + } + // Unroll the last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*((n0+1)-2) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau + dmin = math.Min(dmin, dnm1) + + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau + dmin = math.Min(dmin, dn) + } + z[j4+2] = dn + z[4*(n0+1)-pp-1] = emin + return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go new file mode 100644 index 00000000..94f69395 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go @@ -0,0 +1,109 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlasq6 computes one dqd transform in ping-pong form with protection against +// overflow and underflow. z has length at least 4*(n0+1) and holds the qd array. +// i0 is the zero-based first index. +// n0 is the zero-based last index. +// +// Dlasq6 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq6(i0, n0 int, z []float64, pp int) (dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { + if len(z) < 4*(n0+1) { + panic(badZ) + } + if n0-i0-1 <= 0 { + return dmin, dmin1, dmin2, dn, dnm1, dnm2 + } + safmin := dlamchS + j4 := 4*(i0+1) + pp - 4 // -4 rather than -3 for zero indexing + emin := z[j4+4] + d := z[j4] + dmin = d + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 // Translate back to zero-indexed. + z[j4-2] = d + z[j4-1] + if z[j4-2] == 0 { + z[j4] = 0 + d = z[j4+1] + dmin = d + emin = 0 + } else if safmin*z[j4+1] < z[j4-2] && safmin*z[j4-2] < z[j4+1] { + tmp := z[j4+1] / z[j4-2] + z[j4] = z[j4-1] * tmp + d *= tmp + } else { + z[j4] = z[j4+1] * (z[j4-1] / z[j4-2]) + d = z[j4+1] * (d / z[j4-2]) + } + dmin = math.Min(dmin, d) + emin = math.Min(emin, z[j4]) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + if z[j4-3] == 0 { + z[j4-1] = 0 + d = z[j4+2] + dmin = d + emin = 0 + } else if safmin*z[j4+2] < z[j4-3] && safmin*z[j4-3] < z[j4+2] { + tmp := z[j4+2] / z[j4-3] + z[j4-1] = z[j4] * tmp + d *= tmp + } else { + z[j4-1] = z[j4+2] * (z[j4] / z[j4-3]) + d = z[j4+2] * (d / z[j4-3]) + } + dmin = math.Min(dmin, d) + emin = math.Min(emin, z[j4-1]) + } + } + // Unroll last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*(n0-1) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + if z[j4-2] == 0 { + z[j4] = 0 + dnm1 = z[j4p2+2] + dmin = dnm1 + emin = 0 + } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { + tmp := z[j4p2+2] / z[j4-2] + z[j4] = z[j4p2] * tmp + dnm1 = dnm2 * tmp + } else { + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2] * (dnm2 / z[j4-2]) + } + dmin = math.Min(dmin, dnm1) + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + if z[j4-2] == 0 { + z[j4] = 0 + dn = z[j4p2+2] + dmin = dn + emin = 0 + } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { + tmp := z[j4p2+2] / z[j4-2] + z[j4] = z[j4p2] * tmp + dn = dnm1 * tmp + } else { + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2] * (dnm1 / z[j4-2]) + } + dmin = math.Min(dmin, dn) + z[j4+2] = dn + z[4*(n0+1)-pp-1] = emin + return dmin, dmin1, dmin2, dn, dnm1, dnm2 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go new file mode 100644 index 00000000..dde44ddb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go @@ -0,0 +1,268 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlasr applies a sequence of plane rotations to the m×n matrix A. This series +// of plane rotations is implicitly represented by a matrix P. P is multiplied +// by a depending on the value of side -- A = P * A if side == lapack.Left, +// A = A * P^T if side == lapack.Right. +// +//The exact value of P depends on the value of pivot, but in all cases P is +// implicitly represented by a series of 2×2 rotation matrices. The entries of +// rotation matrix k are defined by s[k] and c[k] +// R(k) = [ c[k] s[k]] +// [-s[k] s[k]] +// If direct == lapack.Forward, the rotation matrices are applied as +// P = P(z-1) * ... * P(2) * P(1), while if direct == lapack.Backward they are +// applied as P = P(1) * P(2) * ... * P(n). +// +// pivot defines the mapping of the elements in R(k) to P(k). +// If pivot == lapack.Variable, the rotation is performed for the (k, k+1) plane. +// P(k) = [1 ] +// [ ... ] +// [ 1 ] +// [ c[k] s[k] ] +// [ -s[k] c[k] ] +// [ 1 ] +// [ ... ] +// [ 1] +// if pivot == lapack.Top, the rotation is performed for the (1, k+1) plane, +// P(k) = [c[k] s[k] ] +// [ 1 ] +// [ ... ] +// [ 1 ] +// [-s[k] c[k] ] +// [ 1 ] +// [ ... ] +// [ 1] +// and if pivot == lapack.Bottom, the rotation is performed for the (k, z) plane. +// P(k) = [1 ] +// [ ... ] +// [ 1 ] +// [ c[k] s[k]] +// [ 1 ] +// [ ... ] +// [ 1 ] +// [ -s[k] c[k]] +// s and c have length m - 1 if side == blas.Left, and n - 1 if side == blas.Right. +// +// Dlasr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom { + panic(badPivot) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if side == blas.Left { + if len(c) < m-1 { + panic(badSlice) + } + if len(s) < m-1 { + panic(badSlice) + } + } else { + if len(c) < n-1 { + panic(badSlice) + } + if len(s) < n-1 { + panic(badSlice) + } + } + if m == 0 || n == 0 { + return + } + if side == blas.Left { + if pivot == lapack.Variable { + if direct == lapack.Forward { + for j := 0; j < m-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp2 := a[j*lda+i] + tmp := a[(j+1)*lda+i] + a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 + a[j*lda+i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := m - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp2 := a[j*lda+i] + tmp := a[(j+1)*lda+i] + a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 + a[j*lda+i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } else if pivot == lapack.Top { + if direct == lapack.Forward { + for j := 1; j < m; j++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[i] + a[j*lda+i] = ctmp*tmp - stmp*tmp2 + a[i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := m - 1; j >= 1; j-- { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[i] + a[j*lda+i] = ctmp*tmp - stmp*tmp2 + a[i] = stmp*tmp + ctmp*tmp2 + } + } + } + } + } + return + } + if direct == lapack.Forward { + for j := 0; j < m-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[(m-1)*lda+i] + a[j*lda+i] = stmp*tmp2 + ctmp*tmp + a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp + } + } + } + return + } + for j := m - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[(m-1)*lda+i] + a[j*lda+i] = stmp*tmp2 + ctmp*tmp + a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp + } + } + } + return + } + if pivot == lapack.Variable { + if direct == lapack.Forward { + for j := 0; j < n-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j+1] + tmp2 := a[i*lda+j] + a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 + a[i*lda+j] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := n - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j+1] + tmp2 := a[i*lda+j] + a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 + a[i*lda+j] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } else if pivot == lapack.Top { + if direct == lapack.Forward { + for j := 1; j < n; j++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda] + a[i*lda+j] = ctmp*tmp - stmp*tmp2 + a[i*lda] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := n - 1; j >= 1; j-- { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda] + a[i*lda+j] = ctmp*tmp - stmp*tmp2 + a[i*lda] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + if direct == lapack.Forward { + for j := 0; j < n-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda+n-1] + a[i*lda+j] = stmp*tmp2 + ctmp*tmp + a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp + } + + } + } + return + } + for j := n - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda+n-1] + a[i*lda+j] = stmp*tmp2 + ctmp*tmp + a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go new file mode 100644 index 00000000..eb63c63d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "sort" + + "gonum.org/v1/gonum/lapack" +) + +// Dlasrt sorts the numbers in the input slice d. If s == lapack.SortIncreasing, +// the elements are sorted in increasing order. If s == lapack.SortDecreasing, +// the elements are sorted in decreasing order. For other values of s Dlasrt +// will panic. +// +// Dlasrt is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasrt(s lapack.Sort, n int, d []float64) { + checkVector(n, d, 1) + d = d[:n] + switch s { + default: + panic(badSort) + case lapack.SortIncreasing: + sort.Float64s(d) + case lapack.SortDecreasing: + sort.Sort(sort.Reverse(sort.Float64Slice(d))) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go new file mode 100644 index 00000000..186b840b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go @@ -0,0 +1,31 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlassq updates a sum of squares in scaled form. The input parameters scale and +// sumsq represent the current scale and total sum of squares. These values are +// updated with the information in the first n elements of the vector specified +// by x and incX. +// +// Dlassq is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlassq(n int, x []float64, incx int, scale float64, sumsq float64) (scl, smsq float64) { + if n <= 0 { + return scale, sumsq + } + for ix := 0; ix <= (n-1)*incx; ix += incx { + absxi := math.Abs(x[ix]) + if absxi > 0 || math.IsNaN(absxi) { + if scale < absxi { + sumsq = 1 + sumsq*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumsq += (absxi / scale) * (absxi / scale) + } + } + } + return scale, sumsq +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go new file mode 100644 index 00000000..ba1445c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go @@ -0,0 +1,115 @@ +// Copyright ©2015 The gonum 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 gonum + +import "math" + +// Dlasv2 computes the singular value decomposition of a 2×2 matrix. +// [ csl snl] [f g] [csr -snr] = [ssmax 0] +// [-snl csl] [0 h] [snr csr] = [ 0 ssmin] +// ssmax is the larger absolute singular value, and ssmin is the smaller absolute +// singular value. [cls, snl] and [csr, snr] are the left and right singular vectors. +// +// Dlasv2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) { + ft := f + fa := math.Abs(ft) + ht := h + ha := math.Abs(h) + // pmax points to the largest element of the matrix in terms of absolute value. + // 1 if F, 2 if G, 3 if H. + pmax := 1 + swap := ha > fa + if swap { + pmax = 3 + ft, ht = ht, ft + fa, ha = ha, fa + } + gt := g + ga := math.Abs(gt) + var clt, crt, slt, srt float64 + if ga == 0 { + ssmin = ha + ssmax = fa + clt = 1 + crt = 1 + slt = 0 + srt = 0 + } else { + gasmall := true + if ga > fa { + pmax = 2 + if (fa / ga) < dlamchE { + gasmall = false + ssmax = ga + if ha > 1 { + ssmin = fa / (ga / ha) + } else { + ssmin = (fa / ga) * ha + } + clt = 1 + slt = ht / gt + srt = 1 + crt = ft / gt + } + } + if gasmall { + d := fa - ha + l := d / fa + if d == fa { // deal with inf + l = 1 + } + m := gt / ft + t := 2 - l + s := math.Hypot(t, m) + var r float64 + if l == 0 { + r = math.Abs(m) + } else { + r = math.Hypot(l, m) + } + a := 0.5 * (s + r) + ssmin = ha / a + ssmax = fa * a + if m == 0 { + if l == 0 { + t = math.Copysign(2, ft) * math.Copysign(1, gt) + } else { + t = gt/math.Copysign(d, ft) + m/t + } + } else { + t = (m/(s+t) + m/(r+l)) * (1 + a) + } + l = math.Hypot(t, 2) + crt = 2 / l + srt = t / l + clt = (crt + srt*m) / a + slt = (ht / ft) * srt / a + } + } + if swap { + csl = srt + snl = crt + csr = slt + snr = clt + } else { + csl = clt + snl = slt + csr = crt + snr = srt + } + var tsign float64 + switch pmax { + case 1: + tsign = math.Copysign(1, csr) * math.Copysign(1, csl) * math.Copysign(1, f) + case 2: + tsign = math.Copysign(1, snr) * math.Copysign(1, csl) * math.Copysign(1, g) + case 3: + tsign = math.Copysign(1, snr) * math.Copysign(1, snl) * math.Copysign(1, h) + } + ssmax = math.Copysign(ssmax, tsign) + ssmin = math.Copysign(ssmin, tsign*math.Copysign(1, f)*math.Copysign(1, h)) + return ssmin, ssmax, snr, csr, snl, csl +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go new file mode 100644 index 00000000..22ef3533 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlaswp swaps the rows k1 to k2 of a rectangular matrix A according to the +// indices in ipiv so that row k is swapped with ipiv[k]. +// +// n is the number of columns of A and incX is the increment for ipiv. If incX +// is 1, the swaps are applied from k1 to k2. If incX is -1, the swaps are +// applied in reverse order from k2 to k1. For other values of incX Dlaswp will +// panic. ipiv must have length k2+1, otherwise Dlaswp will panic. +// +// The indices k1, k2, and the elements of ipiv are zero-based. +// +// Dlaswp is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv []int, incX int) { + switch { + case n < 0: + panic(nLT0) + case k2 < 0: + panic(badK2) + case k1 < 0 || k2 < k1: + panic(badK1) + case len(ipiv) != k2+1: + panic(badIpiv) + case incX != 1 && incX != -1: + panic(absIncNotOne) + } + + if n == 0 { + return + } + bi := blas64.Implementation() + if incX == 1 { + for k := k1; k <= k2; k++ { + bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) + } + return + } + for k := k2; k >= k1; k-- { + bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go new file mode 100644 index 00000000..aa983bb9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go @@ -0,0 +1,290 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlasy2 solves the Sylvester matrix equation where the matrices are of order 1 +// or 2. It computes the unknown n1×n2 matrix X so that +// TL*X + sgn*X*TR = scale*B, if tranl == false and tranr == false, +// TL^T*X + sgn*X*TR = scale*B, if tranl == true and tranr == false, +// TL*X + sgn*X*TR^T = scale*B, if tranl == false and tranr == true, +// TL^T*X + sgn*X*TR^T = scale*B, if tranl == true and tranr == true, +// where TL is n1×n1, TR is n2×n2, B is n1×n2, and 1 <= n1,n2 <= 2. +// +// isgn must be 1 or -1, and n1 and n2 must be 0, 1, or 2, but these conditions +// are not checked. +// +// Dlasy2 returns three values, a scale factor that is chosen less than or equal +// to 1 to prevent the solution overflowing, the infinity norm of the solution, +// and an indicator of success. If ok is false, TL and TR have eigenvalues that +// are too close, so TL or TR is perturbed to get a non-singular equation. +// +// Dlasy2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasy2(tranl, tranr bool, isgn, n1, n2 int, tl []float64, ldtl int, tr []float64, ldtr int, b []float64, ldb int, x []float64, ldx int) (scale, xnorm float64, ok bool) { + // TODO(vladimir-ch): Add input validation checks conditionally skipped + // using the build tag mechanism. + + ok = true + // Quick return if possible. + if n1 == 0 || n2 == 0 { + return scale, xnorm, ok + } + + // Set constants to control overflow. + eps := dlamchP + smlnum := dlamchS / eps + sgn := float64(isgn) + + if n1 == 1 && n2 == 1 { + // 1×1 case: TL11*X + sgn*X*TR11 = B11. + tau1 := tl[0] + sgn*tr[0] + bet := math.Abs(tau1) + if bet <= smlnum { + tau1 = smlnum + bet = smlnum + ok = false + } + scale = 1 + gam := math.Abs(b[0]) + if smlnum*gam > bet { + scale = 1 / gam + } + x[0] = b[0] * scale / tau1 + xnorm = math.Abs(x[0]) + return scale, xnorm, ok + } + + if n1+n2 == 3 { + // 1×2 or 2×1 case. + var ( + smin float64 + tmp [4]float64 // tmp is used as a 2×2 row-major matrix. + btmp [2]float64 + ) + if n1 == 1 && n2 == 2 { + // 1×2 case: TL11*[X11 X12] + sgn*[X11 X12]*op[TR11 TR12] = [B11 B12]. + // [TR21 TR22] + smin = math.Abs(tl[0]) + smin = math.Max(smin, math.Max(math.Abs(tr[0]), math.Abs(tr[1]))) + smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) + smin = math.Max(eps*smin, smlnum) + tmp[0] = tl[0] + sgn*tr[0] + tmp[3] = tl[0] + sgn*tr[ldtr+1] + if tranr { + tmp[1] = sgn * tr[1] + tmp[2] = sgn * tr[ldtr] + } else { + tmp[1] = sgn * tr[ldtr] + tmp[2] = sgn * tr[1] + } + btmp[0] = b[0] + btmp[1] = b[1] + } else { + // 2×1 case: op[TL11 TL12]*[X11] + sgn*[X11]*TR11 = [B11]. + // [TL21 TL22]*[X21] [X21] [B21] + smin = math.Abs(tr[0]) + smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) + smin = math.Max(eps*smin, smlnum) + tmp[0] = tl[0] + sgn*tr[0] + tmp[3] = tl[ldtl+1] + sgn*tr[0] + if tranl { + tmp[1] = tl[ldtl] + tmp[2] = tl[1] + } else { + tmp[1] = tl[1] + tmp[2] = tl[ldtl] + } + btmp[0] = b[0] + btmp[1] = b[ldb] + } + + // Solve 2×2 system using complete pivoting. + // Set pivots less than smin to smin. + + bi := blas64.Implementation() + ipiv := bi.Idamax(len(tmp), tmp[:], 1) + // Compute the upper triangular matrix [u11 u12]. + // [ 0 u22] + u11 := tmp[ipiv] + if math.Abs(u11) <= smin { + ok = false + u11 = smin + } + locu12 := [4]int{1, 0, 3, 2} // Index in tmp of the element on the same row as the pivot. + u12 := tmp[locu12[ipiv]] + locl21 := [4]int{2, 3, 0, 1} // Index in tmp of the element on the same column as the pivot. + l21 := tmp[locl21[ipiv]] / u11 + locu22 := [4]int{3, 2, 1, 0} // Index in tmp of the remaining element. + u22 := tmp[locu22[ipiv]] - l21*u12 + if math.Abs(u22) <= smin { + ok = false + u22 = smin + } + if ipiv&0x2 != 0 { // true for ipiv equal to 2 and 3. + // The pivot was in the second row, swap the elements of + // the right-hand side. + btmp[0], btmp[1] = btmp[1], btmp[0]-l21*btmp[1] + } else { + btmp[1] -= l21 * btmp[0] + } + scale = 1 + if 2*smlnum*math.Abs(btmp[1]) > math.Abs(u22) || 2*smlnum*math.Abs(btmp[0]) > math.Abs(u11) { + scale = 0.5 / math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) + btmp[0] *= scale + btmp[1] *= scale + } + // Solve the system [u11 u12] [x21] = [ btmp[0] ]. + // [ 0 u22] [x22] [ btmp[1] ] + x22 := btmp[1] / u22 + x21 := btmp[0]/u11 - (u12/u11)*x22 + if ipiv&0x1 != 0 { // true for ipiv equal to 1 and 3. + // The pivot was in the second column, swap the elements + // of the solution. + x21, x22 = x22, x21 + } + x[0] = x21 + if n1 == 1 { + x[1] = x22 + xnorm = math.Abs(x[0]) + math.Abs(x[1]) + } else { + x[ldx] = x22 + xnorm = math.Max(math.Abs(x[0]), math.Abs(x[ldx])) + } + return scale, xnorm, ok + } + + // 2×2 case: op[TL11 TL12]*[X11 X12] + SGN*[X11 X12]*op[TR11 TR12] = [B11 B12]. + // [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22] + // + // Solve equivalent 4×4 system using complete pivoting. + // Set pivots less than smin to smin. + + smin := math.Max(math.Abs(tr[0]), math.Abs(tr[1])) + smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) + smin = math.Max(eps*smin, smlnum) + + var t [4][4]float64 + t[0][0] = tl[0] + sgn*tr[0] + t[1][1] = tl[0] + sgn*tr[ldtr+1] + t[2][2] = tl[ldtl+1] + sgn*tr[0] + t[3][3] = tl[ldtl+1] + sgn*tr[ldtr+1] + if tranl { + t[0][2] = tl[ldtl] + t[1][3] = tl[ldtl] + t[2][0] = tl[1] + t[3][1] = tl[1] + } else { + t[0][2] = tl[1] + t[1][3] = tl[1] + t[2][0] = tl[ldtl] + t[3][1] = tl[ldtl] + } + if tranr { + t[0][1] = sgn * tr[1] + t[1][0] = sgn * tr[ldtr] + t[2][3] = sgn * tr[1] + t[3][2] = sgn * tr[ldtr] + } else { + t[0][1] = sgn * tr[ldtr] + t[1][0] = sgn * tr[1] + t[2][3] = sgn * tr[ldtr] + t[3][2] = sgn * tr[1] + } + + var btmp [4]float64 + btmp[0] = b[0] + btmp[1] = b[1] + btmp[2] = b[ldb] + btmp[3] = b[ldb+1] + + // Perform elimination. + var jpiv [4]int // jpiv records any column swaps for pivoting. + for i := 0; i < 3; i++ { + var ( + xmax float64 + ipsv, jpsv int + ) + for ip := i; ip < 4; ip++ { + for jp := i; jp < 4; jp++ { + if math.Abs(t[ip][jp]) >= xmax { + xmax = math.Abs(t[ip][jp]) + ipsv = ip + jpsv = jp + } + } + } + if ipsv != i { + // The pivot is not in the top row of the unprocessed + // block, swap rows ipsv and i of t and btmp. + t[ipsv], t[i] = t[i], t[ipsv] + btmp[ipsv], btmp[i] = btmp[i], btmp[ipsv] + } + if jpsv != i { + // The pivot is not in the left column of the + // unprocessed block, swap columns jpsv and i of t. + for k := 0; k < 4; k++ { + t[k][jpsv], t[k][i] = t[k][i], t[k][jpsv] + } + } + jpiv[i] = jpsv + if math.Abs(t[i][i]) < smin { + ok = false + t[i][i] = smin + } + for k := i + 1; k < 4; k++ { + t[k][i] /= t[i][i] + btmp[k] -= t[k][i] * btmp[i] + for j := i + 1; j < 4; j++ { + t[k][j] -= t[k][i] * t[i][j] + } + } + } + if math.Abs(t[3][3]) < smin { + ok = false + t[3][3] = smin + } + scale = 1 + if 8*smlnum*math.Abs(btmp[0]) > math.Abs(t[0][0]) || + 8*smlnum*math.Abs(btmp[1]) > math.Abs(t[1][1]) || + 8*smlnum*math.Abs(btmp[2]) > math.Abs(t[2][2]) || + 8*smlnum*math.Abs(btmp[3]) > math.Abs(t[3][3]) { + + maxbtmp := math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) + maxbtmp = math.Max(maxbtmp, math.Max(math.Abs(btmp[2]), math.Abs(btmp[3]))) + scale = 1 / 8 / maxbtmp + btmp[0] *= scale + btmp[1] *= scale + btmp[2] *= scale + btmp[3] *= scale + } + // Compute the solution of the upper triangular system t * tmp = btmp. + var tmp [4]float64 + for i := 3; i >= 0; i-- { + temp := 1 / t[i][i] + tmp[i] = btmp[i] * temp + for j := i + 1; j < 4; j++ { + tmp[i] -= temp * t[i][j] * tmp[j] + } + } + for i := 2; i >= 0; i-- { + if jpiv[i] != i { + tmp[i], tmp[jpiv[i]] = tmp[jpiv[i]], tmp[i] + } + } + x[0] = tmp[0] + x[1] = tmp[1] + x[ldx] = tmp[2] + x[ldx+1] = tmp[3] + xnorm = math.Max(math.Abs(tmp[0])+math.Abs(tmp[1]), math.Abs(tmp[2])+math.Abs(tmp[3])) + return scale, xnorm, ok +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go new file mode 100644 index 00000000..28bc2325 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go @@ -0,0 +1,145 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatrd reduces nb rows and columns of a real n×n symmetric matrix A to symmetric +// tridiagonal form. It computes the orthonormal similarity transformation +// Q^T * A * Q +// and returns the matrices V and W to apply to the unreduced part of A. If +// uplo == blas.Upper, the upper triangle is supplied and the last nb rows are +// reduced. If uplo == blas.Lower, the lower triangle is supplied and the first +// nb rows are reduced. +// +// a contains the symmetric matrix on entry with active triangular half specified +// by uplo. On exit, the nb columns have been reduced to tridiagonal form. The +// diagonal contains the diagonal of the reduced matrix, the off-diagonal is +// set to 1, and the remaining elements contain the data to construct Q. +// +// If uplo == blas.Upper, with n = 5 and nb = 2 on exit a is +// [ a a a v4 v5] +// [ a a v4 v5] +// [ a 1 v5] +// [ d 1] +// [ d] +// +// If uplo == blas.Lower, with n = 5 and nb = 2, on exit a is +// [ d ] +// [ 1 d ] +// [v1 1 a ] +// [v1 v2 a a ] +// [v1 v2 a a a] +// +// e contains the superdiagonal elements of the reduced matrix. If uplo == blas.Upper, +// e[n-nb:n-1] contains the last nb columns of the reduced matrix, while if +// uplo == blas.Lower, e[:nb] contains the first nb columns of the reduced matrix. +// e must have length at least n-1, and Dlatrd will panic otherwise. +// +// tau contains the scalar factors of the elementary reflectors needed to construct Q. +// The reflectors are stored in tau[n-nb:n-1] if uplo == blas.Upper, and in +// tau[:nb] if uplo == blas.Lower. tau must have length n-1, and Dlatrd will panic +// otherwise. +// +// w is an n×nb matrix. On exit it contains the data to update the unreduced part +// of A. +// +// The matrix Q is represented as a product of elementary reflectors. Each reflector +// H has the form +// I - tau * v * v^T +// If uplo == blas.Upper, +// Q = H_{n-1} * H_{n-2} * ... * H_{n-nb} +// where v[:i-1] is stored in A[:i-1,i], v[i-1] = 1, and v[i:n] = 0. +// +// If uplo == blas.Lower, +// Q = H_0 * H_1 * ... * H_{nb-1} +// where v[:i+1] = 0, v[i+1] = 1, and v[i+2:n] is stored in A[i+2:n,i]. +// +// The vectors v form the n×nb matrix V which is used with W to apply a +// symmetric rank-2 update to the unreduced part of A +// A = A - V * W^T - W * V^T +// +// Dlatrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlatrd(uplo blas.Uplo, n, nb int, a []float64, lda int, e, tau, w []float64, ldw int) { + checkMatrix(n, n, a, lda) + checkMatrix(n, nb, w, ldw) + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if n <= 0 { + return + } + bi := blas64.Implementation() + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + iw := i - n + nb + if i < n-1 { + // Update A(0:i, i). + bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, a[i+1:], lda, + w[i*ldw+iw+1:], 1, 1, a[i:], lda) + bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, w[iw+1:], ldw, + a[i*lda+i+1:], 1, 1, a[i:], lda) + } + if i > 0 { + // Generate elementary reflector H_i to annihilate A(0:i-2,i). + e[i-1], tau[i-1] = impl.Dlarfg(i, a[(i-1)*lda+i], a[i:], lda) + a[(i-1)*lda+i] = 1 + + // Compute W(0:i-1, i). + bi.Dsymv(blas.Upper, i, 1, a, lda, a[i:], lda, 0, w[iw:], ldw) + if i < n-1 { + bi.Dgemv(blas.Trans, i, n-i-1, 1, w[iw+1:], ldw, + a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) + bi.Dgemv(blas.NoTrans, i, n-i-1, -1, a[i+1:], lda, + w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) + bi.Dgemv(blas.Trans, i, n-i-1, 1, a[i+1:], lda, + a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) + bi.Dgemv(blas.NoTrans, i, n-i-1, -1, w[iw+1:], ldw, + w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) + } + bi.Dscal(i, tau[i-1], w[iw:], ldw) + alpha := -0.5 * tau[i-1] * bi.Ddot(i, w[iw:], ldw, a[i:], lda) + bi.Daxpy(i, alpha, a[i:], lda, w[iw:], ldw) + } + } + } else { + // Reduce first nb columns of lower triangle. + for i := 0; i < nb; i++ { + // Update A(i:n, i) + bi.Dgemv(blas.NoTrans, n-i, i, -1, a[i*lda:], lda, + w[i*ldw:], 1, 1, a[i*lda+i:], lda) + bi.Dgemv(blas.NoTrans, n-i, i, -1, w[i*ldw:], ldw, + a[i*lda:], 1, 1, a[i*lda+i:], lda) + if i < n-1 { + // Generate elementary reflector H_i to annihilate A(i+2:n,i). + e[i], tau[i] = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + a[(i+1)*lda+i] = 1 + + // Compute W(i+1:n,i). + bi.Dsymv(blas.Lower, n-i-1, 1, a[(i+1)*lda+i+1:], lda, + a[(i+1)*lda+i:], lda, 0, w[(i+1)*ldw+i:], ldw) + bi.Dgemv(blas.Trans, n-i-1, i, 1, w[(i+1)*ldw:], ldw, + a[(i+1)*lda+i:], lda, 0, w[i:], ldw) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, a[(i+1)*lda:], lda, + w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) + bi.Dgemv(blas.Trans, n-i-1, i, 1, a[(i+1)*lda:], lda, + a[(i+1)*lda+i:], lda, 0, w[i:], ldw) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, w[(i+1)*ldw:], ldw, + w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) + bi.Dscal(n-i-1, tau[i], w[(i+1)*ldw+i:], ldw) + alpha := -0.5 * tau[i] * bi.Ddot(n-i-1, w[(i+1)*ldw+i:], ldw, + a[(i+1)*lda+i:], lda) + bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, + w[(i+1)*ldw+i:], ldw) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go new file mode 100644 index 00000000..64470f59 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go @@ -0,0 +1,350 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatrs solves a triangular system of equations scaled to prevent overflow. It +// solves +// A * x = scale * b if trans == blas.NoTrans +// A^T * x = scale * b if trans == blas.Trans +// where the scale s is set for numeric stability. +// +// A is an n×n triangular matrix. On entry, the slice x contains the values of +// of b, and on exit it contains the solution vector x. +// +// If normin == true, cnorm is an input and cnorm[j] contains the norm of the off-diagonal +// part of the j^th column of A. If trans == blas.NoTrans, cnorm[j] must be greater +// than or equal to the infinity norm, and greater than or equal to the one-norm +// otherwise. If normin == false, then cnorm is treated as an output, and is set +// to contain the 1-norm of the off-diagonal part of the j^th column of A. +// +// Dlatrs is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n int, a []float64, lda int, x []float64, cnorm []float64) (scale float64) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + if diag != blas.Unit && diag != blas.NonUnit { + panic(badDiag) + } + upper := uplo == blas.Upper + noTrans := trans == blas.NoTrans + nonUnit := diag == blas.NonUnit + + if n < 0 { + panic(nLT0) + } + checkMatrix(n, n, a, lda) + checkVector(n, x, 1) + checkVector(n, cnorm, 1) + + if n == 0 { + return 0 + } + smlnum := dlamchS / dlamchP + bignum := 1 / smlnum + scale = 1 + bi := blas64.Implementation() + if !normin { + if upper { + cnorm[0] = 0 + for j := 1; j < n; j++ { + cnorm[j] = bi.Dasum(j, a[j:], lda) + } + } else { + for j := 0; j < n-1; j++ { + cnorm[j] = bi.Dasum(n-j-1, a[(j+1)*lda+j:], lda) + } + cnorm[n-1] = 0 + } + } + // Scale the column norms by tscal if the maximum element in cnorm is greater than bignum. + imax := bi.Idamax(n, cnorm, 1) + tmax := cnorm[imax] + var tscal float64 + if tmax <= bignum { + tscal = 1 + } else { + tscal = 1 / (smlnum * tmax) + bi.Dscal(n, tscal, cnorm, 1) + } + + // Compute a bound on the computed solution vector to see if bi.Dtrsv can be used. + j := bi.Idamax(n, x, 1) + xmax := math.Abs(x[j]) + xbnd := xmax + var grow float64 + var jfirst, jlast, jinc int + if noTrans { + if upper { + jfirst = n - 1 + jlast = -1 + jinc = -1 + } else { + jfirst = 0 + jlast = n + jinc = 1 + } + // Compute the growth in A * x = b. + if tscal != 1 { + grow = 0 + goto Solve + } + if nonUnit { + grow = 1 / math.Max(xbnd, smlnum) + xbnd = grow + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + tjj := math.Abs(a[j*lda+j]) + xbnd = math.Min(xbnd, math.Min(1, tjj)*grow) + if tjj+cnorm[j] >= smlnum { + grow *= tjj / (tjj + cnorm[j]) + } else { + grow = 0 + } + } + grow = xbnd + } else { + grow = math.Min(1, 1/math.Max(xbnd, smlnum)) + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + grow *= 1 / (1 + cnorm[j]) + } + } + } else { + if upper { + jfirst = 0 + jlast = n + jinc = 1 + } else { + jfirst = n - 1 + jlast = -1 + jinc = -1 + } + if tscal != 1 { + grow = 0 + goto Solve + } + if nonUnit { + grow = 1 / (math.Max(xbnd, smlnum)) + xbnd = grow + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + xj := 1 + cnorm[j] + grow = math.Min(grow, xbnd/xj) + tjj := math.Abs(a[j*lda+j]) + if xj > tjj { + xbnd *= tjj / xj + } + } + grow = math.Min(grow, xbnd) + } else { + grow = math.Min(1, 1/math.Max(xbnd, smlnum)) + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + xj := 1 + cnorm[j] + grow /= xj + } + } + } + +Solve: + if grow*tscal > smlnum { + // Use the Level 2 BLAS solve if the reciprocal of the bound on + // elements of X is not too small. + bi.Dtrsv(uplo, trans, diag, n, a, lda, x, 1) + if tscal != 1 { + bi.Dscal(n, 1/tscal, cnorm, 1) + } + return scale + } + + // Use a Level 1 BLAS solve, scaling intermediate results. + if xmax > bignum { + scale = bignum / xmax + bi.Dscal(n, scale, x, 1) + xmax = bignum + } + if noTrans { + for j := jfirst; j != jlast; j += jinc { + xj := math.Abs(x[j]) + var tjj, tjjs float64 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + if tscal == 1 { + goto Skip1 + } + } + tjj = math.Abs(tjjs) + if tjj > smlnum { + if tjj < 1 { + if xj > tjj*bignum { + rec := 1 / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + x[j] /= tjjs + xj = math.Abs(x[j]) + } else if tjj > 0 { + if xj > tjj*bignum { + rec := (tjj * bignum) / xj + if cnorm[j] > 1 { + rec /= cnorm[j] + } + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + x[j] /= tjjs + xj = math.Abs(x[j]) + } else { + for i := 0; i < n; i++ { + x[i] = 0 + } + x[j] = 1 + xj = 1 + scale = 0 + xmax = 0 + } + Skip1: + if xj > 1 { + rec := 1 / xj + if cnorm[j] > (bignum-xmax)*rec { + rec *= 0.5 + bi.Dscal(n, rec, x, 1) + scale *= rec + } + } else if xj*cnorm[j] > bignum-xmax { + bi.Dscal(n, 0.5, x, 1) + scale *= 0.5 + } + if upper { + if j > 0 { + bi.Daxpy(j, -x[j]*tscal, a[j:], lda, x, 1) + i := bi.Idamax(j, x, 1) + xmax = math.Abs(x[i]) + } + } else { + if j < n-1 { + bi.Daxpy(n-j-1, -x[j]*tscal, a[(j+1)*lda+j:], lda, x[j+1:], 1) + i := j + bi.Idamax(n-j-1, x[j+1:], 1) + xmax = math.Abs(x[i]) + } + } + } + } else { + for j := jfirst; j != jlast; j += jinc { + xj := math.Abs(x[j]) + uscal := tscal + rec := 1 / math.Max(xmax, 1) + var tjjs float64 + if cnorm[j] > (bignum-xj)*rec { + rec *= 0.5 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + } + tjj := math.Abs(tjjs) + if tjj > 1 { + rec = math.Min(1, rec*tjj) + uscal /= tjjs + } + if rec < 1 { + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + var sumj float64 + if uscal == 1 { + if upper { + sumj = bi.Ddot(j, a[j:], lda, x, 1) + } else if j < n-1 { + sumj = bi.Ddot(n-j-1, a[(j+1)*lda+j:], lda, x[j+1:], 1) + } + } else { + if upper { + for i := 0; i < j; i++ { + sumj += (a[i*lda+j] * uscal) * x[i] + } + } else if j < n { + for i := j + 1; i < n; i++ { + sumj += (a[i*lda+j] * uscal) * x[i] + } + } + } + if uscal == tscal { + x[j] -= sumj + xj := math.Abs(x[j]) + var tjjs float64 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + if tscal == 1 { + goto Skip2 + } + } + tjj := math.Abs(tjjs) + if tjj > smlnum { + if tjj < 1 { + if xj > tjj*bignum { + rec = 1 / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + x[j] /= tjjs + } else if tjj > 0 { + if xj > tjj*bignum { + rec = (tjj * bignum) / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + x[j] /= tjjs + } else { + for i := 0; i < n; i++ { + x[i] = 0 + } + x[j] = 1 + scale = 0 + xmax = 0 + } + } else { + x[j] = x[j]/tjjs - sumj + } + Skip2: + xmax = math.Max(xmax, math.Abs(x[j])) + } + } + scale /= tscal + if tscal != 1 { + bi.Dscal(n, 1/tscal, cnorm, 1) + } + return scale +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go new file mode 100644 index 00000000..f69b4285 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go @@ -0,0 +1,28 @@ +// Copyright ©2015 The gonum 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 gonum is a pure-go implementation of the LAPACK API. The LAPACK API defines +// a set of algorithms for advanced matrix operations. +// +// The function definitions and implementations follow that of the netlib reference +// implementation. Please see http://www.netlib.org/lapack/explore-html/ for more +// information, and http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html +// for more license information. +// +// Slice function arguments frequently represent vectors and matrices. The data +// layout is identical to that found in https://godoc.org/gonum.org/v1/gonum/blas/gonum. +// +// Most LAPACK functions are built on top the routines defined in the BLAS API, +// and as such the computation time for many LAPACK functions is +// dominated by BLAS calls. Here, BLAS is accessed through the +// the blas64 package (https://godoc.org/golang.org/v1/gonum/blas/blas64). In particular, +// this implies that an external BLAS library will be used if it is +// registered in blas64. +// +// The full LAPACK capability has not been implemented at present. The full +// API is very large, containing approximately 200 functions for double precision +// alone. Future additions will be focused on supporting the gonum matrix +// package (https://godoc.org/github.com/gonum/matrix/mat64), though pull requests +// with implementations and tests for LAPACK function are encouraged. +package gonum // import "gonum.org/v1/gonum/lapack/gonum" diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go new file mode 100644 index 00000000..728924f6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go @@ -0,0 +1,65 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorg2l generates an m×n matrix Q with orthonormal columns which is defined +// as the last n columns of a product of k elementary reflectors of order m. +// Q = H_{k-1} * ... * H_1 * H_0 +// See Dgelqf for more information. It must be that m >= n >= k. +// +// tau contains the scalar reflectors computed by Dgeqlf. tau must have length +// at least k, and Dorg2l will panic otherwise. +// +// work contains temporary memory, and must have length at least n. Dorg2l will +// panic otherwise. +// +// Dorg2l is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + if m < n { + panic(mLTN) + } + if k > n { + panic(kGTN) + } + if n == 0 { + return + } + + // Initialize columns 0:n-k to columns of the unit matrix. + for j := 0; j < n-k; j++ { + for l := 0; l < m; l++ { + a[l*lda+j] = 0 + } + a[(m-n+j)*lda+j] = 1 + } + + bi := blas64.Implementation() + for i := 0; i < k; i++ { + ii := n - k + i + + // Apply H_i to A[0:m-k+i, 0:n-k+i] from the left. + a[(m-n+ii)*lda+ii] = 1 + impl.Dlarf(blas.Left, m-n+ii+1, ii, a[ii:], lda, tau[i], a, lda, work) + bi.Dscal(m-n+ii, -tau[i], a[ii:], lda) + a[(m-n+ii)*lda+ii] = 1 - tau[i] + + // Set A[m-k+i:m, n-k+i+1] to zero. + for l := m - n + ii + 1; l < m; l++ { + a[l*lda+ii] = 0 + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go new file mode 100644 index 00000000..25f0ee54 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorg2r generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors as computed by Dgeqrf. +// Q = H_0 * H_1 * ... * H_{k-1} +// len(tau) >= k, 0 <= k <= n, 0 <= n <= m, len(work) >= n. +// Dorg2r will panic if these conditions are not met. +// +// Dorg2r is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + if k > n { + panic(kGTN) + } + if n > m { + panic(mLTN) + } + if len(work) < n { + panic(badWork) + } + if n == 0 { + return + } + bi := blas64.Implementation() + // Initialize columns k+1:n to columns of the unit matrix. + for l := 0; l < m; l++ { + for j := k; j < n; j++ { + a[l*lda+j] = 0 + } + } + for j := k; j < n; j++ { + a[j*lda+j] = 1 + } + for i := k - 1; i >= 0; i-- { + for i := range work { + work[i] = 0 + } + if i < n-1 { + a[i*lda+i] = 1 + impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tau[i], a[i*lda+i+1:], lda, work) + } + if i < m-1 { + bi.Dscal(m-i-1, -tau[i], a[(i+1)*lda+i:], lda) + } + a[i*lda+i] = 1 - tau[i] + for l := 0; l < i; l++ { + a[l*lda+i] = 0 + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go new file mode 100644 index 00000000..b8789661 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go @@ -0,0 +1,124 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/lapack" + +// Dorgbr generates one of the matrices Q or P^T computed by Dgebrd +// computed from the decomposition Dgebrd. See Dgebd2 for the description of +// Q and P^T. +// +// If vect == lapack.ApplyQ, then a is assumed to have been an m×k matrix and +// Q is of order m. If m >= k, then Dorgbr returns the first n columns of Q +// where m >= n >= k. If m < k, then Dorgbr returns Q as an m×m matrix. +// +// If vect == lapack.ApplyP, then A is assumed to have been a k×n matrix, and +// P^T is of order n. If k < n, then Dorgbr returns the first m rows of P^T, +// where n >= m >= k. If k >= n, then Dorgbr returns P^T as an n×n matrix. +// +// Dorgbr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + mn := min(m, n) + wantq := vect == lapack.ApplyQ + if wantq { + if m < n || n < min(m, k) || m < min(m, k) { + panic(badDims) + } + } else { + if n < m || m < min(n, k) || n < min(n, k) { + panic(badDims) + } + } + if wantq { + if m >= k { + checkMatrix(m, k, a, lda) + } else { + checkMatrix(m, m, a, lda) + } + } else { + if n >= k { + checkMatrix(k, n, a, lda) + } else { + checkMatrix(n, n, a, lda) + } + } + work[0] = 1 + if wantq { + if m >= k { + impl.Dorgqr(m, n, k, a, lda, tau, work, -1) + } else if m > 1 { + impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, -1) + } + } else { + if k < n { + impl.Dorglq(m, n, k, a, lda, tau, work, -1) + } else if n > 1 { + impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, -1) + } + } + lworkopt := int(work[0]) + lworkopt = max(lworkopt, mn) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < mn { + panic(badWork) + } + if m == 0 || n == 0 { + work[0] = 1 + return + } + if wantq { + // Form Q, determined by a call to Dgebrd to reduce an m×k matrix. + if m >= k { + impl.Dorgqr(m, n, k, a, lda, tau, work, lwork) + } else { + // Shift the vectors which define the elementary reflectors one + // column to the right, and set the first row and column of Q to + // those of the unit matrix. + for j := m - 1; j >= 1; j-- { + a[j] = 0 + for i := j + 1; i < m; i++ { + a[i*lda+j] = a[i*lda+j-1] + } + } + a[0] = 1 + for i := 1; i < m; i++ { + a[i*lda] = 0 + } + if m > 1 { + // Form Q[1:m-1, 1:m-1] + impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, lwork) + } + } + } else { + // Form P^T, determined by a call to Dgebrd to reduce a k×n matrix. + if k < n { + impl.Dorglq(m, n, k, a, lda, tau, work, lwork) + } else { + // Shift the vectors which define the elementary reflectors one + // row downward, and set the first row and column of P^T to + // those of the unit matrix. + a[0] = 1 + for i := 1; i < n; i++ { + a[i*lda] = 0 + } + for j := 1; j < n; j++ { + for i := j - 1; i >= 1; i-- { + a[i*lda+j] = a[(i-1)*lda+j] + } + a[j] = 0 + } + if n > 1 { + impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) + } + } + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go new file mode 100644 index 00000000..dcdc0dec --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go @@ -0,0 +1,93 @@ +// Copyright ©2016 The gonum 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 gonum + +// Dorghr generates an n×n orthogonal matrix Q which is defined as the product +// of ihi-ilo elementary reflectors: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// +// a and lda represent an n×n matrix that contains the elementary reflectors, as +// returned by Dgehrd. On return, a is overwritten by the n×n orthogonal matrix +// Q. Q will be equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo = 0, ihi = -1, if n == 0. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length n-1. +// +// work must have length at least max(1,lwork) and lwork must be at least +// ihi-ilo. For optimum performance lwork must be at least (ihi-ilo)*nb where nb +// is the optimal blocksize. On return, work[0] will contain the optimal value +// of lwork. +// +// If lwork == -1, instead of performing Dorghr, only the optimal value of lwork +// will be stored into work[0]. +// +// If any requirement on input sizes is not met, Dorghr will panic. +// +// Dorghr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + nh := ihi - ilo + switch { + case ilo < 0 || max(1, n) <= ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, nh) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + lwkopt := max(1, nh) * impl.Ilaenv(1, "DORGQR", " ", nh, nh, nh, -1) + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return + } + + // Shift the vectors which define the elementary reflectors one column + // to the right. + for i := ilo + 2; i < ihi+1; i++ { + copy(a[i*lda+ilo+1:i*lda+i], a[i*lda+ilo:i*lda+i-1]) + } + // Set the first ilo+1 and the last n-ihi-1 rows and columns to those of + // the identity matrix. + for i := 0; i < ilo+1; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = 1 + } + for i := ilo + 1; i < ihi+1; i++ { + for j := 0; j <= ilo; j++ { + a[i*lda+j] = 0 + } + for j := i; j < n; j++ { + a[i*lda+j] = 0 + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = 1 + } + if nh > 0 { + // Generate Q[ilo+1:ihi+1,ilo+1:ihi+1]. + impl.Dorgqr(nh, nh, nh, a[(ilo+1)*lda+ilo+1:], lda, tau[ilo:ihi], work, lwork) + } + work[0] = float64(lwkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go new file mode 100644 index 00000000..3cdc10b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go @@ -0,0 +1,63 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorgl2 generates an m×n matrix Q with orthonormal rows defined by the +// first m rows product of elementary reflectors as computed by Dgelqf. +// Q = H_0 * H_1 * ... * H_{k-1} +// len(tau) >= k, 0 <= k <= m, 0 <= m <= n, len(work) >= m. +// Dorgl2 will panic if these conditions are not met. +// +// Dorgl2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if k > m { + panic(kGTM) + } + if k > m { + panic(kGTM) + } + if m > n { + panic(nLTM) + } + if len(work) < m { + panic(badWork) + } + if m == 0 { + return + } + bi := blas64.Implementation() + if k < m { + for i := k; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + } + for j := k; j < m; j++ { + a[j*lda+j] = 1 + } + } + for i := k - 1; i >= 0; i-- { + if i < n-1 { + if i < m-1 { + a[i*lda+i] = 1 + impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tau[i], a[(i+1)*lda+i:], lda, work) + } + bi.Dscal(n-i-1, -tau[i], a[i*lda+i+1:], 1) + } + a[i*lda+i] = 1 - tau[i] + for l := 0; l < i; l++ { + a[i*lda+l] = 0 + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go new file mode 100644 index 00000000..0535027b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorglq generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors as computed by Dgelqf. +// Q = H_0 * H_1 * ... * H_{k-1} +// Dorglq is the blocked version of Dorgl2 that makes greater use of level-3 BLAS +// routines. +// +// len(tau) >= k, 0 <= k <= n, and 0 <= n <= m. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= m, and the amount of blocking is limited by the usable length. +// If lwork == -1, instead of computing Dorglq the optimal work length is stored +// into work[0]. +// +// Dorglq will panic if the conditions on input values are not met. +// +// Dorglq is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DORGLQ", " ", m, n, k, -1) + // work is treated as an n×nb matrix + if lwork == -1 { + work[0] = float64(max(1, m) * nb) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > m { + panic(kGTM) + } + if m > n { + panic(nLTM) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + if m == 0 { + return + } + nbmin := 2 // Minimum number of blocks + var nx int // Minimum number of rows + iws := m // Length of work needed + var ldwork int + if nb > 1 && nb < k { + nx = max(0, impl.Ilaenv(3, "DORGLQ", " ", m, n, k, -1)) + if nx < k { + ldwork = nb + iws = m * ldwork + if lwork < iws { + nb = lwork / m + ldwork = nb + nbmin = max(2, impl.Ilaenv(2, "DORGLQ", " ", m, n, k, -1)) + } + } + } + var ki, kk int + if nb >= nbmin && nb < k && nx < k { + // The first kk rows are handled by the blocked method. + // Note: lapack has nx here, but this means the last nx rows are handled + // serially which could be quite different than nb. + ki = ((k - nb - 1) / nb) * nb + kk = min(k, ki+nb) + for i := kk; i < m; i++ { + for j := 0; j < kk; j++ { + a[i*lda+j] = 0 + } + } + } + if kk < m { + // Perform the operation on colums kk to the end. + impl.Dorgl2(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) + } + if kk == 0 { + return + } + // Perform the operation on column-blocks + for i := ki; i >= 0; i -= nb { + ib := min(nb, k-i) + if i+ib < m { + impl.Dlarft(lapack.Forward, lapack.RowWise, + n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + + impl.Dlarfb(blas.Right, blas.Trans, lapack.Forward, lapack.RowWise, + m-i-ib, n-i, ib, + a[i*lda+i:], lda, + work, ldwork, + a[(i+ib)*lda+i:], lda, + work[ib*ldwork:], ldwork) + } + impl.Dorgl2(ib, n-i, ib, a[i*lda+i:], lda, tau[i:], work) + for l := i; l < i+ib; l++ { + for j := 0; j < i; j++ { + a[l*lda+j] = 0 + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go new file mode 100644 index 00000000..f13bf727 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorgql generates the m×n matrix Q with orthonormal columns defined as the +// last n columns of a product of k elementary reflectors of order m +// Q = H_{k-1} * ... * H_1 * H_0. +// +// It must hold that +// 0 <= k <= n <= m, +// and Dorgql will panic otherwise. +// +// On entry, the (n-k+i)-th column of A must contain the vector which defines +// the elementary reflector H_i, for i=0,...,k-1, and tau[i] must contain its +// scalar factor. On return, a contains the m×n matrix Q. +// +// tau must have length at least k, and Dorgql will panic otherwise. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), otherwise Dorgql will panic. For optimum performance lwork must +// be a sufficiently large multiple of n. +// +// If lwork == -1, instead of computing Dorgql the optimal work length is stored +// into work[0]. +// +// Dorgql is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case n < 0: + panic(nLT0) + case m < n: + panic(mLTN) + case k < 0: + panic(kLT0) + case k > n: + panic(kGTN) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + } + + if n == 0 { + work[0] = 1 + return + } + + nb := impl.Ilaenv(1, "DORGQL", " ", m, n, k, -1) + if lwork == -1 { + work[0] = float64(n * nb) + return + } + + nbmin := 2 + var nx, ldwork int + iws := n + if nb > 1 && nb < k { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(3, "DORGQL", " ", m, n, k, -1)) + if nx < k { + // Determine if workspace is large enough for blocked code. + iws = n * nb + if lwork < iws { + // Not enough workspace to use optimal nb: reduce nb and determine + // the minimum value of nb. + nb = lwork / n + nbmin = max(2, impl.Ilaenv(2, "DORGQL", " ", m, n, k, -1)) + } + ldwork = nb + } + } + + var kk int + if nb >= nbmin && nb < k && nx < k { + // Use blocked code after the first block. The last kk columns are handled + // by the block method. + kk = min(k, ((k-nx+nb-1)/nb)*nb) + + // Set A(m-kk:m, 0:n-kk) to zero. + for i := m - kk; i < m; i++ { + for j := 0; j < n-kk; j++ { + a[i*lda+j] = 0 + } + } + } + + // Use unblocked code for the first or only block. + impl.Dorg2l(m-kk, n-kk, k-kk, a, lda, tau, work) + if kk > 0 { + // Use blocked code. + for i := k - kk; i < k; i += nb { + ib := min(nb, k-i) + if n-k+i > 0 { + // Form the triangular factor of the block reflector + // H = H_{i+ib-1} * ... * H_{i+1} * H_i. + impl.Dlarft(lapack.Backward, lapack.ColumnWise, m-k+i+ib, ib, + a[n-k+i:], lda, tau[i:], work, ldwork) + + // Apply H to A[0:m-k+i+ib, 0:n-k+i] from the left. + impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Backward, lapack.ColumnWise, + m-k+i+ib, n-k+i, ib, a[n-k+i:], lda, work, ldwork, + a, lda, work[ib*ldwork:], ldwork) + } + + // Apply H to rows 0:m-k+i+ib of current block. + impl.Dorg2l(m-k+i+ib, ib, ib, a[n-k+i:], lda, tau[i:], work) + + // Set rows m-k+i+ib:m of current block to zero. + for j := n - k + i; j < n-k+i+ib; j++ { + for l := m - k + i + ib; l < m; l++ { + a[l*lda+j] = 0 + } + } + } + } + work[0] = float64(iws) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go new file mode 100644 index 00000000..0d525d8a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go @@ -0,0 +1,120 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorgqr generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1} +// as computed by Dgeqrf. +// Dorgqr is the blocked version of Dorg2r that makes greater use of level-3 BLAS +// routines. +// +// The length of tau must be at least k, and the length of work must be at least n. +// It also must be that 0 <= k <= n and 0 <= n <= m. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= n, and the amount of blocking is limited by the usable +// length. If lwork == -1, instead of computing Dorgqr the optimal work length +// is stored into work[0]. +// +// Dorgqr will panic if the conditions on input values are not met. +// +// Dorgqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DORGQR", " ", m, n, k, -1) + // work is treated as an n×nb matrix + if lwork == -1 { + work[0] = float64(max(1, n) * nb) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > n { + panic(kGTN) + } + if n > m { + panic(mLTN) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < n { + panic(badWork) + } + if n == 0 { + return + } + nbmin := 2 // Minimum number of blocks + var nx int // Minimum number of rows + iws := n // Length of work needed + var ldwork int + if nb > 1 && nb < k { + nx = max(0, impl.Ilaenv(3, "DORGQR", " ", m, n, k, -1)) + if nx < k { + ldwork = nb + iws = n * ldwork + if lwork < iws { + nb = lwork / n + ldwork = nb + nbmin = max(2, impl.Ilaenv(2, "DORGQR", " ", m, n, k, -1)) + } + } + } + var ki, kk int + if nb >= nbmin && nb < k && nx < k { + // The first kk columns are handled by the blocked method. + // Note: lapack has nx here, but this means the last nx rows are handled + // serially which could be quite different than nb. + ki = ((k - nb - 1) / nb) * nb + kk = min(k, ki+nb) + for j := kk; j < n; j++ { + for i := 0; i < kk; i++ { + a[i*lda+j] = 0 + } + } + } + if kk < n { + // Perform the operation on colums kk to the end. + impl.Dorg2r(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) + } + if kk == 0 { + return + } + // Perform the operation on column-blocks + for i := ki; i >= 0; i -= nb { + ib := min(nb, k-i) + if i+ib < n { + impl.Dlarft(lapack.Forward, lapack.ColumnWise, + m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + + impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Forward, lapack.ColumnWise, + m-i, n-i-ib, ib, + a[i*lda+i:], lda, + work, ldwork, + a[i*lda+i+ib:], lda, + work[ib*ldwork:], ldwork) + } + impl.Dorg2r(m-i, ib, ib, a[i*lda+i:], lda, tau[i:], work) + // Set rows 0:i-1 of current block to zero + for j := i; j < i+ib; j++ { + for l := 0; l < i; l++ { + a[l*lda+j] = 0 + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go new file mode 100644 index 00000000..39b7df29 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dorgtr generates a real orthogonal matrix Q which is defined as the product +// of n-1 elementary reflectors of order n as returned by Dsytrd. +// +// The construction of Q depends on the value of uplo: +// Q = H_{n-1} * ... * H_1 * H_0 if uplo == blas.Upper +// Q = H_0 * H_1 * ... * H_{n-1} if uplo == blas.Lower +// where H_i is constructed from the elementary reflectors as computed by Dsytrd. +// See the documentation for Dsytrd for more information. +// +// tau must have length at least n-1, and Dorgtr will panic otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= max(1,n-1), and Dorgtr will panic otherwise. The amount of blocking +// is limited by the usable length. +// If lwork == -1, instead of computing Dorgtr the optimal work length is stored +// into work[0]. +// +// Dorgtr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(badWork) + } + if lwork < n-1 && lwork != -1 { + panic(badWork) + } + upper := uplo == blas.Upper + if !upper && uplo != blas.Lower { + panic(badUplo) + } + + if n == 0 { + work[0] = 1 + return + } + + var nb int + if upper { + nb = impl.Ilaenv(1, "DORGQL", " ", n-1, n-1, n-1, -1) + } else { + nb = impl.Ilaenv(1, "DORGQR", " ", n-1, n-1, n-1, -1) + } + lworkopt := max(1, n-1) * nb + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + if upper { + // Q was determined by a call to Dsytrd with uplo == blas.Upper. + // Shift the vectors which define the elementary reflectors one column + // to the left, and set the last row and column of Q to those of the unit + // matrix. + for j := 0; j < n-1; j++ { + for i := 0; i < j; i++ { + a[i*lda+j] = a[i*lda+j+1] + } + a[(n-1)*lda+j] = 0 + } + for i := 0; i < n-1; i++ { + a[i*lda+n-1] = 0 + } + a[(n-1)*lda+n-1] = 1 + + // Generate Q[0:n-1, 0:n-1]. + impl.Dorgql(n-1, n-1, n-1, a, lda, tau, work, lwork) + } else { + // Q was determined by a call to Dsytrd with uplo == blas.Upper. + // Shift the vectors which define the elementary reflectors one column + // to the right, and set the first row and column of Q to those of the unit + // matrix. + for j := n - 1; j > 0; j-- { + a[j] = 0 + for i := j + 1; i < n; i++ { + a[i*lda+j] = a[i*lda+j-1] + } + } + a[0] = 1 + for i := 1; i < n; i++ { + a[i*lda] = 0 + } + if n > 1 { + // Generate Q[1:n, 1:n]. + impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) + } + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go new file mode 100644 index 00000000..15864fcc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go @@ -0,0 +1,88 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dorm2r multiplies a general matrix C by an orthogonal matrix from a QR factorization +// determined by Dgeqrf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right +// a is of size n×k. +// +// tau contains the Householder factors and is of length at least k and this function +// will panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dorm2r is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + // Q is m x m + checkMatrix(m, k, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + // Q is n x n + checkMatrix(n, k, a, lda) + if len(work) < m { + panic(badWork) + } + } + checkMatrix(m, n, c, ldc) + if m == 0 || n == 0 || k == 0 { + return + } + if len(tau) < k { + panic(badTau) + } + if left { + if notran { + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + return + } + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + return + } + if notran { + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + return + } + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go new file mode 100644 index 00000000..6518c186 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go @@ -0,0 +1,158 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormbr applies a multiplicative update to the matrix C based on a +// decomposition computed by Dgebrd. +// +// Dormbr overwrites the m×n matrix C with +// Q * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.NoTrans +// C * Q if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.NoTrans +// Q^T * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.Trans +// C * Q^T if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.Trans +// +// P * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.NoTrans +// C * P if vect == lapack.ApplyP, side == blas.Right, and trans == blas.NoTrans +// P^T * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.Trans +// C * P^T if vect == lapack.ApplyP, side == blas.Right, and trans == blas.Trans +// where P and Q are the orthogonal matrices determined by Dgebrd when reducing +// a matrix A to bidiagonal form: A = Q * B * P^T. See Dgebrd for the +// definitions of Q and P. +// +// If vect == lapack.ApplyQ, A is assumed to have been an nq×k matrix, while if +// vect == lapack.ApplyP, A is assumed to have been a k×nq matrix. nq = m if +// side == blas.Left, while nq = n if side == blas.Right. +// +// tau must have length min(nq,k), and Dormbr will panic otherwise. tau contains +// the elementary reflectors to construct Q or P depending on the value of +// vect. +// +// work must have length at least max(1,lwork), and lwork must be either -1 or +// at least max(1,n) if side == blas.Left, and at least max(1,m) if side == +// blas.Right. For optimum performance lwork should be at least n*nb if side == +// blas.Left, and at least m*nb if side == blas.Right, where nb is the optimal +// block size. On return, work[0] will contain the optimal value of lwork. +// +// If lwork == -1, the function only calculates the optimal value of lwork and +// returns it in work[0]. +// +// Dormbr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.NoTrans && trans != blas.Trans { + panic(badTrans) + } + if vect != lapack.ApplyP && vect != lapack.ApplyQ { + panic(badDecompUpdate) + } + nq := n + nw := m + if side == blas.Left { + nq = m + nw = n + } + if vect == lapack.ApplyQ { + checkMatrix(nq, min(nq, k), a, lda) + } else { + checkMatrix(min(nq, k), nq, a, lda) + } + if len(tau) < min(nq, k) { + panic(badTau) + } + checkMatrix(m, n, c, ldc) + if len(work) < lwork { + panic(shortWork) + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + + applyQ := vect == lapack.ApplyQ + left := side == blas.Left + var nb int + + // The current implementation does not use opts, but a future change may + // use these options so construct them. + var opts string + if side == blas.Left { + opts = "L" + } else { + opts = "R" + } + if trans == blas.Trans { + opts += "T" + } else { + opts += "N" + } + if applyQ { + if left { + nb = impl.Ilaenv(1, "DORMQR", opts, m-1, n, m-1, -1) + } else { + nb = impl.Ilaenv(1, "DORMQR", opts, m, n-1, n-1, -1) + } + } else { + if left { + nb = impl.Ilaenv(1, "DORMLQ", opts, m-1, n, m-1, -1) + } else { + nb = impl.Ilaenv(1, "DORMLQ", opts, m, n-1, n-1, -1) + } + } + lworkopt := max(1, nw) * nb + if lwork == -1 { + work[0] = float64(lworkopt) + } + if applyQ { + // Change the operation to get Q depending on the size of the initial + // matrix to Dgebrd. The size matters due to the storage location of + // the off-diagonal elements. + if nq >= k { + impl.Dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork) + } else if nq > 1 { + mi := m + ni := n - 1 + i1 := 0 + i2 := 1 + if left { + mi = m - 1 + ni = n + i1 = 1 + i2 = 0 + } + impl.Dormqr(side, trans, mi, ni, nq-1, a[1*lda:], lda, tau[:nq-1], c[i1*ldc+i2:], ldc, work, lwork) + } + work[0] = float64(lworkopt) + return + } + transt := blas.Trans + if trans == blas.Trans { + transt = blas.NoTrans + } + // Change the operation to get P depending on the size of the initial + // matrix to Dgebrd. The size matters due to the storage location of + // the off-diagonal elements. + if nq > k { + impl.Dormlq(side, transt, m, n, k, a, lda, tau, c, ldc, work, lwork) + } else if nq > 1 { + mi := m + ni := n - 1 + i1 := 0 + i2 := 1 + if left { + mi = m - 1 + ni = n + i1 = 1 + i2 = 0 + } + impl.Dormlq(side, transt, mi, ni, nq-1, a[1:], lda, tau, c[i1*ldc+i2:], ldc, work, lwork) + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go new file mode 100644 index 00000000..fccb5738 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go @@ -0,0 +1,121 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dormhr multiplies an m×n general matrix C with an nq×nq orthogonal matrix Q +// Q * C, if side == blas.Left and trans == blas.NoTrans, +// Q^T * C, if side == blas.Left and trans == blas.Trans, +// C * Q, if side == blas.Right and trans == blas.NoTrans, +// C * Q^T, if side == blas.Right and trans == blas.Trans, +// where nq == m if side == blas.Left and nq == n if side == blas.Right. +// +// Q is defined implicitly as the product of ihi-ilo elementary reflectors, as +// returned by Dgehrd: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Q is equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < m, if m > 0 and side == blas.Left, +// ilo = 0 and ihi = -1, if m = 0 and side == blas.Left, +// 0 <= ilo <= ihi < n, if n > 0 and side == blas.Right, +// ilo = 0 and ihi = -1, if n = 0 and side == blas.Right. +// +// a and lda represent an m×m matrix if side == blas.Left and an n×n matrix if +// side == blas.Right. The matrix contains vectors which define the elementary +// reflectors, as returned by Dgehrd. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length m-1 if side == blas.Left and n-1 if side == +// blas.Right. +// +// c and ldc represent the m×n matrix C. On return, c is overwritten by the +// product with Q. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), if side == blas.Left, and max(1,m), if side == blas.Right. For +// optimum performance lwork should be at least n*nb if side == blas.Left and +// m*nb if side == blas.Right, where nb is the optimal block size. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dormhr, only the optimal value of lwork +// will be stored in work[0]. +// +// If any requirement on input sizes is not met, Dormhr will panic. +// +// Dormhr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var ( + nq int // The order of Q. + nw int // The minimum length of work. + ) + switch side { + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + default: + panic(badSide) + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case ilo < 0 || max(1, nq) <= ilo: + panic(badIlo) + case ihi < min(ilo, nq-1) || nq <= ihi: + panic(badIhi) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, c, ldc) + checkMatrix(nq, nq, a, lda) + if len(tau) != nq-1 && nq > 0 { + panic(badTau) + } + + } + + nh := ihi - ilo + var nb int + if side == blas.Left { + opts := "LN" + if trans == blas.Trans { + opts = "LT" + } + nb = impl.Ilaenv(1, "DORMQR", opts, nh, n, nh, -1) + } else { + opts := "RN" + if trans == blas.Trans { + opts = "RT" + } + nb = impl.Ilaenv(1, "DORMQR", opts, m, nh, nh, -1) + } + lwkopt := max(1, nw) * nb + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + if m == 0 || n == 0 || nh == 0 { + work[0] = 1 + return + } + if side == blas.Left { + impl.Dormqr(side, trans, nh, n, nh, a[(ilo+1)*lda+ilo:], lda, + tau[ilo:ihi], c[(ilo+1)*ldc:], ldc, work, lwork) + } else { + impl.Dormqr(side, trans, m, nh, nh, a[(ilo+1)*lda+ilo:], lda, + tau[ilo:ihi], c[ilo+1:], ldc, work, lwork) + } + work[0] = float64(lwkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go new file mode 100644 index 00000000..7c5f1950 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dorml2 multiplies a general matrix C by an orthogonal matrix from an LQ factorization +// determined by Dgelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right +// a is of size k×n. +// +// tau contains the Householder factors and is of length at least k and this function will +// panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dorml2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + checkMatrix(k, m, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + checkMatrix(k, n, a, lda) + if len(work) < m { + panic(badWork) + } + } + checkMatrix(m, n, c, ldc) + if m == 0 || n == 0 || k == 0 { + return + } + switch { + case left && notran: + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + + case left && !notran: + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + + case !left && notran: + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + + case !left && !notran: + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go new file mode 100644 index 00000000..12219d20 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go @@ -0,0 +1,159 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormlq multiplies the matrix C by the orthogonal matrix Q defined by the +// slices a and tau. A and tau are as returned from Dgelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right +// A is of size k×n. This uses a blocked algorithm. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, +// and this function will panic otherwise. +// Dormlq uses a block algorithm, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dormlq, +// the optimal work length will be stored into work[0]. +// +// tau contains the Householder scales and must have length at least k, and +// this function will panic otherwise. +func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + left := side == blas.Left + if left { + checkMatrix(k, m, a, lda) + } else { + checkMatrix(k, n, a, lda) + } + checkMatrix(m, n, c, ldc) + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + nw := m + if left { + nw = n + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + + if m == 0 || n == 0 || k == 0 { + work[0] = 1 + return + } + + const ( + nbmax = 64 + ldt = nbmax + tsize = nbmax * ldt + ) + opts := string(side) + string(trans) + nb := min(nbmax, impl.Ilaenv(1, "DORMLQ", opts, m, n, k, -1)) + lworkopt := max(1, nw)*nb + tsize + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nbmin := 2 + if 1 < nb && nb < k { + iws := nw*nb + tsize + if lwork < iws { + nb = (lwork - tsize) / nw + nbmin = max(2, impl.Ilaenv(2, "DORMLQ", opts, m, n, k, -1)) + } + } + if nb < nbmin || k <= nb { + // Call unblocked code. + impl.Dorml2(side, trans, m, n, k, a, lda, tau, c, ldc, work) + work[0] = float64(lworkopt) + return + } + + t := work[:tsize] + wrk := work[tsize:] + ldwrk := nb + + notran := trans == blas.NoTrans + transt := blas.NoTrans + if notran { + transt = blas.Trans + } + + switch { + case left && notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, + a[i*lda+i:], lda, + t, ldt, + c[i*ldc:], ldc, + wrk, ldwrk) + } + + case left && !notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, + a[i*lda+i:], lda, + t, ldt, + c[i*ldc:], ldc, + wrk, ldwrk) + } + + case !left && notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, + a[i*lda+i:], lda, + t, ldt, + c[i:], ldc, + wrk, ldwrk) + } + + case !left && !notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, + a[i*lda+i:], lda, + t, ldt, + c[i:], ldc, + wrk, ldwrk) + } + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go new file mode 100644 index 00000000..9a02b90d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go @@ -0,0 +1,167 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormqr multiplies an m×n matrix C by an orthogonal matrix Q as +// C = Q * C, if side == blas.Left and trans == blas.NoTrans, +// C = Q^T * C, if side == blas.Left and trans == blas.Trans, +// C = C * Q, if side == blas.Right and trans == blas.NoTrans, +// C = C * Q^T, if side == blas.Right and trans == blas.Trans, +// where Q is defined as the product of k elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1}. +// +// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. +// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. +// The ith column of A contains the vector which defines the elementary +// reflector H_i and tau[i] contains its scalar factor. tau must have length k +// and Dormqr will panic otherwise. Dgeqrf returns A and tau in the required +// form. +// +// work must have length at least max(1,lwork), and lwork must be at least n if +// side == blas.Left and at least m if side == blas.Right, otherwise Dormqr will +// panic. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= m if side == blas.Left and lwork >= n if side == +// blas.Right, and this function will panic otherwise. Larger values of lwork +// will generally give better performance. On return, work[0] will contain the +// optimal value of lwork. +// +// If lwork is -1, instead of performing Dormqr, the optimal workspace size will +// be stored into work[0]. +func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var nq, nw int + switch side { + default: + panic(badSide) + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case m < 0 || n < 0: + panic(negDimension) + case k < 0 || nq < k: + panic("lapack: invalid value of k") + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(nq, k, a, lda) + checkMatrix(m, n, c, ldc) + if len(tau) != k { + panic(badTau) + } + } + + if m == 0 || n == 0 || k == 0 { + work[0] = 1 + return + } + + const ( + nbmax = 64 + ldt = nbmax + tsize = nbmax * ldt + ) + opts := string(side) + string(trans) + nb := min(nbmax, impl.Ilaenv(1, "DORMQR", opts, m, n, k, -1)) + lworkopt := max(1, nw)*nb + tsize + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nbmin := 2 + if 1 < nb && nb < k { + if lwork < nw*nb+tsize { + nb = (lwork - tsize) / nw + nbmin = max(2, impl.Ilaenv(2, "DORMQR", opts, m, n, k, -1)) + } + } + + if nb < nbmin || k <= nb { + // Call unblocked code. + impl.Dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work) + work[0] = float64(lworkopt) + return + } + + var ( + ldwork = nb + left = side == blas.Left + notran = trans == blas.NoTrans + ) + switch { + case left && notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i*ldc:], ldc, + work[tsize:], ldwork) + } + + case left && !notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i*ldc:], ldc, + work[tsize:], ldwork) + } + + case !left && notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i:], ldc, + work[tsize:], ldwork) + } + + case !left && !notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i:], ldc, + work[tsize:], ldwork) + } + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go new file mode 100644 index 00000000..c867e8e8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go @@ -0,0 +1,93 @@ +// Copyright ©2015 The gonum 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 gonum + +import "gonum.org/v1/gonum/blas" + +// Dormr2 multiplies a general matrix C by an orthogonal matrix from a RQ factorization +// determined by Dgerqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of size k×m, and if side == blas.Right +// a is of size k×n. +// +// tau contains the Householder factors and is of length at least k and this function +// will panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dormr2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormr2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + if k > m { + panic(kGTM) + } + checkMatrix(k, m, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + if k > n { + panic(kGTN) + } + checkMatrix(k, n, a, lda) + if len(work) < m { + panic(badWork) + } + } + if len(tau) < k { + panic(badTau) + } + checkMatrix(m, n, c, ldc) + + if m == 0 || n == 0 || k == 0 { + return + } + if left { + if notran { + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+(m-k+i)] + a[i*lda+(m-k+i)] = 1 + impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(m-k+i)] = aii + } + return + } + for i := 0; i < k; i++ { + aii := a[i*lda+(m-k+i)] + a[i*lda+(m-k+i)] = 1 + impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(m-k+i)] = aii + } + return + } + if notran { + for i := 0; i < k; i++ { + aii := a[i*lda+(n-k+i)] + a[i*lda+(n-k+i)] = 1 + impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(n-k+i)] = aii + } + return + } + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+(n-k+i)] + a[i*lda+(n-k+i)] = 1 + impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(n-k+i)] = aii + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go new file mode 100644 index 00000000..6cc5f38f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go @@ -0,0 +1,97 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpbtf2 computes the Cholesky factorization of a symmetric positive banded +// matrix ab. The matrix ab is n×n with kd diagonal bands. The Cholesky +// factorization computed is +// A = U^T * U if ul == blas.Upper +// A = L * L^T if ul == blas.Lower +// ul also specifies the storage of ab. If ul == blas.Upper, then +// ab is stored as an upper-triangular banded matrix with kd super-diagonals, +// and if ul == blas.Lower, ab is stored as a lower-triangular banded matrix +// with kd sub-diagonals. On exit, the banded matrix U or L is stored in-place +// into ab depending on the value of ul. Dpbtf2 returns whether the factorization +// was successfully completed. +// +// The band storage scheme is illustrated below when n = 6, and kd = 2. +// The resulting Cholesky decomposition is stored in the same elements as the +// input band matrix (a11 becomes u11 or l11, etc.). +// +// ul = blas.Upper +// a11 a12 a13 +// a22 a23 a24 +// a33 a34 a35 +// a44 a45 a46 +// a55 a56 * +// a66 * * +// +// ul = blas.Lower +// * * a11 +// * a21 a22 +// a31 a32 a33 +// a42 a43 a44 +// a53 a54 a55 +// a64 a65 a66 +// +// Dpbtf2 is the unblocked version of the algorithm, see Dpbtrf for the blocked +// version. +// +// Dpbtf2 is an internal routine, exported for testing purposes. +func (Implementation) Dpbtf2(ul blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) { + if ul != blas.Upper && ul != blas.Lower { + panic(badUplo) + } + checkSymBanded(ab, n, kd, ldab) + if n == 0 { + return + } + bi := blas64.Implementation() + kld := max(1, ldab-1) + if ul == blas.Upper { + for j := 0; j < n; j++ { + // Compute U(J,J) and test for non positive-definiteness. + ajj := ab[j*ldab] + if ajj <= 0 { + return false + } + ajj = math.Sqrt(ajj) + ab[j*ldab] = ajj + // Compute elements j+1:j+kn of row J and update the trailing submatrix + // within the band. + kn := min(kd, n-j-1) + if kn > 0 { + bi.Dscal(kn, 1/ajj, ab[j*ldab+1:], 1) + bi.Dsyr(blas.Upper, kn, -1, ab[j*ldab+1:], 1, ab[(j+1)*ldab:], kld) + } + } + return true + } + for j := 0; j < n; j++ { + // Compute L(J,J) and test for non positive-definiteness. + ajj := ab[j*ldab+kd] + if ajj <= 0 { + return false + } + ajj = math.Sqrt(ajj) + ab[j*ldab+kd] = ajj + + // Compute elements J+1:J+KN of column J and update the trailing submatrix + // within the band. + kn := min(kd, n-j-1) + if kn > 0 { + bi.Dscal(kn, 1/ajj, ab[(j+1)*ldab+kd-1:], kld) + bi.Dsyr(blas.Lower, kn, -1, ab[(j+1)*ldab+kd-1:], kld, ab[(j+1)*ldab+kd:], kld) + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go new file mode 100644 index 00000000..ce85bd0e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go @@ -0,0 +1,76 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpocon estimates the reciprocal of the condition number of a positive-definite +// matrix A given the Cholesky decomposition of A. The condition number computed +// is based on the 1-norm and the ∞-norm. +// +// anorm is the 1-norm and the ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 3*n and Dpocon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dpocon will panic otherwise. +func (impl Implementation) Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + var rcond float64 + if n == 0 { + return 1 + } + if anorm == 0 { + return rcond + } + + bi := blas64.Implementation() + var ainvnm float64 + smlnum := dlamchS + upper := uplo == blas.Upper + var kase int + var normin bool + isave := new([3]int) + var sl, su float64 + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / ainvnm) / anorm + } + return rcond + } + if upper { + sl = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + normin = true + su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + } else { + sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + normin = true + su = impl.Dlatrs(blas.Lower, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + } + scale := sl * su + if scale != 1 { + ix := bi.Idamax(n, work, 1) + if scale == 0 || scale < math.Abs(work[ix])*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go new file mode 100644 index 00000000..a8891988 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpotf2 computes the Cholesky decomposition of the symmetric positive definite +// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, +// and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T +// is computed and stored in-place into a. If a is not positive definite, false +// is returned. This is the unblocked version of the algorithm. +// +// Dpotf2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { + if ul != blas.Upper && ul != blas.Lower { + panic(badUplo) + } + checkMatrix(n, n, a, lda) + + if n == 0 { + return true + } + + bi := blas64.Implementation() + if ul == blas.Upper { + for j := 0; j < n; j++ { + ajj := a[j*lda+j] + if j != 0 { + ajj -= bi.Ddot(j, a[j:], lda, a[j:], lda) + } + if ajj <= 0 || math.IsNaN(ajj) { + a[j*lda+j] = ajj + return false + } + ajj = math.Sqrt(ajj) + a[j*lda+j] = ajj + if j < n-1 { + bi.Dgemv(blas.Trans, j, n-j-1, + -1, a[j+1:], lda, a[j:], lda, + 1, a[j*lda+j+1:], 1) + bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) + } + } + return true + } + for j := 0; j < n; j++ { + ajj := a[j*lda+j] + if j != 0 { + ajj -= bi.Ddot(j, a[j*lda:], 1, a[j*lda:], 1) + } + if ajj <= 0 || math.IsNaN(ajj) { + a[j*lda+j] = ajj + return false + } + ajj = math.Sqrt(ajj) + a[j*lda+j] = ajj + if j < n-1 { + bi.Dgemv(blas.NoTrans, n-j-1, j, + -1, a[(j+1)*lda:], lda, a[j*lda:], 1, + 1, a[(j+1)*lda+j:], lda) + bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go new file mode 100644 index 00000000..a942259a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpotrf computes the Cholesky decomposition of the symmetric positive definite +// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, +// and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T +// is computed and stored in-place into a. If a is not positive definite, false +// is returned. This is the blocked version of the algorithm. +func (impl Implementation) Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { + if ul != blas.Upper && ul != blas.Lower { + panic(badUplo) + } + checkMatrix(n, n, a, lda) + + if n == 0 { + return true + } + + nb := impl.Ilaenv(1, "DPOTRF", string(ul), n, -1, -1, -1) + if nb <= 1 || n <= nb { + return impl.Dpotf2(ul, n, a, lda) + } + bi := blas64.Implementation() + if ul == blas.Upper { + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dsyrk(blas.Upper, blas.Trans, jb, j, + -1, a[j:], lda, + 1, a[j*lda+j:], lda) + ok = impl.Dpotf2(blas.Upper, jb, a[j*lda+j:], lda) + if !ok { + return ok + } + if j+jb < n { + bi.Dgemm(blas.Trans, blas.NoTrans, jb, n-j-jb, j, + -1, a[j:], lda, a[j+jb:], lda, + 1, a[j*lda+j+jb:], lda) + bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, jb, n-j-jb, + 1, a[j*lda+j:], lda, + a[j*lda+j+jb:], lda) + } + } + return true + } + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dsyrk(blas.Lower, blas.NoTrans, jb, j, + -1, a[j*lda:], lda, + 1, a[j*lda+j:], lda) + ok := impl.Dpotf2(blas.Lower, jb, a[j*lda+j:], lda) + if !ok { + return ok + } + if j+jb < n { + bi.Dgemm(blas.NoTrans, blas.Trans, n-j-jb, jb, j, + -1, a[(j+jb)*lda:], lda, a[j*lda:], lda, + 1, a[(j+jb)*lda+j:], lda) + bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, n-j-jb, jb, + 1, a[j*lda+j:], lda, + a[(j+jb)*lda+j:], lda) + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go new file mode 100644 index 00000000..0ed15214 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Drscl multiplies the vector x by 1/a being careful to avoid overflow or +// underflow where possible. +// +// Drscl is an internal routine. It is exported for testing purposes. +func (impl Implementation) Drscl(n int, a float64, x []float64, incX int) { + checkVector(n, x, incX) + bi := blas64.Implementation() + cden := a + cnum := 1.0 + smlnum := dlamchS + bignum := 1 / smlnum + for { + cden1 := cden * smlnum + cnum1 := cnum / bignum + var mul float64 + var done bool + switch { + case cnum != 0 && math.Abs(cden1) > math.Abs(cnum): + mul = smlnum + done = false + cden = cden1 + case math.Abs(cnum1) > math.Abs(cden): + mul = bignum + done = false + cnum = cnum1 + default: + mul = cnum / cden + done = true + } + bi.Dscal(n, mul, x, incX) + if done { + break + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go new file mode 100644 index 00000000..9a36e1c5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go @@ -0,0 +1,373 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dsteqr computes the eigenvalues and optionally the eigenvectors of a symmetric +// tridiagonal matrix using the implicit QL or QR method. The eigenvectors of a +// full or band symmetric matrix can also be found if Dsytrd, Dsptrd, or Dsbtrd +// have been used to reduce this matrix to tridiagonal form. +// +// d, on entry, contains the diagonal elements of the tridiagonal matrix. On exit, +// d contains the eigenvalues in ascending order. d must have length n and +// Dsteqr will panic otherwise. +// +// e, on entry, contains the off-diagonal elements of the tridiagonal matrix on +// entry, and is overwritten during the call to Dsteqr. e must have length n-1 and +// Dsteqr will panic otherwise. +// +// z, on entry, contains the n×n orthogonal matrix used in the reduction to +// tridiagonal form if compz == lapack.OriginalEV. On exit, if +// compz == lapack.OriginalEV, z contains the orthonormal eigenvectors of the +// original symmetric matrix, and if compz == lapack.TridiagEV, z contains the +// orthonormal eigenvectors of the symmetric tridiagonal matrix. z is not used +// if compz == lapack.None. +// +// work must have length at least max(1, 2*n-2) if the eigenvectors are computed, +// and Dsteqr will panic otherwise. +// +// Dsteqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if compz != lapack.None && compz != lapack.TridiagEV && compz != lapack.OriginalEV { + panic(badEVComp) + } + if compz != lapack.None { + if len(work) < max(1, 2*n-2) { + panic(badWork) + } + checkMatrix(n, n, z, ldz) + } + + var icompz int + if compz == lapack.OriginalEV { + icompz = 1 + } else if compz == lapack.TridiagEV { + icompz = 2 + } + + if n == 0 { + return true + } + if n == 1 { + if icompz == 2 { + z[0] = 1 + } + return true + } + + bi := blas64.Implementation() + + eps := dlamchE + eps2 := eps * eps + safmin := dlamchS + safmax := 1 / safmin + ssfmax := math.Sqrt(safmax) / 3 + ssfmin := math.Sqrt(safmin) / eps2 + + // Compute the eigenvalues and eigenvectors of the tridiagonal matrix. + if icompz == 2 { + impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) + } + const maxit = 30 + nmaxit := n * maxit + + jtot := 0 + + // Determine where the matrix splits and choose QL or QR iteration for each + // block, according to whether top or bottom diagonal element is smaller. + l1 := 0 + nm1 := n - 1 + + type scaletype int + const ( + down scaletype = iota + 1 + up + ) + var iscale scaletype + + for { + if l1 > n-1 { + // Order eigenvalues and eigenvectors. + if icompz == 0 { + impl.Dlasrt(lapack.SortIncreasing, n, d) + } else { + // TODO(btracey): Consider replacing this sort with a call to sort.Sort. + for ii := 1; ii < n; ii++ { + i := ii - 1 + k := i + p := d[i] + for j := ii; j < n; j++ { + if d[j] < p { + k = j + p = d[j] + } + } + if k != i { + d[k] = d[i] + d[i] = p + bi.Dswap(n, z[i:], ldz, z[k:], ldz) + } + } + } + return true + } + if l1 > 0 { + e[l1-1] = 0 + } + var m int + if l1 <= nm1 { + for m = l1; m < nm1; m++ { + test := math.Abs(e[m]) + if test == 0 { + break + } + if test <= (math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1])))*eps { + e[m] = 0 + break + } + } + } + l := l1 + lsv := l + lend := m + lendsv := lend + l1 = m + 1 + if lend == l { + continue + } + + // Scale submatrix in rows and columns L to Lend + anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) + switch { + case anorm == 0: + continue + case anorm > ssfmax: + iscale = down + // Pretend that d and e are matrices with 1 column. + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], 1) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], 1) + case anorm < ssfmin: + iscale = up + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], 1) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], 1) + } + + // Choose between QL and QR. + if math.Abs(d[lend]) < math.Abs(d[l]) { + lend = lsv + l = lendsv + } + if lend > l { + // QL Iteration. Look for small subdiagonal element. + for { + if l != lend { + for m = l; m < lend; m++ { + v := math.Abs(e[m]) + if v*v <= (eps2*math.Abs(d[m]))*math.Abs(d[m+1])+safmin { + break + } + } + } else { + m = lend + } + if m < lend { + e[m] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l++ + if l > lend { + break + } + continue + } + + // If remaining matrix is 2×2, use Dlae2 to compute its eigensystem. + if m == l+1 { + if icompz > 0 { + d[l], d[l+1], work[l], work[n-1+l] = impl.Dlaev2(d[l], e[l], d[l+1]) + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, + n, 2, work[l:], work[n-1+l:], z[l:], ldz) + } else { + d[l], d[l+1] = impl.Dlae2(d[l], e[l], d[l+1]) + } + e[l] = 0 + l += 2 + if l > lend { + break + } + continue + } + + if jtot == nmaxit { + break + } + jtot++ + + // Form shift + g := (d[l+1] - p) / (2 * e[l]) + r := impl.Dlapy2(g, 1) + g = d[m] - p + e[l]/(g+math.Copysign(r, g)) + s := 1.0 + c := 1.0 + p = 0.0 + + // Inner loop + for i := m - 1; i >= l; i-- { + f := s * e[i] + b := c * e[i] + c, s, r = impl.Dlartg(g, f) + if i != m-1 { + e[i+1] = r + } + g = d[i+1] - p + r = (d[i]-g)*s + 2*c*b + p = s * r + d[i+1] = g + p + g = c*r - b + + // If eigenvectors are desired, then save rotations. + if icompz > 0 { + work[i] = c + work[n-1+i] = -s + } + } + // If eigenvectors are desired, then apply saved rotations. + if icompz > 0 { + mm := m - l + 1 + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, + n, mm, work[l:], work[n-1+l:], z[l:], ldz) + } + d[l] -= p + e[l] = g + } + } else { + // QR Iteration. + // Look for small superdiagonal element. + for { + if l != lend { + for m = l; m > lend; m-- { + v := math.Abs(e[m-1]) + if v*v <= (eps2*math.Abs(d[m])*math.Abs(d[m-1]) + safmin) { + break + } + } + } else { + m = lend + } + if m > lend { + e[m-1] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found + l-- + if l < lend { + break + } + continue + } + + // If remaining matrix is 2×2, use Dlae2 to compute its eigenvalues. + if m == l-1 { + if icompz > 0 { + d[l-1], d[l], work[m], work[n-1+m] = impl.Dlaev2(d[l-1], e[l-1], d[l]) + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, + n, 2, work[m:], work[n-1+m:], z[l-1:], ldz) + } else { + d[l-1], d[l] = impl.Dlae2(d[l-1], e[l-1], d[l]) + } + e[l-1] = 0 + l -= 2 + if l < lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + g := (d[l-1] - p) / (2 * e[l-1]) + r := impl.Dlapy2(g, 1) + g = d[m] - p + (e[l-1])/(g+math.Copysign(r, g)) + s := 1.0 + c := 1.0 + p = 0.0 + + // Inner loop. + for i := m; i < l; i++ { + f := s * e[i] + b := c * e[i] + c, s, r = impl.Dlartg(g, f) + if i != m { + e[i-1] = r + } + g = d[i] - p + r = (d[i+1]-g)*s + 2*c*b + p = s * r + d[i] = g + p + g = c*r - b + + // If eigenvectors are desired, then save rotations. + if icompz > 0 { + work[i] = c + work[n-1+i] = s + } + } + + // If eigenvectors are desired, then apply saved rotations. + if icompz > 0 { + mm := l - m + 1 + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, + n, mm, work[m:], work[n-1+m:], z[m:], ldz) + } + d[l] -= p + e[l-1] = g + } + } + + // Undo scaling if necessary. + switch iscale { + case down: + // Pretend that d and e are matrices with 1 column. + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], 1) + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv, 1, e[lsv:], 1) + case up: + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], 1) + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv, 1, e[lsv:], 1) + } + + // Check for no convergence to an eigenvalue after a total of n*maxit iterations. + if jtot >= nmaxit { + break + } + } + for i := 0; i < n-1; i++ { + if e[i] != 0 { + return false + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go new file mode 100644 index 00000000..1ed59820 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go @@ -0,0 +1,278 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dsterf computes all eigenvalues of a symmetric tridiagonal matrix using the +// Pal-Walker-Kahan variant of the QL or QR algorithm. +// +// d contains the diagonal elements of the tridiagonal matrix on entry, and +// contains the eigenvalues in ascending order on exit. d must have length at +// least n, or Dsterf will panic. +// +// e contains the off-diagonal elements of the tridiagonal matrix on entry, and is +// overwritten during the call to Dsterf. e must have length of at least n-1 or +// Dsterf will panic. +// +// Dsterf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsterf(n int, d, e []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if n == 0 { + return true + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + + const ( + none = 0 // The values are not scaled. + down = 1 // The values are scaled below ssfmax threshold. + up = 2 // The values are scaled below ssfmin threshold. + ) + + // Determine the unit roundoff for this environment. + eps := dlamchE + eps2 := eps * eps + safmin := dlamchS + safmax := 1 / safmin + ssfmax := math.Sqrt(safmax) / 3 + ssfmin := math.Sqrt(safmin) / eps2 + + // Compute the eigenvalues of the tridiagonal matrix. + maxit := 30 + nmaxit := n * maxit + jtot := 0 + + l1 := 0 + + for { + if l1 > n-1 { + impl.Dlasrt(lapack.SortIncreasing, n, d) + return true + } + if l1 > 0 { + e[l1-1] = 0 + } + var m int + for m = l1; m < n-1; m++ { + if math.Abs(e[m]) <= math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1]))*eps { + e[m] = 0 + break + } + } + + l := l1 + lsv := l + lend := m + lendsv := lend + l1 = m + 1 + if lend == 0 { + continue + } + + // Scale submatrix in rows and columns l to lend. + anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) + iscale := none + if anorm == 0 { + continue + } + if anorm > ssfmax { + iscale = down + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], n) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], n) + } else if anorm < ssfmin { + iscale = up + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], n) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], n) + } + + el := e[l:lend] + for i, v := range el { + el[i] *= v + } + + // Choose between QL and QR iteration. + if math.Abs(d[lend]) < math.Abs(d[l]) { + lend = lsv + l = lendsv + } + if lend >= l { + // QL Iteration. + // Look for small sub-diagonal element. + for { + if l != lend { + for m = l; m < lend; m++ { + if math.Abs(e[m]) <= eps2*(math.Abs(d[m]*d[m+1])) { + break + } + } + } else { + m = lend + } + if m < lend { + e[m] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l++ + if l > lend { + break + } + continue + } + // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. + if m == l+1 { + d[l], d[l+1] = impl.Dlae2(d[l], math.Sqrt(e[l]), d[l+1]) + e[l] = 0 + l += 2 + if l > lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + rte := math.Sqrt(e[l]) + sigma := (d[l+1] - p) / (2 * rte) + r := impl.Dlapy2(sigma, 1) + sigma = p - (rte / (sigma + math.Copysign(r, sigma))) + + c := 1.0 + s := 0.0 + gamma := d[m] - sigma + p = gamma * gamma + + // Inner loop. + for i := m - 1; i >= l; i-- { + bb := e[i] + r := p + bb + if i != m-1 { + e[i+1] = s * r + } + oldc := c + c = p / r + s = bb / r + oldgam := gamma + alpha := d[i] + gamma = c*(alpha-sigma) - s*oldgam + d[i+1] = oldgam + (alpha - gamma) + if c != 0 { + p = (gamma * gamma) / c + } else { + p = oldc * bb + } + } + e[l] = s * p + d[l] = sigma + gamma + } + } else { + for { + // QR Iteration. + // Look for small super-diagonal element. + for m = l; m > lend; m-- { + if math.Abs(e[m-1]) <= eps2*math.Abs(d[m]*d[m-1]) { + break + } + } + if m > lend { + e[m-1] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l-- + if l < lend { + break + } + continue + } + + // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. + if m == l-1 { + d[l], d[l-1] = impl.Dlae2(d[l], math.Sqrt(e[l-1]), d[l-1]) + e[l-1] = 0 + l -= 2 + if l < lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + rte := math.Sqrt(e[l-1]) + sigma := (d[l-1] - p) / (2 * rte) + r := impl.Dlapy2(sigma, 1) + sigma = p - (rte / (sigma + math.Copysign(r, sigma))) + + c := 1.0 + s := 0.0 + gamma := d[m] - sigma + p = gamma * gamma + + // Inner loop. + for i := m; i < l; i++ { + bb := e[i] + r := p + bb + if i != m { + e[i-1] = s * r + } + oldc := c + c = p / r + s = bb / r + oldgam := gamma + alpha := d[i+1] + gamma = c*(alpha-sigma) - s*oldgam + d[i] = oldgam + alpha - gamma + if c != 0 { + p = (gamma * gamma) / c + } else { + p = oldc * bb + } + } + e[l-1] = s * p + d[l] = sigma + gamma + } + } + + // Undo scaling if necessary + switch iscale { + case down: + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], n) + case up: + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], n) + } + + // Check for no convergence to an eigenvalue after a total of n*maxit iterations. + if jtot >= nmaxit { + break + } + } + for _, v := range e[:n-1] { + if v != 0 { + return false + } + } + impl.Dlasrt(lapack.SortIncreasing, n, d) + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go new file mode 100644 index 00000000..35241728 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dsyev computes all eigenvalues and, optionally, the eigenvectors of a real +// symmetric matrix A. +// +// w contains the eigenvalues in ascending order upon return. w must have length +// at least n, and Dsyev will panic otherwise. +// +// On entry, a contains the elements of the symmetric matrix A in the triangular +// portion specified by uplo. If jobz == lapack.ComputeEV a contains the +// orthonormal eigenvectors of A on exit, otherwise on exit the specified +// triangular region is overwritten. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 3*n-1, and Dsyev will panic otherwise. The amount of blocking is +// limited by the usable length. If lwork == -1, instead of computing Dsyev the +// optimal work length is stored into work[0]. +func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + upper := uplo == blas.Upper + wantz := jobz == lapack.ComputeEV + var opts string + if upper { + opts = "U" + } else { + opts = "L" + } + nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) + lworkopt := max(1, (nb+2)*n) + work[0] = float64(lworkopt) + if lwork == -1 { + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < 3*n-1 { + panic(badWork) + } + if n == 0 { + return true + } + if n == 1 { + w[0] = a[0] + work[0] = 2 + if wantz { + a[0] = 1 + } + return true + } + safmin := dlamchS + eps := dlamchP + smlnum := safmin / eps + bignum := 1 / smlnum + rmin := math.Sqrt(smlnum) + rmax := math.Sqrt(bignum) + + // Scale matrix to allowable range, if necessary. + anrm := impl.Dlansy(lapack.MaxAbs, uplo, n, a, lda, work) + scaled := false + var sigma float64 + if anrm > 0 && anrm < rmin { + scaled = true + sigma = rmin / anrm + } else if anrm > rmax { + scaled = true + sigma = rmax / anrm + } + if scaled { + kind := lapack.LowerTri + if upper { + kind = lapack.UpperTri + } + impl.Dlascl(kind, 0, 0, 1, sigma, n, n, a, lda) + } + var inde int + indtau := inde + n + indwork := indtau + n + llwork := lwork - indwork + impl.Dsytrd(uplo, n, a, lda, w, work[inde:], work[indtau:], work[indwork:], llwork) + + // For eigenvalues only, call Dsterf. For eigenvectors, first call Dorgtr + // to generate the orthogonal matrix, then call Dsteqr. + if !wantz { + ok = impl.Dsterf(n, w, work[inde:]) + } else { + impl.Dorgtr(uplo, n, a, lda, work[indtau:], work[indwork:], llwork) + ok = impl.Dsteqr(lapack.EVComp(jobz), n, w, work[inde:], a, lda, work[indtau:]) + } + if !ok { + return false + } + + // If the matrix was scaled, then rescale eigenvalues appropriately. + if scaled { + bi := blas64.Implementation() + bi.Dscal(n, 1/sigma, w, 1) + } + work[0] = float64(lworkopt) + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go new file mode 100644 index 00000000..a4d69201 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go @@ -0,0 +1,123 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dsytd2 reduces a symmetric n×n matrix A to symmetric tridiagonal form T by an +// orthogonal similarity transformation +// Q^T * A * Q = T +// On entry, the matrix is contained in the specified triangle of a. On exit, +// if uplo == blas.Upper, the diagonal and first super-diagonal of a are +// overwritten with the elements of T. The elements above the first super-diagonal +// are overwritten with the the elementary reflectors that are used with the +// elements written to tau in order to construct Q. If uplo == blas.Lower, the +// elements are written in the lower triangular region. +// +// d must have length at least n. e and tau must have length at least n-1. Dsytd2 +// will panic if these sizes are not met. +// +// Q is represented as a product of elementary reflectors. +// If uplo == blas.Upper +// Q = H_{n-2} * ... * H_1 * H_0 +// and if uplo == blas.Lower +// Q = H_0 * H_1 * ... * H_{n-2} +// where +// H_i = I - tau * v * v^T +// where tau is stored in tau[i], and v is stored in a. +// +// If uplo == blas.Upper, v[0:i-1] is stored in A[0:i-1,i+1], v[i] = 1, and +// v[i+1:] = 0. The elements of a are +// [ d e v2 v3 v4] +// [ d e v3 v4] +// [ d e v4] +// [ d e] +// [ d] +// If uplo == blas.Lower, v[0:i+1] = 0, v[i+1] = 1, and v[i+2:] is stored in +// A[i+2:n,i]. +// The elements of a are +// [ d ] +// [ e d ] +// [v1 e d ] +// [v1 v2 e d ] +// [v1 v2 v3 e d] +// +// Dsytd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) { + checkMatrix(n, n, a, lda) + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if n <= 0 { + return + } + bi := blas64.Implementation() + if uplo == blas.Upper { + // Reduce the upper triangle of A. + for i := n - 2; i >= 0; i-- { + // Generate elementary reflector H_i = I - tau * v * v^T to + // annihilate A[i:i-1, i+1]. + var taui float64 + a[i*lda+i+1], taui = impl.Dlarfg(i+1, a[i*lda+i+1], a[i+1:], lda) + e[i] = a[i*lda+i+1] + if taui != 0 { + // Apply H_i from both sides to A[0:i,0:i]. + a[i*lda+i+1] = 1 + + // Compute x := tau * A * v storing x in tau[0:i]. + bi.Dsymv(uplo, i+1, taui, a, lda, a[i+1:], lda, 0, tau, 1) + + // Compute w := x - 1/2 * tau * (x^T * v) * v. + alpha := -0.5 * taui * bi.Ddot(i+1, tau, 1, a[i+1:], lda) + bi.Daxpy(i+1, alpha, a[i+1:], lda, tau, 1) + + // Apply the transformation as a rank-2 update + // A = A - v * w^T - w * v^T. + bi.Dsyr2(uplo, i+1, -1, a[i+1:], lda, tau, 1, a, lda) + a[i*lda+i+1] = e[i] + } + d[i+1] = a[(i+1)*lda+i+1] + tau[i] = taui + } + d[0] = a[0] + return + } + // Reduce the lower triangle of A. + for i := 0; i < n-1; i++ { + // Generate elementary reflector H_i = I - tau * v * v^T to + // annihilate A[i+2:n, i]. + var taui float64 + a[(i+1)*lda+i], taui = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + e[i] = a[(i+1)*lda+i] + if taui != 0 { + // Apply H_i from both sides to A[i+1:n, i+1:n]. + a[(i+1)*lda+i] = 1 + + // Compute x := tau * A * v, storing y in tau[i:n-1]. + bi.Dsymv(uplo, n-i-1, taui, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, tau[i:], 1) + + // Compute w := x - 1/2 * tau * (x^T * v) * v. + alpha := -0.5 * taui * bi.Ddot(n-i-1, tau[i:], 1, a[(i+1)*lda+i:], lda) + bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, tau[i:], 1) + + // Apply the transformation as a rank-2 update + // A = A - v * w^T - w * v^T. + bi.Dsyr2(uplo, n-i-1, -1, a[(i+1)*lda+i:], lda, tau[i:], 1, a[(i+1)*lda+i+1:], lda) + a[(i+1)*lda+i] = e[i] + } + d[i] = a[i*lda+i] + tau[i] = taui + } + d[n-1] = a[(n-1)*lda+n-1] +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go new file mode 100644 index 00000000..f8a4ca95 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go @@ -0,0 +1,178 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dsytrd reduces a symmetric n×n matrix A to symmetric tridiagonal form by an +// orthogonal similarity transformation +// Q^T * A * Q = T +// where Q is an orthonormal matrix and T is symmetric and tridiagonal. +// +// On entry, a contains the elements of the input matrix in the triangle specified +// by uplo. On exit, the diagonal and sub/super-diagonal are overwritten by the +// corresponding elements of the tridiagonal matrix T. The remaining elements in +// the triangle, along with the array tau, contain the data to construct Q as +// the product of elementary reflectors. +// +// If uplo == blas.Upper, Q is constructed with +// Q = H_{n-2} * ... * H_1 * H_0 +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[i+1:n] = 0, v[i] = 1, v[0:i-1] is stored in A[0:i-1, i+1]. +// The elements of A are +// [ d e v1 v2 v3] +// [ d e v2 v3] +// [ d e v3] +// [ d e] +// [ e] +// +// If uplo == blas.Lower, Q is constructed with +// Q = H_0 * H_1 * ... * H_{n-2} +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[0:i+1] = 0, v[i+1] = 1, v[i+2:n] is stored in A[i+2:n, i]. +// The elements of A are +// [ d ] +// [ e d ] +// [v0 e d ] +// [v0 v1 e d ] +// [v0 v1 v2 e d] +// +// d must have length n, and e and tau must have length n-1. Dsytrd will panic if +// these conditions are not met. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 1, and Dsytrd will panic otherwise. The amount of blocking is +// limited by the usable length. +// If lwork == -1, instead of computing Dsytrd the optimal work length is stored +// into work[0]. +// +// Dsytrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + + var upper bool + var opts string + switch uplo { + case blas.Upper: + upper = true + opts = "U" + case blas.Lower: + opts = "L" + default: + panic(badUplo) + } + + if n == 0 { + work[0] = 1 + return + } + + nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) + lworkopt := n * nb + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nx := n + bi := blas64.Implementation() + var ldwork int + if 1 < nb && nb < n { + // Determine when to cross over from blocked to unblocked code. The last + // block is always handled by unblocked code. + opts := "L" + if upper { + opts = "U" + } + nx = max(nb, impl.Ilaenv(3, "DSYTRD", opts, n, -1, -1, -1)) + if nx < n { + // Determine if workspace is large enough for blocked code. + ldwork = nb + iws := n * ldwork + if lwork < iws { + // Not enough workspace to use optimal nb: determine the minimum + // value of nb and reduce nb or force use of unblocked code by + // setting nx = n. + nb = max(lwork/n, 1) + nbmin := impl.Ilaenv(2, "DSYTRD", opts, n, -1, -1, -1) + if nb < nbmin { + nx = n + } + } + } else { + nx = n + } + } else { + nb = 1 + } + ldwork = nb + + if upper { + // Reduce the upper triangle of A. Columns 0:kk are handled by the + // unblocked method. + var i int + kk := n - ((n-nx+nb-1)/nb)*nb + for i = n - nb; i >= kk; i -= nb { + // Reduce columns i:i+nb to tridiagonal form and form the matrix W + // which is needed to update the unreduced part of the matrix. + impl.Dlatrd(uplo, i+nb, nb, a, lda, e, tau, work, ldwork) + + // Update the unreduced submatrix A[0:i-1,0:i-1], using an update + // of the form A = A - V*W^T - W*V^T. + bi.Dsyr2k(uplo, blas.NoTrans, i, nb, -1, a[i:], lda, work, ldwork, 1, a, lda) + + // Copy superdiagonal elements back into A, and diagonal elements into D. + for j := i; j < i+nb; j++ { + a[(j-1)*lda+j] = e[j-1] + d[j] = a[j*lda+j] + } + } + // Use unblocked code to reduce the last or only block + // check that i == kk. + impl.Dsytd2(uplo, kk, a, lda, d, e, tau) + } else { + var i int + // Reduce the lower triangle of A. + for i = 0; i < n-nx; i += nb { + // Reduce columns 0:i+nb to tridiagonal form and form the matrix W + // which is needed to update the unreduced part of the matrix. + impl.Dlatrd(uplo, n-i, nb, a[i*lda+i:], lda, e[i:], tau[i:], work, ldwork) + + // Update the unreduced submatrix A[i+ib:n, i+ib:n], using an update + // of the form A = A + V*W^T - W*V^T. + bi.Dsyr2k(uplo, blas.NoTrans, n-i-nb, nb, -1, a[(i+nb)*lda+i:], lda, + work[nb*ldwork:], ldwork, 1, a[(i+nb)*lda+i+nb:], lda) + + // Copy subdiagonal elements back into A, and diagonal elements into D. + for j := i; j < i+nb; j++ { + a[(j+1)*lda+j] = e[j] + d[j] = a[j*lda+j] + } + } + // Use unblocked code to reduce the last or only block. + impl.Dsytd2(uplo, n-i, a[i*lda+i:], lda, d[i:], e[i:], tau[i:]) + } + work[0] = float64(lworkopt) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go new file mode 100644 index 00000000..ca0326ef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go @@ -0,0 +1,357 @@ +// Copyright ©2017 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtgsja computes the generalized singular value decomposition (GSVD) +// of two real upper triangular or trapezoidal matrices A and B. +// +// A and B have the following forms, which may be obtained by the +// preprocessing subroutine Dggsvp from a general m×n matrix A and p×n +// matrix B: +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// B = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// On exit, +// +// U^T*A*Q = D1*[ 0 R ], V^T*B*Q = D2*[ 0 R ], +// +// where U, V and Q are orthogonal matrices. +// R is a non-singular upper triangular matrix, and D1 and D2 are +// diagonal matrices, which are of the following structures: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[0:m, n-k-l:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// The computation of the orthogonal transformation matrices U, V or Q +// is optional. These matrices may either be formed explicitly, or they +// may be post-multiplied into input matrices U1, V1, or Q1. +// +// Dtgsja essentially uses a variant of Kogbetliantz algorithm to reduce +// min(l,m-k)×l triangular or trapezoidal matrix A23 and l×l +// matrix B13 to the form: +// +// U1^T*A13*Q1 = C1*R1; V1^T*B13*Q1 = S1*R1, +// +// where U1, V1 and Q1 are orthogonal matrices. C1 and S1 are diagonal +// matrices satisfying +// +// C1^2 + S1^2 = I, +// +// and R1 is an l×l non-singular upper triangular matrix. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDUnit Use unit-initialized matrix +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// k and l specify the sub-blocks in the input matrices A and B: +// A23 = A[k:min(k+l,m), n-l:n) and B13 = B[0:l, n-l:n] +// of A and B, whose GSVD is going to be computed by Dtgsja. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps, +// where eps is the machine epsilon. +// +// work must have length at least 2*n, otherwise Dtgsja will panic. +// +// alpha and beta must have length n or Dtgsja will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, A[n-k:n, 0:min(k+l,m)] contains the triangular matrix R or part of R +// and if necessary, B[m-k:l, n+m-k-l:n] contains a part of R. +// +// Dtgsja returns whether the routine converged and the number of iteration cycles +// that were run. +// +// Dtgsja is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) { + const maxit = 40 + + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + initu := jobU == lapack.GSVDUnit + wantu := initu || jobU == lapack.GSVDU + if !initu && !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + initv := jobV == lapack.GSVDUnit + wantv := initv || jobV == lapack.GSVDV + if !initv && !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + initq := jobQ == lapack.GSVDUnit + wantq := initq || jobQ == lapack.GSVDQ + if !initq && !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(work) < 2*n { + panic(badWork) + } + + // Initialize U, V and Q, if necessary + if initu { + impl.Dlaset(blas.All, m, m, 0, 1, u, ldu) + } + if initv { + impl.Dlaset(blas.All, p, p, 0, 1, v, ldv) + } + if initq { + impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) + } + + bi := blas64.Implementation() + minTol := math.Min(tola, tolb) + + // Loop until convergence. + upper := false + for cycles = 1; cycles <= maxit; cycles++ { + upper = !upper + + for i := 0; i < l-1; i++ { + for j := i + 1; j < l; j++ { + var a1, a2, a3 float64 + if k+i < m { + a1 = a[(k+i)*lda+n-l+i] + } + if k+j < m { + a3 = a[(k+j)*lda+n-l+j] + } + + b1 := b[i*ldb+n-l+i] + b3 := b[j*ldb+n-l+j] + + var b2 float64 + if upper { + if k+i < m { + a2 = a[(k+i)*lda+n-l+j] + } + b2 = b[i*ldb+n-l+j] + } else { + if k+j < m { + a2 = a[(k+j)*lda+n-l+i] + } + b2 = b[j*ldb+n-l+i] + } + + csu, snu, csv, snv, csq, snq := impl.Dlags2(upper, a1, a2, a3, b1, b2, b3) + + // Update (k+i)-th and (k+j)-th rows of matrix A: U^T*A. + if k+j < m { + bi.Drot(l, a[(k+j)*lda+n-l:], 1, a[(k+i)*lda+n-l:], 1, csu, snu) + } + + // Update i-th and j-th rows of matrix B: V^T*B. + bi.Drot(l, b[j*ldb+n-l:], 1, b[i*ldb+n-l:], 1, csv, snv) + + // Update (n-l+i)-th and (n-l+j)-th columns of matrices + // A and B: A*Q and B*Q. + bi.Drot(min(k+l, m), a[n-l+j:], lda, a[n-l+i:], lda, csq, snq) + bi.Drot(l, b[n-l+j:], ldb, b[n-l+i:], ldb, csq, snq) + + if upper { + if k+i < m { + a[(k+i)*lda+n-l+j] = 0 + } + b[i*ldb+n-l+j] = 0 + } else { + if k+j < m { + a[(k+j)*lda+n-l+i] = 0 + } + b[j*ldb+n-l+i] = 0 + } + + // Update orthogonal matrices U, V, Q, if desired. + if wantu && k+j < m { + bi.Drot(m, u[k+j:], ldu, u[k+i:], ldu, csu, snu) + } + if wantv { + bi.Drot(p, v[j:], ldv, v[i:], ldv, csv, snv) + } + if wantq { + bi.Drot(n, q[n-l+j:], ldq, q[n-l+i:], ldq, csq, snq) + } + } + } + + if !upper { + // The matrices A13 and B13 were lower triangular at the start + // of the cycle, and are now upper triangular. + // + // Convergence test: test the parallelism of the corresponding + // rows of A and B. + var error float64 + for i := 0; i < min(l, m-k); i++ { + bi.Dcopy(l-i, a[(k+i)*lda+n-l+i:], 1, work, 1) + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, work[l:], 1) + ssmin := impl.Dlapll(l-i, work, 1, work[l:], 1) + error = math.Max(error, ssmin) + } + if math.Abs(error) <= minTol { + // The algorithm has converged. + // Compute the generalized singular value pairs (alpha, beta) + // and set the triangular matrix R to array A. + for i := 0; i < k; i++ { + alpha[i] = 1 + beta[i] = 0 + } + + for i := 0; i < min(l, m-k); i++ { + a1 := a[(k+i)*lda+n-l+i] + b1 := b[i*ldb+n-l+i] + + if a1 != 0 { + gamma := b1 / a1 + + // Change sign if necessary. + if gamma < 0 { + bi.Dscal(l-i, -1, b[i*ldb+n-l+i:], 1) + if wantv { + bi.Dscal(p, -1, v[i:], ldv) + } + } + beta[k+i], alpha[k+i], _ = impl.Dlartg(math.Abs(gamma), 1) + + if alpha[k+i] >= beta[k+i] { + bi.Dscal(l-i, 1/alpha[k+i], a[(k+i)*lda+n-l+i:], 1) + } else { + bi.Dscal(l-i, 1/beta[k+i], b[i*ldb+n-l+i:], 1) + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) + } + } else { + alpha[k+i] = 0 + beta[k+i] = 1 + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) + } + } + + for i := m; i < k+l; i++ { + alpha[i] = 0 + beta[i] = 1 + } + if k+l < n { + for i := k + l; i < n; i++ { + alpha[i] = 0 + beta[i] = 0 + } + } + + return cycles, true + } + } + } + + // The algorithm has not converged after maxit cycles. + return cycles, false +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go new file mode 100644 index 00000000..14101325 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go @@ -0,0 +1,82 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtrcon estimates the reciprocal of the condition number of a triangular matrix A. +// The condition number computed may be based on the 1-norm or the ∞-norm. +// +// work is a temporary data slice of length at least 3*n and Dtrcon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dtrcon will panic otherwise. +func (impl Implementation) Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 { + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + if n == 0 { + return 1 + } + bi := blas64.Implementation() + + var rcond float64 + smlnum := dlamchS * float64(n) + + anorm := impl.Dlantr(norm, uplo, diag, n, n, a, lda, work) + + if anorm <= 0 { + return rcond + } + var ainvnm float64 + var normin bool + kase1 := 2 + if norm == lapack.MaxColumnSum { + kase1 = 1 + } + var kase int + isave := new([3]int) + var scale float64 + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / anorm) / ainvnm + } + return rcond + } + if kase == kase1 { + scale = impl.Dlatrs(uplo, blas.NoTrans, diag, normin, n, a, lda, work, work[2*n:]) + } else { + scale = impl.Dlatrs(uplo, blas.Trans, diag, normin, n, a, lda, work, work[2*n:]) + } + normin = true + if scale != 1 { + ix := bi.Idamax(n, work, 1) + xnorm := math.Abs(work[ix]) + if scale == 0 || scale < xnorm*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go new file mode 100644 index 00000000..d62d5f05 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go @@ -0,0 +1,866 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtrevc3 computes some or all of the right and/or left eigenvectors of an n×n +// upper quasi-triangular matrix T in Schur canonical form. Matrices of this +// type are produced by the Schur factorization of a real general matrix A +// A = Q T Q^T, +// as computed by Dhseqr. +// +// The right eigenvector x of T corresponding to an +// eigenvalue λ is defined by +// T x = λ x, +// and the left eigenvector is defined by +// y^H T = λ y^H, +// where y^H is the conjugate transpose of y. +// +// The eigenvalues are read directly from the diagonal blocks of T. +// +// This routine returns the matrices X and/or Y of right and left eigenvectors +// of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the +// orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y +// are the matrices of right and left eigenvectors of A. +// +// If side == lapack.RightEV, only right eigenvectors will be computed. +// If side == lapack.LeftEV, only left eigenvectors will be computed. +// If side == lapack.RightLeftEV, both right and left eigenvectors will be computed. +// For other values of side, Dtrevc3 will panic. +// +// If howmny == lapack.AllEV, all right and/or left eigenvectors will be +// computed. +// If howmny == lapack.AllEVMulQ, all right and/or left eigenvectors will be +// computed and multiplied from left by the matrices in VR and/or VL. +// If howmny == lapack.SelectedEV, right and/or left eigenvectors will be +// computed as indicated by selected. +// For other values of howmny, Dtrevc3 will panic. +// +// selected specifies which eigenvectors will be computed. It must have length n +// if howmny == lapack.SelectedEV, and it is not referenced otherwise. +// If w_j is a real eigenvalue, the corresponding real eigenvector will be +// computed if selected[j] is true. +// If w_j and w_{j+1} are the real and imaginary parts of a complex eigenvalue, +// the corresponding complex eigenvector is computed if either selected[j] or +// selected[j+1] is true, and on return selected[j] will be set to true and +// selected[j+1] will be set to false. +// +// VL and VR are n×mm matrices. If howmny is lapack.AllEV or +// lapack.AllEVMulQ, mm must be at least n. If howmny == +// lapack.SelectedEV, mm must be large enough to store the selected +// eigenvectors. Each selected real eigenvector occupies one column and each +// selected complex eigenvector occupies two columns. If mm is not sufficiently +// large, Dtrevc3 will panic. +// +// On entry, if howmny == lapack.AllEVMulQ, it is assumed that VL (if side +// is lapack.LeftEV or lapack.RightLeftEV) contains an n×n matrix QL, +// and that VR (if side is lapack.LeftEV or lapack.RightLeftEV) contains +// an n×n matrix QR. QL and QR are typically the orthogonal matrix Q of Schur +// vectors returned by Dhseqr. +// +// On return, if side is lapack.LeftEV or lapack.RightLeftEV, +// VL will contain: +// if howmny == lapack.AllEV, the matrix Y of left eigenvectors of T, +// if howmny == lapack.AllEVMulQ, the matrix Q*Y, +// if howmny == lapack.SelectedEV, the left eigenvectors of T specified by +// selected, stored consecutively in the +// columns of VL, in the same order as their +// eigenvalues. +// VL is not referenced if side == lapack.RightEV. +// +// On return, if side is lapack.RightEV or lapack.RightLeftEV, +// VR will contain: +// if howmny == lapack.AllEV, the matrix X of right eigenvectors of T, +// if howmny == lapack.AllEVMulQ, the matrix Q*X, +// if howmny == lapack.SelectedEV, the left eigenvectors of T specified by +// selected, stored consecutively in the +// columns of VR, in the same order as their +// eigenvalues. +// VR is not referenced if side == lapack.LeftEV. +// +// Complex eigenvectors corresponding to a complex eigenvalue are stored in VL +// and VR in two consecutive columns, the first holding the real part, and the +// second the imaginary part. +// +// Each eigenvector will be normalized so that the element of largest magnitude +// has magnitude 1. Here the magnitude of a complex number (x,y) is taken to be +// |x| + |y|. +// +// work must have length at least lwork and lwork must be at least max(1,3*n), +// otherwise Dtrevc3 will panic. For optimum performance, lwork should be at +// least n+2*n*nb, where nb is the optimal blocksize. +// +// If lwork == -1, instead of performing Dtrevc3, the function only estimates +// the optimal workspace size based on n and stores it into work[0]. +// +// Dtrevc3 returns the number of columns in VL and/or VR actually used to store +// the eigenvectors. +// +// Dtrevc3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) (m int) { + switch side { + default: + panic(badEVSide) + case lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV: + } + switch howmny { + default: + panic(badHowMany) + case lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV: + } + switch { + case n < 0: + panic(nLT0) + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, 3*n) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + if howmny == lapack.SelectedEV { + if len(selected) != n { + panic("lapack: bad selected length") + } + // Set m to the number of columns required to store the + // selected eigenvectors, and standardize the slice + // selected. + for j := 0; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // Diagonal 1×1 block corresponding to a + // real eigenvalue. + if selected[j] { + m++ + } + j++ + } else { + // Diagonal 2×2 block corresponding to a + // complex eigenvalue. + if selected[j] || selected[j+1] { + selected[j] = true + selected[j+1] = false + m += 2 + } + j += 2 + } + } + } else { + m = n + } + if m > mm { + panic("lapack: insufficient number of columns") + } + checkMatrix(n, n, t, ldt) + if (side == lapack.RightEV || side == lapack.RightLeftEV) && m > 0 { + checkMatrix(n, m, vr, ldvr) + } + if (side == lapack.LeftEV || side == lapack.RightLeftEV) && m > 0 { + checkMatrix(n, m, vl, ldvl) + } + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return m + } + + const ( + nbmin = 8 + nbmax = 128 + ) + nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1) + + // Quick return in case of a workspace query. + if lwork == -1 { + work[0] = float64(n + 2*n*nb) + return m + } + + // Use blocked version of back-transformation if sufficient workspace. + // Zero-out the workspace to avoid potential NaN propagation. + if howmny == lapack.AllEVMulQ && lwork >= n+2*n*nbmin { + nb = min((lwork-n)/(2*n), nbmax) + impl.Dlaset(blas.All, n, 1+2*nb, 0, 0, work[:n+2*nb*n], 1+2*nb) + } else { + nb = 1 + } + + // Set the constants to control overflow. + ulp := dlamchP + smlnum := float64(n) / ulp * dlamchS + bignum := (1 - ulp) / smlnum + + // Split work into a vector of column norms and an n×2*nb matrix b. + norms := work[:n] + ldb := 2 * nb + b := work[n : n+n*ldb] + + // Compute 1-norm of each column of strictly upper triangular part of T + // to control overflow in triangular solver. + norms[0] = 0 + for j := 1; j < n; j++ { + var cn float64 + for i := 0; i < j; i++ { + cn += math.Abs(t[i*ldt+j]) + } + norms[j] = cn + } + + bi := blas64.Implementation() + + var ( + x [4]float64 + + iv int // Index of column in current block. + is int + + // ip is used below to specify the real or complex eigenvalue: + // ip == 0, real eigenvalue, + // 1, first of conjugate complex pair (wr,wi), + // -1, second of conjugate complex pair (wr,wi). + ip int + iscomplex [nbmax]int // Stores ip for each column in current block. + ) + + if side == lapack.LeftEV { + goto leftev + } + + // Compute right eigenvectors. + + // For complex right vector, iv-1 is for real part and iv for complex + // part. Non-blocked version always uses iv=1, blocked version starts + // with iv=nb-1 and goes down to 0 or 1. + iv = max(2, nb) - 1 + ip = 0 + is = m - 1 + for ki := n - 1; ki >= 0; ki-- { + if ip == -1 { + // Previous iteration (ki+1) was second of + // conjugate pair, so this ki is first of + // conjugate pair. + ip = 1 + continue + } + + if ki == 0 || t[ki*ldt+ki-1] == 0 { + // Last column or zero on sub-diagonal, so this + // ki must be real eigenvalue. + ip = 0 + } else { + // Non-zero on sub-diagonal, so this ki is + // second of conjugate pair. + ip = -1 + } + + if howmny == lapack.SelectedEV { + if ip == 0 { + if !selected[ki] { + continue + } + } else if !selected[ki-1] { + continue + } + } + + // Compute the ki-th eigenvalue (wr,wi). + wr := t[ki*ldt+ki] + var wi float64 + if ip != 0 { + wi = math.Sqrt(math.Abs(t[ki*ldt+ki-1])) * math.Sqrt(math.Abs(t[(ki-1)*ldt+ki])) + } + smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) + + if ip == 0 { + // Real right eigenvector. + + b[ki*ldb+iv] = 1 + // Form right-hand side. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = -t[k*ldt+ki] + } + // Solve upper quasi-triangular system: + // [ T[0:ki,0:ki] - wr ]*X = scale*b. + for j := ki - 1; j >= 0; { + if j == 0 || t[j*ldt+j-1] == 0 { + // 1×1 diagonal block. + scale, xnorm, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) + // Scale X[0,0] to avoid overflow when updating the + // right-hand side. + if xnorm > 1 && norms[j] > bignum/xnorm { + x[0] /= xnorm + scale /= xnorm + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[j*ldb+iv] = x[0] + // Update right-hand side. + bi.Daxpy(j, -x[0], t[j:], ldt, b[iv:], ldb) + j-- + } else { + // 2×2 diagonal block. + scale, xnorm, _ := impl.Dlaln2(false, 2, 1, smin, 1, t[(j-1)*ldt+j-1:], ldt, + 1, 1, b[(j-1)*ldb+iv:], ldb, wr, 0, x[:3], 2) + // Scale X[0,0] and X[1,0] to avoid overflow + // when updating the right-hand side. + if xnorm > 1 { + beta := math.Max(norms[j-1], norms[j]) + if beta > bignum/xnorm { + x[0] /= xnorm + x[2] /= xnorm + scale /= xnorm + } + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[(j-1)*ldb+iv] = x[0] + b[j*ldb+iv] = x[2] + // Update right-hand side. + bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv:], ldb) + bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv:], ldb) + j -= 2 + } + } + // Copy the vector x or Q*x to VR and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VR and normalize. + bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) + ii := bi.Idamax(ki+1, vr[is:], ldvr) + remax := 1 / math.Abs(vr[ii*ldvr+is]) + bi.Dscal(ki+1, remax, vr[is:], ldvr) + for k := ki + 1; k < n; k++ { + vr[k*ldvr+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if ki > 0 { + bi.Dgemv(blas.NoTrans, n, ki, 1, vr, ldvr, b[iv:], ldb, + b[ki*ldb+iv], vr[ki:], ldvr) + } + ii := bi.Idamax(n, vr[ki:], ldvr) + remax := 1 / math.Abs(vr[ii*ldvr+ki]) + bi.Dscal(n, remax, vr[ki:], ldvr) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out below vector. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv] = 0 + } + iscomplex[iv] = ip + // Back-transform and normalization is done below. + } + } else { + // Complex right eigenvector. + + // Initial solve + // [ ( T[ki-1,ki-1] T[ki-1,ki] ) - (wr + i*wi) ]*X = 0. + // [ ( T[ki, ki-1] T[ki, ki] ) ] + if math.Abs(t[(ki-1)*ldt+ki]) >= math.Abs(t[ki*ldt+ki-1]) { + b[(ki-1)*ldb+iv-1] = 1 + b[ki*ldb+iv] = wi / t[(ki-1)*ldt+ki] + } else { + b[(ki-1)*ldb+iv-1] = -wi / t[ki*ldt+ki-1] + b[ki*ldb+iv] = 1 + } + b[ki*ldb+iv-1] = 0 + b[(ki-1)*ldb+iv] = 0 + // Form right-hand side. + for k := 0; k < ki-1; k++ { + b[k*ldb+iv-1] = -b[(ki-1)*ldb+iv-1] * t[k*ldt+ki-1] + b[k*ldb+iv] = -b[ki*ldb+iv] * t[k*ldt+ki] + } + // Solve upper quasi-triangular system: + // [ T[0:ki-1,0:ki-1] - (wr+i*wi) ]*X = scale*(b1+i*b2) + for j := ki - 2; j >= 0; { + if j == 0 || t[j*ldt+j-1] == 0 { + // 1×1 diagonal block. + + scale, xnorm, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv-1:], ldb, wr, wi, x[:2], 2) + // Scale X[0,0] and X[0,1] to avoid + // overflow when updating the right-hand side. + if xnorm > 1 && norms[j] > bignum/xnorm { + x[0] /= xnorm + x[1] /= xnorm + scale /= xnorm + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv-1:], ldb) + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[j*ldb+iv-1] = x[0] + b[j*ldb+iv] = x[1] + // Update the right-hand side. + bi.Daxpy(j, -x[0], t[j:], ldt, b[iv-1:], ldb) + bi.Daxpy(j, -x[1], t[j:], ldt, b[iv:], ldb) + j-- + } else { + // 2×2 diagonal block. + + scale, xnorm, _ := impl.Dlaln2(false, 2, 2, smin, 1, t[(j-1)*ldt+j-1:], ldt, + 1, 1, b[(j-1)*ldb+iv-1:], ldb, wr, wi, x[:], 2) + // Scale X to avoid overflow when updating + // the right-hand side. + if xnorm > 1 { + beta := math.Max(norms[j-1], norms[j]) + if beta > bignum/xnorm { + rec := 1 / xnorm + x[0] *= rec + x[1] *= rec + x[2] *= rec + x[3] *= rec + scale *= rec + } + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv-1:], ldb) + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[(j-1)*ldb+iv-1] = x[0] + b[(j-1)*ldb+iv] = x[1] + b[j*ldb+iv-1] = x[2] + b[j*ldb+iv] = x[3] + // Update the right-hand side. + bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv-1:], ldb) + bi.Daxpy(j-1, -x[1], t[j-1:], ldt, b[iv:], ldb) + bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv-1:], ldb) + bi.Daxpy(j-1, -x[3], t[j:], ldt, b[iv:], ldb) + j -= 2 + } + } + + // Copy the vector x or Q*x to VR and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VR and normalize. + bi.Dcopy(ki+1, b[iv-1:], ldb, vr[is-1:], ldvr) + bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) + emax := 0.0 + for k := 0; k <= ki; k++ { + emax = math.Max(emax, math.Abs(vr[k*ldvr+is-1])+math.Abs(vr[k*ldvr+is])) + } + remax := 1 / emax + bi.Dscal(ki+1, remax, vr[is-1:], ldvr) + bi.Dscal(ki+1, remax, vr[is:], ldvr) + for k := ki + 1; k < n; k++ { + vr[k*ldvr+is-1] = 0 + vr[k*ldvr+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if ki-1 > 0 { + bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv-1:], ldb, + b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) + bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv:], ldb, + b[ki*ldb+iv], vr[ki:], ldvr) + } else { + bi.Dscal(n, b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) + bi.Dscal(n, b[ki*ldb+iv], vr[ki:], ldvr) + } + emax := 0.0 + for k := 0; k < n; k++ { + emax = math.Max(emax, math.Abs(vr[k*ldvr+ki-1])+math.Abs(vr[k*ldvr+ki])) + } + remax := 1 / emax + bi.Dscal(n, remax, vr[ki-1:], ldvr) + bi.Dscal(n, remax, vr[ki:], ldvr) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out below vector. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv-1] = 0 + b[k*ldb+iv] = 0 + } + iscomplex[iv-1] = -ip + iscomplex[iv] = ip + iv-- + // Back-transform and normalization is done below. + } + } + if nb > 1 { + // Blocked version of back-transform. + + // For complex case, ki2 includes both vectors (ki-1 and ki). + ki2 := ki + if ip != 0 { + ki2-- + } + // Columns iv:nb of b are valid vectors. + // When the number of vectors stored reaches nb-1 or nb, + // or if this was last vector, do the Gemm. + if iv < 2 || ki2 == 0 { + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, nb-iv, ki2+nb-iv, + 1, vr, ldvr, b[iv:], ldb, + 0, b[nb+iv:], ldb) + // Normalize vectors. + var remax float64 + for k := iv; k < nb; k++ { + if iscomplex[k] == 0 { + // Real eigenvector. + ii := bi.Idamax(n, b[nb+k:], ldb) + remax = 1 / math.Abs(b[ii*ldb+nb+k]) + } else if iscomplex[k] == 1 { + // First eigenvector of conjugate pair. + emax := 0.0 + for ii := 0; ii < n; ii++ { + emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) + } + remax = 1 / emax + // Second eigenvector of conjugate pair + // will reuse this value of remax. + } + bi.Dscal(n, remax, b[nb+k:], ldb) + } + impl.Dlacpy(blas.All, n, nb-iv, b[nb+iv:], ldb, vr[ki2:], ldvr) + iv = nb - 1 + } else { + iv-- + } + } + is-- + if ip != 0 { + is-- + } + } + + if side == lapack.RightEV { + return m + } + +leftev: + // Compute left eigenvectors. + + // For complex left vector, iv is for real part and iv+1 for complex + // part. Non-blocked version always uses iv=0. Blocked version starts + // with iv=0, goes up to nb-2 or nb-1. + iv = 0 + ip = 0 + is = 0 + for ki := 0; ki < n; ki++ { + if ip == 1 { + // Previous iteration ki-1 was first of conjugate pair, + // so this ki is second of conjugate pair. + ip = -1 + continue + } + + if ki == n-1 || t[(ki+1)*ldt+ki] == 0 { + // Last column or zero on sub-diagonal, so this ki must + // be real eigenvalue. + ip = 0 + } else { + // Non-zero on sub-diagonal, so this ki is first of + // conjugate pair. + ip = 1 + } + if howmny == lapack.SelectedEV && !selected[ki] { + continue + } + + // Compute the ki-th eigenvalue (wr,wi). + wr := t[ki*ldt+ki] + var wi float64 + if ip != 0 { + wi = math.Sqrt(math.Abs(t[ki*ldt+ki+1])) * math.Sqrt(math.Abs(t[(ki+1)*ldt+ki])) + } + smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) + + if ip == 0 { + // Real left eigenvector. + + b[ki*ldb+iv] = 1 + // Form right-hand side. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv] = -t[ki*ldt+k] + } + // Solve transposed quasi-triangular system: + // [ T[ki+1:n,ki+1:n] - wr ]^T * X = scale*b + vmax := 1.0 + vcrit := bignum + for j := ki + 1; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // 1×1 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side. + if norms[j] > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) + // Solve [ T[j,j] - wr ]^T * X = b. + scale, _, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + } + b[j*ldb+iv] = x[0] + vmax = math.Max(math.Abs(b[j*ldb+iv]), vmax) + vcrit = bignum / vmax + j++ + } else { + // 2×2 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side. + beta := math.Max(norms[j], norms[j+1]) + if beta > vcrit { + bi.Dscal(n-ki+1, 1/vmax, b[ki*ldb+iv:], 1) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) + b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j+1:], ldt, b[(ki+1)*ldb+iv:], ldb) + // Solve + // [ T[j,j]-wr T[j,j+1] ]^T * X = scale*[ b1 ] + // [ T[j+1,j] T[j+1,j+1]-wr ] [ b2 ] + scale, _, _ := impl.Dlaln2(true, 2, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:3], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + } + b[j*ldb+iv] = x[0] + b[(j+1)*ldb+iv] = x[2] + vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[(j+1)*ldb+iv]))) + vcrit = bignum / vmax + j += 2 + } + } + // Copy the vector x or Q*x to VL and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VL and normalize. + bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) + ii := bi.Idamax(n-ki, vl[ki*ldvl+is:], ldvl) + ki + remax := 1 / math.Abs(vl[ii*ldvl+is]) + bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) + for k := 0; k < ki; k++ { + vl[k*ldvl+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with Gemv, Q*x. + if n-ki-1 > 0 { + bi.Dgemv(blas.NoTrans, n, n-ki-1, + 1, vl[ki+1:], ldvl, b[(ki+1)*ldb+iv:], ldb, + b[ki*ldb+iv], vl[ki:], ldvl) + } + ii := bi.Idamax(n, vl[ki:], ldvl) + remax := 1 / math.Abs(vl[ii*ldvl+ki]) + bi.Dscal(n, remax, vl[ki:], ldvl) + default: + // Version 2: back-transform block of vectors with Gemm + // zero out above vector. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = 0 + } + iscomplex[iv] = ip + // Back-transform and normalization is done below. + } + } else { + // Complex left eigenvector. + + // Initial solve: + // [ [ T[ki,ki] T[ki,ki+1] ]^T - (wr - i* wi) ]*X = 0. + // [ [ T[ki+1,ki] T[ki+1,ki+1] ] ] + if math.Abs(t[ki*ldt+ki+1]) >= math.Abs(t[(ki+1)*ldt+ki]) { + b[ki*ldb+iv] = wi / t[ki*ldt+ki+1] + b[(ki+1)*ldb+iv+1] = 1 + } else { + b[ki*ldb+iv] = 1 + b[(ki+1)*ldb+iv+1] = -wi / t[(ki+1)*ldt+ki] + } + b[(ki+1)*ldb+iv] = 0 + b[ki*ldb+iv+1] = 0 + // Form right-hand side. + for k := ki + 2; k < n; k++ { + b[k*ldb+iv] = -b[ki*ldb+iv] * t[ki*ldt+k] + b[k*ldb+iv+1] = -b[(ki+1)*ldb+iv+1] * t[(ki+1)*ldt+k] + } + // Solve transposed quasi-triangular system: + // [ T[ki+2:n,ki+2:n]^T - (wr-i*wi) ]*X = b1+i*b2 + vmax := 1.0 + vcrit := bignum + for j := ki + 2; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // 1×1 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side elements. + if norms[j] > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + // Solve [ T[j,j]-(wr-i*wi) ]*(X11+i*X12) = b1+i*b2. + scale, _, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:2], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) + } + b[j*ldb+iv] = x[0] + b[j*ldb+iv+1] = x[1] + vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[j*ldb+iv+1]))) + vcrit = bignum / vmax + j++ + } else { + // 2×2 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side elements. + if math.Max(norms[j], norms[j+1]) > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[(j+1)*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + // Solve 2×2 complex linear equation + // [ [T[j,j] T[j,j+1] ]^T - (wr-i*wi)*I ]*X = scale*b + // [ [T[j+1,j] T[j+1,j+1]] ] + scale, _, _ := impl.Dlaln2(true, 2, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) + } + b[j*ldb+iv] = x[0] + b[j*ldb+iv+1] = x[1] + b[(j+1)*ldb+iv] = x[2] + b[(j+1)*ldb+iv+1] = x[3] + vmax01 := math.Max(math.Abs(x[0]), math.Abs(x[1])) + vmax23 := math.Max(math.Abs(x[2]), math.Abs(x[3])) + vmax = math.Max(vmax, math.Max(vmax01, vmax23)) + vcrit = bignum / vmax + j += 2 + } + } + // Copy the vector x or Q*x to VL and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VL and normalize. + bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) + bi.Dcopy(n-ki, b[ki*ldb+iv+1:], ldb, vl[ki*ldvl+is+1:], ldvl) + emax := 0.0 + for k := ki; k < n; k++ { + emax = math.Max(emax, math.Abs(vl[k*ldvl+is])+math.Abs(vl[k*ldvl+is+1])) + } + remax := 1 / emax + bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) + bi.Dscal(n-ki, remax, vl[ki*ldvl+is+1:], ldvl) + for k := 0; k < ki; k++ { + vl[k*ldvl+is] = 0 + vl[k*ldvl+is+1] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if n-ki-2 > 0 { + bi.Dgemv(blas.NoTrans, n, n-ki-2, + 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv:], ldb, + b[ki*ldb+iv], vl[ki:], ldvl) + bi.Dgemv(blas.NoTrans, n, n-ki-2, + 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv+1:], ldb, + b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) + } else { + bi.Dscal(n, b[ki*ldb+iv], vl[ki:], ldvl) + bi.Dscal(n, b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) + } + emax := 0.0 + for k := 0; k < n; k++ { + emax = math.Max(emax, math.Abs(vl[k*ldvl+ki])+math.Abs(vl[k*ldvl+ki+1])) + } + remax := 1 / emax + bi.Dscal(n, remax, vl[ki:], ldvl) + bi.Dscal(n, remax, vl[ki+1:], ldvl) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out above vector. + // Could go from ki-nv+1 to ki-1. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = 0 + b[k*ldb+iv+1] = 0 + } + iscomplex[iv] = ip + iscomplex[iv+1] = -ip + iv++ + // Back-transform and normalization is done below. + } + } + if nb > 1 { + // Blocked version of back-transform. + // For complex case, ki2 includes both vectors ki and ki+1. + ki2 := ki + if ip != 0 { + ki2++ + } + // Columns [0:iv] of work are valid vectors. When the + // number of vectors stored reaches nb-1 or nb, or if + // this was last vector, do the Gemm. + if iv >= nb-2 || ki2 == n-1 { + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, iv+1, n-ki2+iv, + 1, vl[ki2-iv:], ldvl, b[(ki2-iv)*ldb:], ldb, + 0, b[nb:], ldb) + // Normalize vectors. + var remax float64 + for k := 0; k <= iv; k++ { + if iscomplex[k] == 0 { + // Real eigenvector. + ii := bi.Idamax(n, b[nb+k:], ldb) + remax = 1 / math.Abs(b[ii*ldb+nb+k]) + } else if iscomplex[k] == 1 { + // First eigenvector of conjugate pair. + emax := 0.0 + for ii := 0; ii < n; ii++ { + emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) + } + remax = 1 / emax + // Second eigenvector of conjugate pair + // will reuse this value of remax. + } + bi.Dscal(n, remax, b[nb+k:], ldb) + } + impl.Dlacpy(blas.All, n, iv+1, b[nb:], ldb, vl[ki2-iv:], ldvl) + iv = 0 + } else { + iv++ + } + } + is++ + if ip != 0 { + is++ + } + } + + return m +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go new file mode 100644 index 00000000..4a88931f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum 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 gonum + +import "gonum.org/v1/gonum/lapack" + +// Dtrexc reorders the real Schur factorization of a n×n real matrix +// A = Q*T*Q^T +// so that the diagonal block of T with row index ifst is moved to row ilst. +// +// On entry, T must be in Schur canonical form, that is, block upper triangular +// with 1×1 and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal +// elements equal and its off-diagonal elements of opposite sign. +// +// On return, T will be reordered by an orthogonal similarity transformation Z +// as Z^T*T*Z, and will be again in Schur canonical form. +// +// If compq is lapack.UpdateSchur, on return the matrix Q of Schur vectors will be +// updated by postmultiplying it with Z. +// If compq is lapack.None, the matrix Q is not referenced and will not be +// updated. +// For other values of compq Dtrexc will panic. +// +// ifst and ilst specify the reordering of the diagonal blocks of T. The block +// with row index ifst is moved to row ilst, by a sequence of transpositions +// between adjacent blocks. +// +// If ifst points to the second row of a 2×2 block, ifstOut will point to the +// first row, otherwise it will be equal to ifst. +// +// ilstOut will point to the first row of the block in its final position. If ok +// is true, ilstOut may differ from ilst by +1 or -1. +// +// It must hold that +// 0 <= ifst < n, and 0 <= ilst < n, +// otherwise Dtrexc will panic. +// +// If ok is false, two adjacent blocks were too close to swap because the +// problem is very ill-conditioned. T may have been partially reordered, and +// ilstOut will point to the first row of the block at the position to which it +// has been moved. +// +// work must have length at least n, otherwise Dtrexc will panic. +// +// Dtrexc is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrexc(compq lapack.EVComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) { + checkMatrix(n, n, t, ldt) + var wantq bool + switch compq { + default: + panic("lapack: bad value of compq") + case lapack.None: + // Nothing to do because wantq is already false. + case lapack.UpdateSchur: + wantq = true + checkMatrix(n, n, q, ldq) + } + if (ifst < 0 || n <= ifst) && n > 0 { + panic("lapack: ifst out of range") + } + if (ilst < 0 || n <= ilst) && n > 0 { + panic("lapack: ilst out of range") + } + if len(work) < n { + panic(badWork) + } + + ok = true + + // Quick return if possible. + if n <= 1 { + return ifst, ilst, true + } + + // Determine the first row of specified block + // and find out it is 1×1 or 2×2. + if ifst > 0 && t[ifst*ldt+ifst-1] != 0 { + ifst-- + } + nbf := 1 // Size of the first block. + if ifst+1 < n && t[(ifst+1)*ldt+ifst] != 0 { + nbf = 2 + } + // Determine the first row of the final block + // and find out it is 1×1 or 2×2. + if ilst > 0 && t[ilst*ldt+ilst-1] != 0 { + ilst-- + } + nbl := 1 // Size of the last block. + if ilst+1 < n && t[(ilst+1)*ldt+ilst] != 0 { + nbl = 2 + } + + switch { + case ifst == ilst: + return ifst, ilst, true + + case ifst < ilst: + // Update ilst. + switch { + case nbf == 2 && nbl == 1: + ilst-- + case nbf == 1 && nbl == 2: + ilst++ + } + here := ifst + for here < ilst { + // Swap block with next one below. + if nbf == 1 || nbf == 2 { + // Current block either 1×1 or 2×2. + nbnext := 1 // Size of the next block. + if here+nbf+1 < n && t[(here+nbf+1)*ldt+here+nbf] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbf, nbnext, work) + if !ok { + return ifst, here, false + } + here += nbnext + // Test if 2×2 block breaks into two 1×1 blocks. + if nbf == 2 && t[(here+1)*ldt+here] == 0 { + nbf = 3 + } + continue + } + + // Current block consists of two 1×1 blocks each of + // which must be swapped individually. + nbnext := 1 // Size of the next block. + if here+3 < n && t[(here+3)*ldt+here+2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, nbnext, work) + if !ok { + return ifst, here, false + } + if nbnext == 1 { + // Swap two 1×1 blocks, no problems possible. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) + here++ + continue + } + // Recompute nbnext in case 2×2 split. + if t[(here+2)*ldt+here+1] == 0 { + nbnext = 1 + } + if nbnext == 2 { + // 2×2 block did not split. + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) + if !ok { + return ifst, here, false + } + } else { + // 2×2 block did split. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, 1, work) + } + here += 2 + } + return ifst, here, true + + default: // ifst > ilst + here := ifst + for here > ilst { + // Swap block with next one above. + if nbf == 1 || nbf == 2 { + // Current block either 1×1 or 2×2. + nbnext := 1 + if here-2 >= 0 && t[(here-1)*ldt+here-2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, nbf, work) + if !ok { + return ifst, here, false + } + here -= nbnext + // Test if 2×2 block breaks into two 1×1 blocks. + if nbf == 2 && t[(here+1)*ldt+here] == 0 { + nbf = 3 + } + continue + } + + // Current block consists of two 1×1 blocks each of + // which must be swapped individually. + nbnext := 1 + if here-2 >= 0 && t[(here-1)*ldt+here-2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, 1, work) + if !ok { + return ifst, here, false + } + if nbnext == 1 { + // Swap two 1×1 blocks, no problems possible. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbnext, 1, work) + here-- + continue + } + // Recompute nbnext in case 2×2 split. + if t[here*ldt+here-1] == 0 { + nbnext = 1 + } + if nbnext == 2 { + // 2×2 block did not split. + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 2, 1, work) + if !ok { + return ifst, here, false + } + } else { + // 2×2 block did split. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 1, 1, work) + } + here -= 2 + } + return ifst, here, true + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go new file mode 100644 index 00000000..8998f5eb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go @@ -0,0 +1,57 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrti2 computes the inverse of a triangular matrix, storing the result in place +// into a. This is the BLAS level 2 version of the algorithm. +// +// Dtrti2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + bi := blas64.Implementation() + + nonUnit := diag == blas.NonUnit + // TODO(btracey): Replace this with a row-major ordering. + if uplo == blas.Upper { + for j := 0; j < n; j++ { + var ajj float64 + if nonUnit { + ajj = 1 / a[j*lda+j] + a[j*lda+j] = ajj + ajj *= -1 + } else { + ajj = -1 + } + bi.Dtrmv(blas.Upper, blas.NoTrans, diag, j, a, lda, a[j:], lda) + bi.Dscal(j, ajj, a[j:], lda) + } + return + } + for j := n - 1; j >= 0; j-- { + var ajj float64 + if nonUnit { + ajj = 1 / a[j*lda+j] + a[j*lda+j] = ajj + ajj *= -1 + } else { + ajj = -1 + } + if j < n-1 { + bi.Dtrmv(blas.Lower, blas.NoTrans, diag, n-j-1, a[(j+1)*lda+j+1:], lda, a[(j+1)*lda+j:], lda) + bi.Dscal(n-j-1, ajj, a[(j+1)*lda+j:], lda) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go new file mode 100644 index 00000000..25e43ddc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go @@ -0,0 +1,64 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrtri computes the inverse of a triangular matrix, storing the result in place +// into a. This is the BLAS level 3 version of the algorithm which builds upon +// Dtrti2 to operate on matrix blocks instead of only individual columns. +// +// Dtrtri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +func (impl Implementation) Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + if n == 0 { + return false + } + nonUnit := diag == blas.NonUnit + if nonUnit { + for i := 0; i < n; i++ { + if a[i*lda+i] == 0 { + return false + } + } + } + + bi := blas64.Implementation() + + nb := impl.Ilaenv(1, "DTRTRI", "UD", n, -1, -1, -1) + if nb <= 1 || nb > n { + impl.Dtrti2(uplo, diag, n, a, lda) + return true + } + if uplo == blas.Upper { + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dtrmm(blas.Left, blas.Upper, blas.NoTrans, diag, j, jb, 1, a, lda, a[j:], lda) + bi.Dtrsm(blas.Right, blas.Upper, blas.NoTrans, diag, j, jb, -1, a[j*lda+j:], lda, a[j:], lda) + impl.Dtrti2(blas.Upper, diag, jb, a[j*lda+j:], lda) + } + return true + } + nn := ((n - 1) / nb) * nb + for j := nn; j >= 0; j -= nb { + jb := min(nb, n-j) + if j+jb <= n-1 { + bi.Dtrmm(blas.Left, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, 1, a[(j+jb)*lda+j+jb:], lda, a[(j+jb)*lda+j:], lda) + bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, -1, a[j*lda+j:], lda, a[(j+jb)*lda+j:], lda) + } + impl.Dtrti2(blas.Lower, diag, jb, a[j*lda+j:], lda) + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go new file mode 100644 index 00000000..6760796d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrtrs solves a triangular system of the form A * X = B or A^T * X = B. Dtrtrs +// returns whether the solve completed successfully. If A is singular, no solve is performed. +func (impl Implementation) Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) { + nounit := diag == blas.NonUnit + if n == 0 { + return false + } + // Check for singularity. + if nounit { + for i := 0; i < n; i++ { + if a[i*lda+i] == 0 { + return false + } + } + } + bi := blas64.Implementation() + bi.Dtrsm(blas.Left, uplo, trans, diag, n, nrhs, 1, a, lda, b, ldb) + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/general.go b/vendor/gonum.org/v1/gonum/lapack/gonum/general.go new file mode 100644 index 00000000..4006ea70 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/general.go @@ -0,0 +1,143 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "gonum.org/v1/gonum/lapack" +) + +// Implementation is the native Go implementation of LAPACK routines. It +// is built on top of calls to the return of blas64.Implementation(), so while +// this code is in pure Go, the underlying BLAS implementation may not be. +type Implementation struct{} + +var _ lapack.Float64 = Implementation{} + +// This list is duplicated in lapack/cgo. Keep in sync. +const ( + absIncNotOne = "lapack: increment not one or negative one" + badAlpha = "lapack: bad alpha length" + badAuxv = "lapack: auxv has insufficient length" + badBeta = "lapack: bad beta length" + badD = "lapack: d has insufficient length" + badDecompUpdate = "lapack: bad decomp update" + badDiag = "lapack: bad diag" + badDims = "lapack: bad input dimensions" + badDirect = "lapack: bad direct" + badE = "lapack: e has insufficient length" + badEVComp = "lapack: bad EVComp" + badEVJob = "lapack: bad EVJob" + badEVSide = "lapack: bad EVSide" + badGSVDJob = "lapack: bad GSVDJob" + badHowMany = "lapack: bad HowMany" + badIlo = "lapack: ilo out of range" + badIhi = "lapack: ihi out of range" + badIpiv = "lapack: bad permutation length" + badJob = "lapack: bad Job" + badK1 = "lapack: k1 out of range" + badK2 = "lapack: k2 out of range" + badKperm = "lapack: incorrect permutation length" + badLdA = "lapack: index of a out of range" + badNb = "lapack: nb out of range" + badNorm = "lapack: bad norm" + badPivot = "lapack: bad pivot" + badS = "lapack: s has insufficient length" + badShifts = "lapack: bad shifts" + badSide = "lapack: bad side" + badSlice = "lapack: bad input slice length" + badSort = "lapack: bad Sort" + badStore = "lapack: bad store" + badTau = "lapack: tau has insufficient length" + badTauQ = "lapack: tauQ has insufficient length" + badTauP = "lapack: tauP has insufficient length" + badTrans = "lapack: bad trans" + badVn1 = "lapack: vn1 has insufficient length" + badVn2 = "lapack: vn2 has insufficient length" + badUplo = "lapack: illegal triangle" + badWork = "lapack: insufficient working memory" + badZ = "lapack: insufficient z length" + kGTM = "lapack: k > m" + kGTN = "lapack: k > n" + kLT0 = "lapack: k < 0" + mLTN = "lapack: m < n" + nanScale = "lapack: NaN scale factor" + negDimension = "lapack: negative matrix dimension" + negZ = "lapack: negative z value" + nLT0 = "lapack: n < 0" + nLTM = "lapack: n < m" + offsetGTM = "lapack: offset > m" + shortWork = "lapack: working array shorter than declared" + zeroDiv = "lapack: zero divisor" +) + +// checkMatrix verifies the parameters of a matrix input. +func checkMatrix(m, n int, a []float64, lda int) { + if m < 0 { + panic("lapack: has negative number of rows") + } + if n < 0 { + panic("lapack: has negative number of columns") + } + if lda < n { + panic("lapack: stride less than number of columns") + } + if len(a) < (m-1)*lda+n { + panic("lapack: insufficient matrix slice length") + } +} + +func checkVector(n int, v []float64, inc int) { + if n < 0 { + panic("lapack: negative vector length") + } + if (inc > 0 && (n-1)*inc >= len(v)) || (inc < 0 && (1-n)*inc >= len(v)) { + panic("lapack: insufficient vector slice length") + } +} + +func checkSymBanded(ab []float64, n, kd, lda int) { + if n < 0 { + panic("lapack: negative banded length") + } + if kd < 0 { + panic("lapack: negative bandwidth value") + } + if lda < kd+1 { + panic("lapack: stride less than number of bands") + } + if len(ab) < (n-1)*lda+kd { + panic("lapack: insufficient banded vector length") + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +const ( + // dlamchE is the machine epsilon. For IEEE this is 2^{-53}. + dlamchE = 1.0 / (1 << 53) + + // dlamchB is the radix of the machine (the base of the number system). + dlamchB = 2 + + // dlamchP is base * eps. + dlamchP = dlamchB * dlamchE + + // dlamchS is the "safe minimum", that is, the lowest number such that + // 1/dlamchS does not overflow, or also the smallest normal number. + // For IEEE this is 2^{-1022}. + dlamchS = 1.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) +) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go new file mode 100644 index 00000000..126a6f9d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 gonum + +// Iladlc scans a matrix for its last non-zero column. Returns -1 if the matrix +// is all zeros. +// +// Iladlc is an internal routine. It is exported for testing purposes. +func (Implementation) Iladlc(m, n int, a []float64, lda int) int { + if n == 0 || m == 0 { + return n - 1 + } + checkMatrix(m, n, a, lda) + + // Test common case where corner is non-zero. + if a[n-1] != 0 || a[(m-1)*lda+(n-1)] != 0 { + return n - 1 + } + + // Scan each row tracking the highest column seen. + highest := -1 + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + if a[i*lda+j] != 0 { + highest = max(highest, j) + break + } + } + } + return highest +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go new file mode 100644 index 00000000..1ec7c523 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum 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 gonum + +// Iladlr scans a matrix for its last non-zero row. Returns -1 if the matrix +// is all zeros. +// +// Iladlr is an internal routine. It is exported for testing purposes. +func (Implementation) Iladlr(m, n int, a []float64, lda int) int { + if m == 0 { + return m - 1 + } + + checkMatrix(m, n, a, lda) + + // Check the common case where the corner is non-zero + if a[(m-1)*lda] != 0 || a[(m-1)*lda+n-1] != 0 { + return m - 1 + } + for i := m - 1; i >= 0; i-- { + for j := 0; j < n; j++ { + if a[i*lda+j] != 0 { + return i + } + } + } + return -1 +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go new file mode 100644 index 00000000..750e3c44 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go @@ -0,0 +1,387 @@ +// Copyright ©2015 The gonum 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 gonum + +// Ilaenv returns algorithm tuning parameters for the algorithm given by the +// input string. ispec specifies the parameter to return: +// 1: The optimal block size for a blocked algorithm. +// 2: The minimum block size for a blocked algorithm. +// 3: The block size of unprocessed data at which a blocked algorithm should +// crossover to an unblocked version. +// 4: The number of shifts. +// 5: The minimum column dimension for blocking to be used. +// 6: The crossover point for SVD (to use QR factorization or not). +// 7: The number of processors. +// 8: The crossover point for multi-shift in QR and QZ methods for non-symmetric eigenvalue problems. +// 9: Maximum size of the subproblems in divide-and-conquer algorithms. +// 10: ieee NaN arithmetic can be trusted not to trap. +// 11: infinity arithmetic can be trusted not to trap. +// 12...16: parameters for Dhseqr and related functions. See Iparmq for more +// information. +// +// Ilaenv is an internal routine. It is exported for testing purposes. +func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, n4 int) int { + // TODO(btracey): Replace this with a constant lookup? A list of constants? + sname := s[0] == 'S' || s[0] == 'D' + cname := s[0] == 'C' || s[0] == 'Z' + if !sname && !cname { + panic("lapack: bad name") + } + c2 := s[1:3] + c3 := s[3:6] + c4 := c3[1:3] + + switch ispec { + default: + panic("lapack: bad ispec") + case 1: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 32 + } + return 32 + case "HRD": + if sname { + return 32 + } + return 32 + case "BRD": + if sname { + return 32 + } + return 32 + case "TRI": + if sname { + return 64 + } + return 64 + } + case "PO": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + } + case "SY": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + case "TRD": + return 32 + case "GST": + return 64 + } + case "HE": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + return 64 + case "TRD": + return 32 + case "GST": + return 64 + } + case "OR": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + case 'M': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + case 'M': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + } + case "GB": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + if n4 <= 64 { + return 1 + } + return 32 + } + if n4 <= 64 { + return 1 + } + return 32 + } + case "PB": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + if n4 <= 64 { + return 1 + } + return 32 + } + if n4 <= 64 { + return 1 + } + return 32 + } + case "TR": + switch c3 { + default: + panic("lapack: bad function name") + case "TRI": + if sname { + return 64 + } + return 64 + case "EVC": + if sname { + return 64 + } + return 64 + } + case "LA": + switch c3 { + default: + panic("lapack: bad function name") + case "UUM": + if sname { + return 64 + } + return 64 + } + case "ST": + if sname && c3 == "EBZ" { + return 1 + } + panic("lapack: bad function name") + } + case 2: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 2 + } + return 2 + case "HRD": + if sname { + return 2 + } + return 2 + case "BRD": + if sname { + return 2 + } + return 2 + case "TRI": + if sname { + return 2 + } + return 2 + } + case "SY": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 8 + } + return 8 + case "TRD": + if sname { + return 2 + } + panic("lapack: bad function name") + } + case "HE": + if c3 == "TRD" { + return 2 + } + panic("lapack: bad function name") + case "OR": + if !sname { + panic("lapack: bad function name") + } + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + case 'M': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + case 'M': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + } + } + case 3: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 128 + } + return 128 + case "HRD": + if sname { + return 128 + } + return 128 + case "BRD": + if sname { + return 128 + } + return 128 + } + case "SY": + if sname && c3 == "TRD" { + return 32 + } + panic("lapack: bad function name") + case "HE": + if c3 == "TRD" { + return 32 + } + panic("lapack: bad function name") + case "OR": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 128 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 128 + } + } + } + case 4: + // Used by xHSEQR + return 6 + case 5: + // Not used + return 2 + case 6: + // Used by xGELSS and xGESVD + return int(float64(min(n1, n2)) * 1.6) + case 7: + // Not used + return 1 + case 8: + // Used by xHSEQR + return 50 + case 9: + // used by xGELSD and xGESDD + return 25 + case 10: + // Go guarantees ieee + return 1 + case 11: + // Go guarantees ieee + return 1 + case 12, 13, 14, 15, 16: + // Dhseqr and related functions for eigenvalue problems. + return impl.Iparmq(ispec, s, opts, n1, n2, n3, n4) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go new file mode 100644 index 00000000..4fc255c5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go @@ -0,0 +1,115 @@ +// Copyright ©2016 The gonum 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 gonum + +import "math" + +// Iparmq returns problem and machine dependent parameters useful for Dhseqr and +// related subroutines for eigenvalue problems. +// +// ispec specifies the parameter to return: +// 12: Crossover point between Dlahqr and Dlaqr0. Will be at least 11. +// 13: Deflation window size. +// 14: Nibble crossover point. Determines when to skip a multi-shift QR sweep. +// 15: Number of simultaneous shifts in a multishift QR iteration. +// 16: Select structured matrix multiply. +// For other values of ispec Iparmq will panic. +// +// name is the name of the calling function. name must be in uppercase but this +// is not checked. +// +// opts is not used and exists for future use. +// +// n is the order of the Hessenberg matrix H. +// +// ilo and ihi specify the block [ilo:ihi+1,ilo:ihi+1] that is being processed. +// +// lwork is the amount of workspace available. +// +// Except for ispec input parameters are not checked. +// +// Iparmq is an internal routine. It is exported for testing purposes. +func (Implementation) Iparmq(ispec int, name, opts string, n, ilo, ihi, lwork int) int { + nh := ihi - ilo + 1 + ns := 2 + switch { + case nh >= 30: + ns = 4 + case nh >= 60: + ns = 10 + case nh >= 150: + ns = max(10, nh/int(math.Log(float64(nh))/math.Ln2)) + case nh >= 590: + ns = 64 + case nh >= 3000: + ns = 128 + case nh >= 6000: + ns = 256 + } + ns = max(2, ns-(ns%2)) + + switch ispec { + default: + panic("lapack: bad ispec") + + case 12: + // Matrices of order smaller than nmin get sent to Dlahqr, the + // classic double shift algorithm. This must be at least 11. + const nmin = 75 + return nmin + + case 13: + const knwswp = 500 + if nh <= knwswp { + return ns + } + return 3 * ns / 2 + + case 14: + // Skip a computationally expensive multi-shift QR sweep with + // Dlaqr5 whenever aggressive early deflation finds at least + // nibble*(window size)/100 deflations. The default, small, + // value reflects the expectation that the cost of looking + // through the deflation window with Dlaqr3 will be + // substantially smaller. + const nibble = 14 + return nibble + + case 15: + return ns + + case 16: + if len(name) != 6 { + panic("lapack: bad name") + } + const ( + k22min = 14 + kacmin = 14 + ) + var acc22 int + switch { + case name[1:] == "GGHRD" || name[1:] == "GGHD3": + acc22 = 1 + if nh >= k22min { + acc22 = 2 + } + case name[3:] == "EXC": + if nh >= kacmin { + acc22 = 1 + } + if nh >= k22min { + acc22 = 2 + } + case name[1:] == "HSEQR" || name[1:5] == "LAQR": + if ns >= kacmin { + acc22 = 1 + } + if ns >= k22min { + acc22 = 2 + } + } + return acc22 + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/lapack_test.go b/vendor/gonum.org/v1/gonum/lapack/gonum/lapack_test.go new file mode 100644 index 00000000..5a34fa85 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/lapack_test.go @@ -0,0 +1,441 @@ +// Copyright ©2015 The gonum 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 gonum + +import ( + "testing" + + "gonum.org/v1/gonum/lapack/testlapack" +) + +var appengine bool + +var impl = Implementation{} + +func TestDbdsqr(t *testing.T) { + testlapack.DbdsqrTest(t, impl) +} + +func TestDhseqr(t *testing.T) { + testlapack.DhseqrTest(t, impl) +} + +func TestDgebak(t *testing.T) { + testlapack.DgebakTest(t, impl) +} + +func TestDgebal(t *testing.T) { + testlapack.DgebalTest(t, impl) +} + +func TestDgebd2(t *testing.T) { + testlapack.Dgebd2Test(t, impl) +} + +func TestDgebrd(t *testing.T) { + if appengine { + t.Skip("non-asm implementation fails test") + } + testlapack.DgebrdTest(t, impl) +} + +func TestDgecon(t *testing.T) { + testlapack.DgeconTest(t, impl) +} + +func TestDgeev(t *testing.T) { + if appengine { + t.Skip("non-asm implementation fails test") + } + testlapack.DgeevTest(t, impl) +} + +func TestDgehd2(t *testing.T) { + testlapack.Dgehd2Test(t, impl) +} + +func TestDgehrd(t *testing.T) { + testlapack.DgehrdTest(t, impl) +} + +func TestDgelqf(t *testing.T) { + testlapack.DgelqfTest(t, impl) +} + +func TestDgelq2(t *testing.T) { + testlapack.Dgelq2Test(t, impl) +} + +func TestDgeql2(t *testing.T) { + testlapack.Dgeql2Test(t, impl) +} + +func TestDgels(t *testing.T) { + testlapack.DgelsTest(t, impl) +} + +func TestDgerq2(t *testing.T) { + testlapack.Dgerq2Test(t, impl) +} + +func TestDgeqp3(t *testing.T) { + testlapack.Dgeqp3Test(t, impl) +} + +func TestDgeqr2(t *testing.T) { + testlapack.Dgeqr2Test(t, impl) +} + +func TestDgeqrf(t *testing.T) { + testlapack.DgeqrfTest(t, impl) +} + +func TestDgerqf(t *testing.T) { + testlapack.DgerqfTest(t, impl) +} + +func TestDgesvd(t *testing.T) { + testlapack.DgesvdTest(t, impl) +} + +func TestDgetri(t *testing.T) { + testlapack.DgetriTest(t, impl) +} + +func TestDgetf2(t *testing.T) { + testlapack.Dgetf2Test(t, impl) +} + +func TestDgetrf(t *testing.T) { + testlapack.DgetrfTest(t, impl) +} + +func TestDgetrs(t *testing.T) { + testlapack.DgetrsTest(t, impl) +} + +func TestDggsvd3(t *testing.T) { + testlapack.Dggsvd3Test(t, impl) +} + +func TestDggsvp3(t *testing.T) { + testlapack.Dggsvp3Test(t, impl) +} + +func TestDlabrd(t *testing.T) { + testlapack.DlabrdTest(t, impl) +} + +func TestDlacn2(t *testing.T) { + testlapack.Dlacn2Test(t, impl) +} + +func TestDlacpy(t *testing.T) { + testlapack.DlacpyTest(t, impl) +} + +func TestDlae2(t *testing.T) { + testlapack.Dlae2Test(t, impl) +} + +func TestDlaev2(t *testing.T) { + testlapack.Dlaev2Test(t, impl) +} + +func TestDlaexc(t *testing.T) { + testlapack.DlaexcTest(t, impl) +} + +func TestDlags2(t *testing.T) { + testlapack.Dlags2Test(t, impl) +} + +func TestDlahqr(t *testing.T) { + testlapack.DlahqrTest(t, impl) +} + +func TestDlahr2(t *testing.T) { + testlapack.Dlahr2Test(t, impl) +} + +func TestDlaln2(t *testing.T) { + testlapack.Dlaln2Test(t, impl) +} + +func TestDlange(t *testing.T) { + testlapack.DlangeTest(t, impl) +} + +func TestDlapy2(t *testing.T) { + testlapack.Dlapy2Test(t, impl) +} + +func TestDlapll(t *testing.T) { + testlapack.DlapllTest(t, impl) +} + +func TestDlapmt(t *testing.T) { + testlapack.DlapmtTest(t, impl) +} + +func TestDlas2(t *testing.T) { + testlapack.Dlas2Test(t, impl) +} + +func TestDlascl(t *testing.T) { + testlapack.DlasclTest(t, impl) +} + +func TestDlaset(t *testing.T) { + testlapack.DlasetTest(t, impl) +} + +func TestDlasrt(t *testing.T) { + testlapack.DlasrtTest(t, impl) +} + +func TestDlaswp(t *testing.T) { + testlapack.DlaswpTest(t, impl) +} + +func TestDlasy2(t *testing.T) { + testlapack.Dlasy2Test(t, impl) +} + +func TestDlanst(t *testing.T) { + testlapack.DlanstTest(t, impl) +} + +func TestDlansy(t *testing.T) { + testlapack.DlansyTest(t, impl) +} + +func TestDlantr(t *testing.T) { + testlapack.DlantrTest(t, impl) +} + +func TestDlanv2(t *testing.T) { + testlapack.Dlanv2Test(t, impl) +} + +func TestDlaqr04(t *testing.T) { + testlapack.Dlaqr04Test(t, impl) +} + +func TestDlaqp2(t *testing.T) { + testlapack.Dlaqp2Test(t, impl) +} + +func TestDlaqps(t *testing.T) { + testlapack.DlaqpsTest(t, impl) +} + +func TestDlaqr1(t *testing.T) { + testlapack.Dlaqr1Test(t, impl) +} + +func TestDlaqr23(t *testing.T) { + testlapack.Dlaqr23Test(t, impl) +} + +func TestDlaqr5(t *testing.T) { + testlapack.Dlaqr5Test(t, impl) +} + +func TestDlarf(t *testing.T) { + testlapack.DlarfTest(t, impl) +} + +func TestDlarfb(t *testing.T) { + testlapack.DlarfbTest(t, impl) +} + +func TestDlarfg(t *testing.T) { + testlapack.DlarfgTest(t, impl) +} + +func TestDlarft(t *testing.T) { + testlapack.DlarftTest(t, impl) +} + +func TestDlarfx(t *testing.T) { + testlapack.DlarfxTest(t, impl) +} + +func TestDlartg(t *testing.T) { + testlapack.DlartgTest(t, impl) +} + +func TestDlasq1(t *testing.T) { + testlapack.Dlasq1Test(t, impl) +} + +func TestDlasq2(t *testing.T) { + testlapack.Dlasq2Test(t, impl) +} + +func TestDlasq3(t *testing.T) { + testlapack.Dlasq3Test(t, impl) +} + +func TestDlasq4(t *testing.T) { + testlapack.Dlasq4Test(t, impl) +} + +func TestDlasq5(t *testing.T) { + testlapack.Dlasq5Test(t, impl) +} + +func TestDlasr(t *testing.T) { + testlapack.DlasrTest(t, impl) +} + +func TestDlasv2(t *testing.T) { + testlapack.Dlasv2Test(t, impl) +} + +func TestDlatrd(t *testing.T) { + testlapack.DlatrdTest(t, impl) +} + +func TestDlatrs(t *testing.T) { + testlapack.DlatrsTest(t, impl) +} + +func TestDorg2r(t *testing.T) { + testlapack.Dorg2rTest(t, impl) +} + +func TestDorgbr(t *testing.T) { + testlapack.DorgbrTest(t, impl) +} + +func TestDorghr(t *testing.T) { + testlapack.DorghrTest(t, impl) +} + +func TestDorg2l(t *testing.T) { + testlapack.Dorg2lTest(t, impl) +} + +func TestDorgl2(t *testing.T) { + testlapack.Dorgl2Test(t, impl) +} + +func TestDorglq(t *testing.T) { + testlapack.DorglqTest(t, impl) +} + +func TestDorgql(t *testing.T) { + testlapack.DorgqlTest(t, impl) +} + +func TestDorgqr(t *testing.T) { + testlapack.DorgqrTest(t, impl) +} + +func TestDorgtr(t *testing.T) { + testlapack.DorgtrTest(t, impl) +} + +func TestDormbr(t *testing.T) { + testlapack.DormbrTest(t, impl) +} + +func TestDormhr(t *testing.T) { + testlapack.DormhrTest(t, impl) +} + +func TestDorml2(t *testing.T) { + testlapack.Dorml2Test(t, impl) +} + +func TestDormlq(t *testing.T) { + testlapack.DormlqTest(t, impl) +} + +func TestDormqr(t *testing.T) { + testlapack.DormqrTest(t, impl) +} + +func TestDormr2(t *testing.T) { + testlapack.Dormr2Test(t, impl) +} + +func TestDorm2r(t *testing.T) { + testlapack.Dorm2rTest(t, impl) +} + +func TestDpbtf2(t *testing.T) { + testlapack.Dpbtf2Test(t, impl) +} + +func TestDpocon(t *testing.T) { + testlapack.DpoconTest(t, impl) +} + +func TestDpotf2(t *testing.T) { + testlapack.Dpotf2Test(t, impl) +} + +func TestDpotrf(t *testing.T) { + testlapack.DpotrfTest(t, impl) +} + +func TestDrscl(t *testing.T) { + testlapack.DrsclTest(t, impl) +} + +func TestDsteqr(t *testing.T) { + testlapack.DsteqrTest(t, impl) +} + +func TestDsterf(t *testing.T) { + testlapack.DsterfTest(t, impl) +} + +func TestDsyev(t *testing.T) { + testlapack.DsyevTest(t, impl) +} + +func TestDsytd2(t *testing.T) { + testlapack.Dsytd2Test(t, impl) +} + +func TestDsytrd(t *testing.T) { + testlapack.DsytrdTest(t, impl) +} + +func TestDtgsja(t *testing.T) { + testlapack.DtgsjaTest(t, impl) +} + +func TestDtrcon(t *testing.T) { + testlapack.DtrconTest(t, impl) +} + +func TestDtrevc3(t *testing.T) { + testlapack.Dtrevc3Test(t, impl) +} + +func TestDtrexc(t *testing.T) { + testlapack.DtrexcTest(t, impl) +} + +func TestDtrti2(t *testing.T) { + testlapack.Dtrti2Test(t, impl) +} + +func TestDtrtri(t *testing.T) { + testlapack.DtrtriTest(t, impl) +} + +func TestIladlc(t *testing.T) { + testlapack.IladlcTest(t, impl) +} + +func TestIladlr(t *testing.T) { + testlapack.IladlrTest(t, impl) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlahr2test/main.go b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlahr2test/main.go new file mode 100644 index 00000000..d2c5b604 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlahr2test/main.go @@ -0,0 +1,101 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// dlahr2test generates test data for Dlahr2. Test cases are stored in +// gzip-compressed JSON file testlapack/testdata/dlahr2data.json.gz which is +// read during testing by testlapack/dlahr2.go. +// +// This program uses cgo to call Fortran version of DLAHR2. Therefore, matrices +// passed to the Fortran routine are in column-major format but are written into +// the output file in row-major format. +package main + +import ( + "compress/gzip" + "encoding/json" + "log" + "math/rand" + "os" + "path/filepath" + + "gonum.org/v1/gonum/lapack/internal/testdata/netlib" +) + +type Dlahr2Test struct { + N, K, NB int + A []float64 + + AWant []float64 + TWant []float64 + YWant []float64 + TauWant []float64 +} + +func main() { + file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlahr2data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + w := gzip.NewWriter(file) + + rnd := rand.New(rand.NewSource(1)) + + var tests []Dlahr2Test + for _, n := range []int{4, 5, 6, 7, 11} { + for k := 0; k <= n/2; k++ { + for nb := 1; nb <= k; nb++ { + ain := genrand(n, n-k+1, rnd) + a := make([]float64, len(ain)) + copy(a, ain) + + t := genrand(nb, nb, rnd) + y := genrand(n, nb, rnd) + tau := genrand(nb, 1, rnd) + + netlib.Dlahr2(n, k, nb, a, n, tau, t, nb, y, n) + + tests = append(tests, Dlahr2Test{ + N: n, + K: k, + NB: nb, + A: rowMajor(n, n-k+1, ain), + AWant: rowMajor(n, n-k+1, a), + TWant: rowMajor(nb, nb, t), + YWant: rowMajor(n, nb, y), + TauWant: tau, + }) + } + } + } + json.NewEncoder(w).Encode(tests) + + err = w.Close() + if err != nil { + log.Fatal(err) + } +} + +// genrand returns a general r×c matrix with random entries. +func genrand(r, c int, rnd *rand.Rand) []float64 { + m := make([]float64, r*c) + for i := range m { + m[i] = rnd.NormFloat64() + } + return m +} + +// rowMajor returns the given r×c column-major matrix a in row-major format. +func rowMajor(r, c int, a []float64) []float64 { + if len(a) != r*c { + panic("testdata: slice length mismatch") + } + m := make([]float64, len(a)) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m[i*c+j] = a[i+j*r] + } + } + return m +} diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlaqr5test/main.go b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlaqr5test/main.go new file mode 100644 index 00000000..b3980e93 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlaqr5test/main.go @@ -0,0 +1,185 @@ +// Copyright ©2016 The gonum 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 program generates test data for Dlaqr5. Test cases are stored in +// gzip-compressed JSON file testlapack/testdata/dlaqr5data.json.gz which is +// read during testing by testlapack/dlaqr5.go. +// +// This program uses cgo to call Fortran version of DLAQR5. Therefore, matrices +// passed to the Fortran routine are in column-major format but are written into +// the output file in row-major format. +package main + +import ( + "compress/gzip" + "encoding/json" + "log" + "math/rand" + "os" + "path/filepath" + + "gonum.org/v1/gonum/lapack/internal/testdata/netlib" +) + +type Dlaqr5Test struct { + WantT bool + N int + NShifts int + KTop, KBot int + ShiftR, ShiftI []float64 + H []float64 + + HWant []float64 + ZWant []float64 +} + +func main() { + file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlaqr5data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + w := gzip.NewWriter(file) + + rnd := rand.New(rand.NewSource(1)) + + var tests []Dlaqr5Test + for _, wantt := range []bool{true, false} { + for _, n := range []int{2, 3, 4, 5, 6, 7, 11} { + for k := 0; k <= min(5, n); k++ { + npairs := k + if npairs == 0 { + npairs = 2 * n + } + for ktop := 0; ktop < n-1; ktop++ { + for kbot := ktop + 1; kbot < n; kbot++ { + sr, si := shiftpairs(npairs, rnd) + nshfts := len(sr) + + v := genrand(nshfts/2, 3, rnd) + u := genrand(3*nshfts-3, 3*nshfts-3, rnd) + wh := genrand(3*nshfts-3, n, rnd) + nh := n + wv := genrand(n, 3*nshfts-3, rnd) + nv := n + + h := hessrand(n, rnd) + if ktop > 0 { + h[ktop+(ktop-1)*n] = 0 + } + if kbot < n-1 { + h[kbot+1+kbot*n] = 0 + } + hin := make([]float64, len(h)) + copy(hin, h) + z := eye(n) + + netlib.Dlaqr5(wantt, true, 2, + n, ktop+1, kbot+1, + nshfts, sr, si, + h, n, + 1, n, z, n, + v, 3, + u, 3*nshfts-3, + nh, wh, nh, + nv, wv, 3*nshfts-3) + + tests = append(tests, Dlaqr5Test{ + WantT: wantt, + N: n, + NShifts: nshfts, + KTop: ktop, + KBot: kbot, + ShiftR: sr, + ShiftI: si, + H: rowMajor(n, n, hin), + HWant: rowMajor(n, n, h), + ZWant: rowMajor(n, n, z), + }) + } + } + } + } + } + json.NewEncoder(w).Encode(tests) + + err = w.Close() + if err != nil { + log.Fatal(err) + } +} + +// genrand returns a general r×c matrix with random entries. +func genrand(r, c int, rnd *rand.Rand) []float64 { + m := make([]float64, r*c) + for i := range m { + m[i] = rnd.NormFloat64() + } + return m +} + +// eye returns an identity matrix of order n. +func eye(n int) []float64 { + m := make([]float64, n*n) + for i := 0; i < n*n; i += n + 1 { + m[i] = 1 + } + return m +} + +// hessrand returns a Hessenberg matrix of order n with random non-zero entries +// in column-major format. +func hessrand(n int, rnd *rand.Rand) []float64 { + h := make([]float64, n*n) + for j := 0; j < n; j++ { + for i := 0; i <= min(j+1, n-1); i++ { + h[i+j*n] = rnd.NormFloat64() + } + } + return h +} + +// shiftpairs generates k real and complex conjugate shift pairs. That is, the +// length of sr and si is 2*k. +func shiftpairs(k int, rnd *rand.Rand) (sr, si []float64) { + sr = make([]float64, 2*k) + si = make([]float64, 2*k) + for i := 0; i < len(sr); { + if rnd.Float64() < 0.5 || i == len(sr)-1 { + sr[i] = rnd.NormFloat64() + i++ + continue + } + // Generate a complex conjugate pair. + r := rnd.NormFloat64() + c := rnd.NormFloat64() + sr[i] = r + si[i] = c + sr[i+1] = r + si[i+1] = -c + i += 2 + } + return sr, si +} + +// rowMajor returns the given r×c column-major matrix a in row-major format. +func rowMajor(r, c int, a []float64) []float64 { + if len(a) != r*c { + panic("testdata: slice length mismatch") + } + m := make([]float64, len(a)) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m[i*c+j] = a[i+j*r] + } + } + return m +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Makefile b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Makefile new file mode 100644 index 00000000..f9f94446 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Makefile @@ -0,0 +1,27 @@ +FC = gfortran +FFLAGS = -O2 + +targets = testdlasq1 testdlasq2 testdlasq3 testdlasq4 +objects = dlamch.o lsame.o xerbla.o ieeeck.o iparmq.o ilaenv.o dlasrt.o \ + dlaisnan.o disnan.o dlasq6.o dlasq5.o dlasq4.o dlasq3.o dlasq2.o + +default : $(targets) +.PHONY : default + +testdlasq1 : testdlasq1.o $(objects) dcopy.o dlas2.o dlascl.o dlasq1.o + +testdlasq2 : testdlasq2.o $(objects) + +testdlasq3 : testdlasq3.o $(objects) + +testdlasq4 : testdlasq4.o $(objects) + +% : %.o + $(FC) $(FFLAGS) $^ -o $@ + +%.o : %.f90 + $(FC) $(FFLAGS) -c -o $@ $< + +clean : + rm -f *.o $(targets) *.txt +.PHONY : clean \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Readme.md b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Readme.md new file mode 100644 index 00000000..65c47448 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/Readme.md @@ -0,0 +1,23 @@ +This set of codes generates tests for the dlasq* routines. + +The high level routines are testdlasq*.f90. The testdlasq*.f90 routines are intended in combination with the routines in gonum/lapack/testlapack. +During execution, these high-level routines record the inputs and outputs +to the executed subroutines. For example, testdlasq3, when executed, +generates files gen4tests.txt and gen5tests.txt that record the inputs +and outputs to the evaluation of dlasq4 and dlasq5 respectively. The output +format in gen*tests.txt is the struct literal that matches the respective test +in gonum/lapack/testlapack/dlasq*.go. Thus, these generated tests can be copied +into the testing routine to test the native implementation. + +The testing routines in testlapack have code for generating inputs for these +fortran routines. Typically, one would isolate the particular failing test, +and modify the testlapack routine to print it to the terminal, for example +in testlapack/dlasq3.go one might add + + printDlasq3FortranInput(test) + os.Exit(1) + +This prints variable initialization for dlasq3 routine to the terminal, which +can be copied and pasted into testdlasq3.f90. Please note that this process +is not completely automated. Some of the other initialization may need to +change, particularly the size allocation of the data array(s). \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dcopy.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dcopy.f new file mode 100644 index 00000000..d9d5ac7a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dcopy.f @@ -0,0 +1,115 @@ +*> \brief \b DCOPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DCOPY copies a vector, x, to a vector, y. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,7) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DX(I) + END DO + IF (N.LT.7) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,7 + DY(I) = DX(I) + DY(I+1) = DX(I+1) + DY(I+2) = DX(I+2) + DY(I+3) = DX(I+3) + DY(I+4) = DX(I+4) + DY(I+5) = DX(I+5) + DY(I+6) = DX(I+6) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/disnan.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/disnan.f new file mode 100644 index 00000000..355b8279 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/disnan.f @@ -0,0 +1,80 @@ +*> \brief \b DISNAN tests input for NaN. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DISNAN( DIN ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. +*> otherwise. To be replaced by the Fortran 2003 intrinsic in the +*> future. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN +*> \verbatim +*> DIN is DOUBLE PRECISION +*> Input to test for NaN. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DISNAN( DIN ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL DLAISNAN + EXTERNAL DLAISNAN +* .. +* .. Executable Statements .. + DISNAN = DLAISNAN(DIN,DIN) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlaisnan.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlaisnan.f new file mode 100644 index 00000000..58595c5c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlaisnan.f @@ -0,0 +1,91 @@ +*> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN1, DIN2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This routine is not for general use. It exists solely to avoid +*> over-optimization in DISNAN. +*> +*> DLAISNAN checks for NaNs by comparing its two arguments for +*> inequality. NaN is the only floating-point value where NaN != NaN +*> returns .TRUE. To check for NaNs, pass the same variable as both +*> arguments. +*> +*> A compiler must assume that the two arguments are +*> not the same variable, and the test will not be optimized away. +*> Interprocedural or whole-program optimization may delete this +*> test. The ISNAN functions will be replaced by the correct +*> Fortran 03 intrinsic once the intrinsic is widely available. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN1 +*> \verbatim +*> DIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] DIN2 +*> \verbatim +*> DIN2 is DOUBLE PRECISION +*> Two numbers to compare for inequality. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN1, DIN2 +* .. +* +* ===================================================================== +* +* .. Executable Statements .. + DLAISNAN = (DIN1.NE.DIN2) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlamch.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlamch.f new file mode 100644 index 00000000..25c2c8e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlamch.f @@ -0,0 +1,193 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2011 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlas2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlas2.f new file mode 100644 index 00000000..81077f94 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlas2.f @@ -0,0 +1,183 @@ +*> \brief \b DLAS2 computes singular values of a 2-by-2 triangular matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAS2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION F, G, H, SSMAX, SSMIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAS2 computes the singular values of the 2-by-2 matrix +*> [ F G ] +*> [ 0 H ]. +*> On return, SSMIN is the smaller singular value and SSMAX is the +*> larger singular value. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] F +*> \verbatim +*> F is DOUBLE PRECISION +*> The (1,1) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] G +*> \verbatim +*> G is DOUBLE PRECISION +*> The (1,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] H +*> \verbatim +*> H is DOUBLE PRECISION +*> The (2,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[out] SSMIN +*> \verbatim +*> SSMIN is DOUBLE PRECISION +*> The smaller singular value. +*> \endverbatim +*> +*> \param[out] SSMAX +*> \verbatim +*> SSMAX is DOUBLE PRECISION +*> The larger singular value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Barring over/underflow, all output quantities are correct to within +*> a few units in the last place (ulps), even in the absence of a guard +*> digit in addition/subtraction. +*> +*> In IEEE arithmetic, the code works correctly if one matrix element is +*> infinite. +*> +*> Overflow will not occur unless the largest singular value itself +*> overflows, or is within a few ulps of overflow. (On machines with +*> partial overflow, like the Cray, overflow may occur if the largest +*> singular value is within a factor of 2 of overflow.) +*> +*> Underflow is harmless if underflow is gradual. Otherwise, results +*> may correspond to a matrix modified by perturbations of size near +*> the underflow threshold. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION F, G, H, SSMAX, SSMIN +* .. +* +* ==================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AS, AT, AU, C, FA, FHMN, FHMX, GA, HA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + FA = ABS( F ) + GA = ABS( G ) + HA = ABS( H ) + FHMN = MIN( FA, HA ) + FHMX = MAX( FA, HA ) + IF( FHMN.EQ.ZERO ) THEN + SSMIN = ZERO + IF( FHMX.EQ.ZERO ) THEN + SSMAX = GA + ELSE + SSMAX = MAX( FHMX, GA )*SQRT( ONE+ + $ ( MIN( FHMX, GA ) / MAX( FHMX, GA ) )**2 ) + END IF + ELSE + IF( GA.LT.FHMX ) THEN + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + AU = ( GA / FHMX )**2 + C = TWO / ( SQRT( AS*AS+AU )+SQRT( AT*AT+AU ) ) + SSMIN = FHMN*C + SSMAX = FHMX / C + ELSE + AU = FHMX / GA + IF( AU.EQ.ZERO ) THEN +* +* Avoid possible harmful underflow if exponent range +* asymmetric (true SSMIN may not underflow even if +* AU underflows) +* + SSMIN = ( FHMN*FHMX ) / GA + SSMAX = GA + ELSE + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + C = ONE / ( SQRT( ONE+( AS*AU )**2 )+ + $ SQRT( ONE+( AT*AU )**2 ) ) + SSMIN = ( FHMN*C )*AU + SSMIN = SSMIN + SSMIN + SSMAX = GA / ( C+C ) + END IF + END IF + END IF + RETURN +* +* End of DLAS2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlascl.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlascl.f new file mode 100644 index 00000000..9b9b33c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlascl.f @@ -0,0 +1,364 @@ +*> \brief \b DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASCL + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER TYPE +* INTEGER INFO, KL, KU, LDA, M, N +* DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASCL multiplies the M by N real matrix A by the real scalar +*> CTO/CFROM. This is done without over/underflow as long as the final +*> result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that +*> A may be full, upper triangular, lower triangular, upper Hessenberg, +*> or banded. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TYPE +*> \verbatim +*> TYPE is CHARACTER*1 +*> TYPE indices the storage type of the input matrix. +*> = 'G': A is a full matrix. +*> = 'L': A is a lower triangular matrix. +*> = 'U': A is an upper triangular matrix. +*> = 'H': A is an upper Hessenberg matrix. +*> = 'B': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the lower +*> half stored. +*> = 'Q': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the upper +*> half stored. +*> = 'Z': A is a band matrix with lower bandwidth KL and upper +*> bandwidth KU. See DGBTRF for storage details. +*> \endverbatim +*> +*> \param[in] KL +*> \verbatim +*> KL is INTEGER +*> The lower bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] KU +*> \verbatim +*> KU is INTEGER +*> The upper bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] CFROM +*> \verbatim +*> CFROM is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] CTO +*> \verbatim +*> CTO is DOUBLE PRECISION +*> +*> The matrix A is multiplied by CTO/CFROM. A(I,J) is computed +*> without over/underflow if the final result CTO*A(I,J)/CFROM +*> can be represented without over/underflow. CFROM must be +*> nonzero. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The matrix to be multiplied by CTO/CFROM. See TYPE for the +*> storage type. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> 0 - successful exit +*> <0 - if INFO = -i, the i-th argument had an illegal value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, KL, KU, LDA, M, N + DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL DONE + INTEGER I, ITYPE, J, K1, K2, K3, K4 + DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH, DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 +* + IF( LSAME( TYPE, 'G' ) ) THEN + ITYPE = 0 + ELSE IF( LSAME( TYPE, 'L' ) ) THEN + ITYPE = 1 + ELSE IF( LSAME( TYPE, 'U' ) ) THEN + ITYPE = 2 + ELSE IF( LSAME( TYPE, 'H' ) ) THEN + ITYPE = 3 + ELSE IF( LSAME( TYPE, 'B' ) ) THEN + ITYPE = 4 + ELSE IF( LSAME( TYPE, 'Q' ) ) THEN + ITYPE = 5 + ELSE IF( LSAME( TYPE, 'Z' ) ) THEN + ITYPE = 6 + ELSE + ITYPE = -1 + END IF +* + IF( ITYPE.EQ.-1 ) THEN + INFO = -1 + ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN + INFO = -4 + ELSE IF( DISNAN(CTO) ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -6 + ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR. + $ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN + INFO = -7 + ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN + INFO = -9 + ELSE IF( ITYPE.GE.4 ) THEN + IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN + INFO = -2 + ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR. + $ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) ) + $ THEN + INFO = -3 + ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR. + $ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR. + $ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN + INFO = -9 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASCL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) + $ RETURN +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM +* + CFROMC = CFROM + CTOC = CTO +* + 10 CONTINUE + CFROM1 = CFROMC*SMLNUM + IF( CFROM1.EQ.CFROMC ) THEN +! CFROMC is an inf. Multiply by a correctly signed zero for +! finite CTOC, or a NaN if CTOC is infinite. + MUL = CTOC / CFROMC + DONE = .TRUE. + CTO1 = CTOC + ELSE + CTO1 = CTOC / BIGNUM + IF( CTO1.EQ.CTOC ) THEN +! CTOC is either 0 or an inf. In both cases, CTOC itself +! serves as the correct multiplication factor. + MUL = CTOC + DONE = .TRUE. + CFROMC = ONE + ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN + MUL = SMLNUM + DONE = .FALSE. + CFROMC = CFROM1 + ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN + MUL = BIGNUM + DONE = .FALSE. + CTOC = CTO1 + ELSE + MUL = CTOC / CFROMC + DONE = .TRUE. + END IF + END IF +* + IF( ITYPE.EQ.0 ) THEN +* +* Full matrix +* + DO 30 J = 1, N + DO 20 I = 1, M + A( I, J ) = A( I, J )*MUL + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( ITYPE.EQ.1 ) THEN +* +* Lower triangular matrix +* + DO 50 J = 1, N + DO 40 I = J, M + A( I, J ) = A( I, J )*MUL + 40 CONTINUE + 50 CONTINUE +* + ELSE IF( ITYPE.EQ.2 ) THEN +* +* Upper triangular matrix +* + DO 70 J = 1, N + DO 60 I = 1, MIN( J, M ) + A( I, J ) = A( I, J )*MUL + 60 CONTINUE + 70 CONTINUE +* + ELSE IF( ITYPE.EQ.3 ) THEN +* +* Upper Hessenberg matrix +* + DO 90 J = 1, N + DO 80 I = 1, MIN( J+1, M ) + A( I, J ) = A( I, J )*MUL + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( ITYPE.EQ.4 ) THEN +* +* Lower half of a symmetric band matrix +* + K3 = KL + 1 + K4 = N + 1 + DO 110 J = 1, N + DO 100 I = 1, MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 100 CONTINUE + 110 CONTINUE +* + ELSE IF( ITYPE.EQ.5 ) THEN +* +* Upper half of a symmetric band matrix +* + K1 = KU + 2 + K3 = KU + 1 + DO 130 J = 1, N + DO 120 I = MAX( K1-J, 1 ), K3 + A( I, J ) = A( I, J )*MUL + 120 CONTINUE + 130 CONTINUE +* + ELSE IF( ITYPE.EQ.6 ) THEN +* +* Band matrix +* + K1 = KL + KU + 2 + K2 = KL + 1 + K3 = 2*KL + KU + 1 + K4 = KL + KU + 1 + M + DO 150 J = 1, N + DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 140 CONTINUE + 150 CONTINUE +* + END IF +* + IF( .NOT.DONE ) + $ GO TO 10 +* + RETURN +* +* End of DLASCL +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq1.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq1.f new file mode 100644 index 00000000..f0847781 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq1.f @@ -0,0 +1,226 @@ +*> \brief \b DLASQ1 computes the singular values of a real square bidiagonal matrix. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ1 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ1( N, D, E, WORK, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ), WORK( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ1 computes the singular values of a real N-by-N bidiagonal +*> matrix with diagonal D and off-diagonal E. The singular values +*> are computed to high relative accuracy, in the absence of +*> denormalization, underflow and overflow. The algorithm was first +*> presented in +*> +*> "Accurate singular values and differential qd algorithms" by K. V. +*> Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, +*> 1994, +*> +*> and the present implementation is described in "An implementation of +*> the dqds Algorithm (Positive Case)", LAPACK Working Note. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of rows and columns in the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, D contains the diagonal elements of the +*> bidiagonal matrix whose SVD is desired. On normal exit, +*> D contains the singular values in decreasing order. +*> \endverbatim +*> +*> \param[in,out] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N) +*> On entry, elements E(1:N-1) contain the off-diagonal elements +*> of the bidiagonal matrix whose SVD is desired. +*> On exit, E is overwritten. +*> \endverbatim +*> +*> \param[out] WORK +*> \verbatim +*> WORK is DOUBLE PRECISION array, dimension (4*N) +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> > 0: the algorithm failed +*> = 1, a split was marked by a positive value in E +*> = 2, current block of Z not diagonalized after 100*N +*> iterations (in inner while loop) On exit D and E +*> represent a matrix with the same singular values +*> which the calling subroutine could use to finish the +*> computation, or even feed back into DLASQ1 +*> = 3, termination criterion of outer while loop not met +*> (program created more than N unreduced blocks) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ1( N, D, E, WORK, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ), WORK( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I, IINFO + DOUBLE PRECISION EPS, SCALE, SAFMIN, SIGMN, SIGMX +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DLAS2, DLASCL, DLASQ2, DLASRT, XERBLA +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ1', -INFO ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN + D( 1 ) = ABS( D( 1 ) ) + RETURN + ELSE IF( N.EQ.2 ) THEN + CALL DLAS2( D( 1 ), E( 1 ), D( 2 ), SIGMN, SIGMX ) + D( 1 ) = SIGMX + D( 2 ) = SIGMN + RETURN + END IF +* +* Estimate the largest singular value. +* + SIGMX = ZERO + DO 10 I = 1, N - 1 + D( I ) = ABS( D( I ) ) + SIGMX = MAX( SIGMX, ABS( E( I ) ) ) + 10 CONTINUE + D( N ) = ABS( D( N ) ) +* +* Early return if SIGMX is zero (matrix is already diagonal). +* + IF( SIGMX.EQ.ZERO ) THEN + CALL DLASRT( 'D', N, D, IINFO ) + RETURN + END IF +* + DO 20 I = 1, N + SIGMX = MAX( SIGMX, D( I ) ) + 20 CONTINUE +* +* Copy D and E into WORK (in the Z format) and scale (squaring the +* input data makes scaling by a power of the radix pointless). +* + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + SCALE = SQRT( EPS / SAFMIN ) + + CALL DCOPY( N, D, 1, WORK( 1 ), 2 ) + CALL DCOPY( N-1, E, 1, WORK( 2 ), 2 ) + CALL DLASCL( 'G', 0, 0, SIGMX, SCALE, 2*N-1, 1, WORK, 2*N-1, + $ IINFO ) +* +* Compute the q's and e's. +* + DO 30 I = 1, 2*N - 1 + WORK( I ) = WORK( I )**2 + 30 CONTINUE + WORK( 2*N ) = ZERO +* + + CALL DLASQ2( N, WORK, INFO ) +* + IF( INFO.EQ.0 ) THEN + DO 40 I = 1, N + D( I ) = SQRT( WORK( I ) ) + 40 CONTINUE + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO ) + ELSE IF( INFO.EQ.2 ) THEN +* +* Maximum number of iterations exceeded. Move data from WORK +* into D and E so the calling subroutine can try to finish +* + DO I = 1, N + D( I ) = SQRT( WORK( 2*I-1 ) ) + E( I ) = SQRT( WORK( 2*I ) ) + END DO + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO ) + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, E, N, IINFO ) + END IF +* + RETURN +* +* End of DLASQ1 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq2.f new file mode 100644 index 00000000..602dffc9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq2.f @@ -0,0 +1,652 @@ +*> \brief \b DLASQ2 computes all the eigenvalues of the symmetric positive definite tridiagonal matrix associated with the qd Array Z to high relative accuracy. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ2( N, Z, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ2 computes all the eigenvalues of the symmetric positive +*> definite tridiagonal matrix associated with the qd array Z to high +*> relative accuracy are computed to high relative accuracy, in the +*> absence of denormalization, underflow and overflow. +*> +*> To see the relation of Z to the tridiagonal matrix, let L be a +*> unit lower bidiagonal matrix with subdiagonals Z(2,4,6,,..) and +*> let U be an upper bidiagonal matrix with 1's above and diagonal +*> Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the +*> symmetric tridiagonal to which it is similar. +*> +*> Note : DLASQ2 defines a logical variable, IEEE, which is true +*> on machines which follow ieee-754 floating-point standard in their +*> handling of infinities and NaNs, and false otherwise. This variable +*> is passed to DLASQ3. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of rows and columns in the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> On entry Z holds the qd array. On exit, entries 1 to N hold +*> the eigenvalues in decreasing order, Z( 2*N+1 ) holds the +*> trace, and Z( 2*N+2 ) holds the sum of the eigenvalues. If +*> N > 2, then Z( 2*N+3 ) holds the iteration count, Z( 2*N+4 ) +*> holds NDIVS/NIN^2, and Z( 2*N+5 ) holds the percentage of +*> shifts that failed. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if the i-th argument is a scalar and had an illegal +*> value, then INFO = -i, if the i-th argument is an +*> array and the j-entry had an illegal value, then +*> INFO = -(i*100+j) +*> > 0: the algorithm failed +*> = 1, a split was marked by a positive value in E +*> = 2, current block of Z not diagonalized after 100*N +*> iterations (in inner while loop). On exit Z holds +*> a qd array with the same eigenvalues as the given Z. +*> = 3, termination criterion of outer while loop not met +*> (program created more than N unreduced blocks) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Local Variables: I0:N0 defines a current unreduced segment of Z. +*> The shifts are accumulated in SIGMA. Iteration count is in ITER. +*> Ping-pong is controlled by PP (alternates between 0 and 1). +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLASQ2( N, Z, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, HALF, ONE, TWO, FOUR, HUNDRD + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0, + $ TWO = 2.0D0, FOUR = 4.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL IEEE + INTEGER I0, I1, I4, IINFO, IPN4, ITER, IWHILA, IWHILB, + $ K, KMIN, N0, N1, NBIG, NDIV, NFAIL, PP, SPLT, + $ TTYPE + DOUBLE PRECISION D, DEE, DEEMIN, DESIG, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, E, EMAX, EMIN, EPS, G, OLDEMN, QMAX, + $ QMIN, S, SAFMIN, SIGMA, T, TAU, TEMP, TOL, + $ TOL2, TRACE, ZMAX, TEMPE, TEMPQ +* .. +* .. External Subroutines .. + EXTERNAL DLASQ3, DLASRT, XERBLA +* .. +* .. External Functions .. + INTEGER ILAENV + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH, ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* (in case DLASQ2 is not called by DLASQ1) +* + INFO = 0 + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DLASQ2', 1 ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN +* +* 1-by-1 case. +* + IF( Z( 1 ).LT.ZERO ) THEN + INFO = -201 + CALL XERBLA( 'DLASQ2', 2 ) + END IF + RETURN + ELSE IF( N.EQ.2 ) THEN +* +* 2-by-2 case. +* + IF( Z( 2 ).LT.ZERO .OR. Z( 3 ).LT.ZERO ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( 3 ).GT.Z( 1 ) ) THEN + D = Z( 3 ) + Z( 3 ) = Z( 1 ) + Z( 1 ) = D + END IF + Z( 5 ) = Z( 1 ) + Z( 2 ) + Z( 3 ) + IF( Z( 2 ).GT.Z( 3 )*TOL2 ) THEN + T = HALF*( ( Z( 1 )-Z( 3 ) )+Z( 2 ) ) + S = Z( 3 )*( Z( 2 ) / T ) + IF( S.LE.T ) THEN + S = Z( 3 )*( Z( 2 ) / ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( 3 )*( Z( 2 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( 1 ) + ( S+Z( 2 ) ) + Z( 3 ) = Z( 3 )*( Z( 1 ) / T ) + Z( 1 ) = T + END IF + Z( 2 ) = Z( 3 ) + Z( 6 ) = Z( 2 ) + Z( 1 ) + RETURN + END IF +* +* Check for negative data and compute sums of q's and e's. +* + Z( 2*N ) = ZERO + EMIN = Z( 2 ) + QMAX = ZERO + ZMAX = ZERO + D = ZERO + E = ZERO +* + DO 10 K = 1, 2*( N-1 ), 2 + IF( Z( K ).LT.ZERO ) THEN + INFO = -( 200+K ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( K+1 ).LT.ZERO ) THEN + INFO = -( 200+K+1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( K ) + E = E + Z( K+1 ) + QMAX = MAX( QMAX, Z( K ) ) + EMIN = MIN( EMIN, Z( K+1 ) ) + ZMAX = MAX( QMAX, ZMAX, Z( K+1 ) ) + 10 CONTINUE + IF( Z( 2*N-1 ).LT.ZERO ) THEN + INFO = -( 200+2*N-1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( 2*N-1 ) + QMAX = MAX( QMAX, Z( 2*N-1 ) ) + ZMAX = MAX( QMAX, ZMAX ) +* +* Check for diagonality. +* + IF( E.EQ.ZERO ) THEN + DO 20 K = 2, N + Z( K ) = Z( 2*K-1 ) + 20 CONTINUE + CALL DLASRT( 'D', N, Z, IINFO ) + Z( 2*N-1 ) = D + RETURN + END IF +* + TRACE = D + E +* +* Check for zero data. +* + IF( TRACE.EQ.ZERO ) THEN + Z( 2*N-1 ) = ZERO + RETURN + END IF +* +* Check whether the machine is IEEE conformable. +* + IEEE = ILAENV( 10, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 .AND. + $ ILAENV( 11, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 +* +* Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). +* + DO 30 K = 2*N, 2, -2 + Z( 2*K ) = ZERO + Z( 2*K-1 ) = Z( K ) + Z( 2*K-2 ) = ZERO + Z( 2*K-3 ) = Z( K-1 ) + 30 CONTINUE +* + I0 = 1 + N0 = N +* +* Reverse the qd-array, if warranted. +* + IF( CBIAS*Z( 4*I0-3 ).LT.Z( 4*N0-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 40 I4 = 4*I0, 2*( I0+N0-1 ), 4 + + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + 40 CONTINUE + END IF +* +* Initial split checking via dqd and Li's test. +* + PP = 0 +* + DO 80 K = 1, 2 +* + D = Z( 4*N0+PP-3 ) + DO 50 I4 = 4*( N0-1 ) + PP, 4*I0 + PP, -4 + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + D = Z( I4-3 ) + ELSE + D = Z( I4-3 )*( D / ( D+Z( I4-1 ) ) ) + END IF + 50 CONTINUE +* +* dqd maps Z to ZZ plus Li's test. +* + EMIN = Z( 4*I0+PP+1 ) + D = Z( 4*I0+PP-3 ) + DO 60 I4 = 4*I0 + PP, 4*( N0-1 ) + PP, 4 + Z( I4-2*PP-2 ) = D + Z( I4-1 ) + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + Z( I4-2*PP-2 ) = D + Z( I4-2*PP ) = ZERO + D = Z( I4+1 ) + ELSE IF( SAFMIN*Z( I4+1 ).LT.Z( I4-2*PP-2 ) .AND. + $ SAFMIN*Z( I4-2*PP-2 ).LT.Z( I4+1 ) ) THEN + TEMP = Z( I4+1 ) / Z( I4-2*PP-2 ) + Z( I4-2*PP ) = Z( I4-1 )*TEMP + D = D*TEMP + ELSE + Z( I4-2*PP ) = Z( I4+1 )*( Z( I4-1 ) / Z( I4-2*PP-2 ) ) + D = Z( I4+1 )*( D / Z( I4-2*PP-2 ) ) + END IF + EMIN = MIN( EMIN, Z( I4-2*PP ) ) + 60 CONTINUE + Z( 4*N0-PP-2 ) = D +* +* Now find qmax. +* + QMAX = Z( 4*I0-PP-2 ) + DO 70 I4 = 4*I0 - PP + 2, 4*N0 - PP - 2, 4 + QMAX = MAX( QMAX, Z( I4 ) ) + 70 CONTINUE +* +* Prepare for the next iteration on K. +* + PP = 1 - PP + 80 CONTINUE + +* +* Initialise variables to pass to DLASQ3. +* + TTYPE = 0 + DMIN1 = ZERO + DMIN2 = ZERO + DN = ZERO + DN1 = ZERO + DN2 = ZERO + G = ZERO + TAU = ZERO +* + ITER = 2 + NFAIL = 0 + NDIV = 2*( N0-I0 ) +* + DO 160 IWHILA = 1, N + 1 + + IF( N0.LT.1 ) THEN + GO TO 170 + END IF +* +* While array unfinished do +* +* E(N0) holds the value of SIGMA when submatrix in I0:N0 +* splits from the rest of the array, but is negated. +* + DESIG = ZERO + IF( N0.EQ.N ) THEN + SIGMA = ZERO + ELSE + SIGMA = -Z( 4*N0-1 ) + END IF + IF( SIGMA.LT.ZERO ) THEN + INFO = 1 + RETURN + END IF +* +* Find last unreduced submatrix's top index I0, find QMAX and +* EMIN. Find Gershgorin-type bound if Q's much greater than E's. +* + EMAX = ZERO + IF( N0.GT.I0 ) THEN + EMIN = ABS( Z( 4*N0-5 ) ) + ELSE + EMIN = ZERO + END IF + QMIN = Z( 4*N0-3 ) + QMAX = QMIN + DO 90 I4 = 4*N0, 8, -4 + IF( Z( I4-5 ).LE.ZERO ) + $ GO TO 100 + IF( QMIN.GE.FOUR*EMAX ) THEN + QMIN = MIN( QMIN, Z( I4-3 ) ) + EMAX = MAX( EMAX, Z( I4-5 ) ) + END IF + QMAX = MAX( QMAX, Z( I4-7 )+Z( I4-5 ) ) + EMIN = MIN( EMIN, Z( I4-5 ) ) + 90 CONTINUE + I4 = 4 +* + 100 CONTINUE + I0 = I4 / 4 + + PP = 0 +* + IF( N0-I0.GT.1 ) THEN + DEE = Z( 4*I0-3 ) + DEEMIN = DEE + KMIN = I0 + DO 110 I4 = 4*I0+1, 4*N0-3, 4 + DEE = Z( I4 )*( DEE /( DEE+Z( I4-2 ) ) ) + IF( DEE.LE.DEEMIN ) THEN + DEEMIN = DEE + KMIN = ( I4+3 )/4 + END IF + 110 CONTINUE + IF( (KMIN-I0)*2.LT.N0-KMIN .AND. + $ DEEMIN.LE.HALF*Z(4*N0-3) ) THEN + IPN4 = 4*( I0+N0 ) + PP = 2 + DO 120 I4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-2 ) + Z( I4-2 ) = Z( IPN4-I4-2 ) + Z( IPN4-I4-2 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + TEMP = Z( I4 ) + Z( I4 ) = Z( IPN4-I4-4 ) + Z( IPN4-I4-4 ) = TEMP + 120 CONTINUE + END IF + END IF +* +* Put -(initial shift) into DMIN. +* + DMIN = -MAX( ZERO, QMIN-TWO*SQRT( QMIN )*SQRT( EMAX ) ) +* +* Now I0:N0 is unreduced. +* PP = 0 for ping, PP = 1 for pong. +* PP = 2 indicates that flipping was applied to the Z array and +* and that the tests for deflation upon entry in DLASQ3 +* should not be performed. +* + NBIG = 100*( N0-I0+1 ) + DO 140 IWHILB = 1, NBIG + + IF( I0.GT.N0 ) + $ GO TO 150 +* + + ! Print out test cases + + write(3,*) "{" + write(3,*) "i0: ", I0, "," + write(3,*) "n0: ", N0, "," + write(3,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, 4*n + write (3,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (3,*) "}," + write (3,*) "pp: ", PP, "," + write (3,*) "dmin: ", DMIN, "," + write (3,*) "desig:", DESIG, "," + write (3,*) "qmax: ", QMAX, "," + write (3,*) "ttype:", TTYPE, "," + write (3,*) "dmin1:", DMIN1, "," + write (3,*) "dmin2:", DMIN2, "," + write (3,*) "dn: ", DN, "," + write (3,*) "dn1: ", DN1, "," + write (3,*) "dn2: ", DN2, "," + write (3,*) "g: ", G, "," + write (3,*) "tau: ", TAU, "," + write (3,*) "nFail:", NFAIL, "," + write (3,*) "iter: ", ITER, "," + write (3,*) "sigma:", SIGMA, "," + write (3,*) "nDiv: ", NDIV, "," + +* While submatrix unfinished take a good dqds step. +* + + + CALL DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) + + + ! Write the outputs + write(3,'(9999(g0))',advance="no") "zOut: []float64{" + do i = 1, 4*n + write (3,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (3,*) "}," + write (3,*) "i0Out:",I0, "," + write (3,*) "n0Out:", N0, "," + write (3,*) "ppOut:", PP, "," + write (3,*) "dminOut:", DMIN, "," + write (3,*) "desigOut:", DESIG, "," + write (3,*) "sigmaOut:", SIGMA, "," + write (3,*) "qmaxOut:", QMAX, "," + write (3,*) "nFailOut:", NFAIL, "," + write (3,*) "iterOut:", ITER, "," + write (3,*) "nDivOut:", NDIV, "," + write (3,*) "ttypeOut:", TTYPE, "," + write (3,*) "dmin1Out:", DMIN1, "," + write (3,*) "dmin2Out:", DMIN2, "," + write (3,*) "dnOut:", DN, "," + write (3,*) "dn1Out:", DN1, "," + write (3,*) "dn2Out:", DN2, "," + write (3,*) "gOut:", G, "," + write (3,*) "tauOut:", TAU, "," + + write (3,*) "}," + + + PP = 1 - PP +* +* When EMIN is very small check for splits. +* + IF( PP.EQ.0 .AND. N0-I0.GE.3 ) THEN + IF( Z( 4*N0 ).LE.TOL2*QMAX .OR. + $ Z( 4*N0-1 ).LE.TOL2*SIGMA ) THEN + SPLT = I0 - 1 + QMAX = Z( 4*I0-3 ) + EMIN = Z( 4*I0-1 ) + OLDEMN = Z( 4*I0 ) + DO 130 I4 = 4*I0, 4*( N0-3 ), 4 + IF( Z( I4 ).LE.TOL2*Z( I4-3 ) .OR. + $ Z( I4-1 ).LE.TOL2*SIGMA ) THEN + Z( I4-1 ) = -SIGMA + SPLT = I4 / 4 + QMAX = ZERO + EMIN = Z( I4+3 ) + OLDEMN = Z( I4+4 ) + ELSE + QMAX = MAX( QMAX, Z( I4+1 ) ) + EMIN = MIN( EMIN, Z( I4-1 ) ) + OLDEMN = MIN( OLDEMN, Z( I4 ) ) + END IF + 130 CONTINUE + Z( 4*N0-1 ) = EMIN + Z( 4*N0 ) = OLDEMN + I0 = SPLT + 1 + END IF + END IF +* + 140 CONTINUE +* + INFO = 2 +* +* Maximum number of iterations exceeded, restore the shift +* SIGMA and place the new d's and e's in a qd array. +* This might need to be done for several blocks +* + I1 = I0 + N1 = N0 + 145 CONTINUE + + TEMPQ = Z( 4*I0-3 ) + Z( 4*I0-3 ) = Z( 4*I0-3 ) + SIGMA + DO K = I0+1, N0 + TEMPE = Z( 4*K-5 ) + Z( 4*K-5 ) = Z( 4*K-5 ) * (TEMPQ / Z( 4*K-7 )) + TEMPQ = Z( 4*K-3 ) + Z( 4*K-3 ) = Z( 4*K-3 ) + SIGMA + TEMPE - Z( 4*K-5 ) + END DO +* +* Prepare to do this on the previous block if there is one +* + IF( I1.GT.1 ) THEN + N1 = I1-1 + DO WHILE( ( I1.GE.2 ) .AND. ( Z(4*I1-5).GE.ZERO ) ) + I1 = I1 - 1 + END DO + SIGMA = -Z(4*N1-1) + GO TO 145 + END IF + + DO K = 1, N + Z( 2*K-1 ) = Z( 4*K-3 ) +* +* Only the block 1..N0 is unfinished. The rest of the e's +* must be essentially zero, although sometimes other data +* has been stored in them. +* + IF( K.LT.N0 ) THEN + Z( 2*K ) = Z( 4*K-1 ) + ELSE + Z( 2*K ) = 0 + END IF + END DO + RETURN +* +* end IWHILB +* + 150 CONTINUE +* + 160 CONTINUE +* + INFO = 3 + RETURN +* +* end IWHILA +* + 170 CONTINUE +* + +* Move q's to the front. +* + DO 180 K = 2, N + Z( K ) = Z( 4*K-3 ) + 180 CONTINUE +* +* Sort and compute sum of eigenvalues. +* + CALL DLASRT( 'D', N, Z, IINFO ) +* + + E = ZERO + DO 190 K = N, 1, -1 + E = E + Z( K ) + 190 CONTINUE +* +* Store trace, sum(eigenvalues) and information on performance. +* + + Z( 2*N+1 ) = TRACE + Z( 2*N+2 ) = E + Z( 2*N+3 ) = DBLE( ITER ) + Z( 2*N+4 ) = DBLE( NDIV ) / DBLE( N**2 ) + Z( 2*N+5 ) = HUNDRD*NFAIL / DBLE( ITER ) + + RETURN +* +* End of DLASQ2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq3.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq3.f new file mode 100644 index 00000000..1c4e8ecf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq3.f @@ -0,0 +1,498 @@ +*> \brief \b DLASQ3 checks for deflation, computes a shift and calls dqds. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ3 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, +* ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, +* DN2, G, TAU ) +* +* .. Scalar Arguments .. +* LOGICAL IEEE +* INTEGER I0, ITER, N0, NDIV, NFAIL, PP +* DOUBLE PRECISION DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, +* $ QMAX, SIGMA, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ3 checks for deflation, computes a shift (TAU) and calls dqds. +*> In case of failure it changes shifts, and tries again until output +*> is positive. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in,out] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. +*> \endverbatim +*> +*> \param[in,out] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> PP=2 indicates that flipping was applied to the Z array +*> and that the initial tests for deflation should not be +*> performed. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] SIGMA +*> \verbatim +*> SIGMA is DOUBLE PRECISION +*> Sum of shifts used in current segment. +*> \endverbatim +*> +*> \param[in,out] DESIG +*> \verbatim +*> DESIG is DOUBLE PRECISION +*> Lower order part of SIGMA +*> \endverbatim +*> +*> \param[in] QMAX +*> \verbatim +*> QMAX is DOUBLE PRECISION +*> Maximum value of q. +*> \endverbatim +*> +*> \param[out] NFAIL +*> \verbatim +*> NFAIL is INTEGER +*> Number of times shift was too big. +*> \endverbatim +*> +*> \param[out] ITER +*> \verbatim +*> ITER is INTEGER +*> Number of iterations. +*> \endverbatim +*> +*> \param[out] NDIV +*> \verbatim +*> NDIV is INTEGER +*> Number of divisions. +*> \endverbatim +*> +*> \param[in] IEEE +*> \verbatim +*> IEEE is LOGICAL +*> Flag for IEEE or non IEEE arithmetic (passed to DLASQ5). +*> \endverbatim +*> +*> \param[in,out] TTYPE +*> \verbatim +*> TTYPE is INTEGER +*> Shift type. +*> \endverbatim +*> +*> \param[in,out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN1 +*> \verbatim +*> DN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN2 +*> \verbatim +*> DN2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] G +*> \verbatim +*> G is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> +*> These are passed as arguments in order to save their values +*> between calls to DLASQ3. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, ITER, N0, NDIV, NFAIL, PP + DOUBLE PRECISION DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, + $ QMAX, SIGMA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, QURTR, HALF, ONE, TWO, HUNDRD + PARAMETER ( ZERO = 0.0D0, QURTR = 0.250D0, HALF = 0.5D0, + $ ONE = 1.0D0, TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER IPN4, J4, N0IN, NN, TTYPE + DOUBLE PRECISION EPS, S, T, TEMP, TOL, TOL2 +* .. +* .. External Subroutines .. + EXTERNAL DLASQ4, DLASQ5, DLASQ6 +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + LOGICAL DISNAN + EXTERNAL DISNAN, DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + + N0IN = N0 + EPS = DLAMCH( 'Precision' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* +* Check for deflation. +* + 10 CONTINUE +* + IF( N0.LT.I0 ) + $ RETURN + IF( N0.EQ.I0 ) + $ GO TO 20 + NN = 4*N0 + PP + IF( N0.EQ.( I0+1 ) ) + $ GO TO 40 +* +* Check whether E(N0-1) is negligible, 1 eigenvalue. +* + IF( Z( NN-5 ).GT.TOL2*( SIGMA+Z( NN-3 ) ) .AND. + $ Z( NN-2*PP-4 ).GT.TOL2*Z( NN-7 ) ) + $ GO TO 30 +* + 20 CONTINUE +* + Z( 4*N0-3 ) = Z( 4*N0+PP-3 ) + SIGMA + N0 = N0 - 1 + GO TO 10 +* +* Check whether E(N0-2) is negligible, 2 eigenvalues. +* + 30 CONTINUE +* + IF( Z( NN-9 ).GT.TOL2*SIGMA .AND. + $ Z( NN-2*PP-8 ).GT.TOL2*Z( NN-11 ) ) + $ GO TO 50 +* + 40 CONTINUE +* + IF( Z( NN-3 ).GT.Z( NN-7 ) ) THEN + S = Z( NN-3 ) + Z( NN-3 ) = Z( NN-7 ) + Z( NN-7 ) = S + END IF + T = HALF*( ( Z( NN-7 )-Z( NN-3 ) )+Z( NN-5 ) ) + IF( Z( NN-5 ).GT.Z( NN-3 )*TOL2.AND.T.NE.ZERO ) THEN + S = Z( NN-3 )*( Z( NN-5 ) / T ) + IF( S.LE.T ) THEN + S = Z( NN-3 )*( Z( NN-5 ) / + $ ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( NN-3 )*( Z( NN-5 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( NN-7 ) + ( S+Z( NN-5 ) ) + Z( NN-3 ) = Z( NN-3 )*( Z( NN-7 ) / T ) + Z( NN-7 ) = T + END IF + Z( 4*N0-7 ) = Z( NN-7 ) + SIGMA + Z( 4*N0-3 ) = Z( NN-3 ) + SIGMA + N0 = N0 - 2 + GO TO 10 +* + 50 CONTINUE + IF( PP.EQ.2 ) + $ PP = 0 +* +* Reverse the qd-array, if warranted. +* + + IF( DMIN.LE.ZERO .OR. N0.LT.N0IN ) THEN + IF( CBIAS*Z( 4*I0+PP-3 ).LT.Z( 4*N0+PP-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 60 J4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( J4-3 ) + Z( J4-3 ) = Z( IPN4-J4-3 ) + Z( IPN4-J4-3 ) = TEMP + TEMP = Z( J4-2 ) + Z( J4-2 ) = Z( IPN4-J4-2 ) + Z( IPN4-J4-2 ) = TEMP + TEMP = Z( J4-1 ) + Z( J4-1 ) = Z( IPN4-J4-5 ) + Z( IPN4-J4-5 ) = TEMP + TEMP = Z( J4 ) + Z( J4 ) = Z( IPN4-J4-4 ) + Z( IPN4-J4-4 ) = TEMP + 60 CONTINUE + IF( N0-I0.LE.4 ) THEN + Z( 4*N0+PP-1 ) = Z( 4*I0+PP-1 ) + Z( 4*N0-PP ) = Z( 4*I0-PP ) + END IF + DMIN2 = MIN( DMIN2, Z( 4*N0+PP-1 ) ) + Z( 4*N0+PP-1 ) = MIN( Z( 4*N0+PP-1 ), Z( 4*I0+PP-1 ), + $ Z( 4*I0+PP+3 ) ) + Z( 4*N0-PP ) = MIN( Z( 4*N0-PP ), Z( 4*I0-PP ), + $ Z( 4*I0-PP+4 ) ) + QMAX = MAX( QMAX, Z( 4*I0+PP-3 ), Z( 4*I0+PP+1 ) ) + DMIN = -ZERO + END IF + END IF +* +* Choose a shift. +* + ! Print out DLASQ4 test cases + write(4,*) "{" + write(4,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, NN + write (4,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (4,*) "}," + write (4,*) "i0: ", I0, "," + write (4,*) "n0: ", N0, "," + write (4,*) "pp: ", PP, "," + write (4,*) "n0in: ", N0IN, "," + write (4,*) "dmin: ", DMIN, "," + write (4,*) "dmin1:", DMIN1, "," + write (4,*) "dmin2:", DMIN2, "," + write (4,*) "dn: ", DN, "," + write (4,*) "dn1: ", DN1, "," + write (4,*) "dn2: ", DN2, "," + write (4,*) "tau: ", TAU, "," + write (4,*) "ttype: ", TTYPE, "," + write (4,*) "g: ", G, "," + CALL DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, DN1, + $ DN2, TAU, TTYPE, G ) + + write(4,'(9999(g0))',advance="no") "zOut: []float64{" + do i = 1, NN + write (4,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (4,*) "}," + write (4,*) "tauOut: ", TAU, "," + write (4,*) "ttypeOut: ", TTYPE, "," + write (4,*) "gOut: ", G, "," + write (4,*) "}," + +* +* Call dqds until DMIN > 0. +* + 70 CONTINUE +* + + write(5,*) "{" + write(5,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, NN + write (5,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (5,*) "}," + write (5,*) "i0: ", I0, "," + write (5,*) "n0: ", N0, "," + write (5,*) "pp: ", PP, "," + write (5,*) "tau: ", TAU, "," + write (5,*) "sigma: ", SIGMA, "," + write (5,*) "dmin: ", DMIN, "," + write (5,*) "dmin1:", DMIN1, "," + write (5,*) "dmin2:", DMIN2, "," + write (5,*) "dn: ", DN, "," + write (5,*) "dnm1: ", DN1, "," + write (5,*) "dnm2: ", DN2, "," + + + CALL DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, IEEE, EPS ) + + + + write (5,*) "i0Out: ", I0, "," + write (5,*) "n0Out: ", N0, "," + write (5,*) "ppOut: ", PP, "," + write (5,*) "tauOut: ", TAU, "," + write (5,*) "sigmaOut: ", SIGMA, "," + write (5,*) "dminOut: ", DMIN, "," + write (5,*) "dmin1Out:", DMIN1, "," + write (5,*) "dmin2Out:", DMIN2, "," + write (5,*) "dnOut: ", DN, "," + write (5,*) "dnm1Out: ", DN1, "," + write (5,*) "dnm2Out: ", DN2, "," + write (5,*) "}," + +* + NDIV = NDIV + ( N0-I0+2 ) + + ITER = ITER + 1 +* +* Check status. +* + + IF( DMIN.GE.ZERO .AND. DMIN1.GE.ZERO ) THEN +* +* Success. +* + GO TO 90 +* + ELSE IF( DMIN.LT.ZERO .AND. DMIN1.GT.ZERO .AND. + $ Z( 4*( N0-1 )-PP ).LT.TOL*( SIGMA+DN1 ) .AND. + $ ABS( DN ).LT.TOL*SIGMA ) THEN + +* +* Convergence hidden by negative DN. +* + Z( 4*( N0-1 )-PP+2 ) = ZERO + DMIN = ZERO + GO TO 90 + ELSE IF( DMIN.LT.ZERO ) THEN + +* +* TAU too big. Select new TAU and try again. +* + NFAIL = NFAIL + 1 + IF( TTYPE.LT.-22 ) THEN +* +* Failed twice. Play it safe. +* + TAU = ZERO + ELSE IF( DMIN1.GT.ZERO ) THEN +* +* Late failure. Gives excellent shift. +* + TAU = ( TAU+DMIN )*( ONE-TWO*EPS ) + TTYPE = TTYPE - 11 + ELSE +* +* Early failure. Divide by 4. +* + TAU = QURTR*TAU + TTYPE = TTYPE - 12 + END IF + GO TO 70 + ELSE IF( DISNAN( DMIN ) ) THEN +* +* NaN. +* + IF( TAU.EQ.ZERO ) THEN + GO TO 80 + ELSE + TAU = ZERO + GO TO 70 + END IF + ELSE +* +* Possible underflow. Play it safe. +* + GO TO 80 + END IF +* +* Risk of underflow. +* + 80 CONTINUE + + CALL DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DN1, DN2 ) + + + NDIV = NDIV + ( N0-I0+2 ) + ITER = ITER + 1 + TAU = ZERO +* + 90 CONTINUE + + IF( TAU.LT.SIGMA ) THEN + DESIG = DESIG + TAU + T = SIGMA + DESIG + DESIG = DESIG - ( T-SIGMA ) + ELSE + T = SIGMA + TAU + DESIG = SIGMA - ( T-TAU ) + DESIG + END IF + SIGMA = T +* + RETURN +* +* End of DLASQ3 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq4.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq4.f new file mode 100644 index 00000000..f60f775b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq4.f @@ -0,0 +1,427 @@ +*> \brief \b DLASQ4 computes an approximation to the smallest eigenvalue using values of d from the previous transform. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ4 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, +* DN1, DN2, TAU, TTYPE, G ) +* +* .. Scalar Arguments .. +* INTEGER I0, N0, N0IN, PP, TTYPE +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ4 computes an approximation TAU to the smallest eigenvalue +*> using values of d from the previous transform. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[in] N0IN +*> \verbatim +*> N0IN is INTEGER +*> The value of N0 at start of EIGTEST. +*> \endverbatim +*> +*> \param[in] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[in] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[in] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[in] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N) +*> \endverbatim +*> +*> \param[in] DN1 +*> \verbatim +*> DN1 is DOUBLE PRECISION +*> d(N-1) +*> \endverbatim +*> +*> \param[in] DN2 +*> \verbatim +*> DN2 is DOUBLE PRECISION +*> d(N-2) +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> This is the shift. +*> \endverbatim +*> +*> \param[out] TTYPE +*> \verbatim +*> TTYPE is INTEGER +*> Shift type. +*> \endverbatim +*> +*> \param[in,out] G +*> \verbatim +*> G is REAL +*> G is passed as an argument in order to save its value between +*> calls to DLASQ4. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> CNST1 = 9/16 +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, TAU, TTYPE, G ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER I0, N0, N0IN, PP, TTYPE + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CNST1, CNST2, CNST3 + PARAMETER ( CNST1 = 0.5630D0, CNST2 = 1.010D0, + $ CNST3 = 1.050D0 ) + DOUBLE PRECISION QURTR, THIRD, HALF, ZERO, ONE, TWO, HUNDRD + PARAMETER ( QURTR = 0.250D0, THIRD = 0.3330D0, + $ HALF = 0.50D0, ZERO = 0.0D0, ONE = 1.0D0, + $ TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I4, NN, NP + DOUBLE PRECISION A2, B1, B2, GAM, GAP1, GAP2, S +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* A negative DMIN forces the shift to take that absolute value +* TTYPE records the type of shift. +* + + IF( DMIN.LE.ZERO ) THEN + TAU = -DMIN + TTYPE = -1 + RETURN + END IF +* + NN = 4*N0 + PP + IF( N0IN.EQ.N0 ) THEN +* +* No eigenvalues deflated. +* + IF( DMIN.EQ.DN .OR. DMIN.EQ.DN1 ) THEN +* + B1 = SQRT( Z( NN-3 ) )*SQRT( Z( NN-5 ) ) + B2 = SQRT( Z( NN-7 ) )*SQRT( Z( NN-9 ) ) + A2 = Z( NN-7 ) + Z( NN-5 ) +* +* Cases 2 and 3. +* + IF( DMIN.EQ.DN .AND. DMIN1.EQ.DN1 ) THEN + + GAP2 = DMIN2 - A2 - DMIN2*QURTR + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2 ) THEN + GAP1 = A2 - DN - ( B2 / GAP2 )*B2 + ELSE + GAP1 = A2 - DN - ( B1+B2 ) + END IF + IF( GAP1.GT.ZERO .AND. GAP1.GT.B1 ) THEN + S = MAX( DN-( B1 / GAP1 )*B1, HALF*DMIN ) + TTYPE = -2 + ELSE + S = ZERO + IF( DN.GT.B1 ) + $ S = DN - B1 + IF( A2.GT.( B1+B2 ) ) + $ S = MIN( S, A2-( B1+B2 ) ) + S = MAX( S, THIRD*DMIN ) + TTYPE = -3 + END IF + ELSE +* +* Case 4. +* + TTYPE = -4 + S = QURTR*DMIN + IF( DMIN.EQ.DN ) THEN + GAM = DN + A2 = ZERO + IF( Z( NN-5 ) .GT. Z( NN-7 ) ) + $ RETURN + B2 = Z( NN-5 ) / Z( NN-7 ) + NP = NN - 9 + ELSE + NP = NN - 2*PP + B2 = Z( NP-2 ) + GAM = DN1 + IF( Z( NP-4 ) .GT. Z( NP-2 ) ) + $ RETURN + A2 = Z( NP-4 ) / Z( NP-2 ) + IF( Z( NN-9 ) .GT. Z( NN-11 ) ) + $ RETURN + B2 = Z( NN-9 ) / Z( NN-11 ) + NP = NN - 13 + END IF +* +* Approximate contribution to norm squared from I < NN-1. +* + A2 = A2 + B2 + DO 10 I4 = NP, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 20 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 20 + 10 CONTINUE + 20 CONTINUE + A2 = CNST3*A2 +* +* Rayleigh quotient residual bound. +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + END IF + ELSE IF( DMIN.EQ.DN2 ) THEN +* +* Case 5. +* + TTYPE = -5 + S = QURTR*DMIN +* +* Compute contribution to norm squared from I > NN-2. +* + NP = NN - 2*PP + B1 = Z( NP-2 ) + B2 = Z( NP-6 ) + GAM = DN2 + IF( Z( NP-8 ).GT.B2 .OR. Z( NP-4 ).GT.B1 ) + $ RETURN + A2 = ( Z( NP-8 ) / B2 )*( ONE+Z( NP-4 ) / B1 ) +* +* Approximate contribution to norm squared from I < NN-2. +* + IF( N0-I0.GT.2 ) THEN + B2 = Z( NN-13 ) / Z( NN-15 ) + A2 = A2 + B2 + DO 30 I4 = NN - 17, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 40 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 40 + 30 CONTINUE + 40 CONTINUE + A2 = CNST3*A2 + END IF +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + ELSE +* +* Case 6, no information to guide us. +* + IF( TTYPE.EQ.-6 ) THEN + G = G + THIRD*( ONE-G ) + ELSE IF( TTYPE.EQ.-18 ) THEN + G = QURTR*THIRD + ELSE + G = QURTR + END IF + S = G*DMIN + TTYPE = -6 + END IF +* + ELSE IF( N0IN.EQ.( N0+1 ) ) THEN +* +* One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. +* + IF( DMIN1.EQ.DN1 .AND. DMIN2.EQ.DN2 ) THEN +* +* Cases 7 and 8. +* + TTYPE = -7 + S = THIRD*DMIN1 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 60 + DO 50 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + A2 = B1 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*MAX( B1, A2 ).LT.B2 ) + $ GO TO 60 + 50 CONTINUE + 60 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN1 / ( ONE+B2**2 ) + GAP2 = HALF*DMIN2 - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + TTYPE = -8 + END IF + ELSE +* +* Case 9. +* + S = QURTR*DMIN1 + IF( DMIN1.EQ.DN1 ) + $ S = HALF*DMIN1 + TTYPE = -9 + END IF +* + ELSE IF( N0IN.EQ.( N0+2 ) ) THEN +* +* Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. +* +* Cases 10 and 11. +* + IF( DMIN2.EQ.DN2 .AND. TWO*Z( NN-5 ).LT.Z( NN-7 ) ) THEN + TTYPE = -10 + S = THIRD*DMIN2 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 80 + DO 70 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*B1.LT.B2 ) + $ GO TO 80 + 70 CONTINUE + 80 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN2 / ( ONE+B2**2 ) + GAP2 = Z( NN-7 ) + Z( NN-9 ) - + $ SQRT( Z( NN-11 ) )*SQRT( Z( NN-9 ) ) - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + END IF + ELSE + S = QURTR*DMIN2 + TTYPE = -11 + END IF + ELSE IF( N0IN.GT.( N0+2 ) ) THEN +* +* Case 12, more than two eigenvalues deflated. No information. +* + S = ZERO + TTYPE = -12 + END IF +* + TAU = S + RETURN +* +* End of DLASQ4 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq5.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq5.f new file mode 100644 index 00000000..19470447 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq5.f @@ -0,0 +1,413 @@ +*> \brief \b DLASQ5 computes one dqds transform in ping-pong form. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ5 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, DN, +* DNM1, DNM2, IEEE, EPS ) +* +* .. Scalar Arguments .. +* LOGICAL IEEE +* INTEGER I0, N0, PP +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU, SIGMA, EPS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ5 computes one dqds transform in ping-pong form, one +*> version for IEEE machines another for non IEEE machines. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +*> an extra argument. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[in] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> This is the shift. +*> \endverbatim +*> +*> \param[in] SIGMA +*> \verbatim +*> SIGMA is DOUBLE PRECISION +*> This is the accumulated shift up to this step. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N0), the last value of d. +*> \endverbatim +*> +*> \param[out] DNM1 +*> \verbatim +*> DNM1 is DOUBLE PRECISION +*> d(N0-1). +*> \endverbatim +*> +*> \param[out] DNM2 +*> \verbatim +*> DNM2 is DOUBLE PRECISION +*> d(N0-2). +*> \endverbatim +*> +*> \param[in] IEEE +*> \verbatim +*> IEEE is LOGICAL +*> Flag for IEEE or non IEEE arithmetic. +*> \endverbatim +* +*> \param[in] EPS +*> \verbatim +*> EPS is DOUBLE PRECISION +*> This is the value of epsilon used. +*> \endverbatim +*> +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, + $ DN, DNM1, DNM2, IEEE, EPS ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU, + $ SIGMA, EPS +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO, HALF + PARAMETER ( ZERO = 0.0D0, HALF = 0.5 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, TEMP, DTHRESH +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + DTHRESH = EPS*(SIGMA+TAU) + IF( TAU.LT.DTHRESH*HALF ) TAU = ZERO + IF( TAU.NE.ZERO ) THEN + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) - TAU + DMIN = D + DMIN1 = -Z( J4 ) +* + IF( IEEE ) THEN +* +* Code for IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + TEMP = Z( J4+1 ) / Z( J4-2 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4 ) = Z( J4-1 )*TEMP + EMIN = MIN( Z( J4 ), EMIN ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + TEMP = Z( J4+2 ) / Z( J4-3 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4-1 ) = Z( J4 )*TEMP + EMIN = MIN( Z( J4-1 ), EMIN ) + 20 CONTINUE + END IF + +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DN ) +* + ELSE +* +* Code for non IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 30 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 30 CONTINUE + ELSE + DO 40 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 40 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( DNM2.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( DNM1.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DN ) +* + END IF + ELSE +* This is the version that sets d's to zero if they are small enough + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) - TAU + DMIN = D + DMIN1 = -Z( J4 ) + IF( IEEE ) THEN +* +* Code for IEEE arithmetic. +* + + IF( PP.EQ.0 ) THEN + DO 50 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + TEMP = Z( J4+1 ) / Z( J4-2 ) + D = D*TEMP - TAU + IF( D.LT.DTHRESH ) D = ZERO + DMIN = MIN( DMIN, D ) + Z( J4 ) = Z( J4-1 )*TEMP + EMIN = MIN( Z( J4 ), EMIN ) + 50 CONTINUE + ELSE + DO 60 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + TEMP = Z( J4+2 ) / Z( J4-3 ) + D = D*TEMP - TAU + IF( D.LT.DTHRESH ) D = ZERO + DMIN = MIN( DMIN, D ) + Z( J4-1 ) = Z( J4 )*TEMP + EMIN = MIN( Z( J4-1 ), EMIN ) + 60 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DN ) +* + ELSE +* +* Code for non IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 70 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) - TAU + END IF + IF( D.LT.DTHRESH) D = ZERO + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 70 CONTINUE + ELSE + DO 80 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) - TAU + END IF + IF( D.LT.DTHRESH) D = ZERO + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 80 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( DNM2.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( DNM1.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DN ) +* + END IF + END IF +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ5 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq6.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq6.f new file mode 100644 index 00000000..bcd61f35 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasq6.f @@ -0,0 +1,258 @@ +*> \brief \b DLASQ6 computes one dqd transform in ping-pong form. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ6 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, +* DNM1, DNM2 ) +* +* .. Scalar Arguments .. +* INTEGER I0, N0, PP +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2 +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ6 computes one dqd (shift equal to zero) transform in +*> ping-pong form, with protection against underflow and overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +*> an extra argument. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N0), the last value of d. +*> \endverbatim +*> +*> \param[out] DNM1 +*> \verbatim +*> DNM1 is DOUBLE PRECISION +*> d(N0-1). +*> \endverbatim +*> +*> \param[out] DNM2 +*> \verbatim +*> DNM2 is DOUBLE PRECISION +*> d(N0-2). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, + $ DNM1, DNM2 ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2 +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, SAFMIN, TEMP +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + + print *, "In dlasq6" + STOP + + SAFMIN = DLAMCH( 'Safe minimum' ) + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) + DMIN = D +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + D = Z( J4+1 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+1 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4+1 ) ) THEN + TEMP = Z( J4+1 ) / Z( J4-2 ) + Z( J4 ) = Z( J4-1 )*TEMP + D = D*TEMP + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( Z( J4-3 ).EQ.ZERO ) THEN + Z( J4-1 ) = ZERO + D = Z( J4+2 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+2 ).LT.Z( J4-3 ) .AND. + $ SAFMIN*Z( J4-3 ).LT.Z( J4+2 ) ) THEN + TEMP = Z( J4+2 ) / Z( J4-3 ) + Z( J4-1 ) = Z( J4 )*TEMP + D = D*TEMP + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 20 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DNM1 = Z( J4P2+2 ) + DMIN = DNM1 + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DNM1 = DNM2*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DN = Z( J4P2+2 ) + DMIN = DN + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DN = DNM1*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DN ) +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ6 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasrt.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasrt.f new file mode 100644 index 00000000..f5d0e6cd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/dlasrt.f @@ -0,0 +1,303 @@ +*> \brief \b DLASRT sorts numbers in increasing or decreasing order. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASRT + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER ID +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Sort the numbers in D in increasing order (if ID = 'I') or +*> in decreasing order (if ID = 'D' ). +*> +*> Use Quick Sort, reverting to Insertion sort on arrays of +*> size <= 20. Dimension of STACK limits N to about 2**32. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ID +*> \verbatim +*> ID is CHARACTER*1 +*> = 'I': sort D in increasing order; +*> = 'D': sort D in decreasing order. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The length of the array D. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the array to be sorted. +*> On exit, D has been sorted into increasing order +*> (D(1) <= ... <= D(N) ) or into decreasing order +*> (D(1) >= ... >= D(N) ), depending on ID. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 + RETURN +* +* End of DLASRT +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ieeeck.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ieeeck.f new file mode 100644 index 00000000..132e4367 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ieeeck.f @@ -0,0 +1,203 @@ +*> \brief \b IEEECK +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IEEECK + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* .. Scalar Arguments .. +* INTEGER ISPEC +* REAL ONE, ZERO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> IEEECK is called from the ILAENV to verify that Infinity and +*> possibly NaN arithmetic is safe (i.e. will not trap). +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies whether to test just for inifinity arithmetic +*> or whether to test for infinity and NaN arithmetic. +*> = 0: Verify infinity arithmetic only. +*> = 1: Verify infinity and NaN arithmetic. +*> \endverbatim +*> +*> \param[in] ZERO +*> \verbatim +*> ZERO is REAL +*> Must contain the value 0.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> \endverbatim +*> +*> \param[in] ONE +*> \verbatim +*> ONE is REAL +*> Must contain the value 1.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> +*> RETURN VALUE: INTEGER +*> = 0: Arithmetic failed to produce the correct answers +*> = 1: Arithmetic produced the correct answers +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER ISPEC + REAL ONE, ZERO +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + REAL NAN1, NAN2, NAN3, NAN4, NAN5, NAN6, NEGINF, + $ NEGZRO, NEWZRO, POSINF +* .. +* .. Executable Statements .. + IEEECK = 1 +* + POSINF = ONE / ZERO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = -ONE / ZERO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGZRO = ONE / ( NEGINF+ONE ) + IF( NEGZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = ONE / NEGZRO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEWZRO = NEGZRO + ZERO + IF( NEWZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = ONE / NEWZRO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = NEGINF*POSINF + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = POSINF*POSINF + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* +* +* +* +* Return if we were only asked to check infinity arithmetic +* + IF( ISPEC.EQ.0 ) + $ RETURN +* + NAN1 = POSINF + NEGINF +* + NAN2 = POSINF / NEGINF +* + NAN3 = POSINF / POSINF +* + NAN4 = POSINF*ZERO +* + NAN5 = NEGINF*NEGZRO +* + NAN6 = NAN5*ZERO +* + IF( NAN1.EQ.NAN1 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN2.EQ.NAN2 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN3.EQ.NAN3 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN4.EQ.NAN4 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN5.EQ.NAN5 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN6.EQ.NAN6 ) THEN + IEEECK = 0 + RETURN + END IF +* + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ilaenv.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ilaenv.f new file mode 100644 index 00000000..867464de --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/ilaenv.f @@ -0,0 +1,624 @@ +*> \brief \b ILAENV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download ILAENV + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* .. Scalar Arguments .. +* CHARACTER*( * ) NAME, OPTS +* INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> ILAENV is called from the LAPACK routines to choose problem-dependent +*> parameters for the local environment. See ISPEC for a description of +*> the parameters. +*> +*> ILAENV returns an INTEGER +*> if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC +*> if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value. +*> +*> This version provides a set of parameters which should give good, +*> but not optimal, performance on many of the currently available +*> computers. Users are encouraged to modify this subroutine to set +*> the tuning parameters for their particular machine using the option +*> and problem size information in the arguments. +*> +*> This routine will not function correctly if it is converted to all +*> lower case. Converting it to all upper case is allowed. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies the parameter to be returned as the value of +*> ILAENV. +*> = 1: the optimal blocksize; if this value is 1, an unblocked +*> algorithm will give the best performance. +*> = 2: the minimum block size for which the block routine +*> should be used; if the usable block size is less than +*> this value, an unblocked routine should be used. +*> = 3: the crossover point (in a block routine, for N less +*> than this value, an unblocked routine should be used) +*> = 4: the number of shifts, used in the nonsymmetric +*> eigenvalue routines (DEPRECATED) +*> = 5: the minimum column dimension for blocking to be used; +*> rectangular blocks must have dimension at least k by m, +*> where k is given by ILAENV(2,...) and m by ILAENV(5,...) +*> = 6: the crossover point for the SVD (when reducing an m by n +*> matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds +*> this value, a QR factorization is used first to reduce +*> the matrix to a triangular form.) +*> = 7: the number of processors +*> = 8: the crossover point for the multishift QR method +*> for nonsymmetric eigenvalue problems (DEPRECATED) +*> = 9: maximum size of the subproblems at the bottom of the +*> computation tree in the divide-and-conquer algorithm +*> (used by xGELSD and xGESDD) +*> =10: ieee NaN arithmetic can be trusted not to trap +*> =11: infinity arithmetic can be trusted not to trap +*> 12 <= ISPEC <= 16: +*> xHSEQR or one of its subroutines, +*> see IPARMQ for detailed explanation +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is CHARACTER*(*) +*> The name of the calling subroutine, in either upper case or +*> lower case. +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is CHARACTER*(*) +*> The character options to the subroutine NAME, concatenated +*> into a single character string. For example, UPLO = 'U', +*> TRANS = 'T', and DIAG = 'N' for a triangular routine would +*> be specified as OPTS = 'UTN'. +*> \endverbatim +*> +*> \param[in] N1 +*> \verbatim +*> N1 is INTEGER +*> \endverbatim +*> +*> \param[in] N2 +*> \verbatim +*> N2 is INTEGER +*> \endverbatim +*> +*> \param[in] N3 +*> \verbatim +*> N3 is INTEGER +*> \endverbatim +*> +*> \param[in] N4 +*> \verbatim +*> N4 is INTEGER +*> Problem dimensions for the subroutine NAME; these may not all +*> be required. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> The following conventions have been used when calling ILAENV from the +*> LAPACK routines: +*> 1) OPTS is a concatenation of all of the character options to +*> subroutine NAME, in the same order that they appear in the +*> argument list for NAME, even if they are not used in determining +*> the value of the parameter specified by ISPEC. +*> 2) The problem dimensions N1, N2, N3, N4 are specified in the order +*> that they appear in the argument list for NAME. N1 is used +*> first, N2 second, and so on, and unused problem dimensions are +*> passed a value of -1. +*> 3) The parameter value returned by ILAENV is checked for validity in +*> the calling subroutine. For example, ILAENV is used to retrieve +*> the optimal blocksize for STRTRI as follows: +*> +*> NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 ) +*> IF( NB.LE.1 ) NB = MAX( 1, N ) +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*( * ) NAME, OPTS + INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IC, IZ, NB, NBMIN, NX + LOGICAL CNAME, SNAME + CHARACTER C1*1, C2*2, C4*2, C3*3, SUBNAM*6 +* .. +* .. Intrinsic Functions .. + INTRINSIC CHAR, ICHAR, INT, MIN, REAL +* .. +* .. External Functions .. + INTEGER IEEECK, IPARMQ + EXTERNAL IEEECK, IPARMQ +* .. +* .. Executable Statements .. +* + GO TO ( 10, 10, 10, 80, 90, 100, 110, 120, + $ 130, 140, 150, 160, 160, 160, 160, 160 )ISPEC +* +* Invalid value for ISPEC +* + ILAENV = -1 + RETURN +* + 10 CONTINUE +* +* Convert NAME to upper case if the first character is lower case. +* + ILAENV = 1 + SUBNAM = NAME + IC = ICHAR( SUBNAM( 1: 1 ) ) + IZ = ICHAR( 'Z' ) + IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN +* +* ASCII character set +* + IF( IC.GE.97 .AND. IC.LE.122 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 20 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.97 .AND. IC.LE.122 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 20 CONTINUE + END IF +* + ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN +* +* EBCDIC character set +* + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN + SUBNAM( 1: 1 ) = CHAR( IC+64 ) + DO 30 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) )SUBNAM( I: + $ I ) = CHAR( IC+64 ) + 30 CONTINUE + END IF +* + ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN +* +* Prime machines: ASCII+128 +* + IF( IC.GE.225 .AND. IC.LE.250 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 40 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.225 .AND. IC.LE.250 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 40 CONTINUE + END IF + END IF +* + C1 = SUBNAM( 1: 1 ) + SNAME = C1.EQ.'S' .OR. C1.EQ.'D' + CNAME = C1.EQ.'C' .OR. C1.EQ.'Z' + IF( .NOT.( CNAME .OR. SNAME ) ) + $ RETURN + C2 = SUBNAM( 2: 3 ) + C3 = SUBNAM( 4: 6 ) + C4 = C3( 2: 3 ) +* + GO TO ( 50, 60, 70 )ISPEC +* + 50 CONTINUE +* +* ISPEC = 1: block size +* +* In these examples, separate code is provided for setting NB for +* real and complex. We assume that NB will take the same value in +* single or double precision. +* + NB = 1 +* + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. + $ C3.EQ.'QLF' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'PO' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( SNAME .AND. C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRF' ) THEN + NB = 64 + ELSE IF( C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( C2.EQ.'GB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'PB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'TR' ) THEN + IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'LA' ) THEN + IF( C3.EQ.'UUM' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( SNAME .AND. C2.EQ.'ST' ) THEN + IF( C3.EQ.'EBZ' ) THEN + NB = 1 + END IF + END IF + ILAENV = NB + RETURN +* + 60 CONTINUE +* +* ISPEC = 2: minimum block size +* + NBMIN = 2 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NBMIN = 8 + ELSE + NBMIN = 8 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + END IF + ILAENV = NBMIN + RETURN +* + 70 CONTINUE +* +* ISPEC = 3: crossover point +* + NX = 0 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + END IF + ILAENV = NX + RETURN +* + 80 CONTINUE +* +* ISPEC = 4: number of shifts (used by xHSEQR) +* + ILAENV = 6 + RETURN +* + 90 CONTINUE +* +* ISPEC = 5: minimum column dimension (not used) +* + ILAENV = 2 + RETURN +* + 100 CONTINUE +* +* ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD) +* + ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 ) + RETURN +* + 110 CONTINUE +* +* ISPEC = 7: number of processors (not used) +* + ILAENV = 1 + RETURN +* + 120 CONTINUE +* +* ISPEC = 8: crossover point for multishift (used by xHSEQR) +* + ILAENV = 50 + RETURN +* + 130 CONTINUE +* +* ISPEC = 9: maximum size of the subproblems at the bottom of the +* computation tree in the divide-and-conquer algorithm +* (used by xGELSD and xGESDD) +* + ILAENV = 25 + RETURN +* + 140 CONTINUE +* +* ISPEC = 10: ieee NaN arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 1, 0.0, 1.0 ) + END IF + RETURN +* + 150 CONTINUE +* +* ISPEC = 11: infinity arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 0, 0.0, 1.0 ) + END IF + RETURN +* + 160 CONTINUE +* +* 12 <= ISPEC <= 16: xHSEQR or one of its subroutines. +* + ILAENV = IPARMQ( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) + RETURN +* +* End of ILAENV +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/iparmq.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/iparmq.f new file mode 100644 index 00000000..bd5bd7a0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/iparmq.f @@ -0,0 +1,322 @@ +*> \brief \b IPARMQ +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IPARMQ + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* .. Scalar Arguments .. +* INTEGER IHI, ILO, ISPEC, LWORK, N +* CHARACTER NAME*( * ), OPTS*( * ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This program sets problem and machine dependent parameters +*> useful for xHSEQR and its subroutines. It is called whenever +*> ILAENV is called with 12 <= ISPEC <= 16 +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is integer scalar +*> ISPEC specifies which tunable parameter IPARMQ should +*> return. +*> +*> ISPEC=12: (INMIN) Matrices of order nmin or less +*> are sent directly to xLAHQR, the implicit +*> double shift QR algorithm. NMIN must be +*> at least 11. +*> +*> ISPEC=13: (INWIN) Size of the deflation window. +*> This is best set greater than or equal to +*> the number of simultaneous shifts NS. +*> Larger matrices benefit from larger deflation +*> windows. +*> +*> ISPEC=14: (INIBL) Determines when to stop nibbling and +*> invest in an (expensive) multi-shift QR sweep. +*> If the aggressive early deflation subroutine +*> finds LD converged eigenvalues from an order +*> NW deflation window and LD.GT.(NW*NIBBLE)/100, +*> then the next QR sweep is skipped and early +*> deflation is applied immediately to the +*> remaining active diagonal block. Setting +*> IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a +*> multi-shift QR sweep whenever early deflation +*> finds a converged eigenvalue. Setting +*> IPARMQ(ISPEC=14) greater than or equal to 100 +*> prevents TTQRE from skipping a multi-shift +*> QR sweep. +*> +*> ISPEC=15: (NSHFTS) The number of simultaneous shifts in +*> a multi-shift QR iteration. +*> +*> ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the +*> following meanings. +*> 0: During the multi-shift QR sweep, +*> xLAQR5 does not accumulate reflections and +*> does not use matrix-matrix multiply to +*> update the far-from-diagonal matrix +*> entries. +*> 1: During the multi-shift QR sweep, +*> xLAQR5 and/or xLAQRaccumulates reflections and uses +*> matrix-matrix multiply to update the +*> far-from-diagonal matrix entries. +*> 2: During the multi-shift QR sweep. +*> xLAQR5 accumulates reflections and takes +*> advantage of 2-by-2 block structure during +*> matrix-matrix multiplies. +*> (If xTRMM is slower than xGEMM, then +*> IPARMQ(ISPEC=16)=1 may be more efficient than +*> IPARMQ(ISPEC=16)=2 despite the greater level of +*> arithmetic work implied by the latter choice.) +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is character string +*> Name of the calling subroutine +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is character string +*> This is a concatenation of the string arguments to +*> TTQRE. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is integer scalar +*> N is the order of the Hessenberg matrix H. +*> \endverbatim +*> +*> \param[in] ILO +*> \verbatim +*> ILO is INTEGER +*> \endverbatim +*> +*> \param[in] IHI +*> \verbatim +*> IHI is INTEGER +*> It is assumed that H is already upper triangular +*> in rows and columns 1:ILO-1 and IHI+1:N. +*> \endverbatim +*> +*> \param[in] LWORK +*> \verbatim +*> LWORK is integer scalar +*> The amount of workspace available. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Little is known about how best to choose these parameters. +*> It is possible to use different values of the parameters +*> for each of CHSEQR, DHSEQR, SHSEQR and ZHSEQR. +*> +*> It is probably best to choose different parameters for +*> different matrices and different parameters at different +*> times during the iteration, but this has not been +*> implemented --- yet. +*> +*> +*> The best choices of most of the parameters depend +*> in an ill-understood way on the relative execution +*> rate of xLAQR3 and xLAQR5 and on the nature of each +*> particular eigenvalue problem. Experiment may be the +*> only practical way to determine which choices are most +*> effective. +*> +*> Following is a list of default values supplied by IPARMQ. +*> These defaults may be adjusted in order to attain better +*> performance in any particular computational environment. +*> +*> IPARMQ(ISPEC=12) The xLAHQR vs xLAQR0 crossover point. +*> Default: 75. (Must be at least 11.) +*> +*> IPARMQ(ISPEC=13) Recommended deflation window size. +*> This depends on ILO, IHI and NS, the +*> number of simultaneous shifts returned +*> by IPARMQ(ISPEC=15). The default for +*> (IHI-ILO+1).LE.500 is NS. The default +*> for (IHI-ILO+1).GT.500 is 3*NS/2. +*> +*> IPARMQ(ISPEC=14) Nibble crossover point. Default: 14. +*> +*> IPARMQ(ISPEC=15) Number of simultaneous shifts, NS. +*> a multi-shift QR iteration. +*> +*> If IHI-ILO+1 is ... +*> +*> greater than ...but less ... the +*> or equal to ... than default is +*> +*> 0 30 NS = 2+ +*> 30 60 NS = 4+ +*> 60 150 NS = 10 +*> 150 590 NS = ** +*> 590 3000 NS = 64 +*> 3000 6000 NS = 128 +*> 6000 infinity NS = 256 +*> +*> (+) By default matrices of this order are +*> passed to the implicit double shift routine +*> xLAHQR. See IPARMQ(ISPEC=12) above. These +*> values of NS are used only in case of a rare +*> xLAHQR failure. +*> +*> (**) The asterisks (**) indicate an ad-hoc +*> function increasing from 10 to 64. +*> +*> IPARMQ(ISPEC=16) Select structured matrix multiply. +*> (See ISPEC=16 above for details.) +*> Default: 3. +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, ISPEC, LWORK, N + CHARACTER NAME*( * ), OPTS*( * ) +* +* ================================================================ +* .. Parameters .. + INTEGER INMIN, INWIN, INIBL, ISHFTS, IACC22 + PARAMETER ( INMIN = 12, INWIN = 13, INIBL = 14, + $ ISHFTS = 15, IACC22 = 16 ) + INTEGER NMIN, K22MIN, KACMIN, NIBBLE, KNWSWP + PARAMETER ( NMIN = 75, K22MIN = 14, KACMIN = 14, + $ NIBBLE = 14, KNWSWP = 500 ) + REAL TWO + PARAMETER ( TWO = 2.0 ) +* .. +* .. Local Scalars .. + INTEGER NH, NS +* .. +* .. Intrinsic Functions .. + INTRINSIC LOG, MAX, MOD, NINT, REAL +* .. +* .. Executable Statements .. + IF( ( ISPEC.EQ.ISHFTS ) .OR. ( ISPEC.EQ.INWIN ) .OR. + $ ( ISPEC.EQ.IACC22 ) ) THEN +* +* ==== Set the number simultaneous shifts ==== +* + NH = IHI - ILO + 1 + NS = 2 + IF( NH.GE.30 ) + $ NS = 4 + IF( NH.GE.60 ) + $ NS = 10 + IF( NH.GE.150 ) + $ NS = MAX( 10, NH / NINT( LOG( REAL( NH ) ) / LOG( TWO ) ) ) + IF( NH.GE.590 ) + $ NS = 64 + IF( NH.GE.3000 ) + $ NS = 128 + IF( NH.GE.6000 ) + $ NS = 256 + NS = MAX( 2, NS-MOD( NS, 2 ) ) + END IF +* + IF( ISPEC.EQ.INMIN ) THEN +* +* +* ===== Matrices of order smaller than NMIN get sent +* . to xLAHQR, the classic double shift algorithm. +* . This must be at least 11. ==== +* + IPARMQ = NMIN +* + ELSE IF( ISPEC.EQ.INIBL ) THEN +* +* ==== INIBL: skip a multi-shift qr iteration and +* . whenever aggressive early deflation finds +* . at least (NIBBLE*(window size)/100) deflations. ==== +* + IPARMQ = NIBBLE +* + ELSE IF( ISPEC.EQ.ISHFTS ) THEN +* +* ==== NSHFTS: The number of simultaneous shifts ===== +* + IPARMQ = NS +* + ELSE IF( ISPEC.EQ.INWIN ) THEN +* +* ==== NW: deflation window size. ==== +* + IF( NH.LE.KNWSWP ) THEN + IPARMQ = NS + ELSE + IPARMQ = 3*NS / 2 + END IF +* + ELSE IF( ISPEC.EQ.IACC22 ) THEN +* +* ==== IACC22: Whether to accumulate reflections +* . before updating the far-from-diagonal elements +* . and whether to use 2-by-2 block structure while +* . doing it. A small amount of work could be saved +* . by making this choice dependent also upon the +* . NH=IHI-ILO+1. +* + IPARMQ = 0 + IF( NS.GE.KACMIN ) + $ IPARMQ = 1 + IF( NS.GE.K22MIN ) + $ IPARMQ = 2 +* + ELSE +* ===== invalid value of ispec ===== + IPARMQ = -1 +* + END IF +* +* ==== End of IPARMQ ==== +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/lsame.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq1.f90 b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq1.f90 new file mode 100644 index 00000000..5ee8878d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq1.f90 @@ -0,0 +1,626 @@ +program randomsys1 +implicit none +integer, parameter :: nmax=1000 +real(kind=8), dimension(nmax) :: b, x +real(kind=8), dimension(nmax,nmax) :: a +real(kind=8) :: err +integer :: i, info, lda, ldb, nrhs, n,iter +integer, dimension(nmax) :: ipiv + +real(kind=8), dimension(100) :: d +real(kind=8), dimension(99) :: e +real(kind=8), dimension(400) :: work + +d(1:100) = (/1.8334043365537367D+00, & +1.4451749896846686D+00, & +1.0018566447551758D-01, & +-7.2143260438744417D-01, & +-3.7864653015502087D-01, & +-9.0270111568850808D-01, & +1.2204305489831029D+00, & +-9.7628177811136485D-01, & +8.4199233511256721D-01, & +-2.7938817329922050D-01, & +3.6157779599908046D-01, & +-1.8563411313998144D+00, & +-5.7930081140992240D-01, & +7.4080550463379169D-01, & +1.7021409147402005D+00, & +-5.7992035328196923D-01, & +4.0877426434579855D-01, & +-7.1297236049446144D-01, & +-1.2214095798914903D+00, & +2.9037983248746674D-01, & +7.4685018821608473D-01, & +3.0213735481316539D-01, & +-1.5207207136907624D-01, & +-2.1332671668411556D+00, & +6.8744661834930676D-01, & +-2.0946670404018297D-01, & +-1.5221059713957628D+00, & +1.1117190383859539D+00, & +-6.1175948159744020D-01, & +-4.4149212620857964D-01, & +-5.5702632609947533D-01, & +1.4071858950692646D+00, & +-3.2329881667362437D-01, & +-3.1958092104323499D-01, & +9.0934520529412111D-01, & +9.7881421364746712D-01, & +-5.1202970940327841D-01, & +1.5040024724520102D+00, & +-7.1993831181468571D-01, & +-7.1819661000094503D-01, & +-1.3481185445933910D+00, & +-1.4984426192966893D+00, & +1.1356626654278745D+00, & +1.6427417967661164D+00, & +-1.4184643787388000D+00, & +2.9811560271518989D-01, & +7.8630022575860559D-01, & +-1.8262830018047089D+00, & +6.3058255632564841D-01, & +-2.0692752940382309D-02, & +-7.2726648905906033D-01, & +-1.0461446937034022D+00, & +1.2530345094987356D+00, & +-2.3583665341168443D+00, & +1.9177654334479410D-01, & +-1.3563410975095058D+00, & +-1.0669710425337906D+00, & +1.4840245472507219D+00, & +-6.9185935518981789D-01, & +1.6813910559942205D-01, & +-7.1255209442204559D-01, & +-1.0112797453604008D+00, & +2.8591746998403011D-01, & +-1.9403039239509563D+00, & +-8.1434141084858885D-02, & +1.3873918713367210D+00, & +-8.8212258376548647D-01, & +-1.2253510598547583D+00, & +-3.8677386127356073D-01, & +-1.0262656526479850D+00, & +2.9468734022014376D-01, & +2.3442965677966704D-01, & +1.2219251054024911D+00, & +2.6066505150099868D+00, & +-7.8543147636303856D-01, & +-9.8126277325503253D-01, & +1.1722358680271947D+00, & +-8.1477749181289072D-01, & +1.3437777060446568D-01, & +3.4626341297821356D-01, & +-4.5672026157532375D-01, & +3.0496975959999184D-01, & +3.4636683737604146D-01, & +1.5114807806635011D-01, & +-1.1376177393945328D+00, & +9.3419670621891793D-01, & +7.9186416310239138D-01, & +6.7230421440462595D-01, & +-2.3236847424852280D-01, & +-1.0927137499922757D+00, & +9.8562766620822340D-01, & +-1.1382935431007701D-01, & +-9.2072237463768225D-01, & +6.1142850054965170D-01, & +8.2752057022739134D-03, & +6.7197122515126417D-01, & +-1.1007816668204429D+00, & +-1.2196829073430047D+00, & +-6.1428585523321222D-01, & +6.4599803465517280D-01/) +e(1:99) = (/-9.6393084631802151D-01, & +2.5532567563781607D+00, & +8.2492664240014357D-01, & +8.2628261757058474D-01, & +7.3021658879350859D-01, & +3.4014431785419519D-02, & +3.2121571974900542D-01, & +2.5987166374572213D-02, & +-3.1150206355945814D-01, & +1.3429094629249927D+00, & +8.6246434952180806D-01, & +-8.3756967113851388D-01, & +9.5277237959592009D-01, & +1.1717152179539618D+00, & +2.5980977671460709D-01, & +-6.4468162556415265D-01, & +-1.3751364204170078D+00, & +2.9677172586579936D-01, & +-3.7071376979215720D-01, & +8.2912690407496381D-01, & +-8.6820437618589197D-01, & +5.2500961173269689D-01, & +1.0657701704030644D+00, & +-4.6621502244820201D-03, & +-1.9013997092621748D-01, & +1.5098985741543924D-01, & +1.0102557493909003D+00, & +8.8830298507891103D-01, & +2.0464938169302065D+00, & +4.7910192662606277D-01, & +1.4155288808120892D+00, & +-5.8169388172737679D-01, & +-9.8007278321065916D-01, & +2.4369633027015425D-01, & +1.6173163491335715D-01, & +6.6887624704464499D-01, & +-1.6500999383869115D+00, & +1.4380895281962367D+00, & +4.7508565250807777D-01, & +-3.1332991280327299D-01, & +3.1402552392574451D-01, & +5.6246373170551534D-01, & +2.5944662334710866D-01, & +4.8101648688789655D-01, & +1.7823376751423265D+00, & +3.0160656491545923D-01, & +-8.8915960863742050D-01, & +-4.4783548340444157D-01, & +8.9985836172311440D-01, & +-1.5626460660617920D+00, & +8.9972644535054036D-01, & +2.4456452268563592D-01, & +-3.1377944726557985D+00, & +1.6874136691232020D+00, & +2.4791290942030142D-01, & +1.7055713617986679D+00, & +1.7027580566127303D+00, & +-5.2969836953828042D-01, & +-8.6858804294195124D-01, & +7.6588136514601834D-01, & +8.6161822555855139D-01, & +6.5387844189250555D-01, & +7.0164941351276944D-01, & +4.1171318512873312D-01, & +7.6075070364872455D-01, & +8.5708035578209718D-02, & +-4.3558500874018535D-01, & +-6.2302104134015979D-01, & +8.4912051051824700D-01, & +-1.7120108380813925D-01, & +-9.7880552224113848D-01, & +1.1904436348486702D+00, & +7.0273864977367972D-01, & +-1.0213785672492079D+00, & +4.8392839864322634D-02, & +1.2611184618297511D-01, & +5.3330169134056482D-01, & +1.8070298106837654D+00, & +-2.8022831541922144D-01, & +8.0235047640662738D-01, & +-1.2615220404695868D+00, & +1.1878769364434660D+00, & +-2.1059219864297674D-01, & +3.2897539618854971D-01, & +-5.8928028913554642D-01, & +1.9164347352074701D-02, & +2.8035162764822374D-01, & +-9.6622429734784299D-02, & +3.4216241143907045D-01, & +-2.2358052317750254D+00, & +6.6284070879481805D-01, & +7.4316074303777269D-01, & +1.0280848437626724D+00, & +-2.0939898252763922D-01, & +-1.0268515265064981D+00, & +-1.2648527910628871D-01, & +4.8663846308033204D-01, & +1.2270171407392749D+00, & +-1.6189022502021406D+00/) +work(1:400) = (/6.0466028797961957D-01, & +9.4050908804501243D-01, & +6.6456005321849043D-01, & +4.3771418718698019D-01, & +4.2463749707126569D-01, & +6.8682307286710942D-01, & +6.5637019217476222D-02, & +1.5651925473279124D-01, & +9.6969518914484562D-02, & +3.0091186058528707D-01, & +5.1521262850206540D-01, & +8.1363996099009683D-01, & +2.1426387258237492D-01, & +3.8065718929968601D-01, & +3.1805817433032985D-01, & +4.6888984490242319D-01, & +2.8303415118044517D-01, & +2.9310185733681576D-01, & +6.7908467592021626D-01, & +2.1855305259276428D-01, & +2.0318687664732285D-01, & +3.6087141685690599D-01, & +5.7067327607102258D-01, & +8.6249143744788637D-01, & +2.9311424455385804D-01, & +2.9708256355629153D-01, & +7.5257303555161192D-01, & +2.0658266191369859D-01, & +8.6533501300156102D-01, & +6.9671916574663473D-01, & +5.2382030605000085D-01, & +2.8303083325889995D-02, & +1.5832827774512764D-01, & +6.0725343954551536D-01, & +9.7524161886057836D-01, & +7.9453623373871976D-02, & +5.9480859768306260D-01, & +5.9120651313875290D-02, & +6.9202458735311201D-01, & +3.0152268100655999D-01, & +1.7326623818270528D-01, & +5.4109985500873525D-01, & +5.4415557300088502D-01, & +2.7850762181610883D-01, & +4.2315220157182809D-01, & +5.3058571535070520D-01, & +2.5354050051506050D-01, & +2.8208099496492467D-01, & +7.8860491501934493D-01, & +3.6180548048031691D-01, & +8.8054312274161706D-01, & +2.9711226063977081D-01, & +8.9436172933045366D-01, & +9.7454618399116566D-02, & +9.7691686858626237D-01, & +7.4290998949843021D-02, & +2.2228941700678773D-01, & +6.8107831239257088D-01, & +2.4151508854715265D-01, & +3.1152244431052484D-01, & +9.3284642851843402D-01, & +7.4184895999182299D-01, & +8.0105504265266125D-01, & +7.3023147729480831D-01, & +1.8292491645390843D-01, & +4.2835708180680782D-01, & +8.9699195756187267D-01, & +6.8265348801324377D-01, & +9.7892935557668759D-01, & +9.2221225892172687D-01, & +9.0837275353887081D-02, & +4.9314199770488037D-01, & +9.2698680357441421D-01, & +9.5494544041678175D-01, & +3.4795396362822290D-01, & +6.9083883150567893D-01, & +7.1090719529999513D-01, & +5.6377959581526438D-01, & +6.4948946059294044D-01, & +5.5176504901277490D-01, & +7.5582350749159777D-01, & +4.0380328579570035D-01, & +1.3065111702897217D-01, & +9.8596472934024670D-01, & +8.9634174539621614D-01, & +3.2208397052088172D-01, & +7.2114776519267410D-01, & +6.4453978250932942D-01, & +8.5520507541911234D-02, & +6.6957529769977453D-01, & +6.2272831736370449D-01, & +3.6969284363982191D-01, & +2.3682254680548520D-01, & +5.3528189063440612D-01, & +1.8724610140105305D-01, & +2.3884070280531861D-01, & +6.2809817121836331D-01, & +1.2675292937260130D-01, & +2.8133029380535923D-01, & +4.1032284435628247D-01, & +4.3491247389145765D-01, & +6.2509502830053043D-01, & +5.5014692050772329D-01, & +6.2360882645293014D-01, & +7.2918072673429812D-01, & +8.3053391899480622D-01, & +5.1381551612136129D-04, & +7.3606860149543141D-01, & +3.9998376285699544D-01, & +4.9786811334270198D-01, & +6.0397810228292748D-01, & +4.0961827788499267D-01, & +2.9671281274886468D-02, & +1.9038945142366389D-03, & +2.8430411748625642D-03, & +9.1582131461295702D-01, & +5.8983418500491935D-01, & +5.5939244907101404D-01, & +8.1540517093336062D-01, & +8.7801175865240000D-01, & +4.5844247857565062D-01, & +6.0016559532333080D-01, & +2.6265150609689439D-02, & +8.4583278724804167D-01, & +2.4969320116349378D-01, & +6.4178429079958299D-01, & +2.4746660783662855D-01, & +1.7365584472313275D-01, & +5.9262375321244554D-01, & +8.1439455096702107D-01, & +6.9383813651720949D-01, & +3.0322547833006870D-02, & +5.3921010589094598D-01, & +9.7567481498731645D-01, & +7.5076305647959851D-01, & +2.9400631279501488D-01, & +7.5316127773675856D-01, & +1.5096404497960700D-01, & +3.5576726540923664D-01, & +8.3193085296981628D-01, & +2.3183004193767690D-01, & +6.2783460500002275D-01, & +4.9839430127597562D-01, & +8.9836089260366833D-02, & +2.5193959794895041D-02, & +3.9221618315402479D-01, & +5.8938308640079917D-01, & +9.2961163544903025D-01, & +5.7208680144308399D-01, & +5.8857634514348212D-01, & +4.1176268834501623D-01, & +5.5258038981424384D-01, & +4.9160739613162047D-01, & +9.5795391353751358D-01, & +7.9720854091080284D-01, & +1.0738111282075208D-01, & +7.8303497339600214D-01, & +3.9325099922888668D-01, & +1.3041384617379179D-01, & +1.9003276633920804D-01, & +7.3982578101583363D-01, & +6.5404140923127974D-01, & +9.8383788985732593D-02, & +5.2038028571222783D-01, & +9.9729663719935122D-02, & +1.5184340208190175D-01, & +7.6190262303755044D-02, & +3.1520808532012451D-01, & +1.5965092146489504D-01, & +1.3780406161952607D-01, & +3.2261068286779754D-01, & +5.3907451703947940D-01, & +5.7085162734549566D-01, & +5.1278175811108151D-01, & +6.8417513009745512D-01, & +6.5304020513536076D-01, & +5.2449975954986505D-01, & +6.5427013442414605D-01, & +7.1636837490167116D-01, & +6.3664421403817983D-01, & +1.2825909106361078D-02, & +3.0682195787138565D-02, & +9.8030874806304999D-02, & +3.6911170916434483D-01, & +8.2645412563474197D-01, & +3.4768170859156955D-01, & +3.4431501772636058D-01, & +2.5299982364784412D-01, & +2.1647114665497036D-01, & +5.5500213563479417D-01, & +4.0207084527183062D-01, & +5.0649706367641834D-01, & +1.6867966833433606D-01, & +3.3136826030698385D-01, & +8.2792809615055885D-01, & +7.0028787314581509D-01, & +5.7926259664335768D-02, & +9.9915949022033324D-01, & +4.1154036322047599D-01, & +1.1167463676480495D-01, & +7.8075408455849260D-01, & +9.2117624440742188D-02, & +5.3494624494407637D-02, & +7.1469581589162956D-01, & +2.5076227542918023D-01, & +8.4863292090315690D-01, & +9.7388187407067284D-01, & +2.1256094905031958D-01, & +2.1533783325605065D-02, & +9.4519476038882588D-01, & +9.2970155499924934D-02, & +6.4583337452397671D-01, & +3.1188554282705405D-01, & +4.4846436394045647D-01, & +4.8723924858036949D-01, & +8.2479676511350006D-02, & +6.7182910623463954D-01, & +4.0018828942364343D-01, & +9.0027514726431157D-01, & +9.4988320610125321D-01, & +3.1933126760711733D-01, & +4.9938549375241320D-01, & +4.0043231714181288D-01, & +1.9808670325451940D-02, & +6.4503886601944815D-01, & +4.2868843006993296D-01, & +3.3959675138730994D-01, & +8.8744750085050050D-01, & +2.3632747430436052D-01, & +7.6500821493327975D-01, & +3.5754647436084384D-02, & +7.2757725604152290D-01, & +6.2583662695812525D-01, & +5.1308750608785669D-01, & +7.2448356792351315D-02, & +7.2422905845916841D-01, & +8.7984484630570914D-01, & +9.7776347735771851D-01, & +8.4750026226468134D-01, & +8.3219793814993315D-01, & +2.4784452318699535D-01, & +9.1339906293647088D-01, & +7.5037210134653420D-02, & +8.3510380115435290D-01, & +6.2933169164530067D-01, & +7.5174057889673473D-01, & +6.3200343378879975D-01, & +9.6934213238731665D-02, & +1.4827369494876504D-02, & +5.8383474186253115D-01, & +6.8756195202154743D-02, & +9.9827381100849455D-01, & +6.4918841659842363D-01, & +9.8546557863324791D-01, & +8.3480576021921249D-01, & +3.3205608571906026D-01, & +6.6139318058334262D-01, & +9.5602062659660969D-01, & +3.1051027622482125D-01, & +1.8439069400202679D-01, & +9.6709434137177297D-01, & +8.3324181552815457D-01, & +3.0954845052732810D-01, & +8.0587176753764456D-01, & +4.1732584219038238D-01, & +7.1853044935277477D-01, & +4.0673677545039083D-01, & +8.9580326774414576D-01, & +9.5817636260259365D-01, & +1.8713221139656417D-02, & +7.9167230908208319D-01, & +4.2355315388584103D-01, & +1.5181277223073395D-02, & +4.3269824007906393D-01, & +9.0477623706573340D-01, & +8.5570441457488644D-01, & +4.2921642176334200D-02, & +6.5903053300775438D-01, & +3.4785904313005395D-01, & +5.0348679004869112D-01, & +8.3994742117055976D-01, & +2.3109568410543832D-02, & +1.2436351859954159D-01, & +2.6117561918821841D-01, & +8.3494750649349414D-01, & +3.1480479595597533D-01, & +7.6812064740880894D-03, & +8.9975012571752733D-01, & +3.7026753645051064D-01, & +1.0019940926941497D-01, & +6.4320402657020315D-01, & +7.6988908998308336D-01, & +7.9112533566198451D-01, & +2.6238190747072776D-01, & +3.4686388037925503D-01, & +2.1465371537694145D-01, & +8.2209289717657175D-01, & +3.5113429966521320D-01, & +5.9919425250588099D-01, & +5.7835125693111211D-01, & +4.1358098797631293D-01, & +1.1985050890286310D-01, & +9.1161370679159903D-01, & +5.3785580105748208D-02, & +2.2891758676059876D-01, & +3.2417396306138829D-01, & +3.5076512764716117D-01, & +3.4928874777426255D-01, & +3.0380212985436572D-01, & +9.6874615996581170D-01, & +6.7152655046083776D-01, & +2.0794312837315651D-01, & +9.6313940120247044D-01, & +3.0220237504213365D-01, & +8.0794108095480799D-01, & +1.3408416275024179D-01, & +9.4776028919455635D-01, & +6.4086482116825383D-01, & +9.5325875425035178D-01, & +8.0987422593395209D-01, & +1.8159084675756379D-01, & +9.4275737153737327D-01, & +8.3124103554376771D-01, & +4.9468043578205978D-01, & +8.5531034647693982D-01, & +7.1074391181909824D-01, & +2.7349475629159786D-01, & +4.0763287189198161D-01, & +9.0976128251911847D-01, & +9.4439713870030451D-01, & +4.9863245185560190D-01, & +2.8863831012730923D-01, & +9.7589525649963815D-01, & +4.5258447627808124D-01, & +4.4990698677957075D-02, & +3.1536198151820755D-01, & +9.5190614812037189D-01, & +7.5156308247423609D-01, & +5.3579099898961424D-01, & +6.6971458883510748D-01, & +8.6517499748328641D-01, & +4.5888445390388938D-01, & +5.7855090249582031D-01, & +4.8152982184966137D-01, & +5.5061576198318274D-01, & +9.5062324380815433D-01, & +5.0986542047295536D-01, & +7.4251472966182985D-01, & +4.9079401441435533D-01, & +6.6151414870689360D-02, & +2.6249066264989940D-01, & +9.2546794407799982D-01, & +3.7148665165822231D-01, & +4.0941940003107308D-01, & +4.1575196973399631D-01, & +9.7261599736539445D-02, & +9.0162762447969347D-01, & +4.4446597981328932D-03, & +2.7392454335102678D-01, & +1.0930666111680035D-01, & +8.5544841289295426D-01, & +2.5705535663902546D-01, & +9.8913209203202213D-01, & +9.2641142236812712D-01, & +1.7094603208839290D-01, & +3.0388712489325242D-01, & +5.3345144978115477D-01, & +1.7648961347647024D-01, & +8.1359077477652830D-01, & +7.0513712380125892D-01, & +2.5720755742139950D-01, & +2.5036892046498466D-01, & +3.3509436689927874D-01, & +7.5124063162526056D-01, & +4.8797826077860845D-03, & +8.4099320643626019D-01, & +2.2957358869665739D-01, & +1.3285547727582237D-02, & +9.4993740716879371D-01, & +8.9937146465701423D-01, & +9.6262420114388625D-01, & +4.3000361954927006D-02, & +7.1266261216467264D-01, & +5.1094098258212241D-02, & +4.0753210485857738D-01, & +4.7569737399615403D-01, & +3.4746838606940983D-01, & +4.0719938711096422D-02, & +5.9756620514440806D-01, & +2.6012467360309705D-01, & +8.3285585557738717D-01, & +9.6049750529821787D-01, & +9.3670756890653750D-01, & +2.2932023844733959D-01, & +7.2031310018914962D-01, & +7.5648232426876405D-01, & +4.5015392507594826D-01, & +3.3897738839543617D-01, & +4.7249205225111501D-01, & +9.8599436000817042D-01/) +n = 100 +info = 0 + +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3, STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5, STATUS='REPLACE', file = "gen5tests.txt") + +call dlasq1(n, d, e, work, info) + +close(5) +close(3) +close(4) + +end \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq2.f90 b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq2.f90 new file mode 100644 index 00000000..c908f7d6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq2.f90 @@ -0,0 +1,171 @@ +! $CLASSHG/codes/lapack/random/randomsys1.f90 + +program randomsys1 +implicit none +integer, parameter :: nmax=1000 +real(kind=8), dimension(nmax) :: b, x +real(kind=8), dimension(nmax,nmax) :: a +real(kind=8) :: err +integer :: i, info, lda, ldb, nrhs, n,iter +integer, dimension(nmax) :: ipiv + +real(kind=8), dimension(84) :: z + +z(1:84) = (/2.3962280929192509D-01, & +6.4346010490580374D-01, & +5.4886677265274941D-01, & +1.8435046456575191D-01, & +4.2690013698472401D-01, & +6.2760930131666248D-01, & +8.7243363936287288D-02, & +5.3710399529030350D-01, & +8.4474604576675638D-01, & +4.0947669295022632D-01, & +2.0315141244999760D-01, & +8.2714283129979482D-01, & +9.6582843029739029D-01, & +3.7773539690481128D-01, & +6.4713340225873406D-01, & +6.7774351756798612D-01, & +4.4568905572928591D-01, & +1.7208265726837521D-01, & +3.5202074329011412D-01, & +3.2913965083413110D-01, & +7.4682622623737438D-01, & +2.7151044969605542D-01, & +5.6129178633962351D-01, & +1.3244294692867761D-01, & +7.9837660640147112D-01, & +2.0595995860196409D-01, & +2.6555102564257749D-02, & +1.9623902644848701D-01, & +7.8452468963715605D-03, & +8.2177375597112101D-01, & +9.4444982187044924D-01, & +4.6799576958310329D-01, & +1.1359180530395520D-01, & +1.6049482525711320D-01, & +8.4523811016138373D-01, & +8.5370708147160490D-01, & +3.0139325968162661D-01, & +2.5117154067021252D-01, & +2.0086476380364379D-01, & +2.6078975734443288D-01, & +2.5710509100784901D-01, & +6.2861740244633146D-01, & +4.7397018497236110D-01, & +8.6989475348440182D-01, & +6.4860795895959611D-01, & +8.8943219043019872D-01, & +7.9524758401855578D-01, & +8.8016617212154102D-01, & +2.1472721943810300D-01, & +9.5183566464760194D-01, & +7.1911522894148772D-01, & +1.1065249711733080D-01, & +9.5745872307341484D-01, & +6.4694742306793951D-01, & +5.8182607574435841D-01, & +1.2922028370755401D-02, & +2.7617229134380777D-01, & +8.0045359255855852D-01, & +3.2789738555900377D-01, & +5.7940374386642890D-01, & +2.3961554431041750D-02, & +6.6990484757537938D-01, & +1.8144929371280860D-01, & +2.8661849362222419D-01, & +6.5845572125062690D-01, & +5.8896512277754309D-01, & +6.3697665190607378D-02, & +1.3281935295985961D-01, & +7.4166314172628711D-01, & +5.0033182787066932D-01, & +3.1440772963953763D-02, & +9.9073931564031925D-01, & +3.4236965949145941D-03, & +6.9929220728508257D-01, & +7.5905196170645428D-01, & +2.5421825141163590D-01, & +3.3146571845550887D-01, & +5.7286596840196446D-01, & +9.9158547964144228D-01, & +4.8967497301052382D-01, & +5.6113697207961410D-01, & +6.0641422150435165D-01, & +8.5675901647669139D-02, & +2.5817319326781851D-01/) +n = 21 +info = 0 + +open(unit = 2,STATUS='REPLACE', file = "gen2tests.txt") +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3,STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5,STATUS='REPLACE', file = "gen5tests.txt") + +write(2,*) "{" +write(2,'(9999(g0))',advance="no") "z: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))',advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "n: " ,n,"," + + +call dlasq2(n, z, info) + +write(2,'(9999(g0))', advance="no") "zOut: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "info:", info, "," +write(2,*) "}," + +print *, "Done fixed dlasq2" + +close(5) +close(3) +close(4) +close(2) + +! For random tests +n = 21 + +open(unit = 2, STATUS='REPLACE', file = "gen2tests.txt") +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3, STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5, STATUS='REPLACE', file = "gen5tests.txt") + +do iter = 1, 2 + +call random_number(z(1:4*n)) + +write(2,*) "{" +write(2,'(9999(g0))', advance="no") "z: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "n: " ,n,"," + +call dlasq2(n, z, info) + +write(2,'(9999(g0))', advance="no") "zOut: []float64{" +do i = 1, 4*n + write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "info:", info, "," +write(2,*) "}," + +print *, "Done with dlasq2" + +end do + +close(5) +close(3) +close(4) +close(2) + +end program randomsys1 \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq3.f90 b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq3.f90 new file mode 100644 index 00000000..8cc5cf0f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq3.f90 @@ -0,0 +1,132 @@ +program testdlasq3 +implicit none + +! Dlasq3 tests +integer :: i0, n0, pp,ttype, nFail,iter,nDiv,n +real(kind=8), dimension(84) :: z +real(kind=8) :: dmin,desig,qmax,dmin1,dmin2,dn,dn1,dn2,g,tau,sigma +logical :: ieee + +n = 84 + +ieee = .True. + +z(1:84) = (/1.9143652461808209D+00, & +1.5643842977038900D+00, & +2.4933891621438989D-01, & +3.4998094847693051D-01, & +1.3159965131315450D+00, & +1.3638621124906269D+00, & +9.8984666119707590D-02, & +2.0147331685530781D-01, & +6.0239739795872871D-01, & +6.4655447927417942D-01, & +2.2100334106387809D-03, & +5.4827584804256833D-02, & +9.8618572336789667D-02, & +2.4281908107454921D-02, & +4.7563214844548191D-01, & +7.6546697639973529D-02, & +2.5887481436771148D-01, & +6.1277840695087704D-01, & +1.0786113766900041D-01, & +1.2172855586231640D-01, & +6.4428964922552456D-01, & +2.2938358048981550D-01, & +6.2032304866397048D-01, & +5.2276720640470942D-01, & +3.6956606786075852D-01, & +7.6452331847458654D-01, & +5.3788380542522651D-01, & +2.2536579805014259D-01, & +3.5625331812646233D-01, & +8.8204867223354833D-01, & +2.2221324964361449D-02, & +1.2088451318140349D-02, & +1.2750943030216850D+00, & +6.5487468521633574D-01, & +1.6473243548212180D-01, & +6.4244094276971109D-01, & +1.0075305765438660D+00, & +3.2695517365467008D-01, & +3.4538816017831181D-01, & +8.4530783837131718D-01, & +2.6793917191534039D-01, & +4.1167148387782809D-01, & +7.3286777366837230D-01, & +2.0165584821582411D-01, & +8.3608281383074101D-01, & +9.7375794521953263D-01, & +4.8136607095928219D-01, & +5.9519264227958080D-01, & +6.4953705136764595D-01, & +6.7618762481481709D-01, & +2.3254758802226480D-01, & +4.5471549751211121D-01, & +1.9936248028938069D-01, & +3.3218193673422552D-01, & +3.7823189169112570D-01, & +9.9728131577419957D-02, & +9.8304494035037460D-01, & +7.5610809968448423D-01, & +4.4297338640403672D-01, & +6.0516873235701607D-01, & +1.1732795506024030D+00, & +7.1957244803166864D-01, & +5.0355240691445868D-01, & +8.9668048897477137D-01, & +3.0589803950585209D-01, & +6.5888323539286620D-01, & +3.0146344334154529D-01, & +1.5056721102744461D-01, & +1.2894222375675779D+00, & +6.1246453109936005D-01, & +7.5833643057994404D-01, & +9.7842114980976291D-01, & +4.9778147794615712D-01, & +9.9938135774918690D-01, & +2.8414688478625982D-01, & +2.5673655077691432D-01, & +9.2575397942057647D-01, & +5.5092683856146663D-01, & +5.2313556054509897D-05, & +6.5897402564536967D-01, & +2.1178692213810329D-05, & +7.3492248268320243D-05, & +0.0000000000000000D+00, & +0.0000000000000000D+00/) +i0 = 1 +n0 = 21 +pp = 0 +dmin = -0.0000000000000000D+00 +sigma = 0.0000000000000000D+00 +desig = 0.0000000000000000D+00 +qmax = 2.1637041623952107D+00 +nFail = 0 +iter = 2 +nDiv = 40 +ttype = 0 +dmin1 = 0.0000000000000000D+00 +dmin2 = 0.0000000000000000D+00 +dn = 0.0000000000000000D+00 +dn1 = 0.0000000000000000D+00 +dn2 = 0.0000000000000000D+00 +g = 0.0000000000000000D+00 +tau = 0.0000000000000000D+00 + +print *, "Starting Dlasq3" +open(unit = 4, file = "gen4tests.txt") +open(unit = 5, file = "gen5tests.txt") +call Dlasq3(i0, n0, z, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ieee, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau) +close(4) +close(5) + +print *, "Done calling dlasq3" +print *, Z(1:n) + +print *, I0, N0, PP +print *, DMIN, DESIG, SIGMA, QMAX +print *, NFAIL, ITER, NDIV, TTYPE +print *, DMIN1, DMIN2, DN, DN1, DN2, G, TAU + +end \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq4.f90 b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq4.f90 new file mode 100644 index 00000000..3c84983a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/testdlasq4.f90 @@ -0,0 +1,435 @@ +program testdlasq4 +implicit none + +! Dlasq4 tests +integer :: i0, n0, pp, ttype, iter, nDiv, n, n0in +real(kind=8), dimension(401) :: z +real(kind=8) :: dmin, desig, qmax, dmin1, dmin2, dn, dn1, dn2, g, tau, sigma +logical :: ieee + +z(1:401) = (/2.9266499599402414D+02, & +2.9276699640004830D+02, & +2.9210200041216615D+02, & +2.9171973344922628D+02, & +2.9254120660184350D+02, & +2.9246923723528141D+02, & +2.8739845025761718D+02, & +2.8713781898215319D+02, & +2.9216230331620721D+02, & +2.9216609319427272D+02, & +2.9037912623973870D+02, & +2.9019341222762625D+02, & +2.9184732870824223D+02, & +2.9211597271231784D+02, & +2.9133173969911888D+02, & +2.9116703928303986D+02, & +2.9158395177813247D+02, & +2.9142053084921997D+02, & +2.8936184155474774D+02, & +2.9014388604362898D+02, & +2.9216722380092682D+02, & +2.9216917065163557D+02, & +2.9033857172870131D+02, & +2.9017428768626024D+02, & +2.9187084534700494D+02, & +2.9185392666684271D+02, & +2.8851014988393416D+02, & +2.8849290783118727D+02, & +2.9182506564169046D+02, & +2.9184679532940385D+02, & +2.9022222656964715D+02, & +2.9051820223150668D+02, & +2.9219746119018231D+02, & +2.9219997046052623D+02, & +2.9076912988009974D+02, & +2.9110108536012547D+02, & +2.9226281758828725D+02, & +2.9246883105892533D+02, & +2.9221612201279271D+02, & +2.9059157967819368D+02, & +2.9112833071623868D+02, & +2.9210680427275844D+02, & +2.9199887004058536D+02, & +2.9151030826460186D+02, & +2.9154564759046622D+02, & +2.9212462005167004D+02, & +2.9212108612522559D+02, & +2.9225720737270348D+02, & +2.9226471402909704D+02, & +2.9186949422820902D+02, & +2.9179442772569342D+02, & +2.9025839700680774D+02, & +2.9028281327393216D+02, & +2.9168280284451140D+02, & +2.9168036127921908D+02, & +2.9115346030764749D+02, & +2.9115401102000044D+02, & +2.9212282665919003D+02, & +2.9212277159409672D+02, & +2.9212554020600300D+02, & +2.9212559651286460D+02, & +2.9050907549403615D+02, & +2.9050344542208029D+02, & +2.9211004769628386D+02, & +2.9211127836880860D+02, & +2.9159257985266015D+02, & +2.9158027318883302D+02, & +2.9042716308833894D+02, & +2.9043622253245718D+02, & +2.9134221002346220D+02, & +2.9134130414047053D+02, & +2.9193179671375327D+02, & +2.9193426987096007D+02, & +2.9145366956406895D+02, & +2.9145119646828226D+02, & +2.9144876630819033D+02, & +2.9145122608379586D+02, & +2.9058395601500280D+02, & +2.9055935887314877D+02, & +2.9123982459393329D+02, & +2.9125037059550806D+02, & +2.9111624624209884D+02, & +2.9110570030194424D+02, & +2.9250004994137356D+02, & +2.9254994096967755D+02, & +2.9166071282413282D+02, & +2.9116180260251298D+02, & +2.8862845048087325D+02, & +2.8925662460652461D+02, & +2.9012609983518610D+02, & +2.9010672249354360D+02, & +2.9142999275190090D+02, & +2.9150806548221971D+02, & +2.9078477842534176D+02, & +2.8840517363552317D+02, & +2.8946267131307206D+02, & +2.9189614533792309D+02, & +2.9232617409967031D+02, & +2.9223702224333306D+02, & +2.9149978725880743D+02, & +2.9168777367421643D+02, & +2.9213296087125275D+02, & +2.9211416223585388D+02, & +2.9151431726536367D+02, & +2.9159900781717892D+02, & +2.9215362494632291D+02, & +2.9214515589728342D+02, & +2.9229900293632022D+02, & +2.9231644811476662D+02, & +2.9119079594655176D+02, & +2.9016344223508082D+02, & +2.9040052826233938D+02, & +2.9146756071890462D+02, & +2.9216592215429023D+02, & +2.9212317137116514D+02, & +2.9220217331561315D+02, & +2.9227234439098311D+02, & +2.9210931773273273D+02, & +2.9139146663504778D+02, & +2.9047426145779627D+02, & +2.9113243832972501D+02, & +2.9163901100086372D+02, & +2.9155399887833846D+02, & +2.9145039523229758D+02, & +2.9151950918932886D+02, & +2.9116352441156198D+02, & +2.9094410515950784D+02, & +2.9056083843332891D+02, & +2.9097140423254604D+02, & +2.9185385310744653D+02, & +2.9181279658894493D+02, & +2.9031697123096876D+02, & +2.9033298229128292D+02, & +2.9212507489852788D+02, & +2.9212491479406674D+02, & +2.9123248207180859D+02, & +2.9123278004625678D+02, & +2.9210890357464513D+02, & +2.9210887378334229D+02, & +2.9240010366769212D+02, & +2.9240021314868147D+02, & +2.9212046105624000D+02, & +2.9212035158139264D+02, & +2.9215242607939217D+02, & +2.9215256473001551D+02, & +2.9086373488934720D+02, & +2.9084987044121846D+02, & +2.9162085042968522D+02, & +2.9163097873649599D+02, & +2.9113228736441005D+02, & +2.9112215911901944D+02, & +2.9210393504686402D+02, & +2.9211255232953414D+02, & +2.9191445519642213D+02, & +2.9182828243114074D+02, & +2.9127013482394887D+02, & +2.9129823908392501D+02, & +2.9220880435635905D+02, & +2.9220599393650343D+02, & +2.9144676491963560D+02, & +2.9145286023012017D+02, & +2.9148058174349006D+02, & +2.9147448649442555D+02, & +2.9186619188590822D+02, & +2.9187731897876392D+02, & +2.9151148084374620D+02, & +2.9150035381231066D+02, & +2.9224292392669071D+02, & +2.9224832614828313D+02, & +2.9140236136264468D+02, & +2.9134833920814032D+02, & +2.9241531971951883D+02, & +2.9247972954055604D+02, & +2.9164613863843044D+02, & +2.8920404894780614D+02, & +2.8913485112658549D+02, & +2.9142701775363003D+02, & +2.9213449277295280D+02, & +2.9191925854858397D+02, & +2.9217029610406047D+02, & +2.9224915292105180D+02, & +2.9220325626287905D+02, & +2.9212439945202976D+02, & +2.9057154227612733D+02, & +2.9093384291672965D+02, & +2.9183595231931184D+02, & +2.9179972231667176D+02, & +2.9133916987034183D+02, & +2.9135453536038978D+02, & +2.9047085843212886D+02, & +2.9031720414585078D+02, & +2.9113106705127024D+02, & +2.9119455617800747D+02, & +2.9230127009862616D+02, & +2.9229492119209442D+02, & +2.9098170102485551D+02, & +2.9110028345622749D+02, & +2.9215236246918653D+02, & +2.9215215113995436D+02, & +2.9124650182241129D+02, & +2.9124684419934567D+02, & +2.9216244260160767D+02, & +2.9216240837005626D+02, & +2.9314769094184447D+02, & +2.9314772207133655D+02, & +2.9212215646682506D+02, & +2.9212184517804621D+02, & +2.9224739389310008D+02, & +2.9224802593241526D+02, & +2.8978611958992855D+02, & +2.8915408641678846D+02, & +2.9118533307571403D+02, & +2.9194553410039072D+02, & +2.9244688594134544D+02, & +2.9237086584501975D+02, & +2.9189894464487475D+02, & +2.9210832103555418D+02, & +2.9227685116407457D+02, & +2.9225842459914986D+02, & +2.9224821267514392D+02, & +2.9226591109467802D+02, & +2.9158625025645608D+02, & +2.9140926612253548D+02, & +2.9125298964526195D+02, & +2.9136239316241648D+02, & +2.9182040805585694D+02, & +2.9171100460012258D+02, & +2.9126693393315793D+02, & +2.9130800749967943D+02, & +2.9084722625682167D+02, & +2.9043649120580767D+02, & +2.9153791610078673D+02, & +2.9210440912405335D+02, & +2.9188686486416555D+02, & +2.9138068978583891D+02, & +2.9158124399039616D+02, & +2.9213540811751852D+02, & +2.9211624446790427D+02, & +2.9138960755567365D+02, & +2.9060415959100914D+02, & +2.9118025885063923D+02, & +2.9132902926505932D+02, & +2.9120918643494110D+02, & +2.9222955158764825D+02, & +2.9236106160611405D+02, & +2.9219941546106151D+02, & +2.9167905448737707D+02, & +2.8956733560159137D+02, & +2.9016660738228080D+02, & +2.9069372888915495D+02, & +2.9058385568123452D+02, & +2.9219861470697771D+02, & +2.9223599112669444D+02, & +2.9150234673408067D+02, & +2.9112858259833354D+02, & +2.9011809831967531D+02, & +2.9046138673473865D+02, & +2.9176526297220903D+02, & +2.9173093419212285D+02, & +2.9150067445343569D+02, & +2.9152418894132262D+02, & +2.9197021328944544D+02, & +2.9194669886297868D+02, & +2.9168012546172463D+02, & +2.9169701864791432D+02, & +2.9061916960844030D+02, & +2.9045023836074438D+02, & +2.9212529304266053D+02, & +2.9217230349727680D+02, & +2.9156357220873417D+02, & +2.9093467723991887D+02, & +2.9015918793416472D+02, & +2.9095983823965622D+02, & +2.9124303667219704D+02, & +2.9116297170306802D+02, & +2.9162557939634507D+02, & +2.9193291492830070D+02, & +2.9138731414547760D+02, & +2.9079978674942083D+02, & +2.9159254111122891D+02, & +2.9228695093326087D+02, & +2.9225423965335352D+02, & +2.9126542837357596D+02, & +2.9173807466948557D+02, & +2.9270696227984581D+02, & +2.9274075480094893D+02, & +2.9210759999419366D+02, & +2.9091701924155882D+02, & +2.9163130710260498D+02, & +2.9157158980248664D+02, & +2.9031984685457667D+02, & +2.8939239820067894D+02, & +2.9070124438246870D+02, & +2.9196350995833507D+02, & +2.9189730956351508D+02, & +2.9047434516138509D+02, & +2.9050934070611282D+02, & +2.9179387236503283D+02, & +2.9179037287198020D+02, & +2.9197909575321057D+02, & +2.9198343084479546D+02, & +2.9146450345905629D+02, & +2.9146016842889151D+02, & +2.9233889755268928D+02, & +2.9234209014701219D+02, & +2.9032302536354865D+02, & +2.8837665454569191D+02, & +2.8923259893670223D+02, & +2.9119948081590582D+02, & +2.9158422265927129D+02, & +2.9138706789415261D+02, & +2.9131767302238063D+02, & +2.9147948119882238D+02, & +2.9186937598758146D+02, & +2.9170756787255982D+02, & +2.9181460198203825D+02, & +2.9210008868832023D+02, & +2.9132088639794199D+02, & +2.9113460155819826D+02, & +2.9159448593680958D+02, & +2.9214172380575934D+02, & +2.9182660907964311D+02, & +2.8938570202792107D+02, & +2.8829979954353007D+02, & +2.9064250900128923D+02, & +2.9110347860364448D+02, & +2.9039527564479215D+02, & +2.9152783923893156D+02, & +2.9213818222324863D+02, & +2.9211881276563861D+02, & +2.9133414472425187D+02, & +2.9125375097531855D+02, & +2.9190226937530139D+02, & +2.9164903795105636D+02, & +2.8851961249369930D+02, & +2.8835729910731652D+02, & +2.9144629542849515D+02, & +2.9171485796658368D+02, & +2.9126891989861593D+02, & +2.9051052150188838D+02, & +2.9113570969073521D+02, & +2.9141652614094619D+02, & +2.9133186866181995D+02, & +2.8912484642922516D+02, & +2.8915669391948876D+02, & +2.9117142770169869D+02, & +2.9117110928821620D+02, & +2.9183490795481288D+02, & +2.9183646161652371D+02, & +2.9254379194824975D+02, & +2.9254363658822064D+02, & +2.9192127768678108D+02, & +2.9192154096878102D+02, & +2.9151073810022524D+02, & +2.9151047487964541D+02, & +2.9013993357169915D+02, & +2.9014000572685774D+02, & +2.9145714571416084D+02, & +2.9145713856006512D+02, & +2.9196091751473017D+02, & +2.9196093255283131D+02, & +2.9195731369267685D+02, & +2.9195729871599588D+02, & +2.9149460806187619D+02, & +2.9149461579988633D+02, & +2.9034687539457741D+02, & +2.9034679862867739D+02, & +2.9010765498373922D+02, & +2.9010767881379803D+02, & +2.8967492890608241D+02, & +2.8967469674750663D+02, & +2.9215189060671338D+02, & +2.9215194287124120D+02, & +2.8956132995364590D+02, & +2.8950907156783751D+02, & +2.9210783379750950D+02, & +2.9211890340058585D+02, & +2.9139896954309916D+02, & +2.9128827357375536D+02, & +2.9190012628763964D+02, & +2.9212457714005234D+02, & +2.9221336158434212D+02, & +2.9217879707919576D+02, & +2.9127472708852724D+02, & +2.9132783649002283D+02, & +2.9227509889951233D+02, & +2.9226978796550475D+02, & +2.9142078378447616D+02, & +2.9142906715955786D+02, & +2.9017517054475991D+02, & +2.8992337408144391D+02, & +2.8477362931531121D+02, & +2.8514676291150971D+02, & +2.8393423954726200D+02, & +2.8313625395453965D+02, & +2.8449999402409759D+02, & +2.8534282615303522D+02, & +2.8523140662657408D+02, & +2.8739845025761718D+02, & +2.8713781898215319D+02, & +0.0000000000000000D+00/) +i0 = 1 +n0 = 100 +pp = 1 +n0in = 100 +dmin = 7.9798559272231942D+282 +dmin1 = 7.9798559272231942D+282 +dmin2 = 2.3215857579138407D+285 +dn = 2.3140662657409930D+284 +dn1 = 7.9798559272231942D+282 +dn2 = 8.2833136615500372D+288 +g = 2.5000000000000000D-01 +tau = 6.1420124051338430D+283 +ttype = -4 + +ieee = .True. + +print *, "Starting Dlasq4" + +call Dlasq4(i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn, dn1, dn2, tau, ttype, g) + +print *, "Done calling dlasq4" +print *, "tau = ", tau +print *, tau, ttype, g + +end \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/xerbla.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/xerbla.f new file mode 100644 index 00000000..3e93bc4e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dlasqtest/xerbla.f @@ -0,0 +1,99 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download XERBLA + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/Makefile b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/Makefile new file mode 100644 index 00000000..7d22727a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/Makefile @@ -0,0 +1,20 @@ +FC = gfortran +FFLAGS = -O2 + +targets = testdsterf +objects = disnan.o dlamch.o dlanst.o dlaisnan.o dlassq.o dlapy2.o lsame.o dlae2.o dlascl.o dlasrt.o dsterf.o xerbla.o + +default : $(targets) +.PHONY : default + +testdsterf : testdsterf.o $(objects) + +% : %.o + $(FC) $(FFLAGS) $^ -o $@ + +%.o : %.f90 + $(FC) $(FFLAGS) -c -o $@ $< + +clean : + rm -f *.o $(targets) *.txt +.PHONY : clean \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/disnan.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/disnan.f new file mode 100644 index 00000000..355b8279 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/disnan.f @@ -0,0 +1,80 @@ +*> \brief \b DISNAN tests input for NaN. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DISNAN( DIN ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. +*> otherwise. To be replaced by the Fortran 2003 intrinsic in the +*> future. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN +*> \verbatim +*> DIN is DOUBLE PRECISION +*> Input to test for NaN. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DISNAN( DIN ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL DLAISNAN + EXTERNAL DLAISNAN +* .. +* .. Executable Statements .. + DISNAN = DLAISNAN(DIN,DIN) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlae2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlae2.f new file mode 100644 index 00000000..302eeaa1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlae2.f @@ -0,0 +1,185 @@ +*> \brief \b DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAE2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAE2( A, B, C, RT1, RT2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION A, B, C, RT1, RT2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix +*> [ A B ] +*> [ B C ]. +*> On return, RT1 is the eigenvalue of larger absolute value, and RT2 +*> is the eigenvalue of smaller absolute value. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION +*> The (1,1) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is DOUBLE PRECISION +*> The (1,2) and (2,1) elements of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] C +*> \verbatim +*> C is DOUBLE PRECISION +*> The (2,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[out] RT1 +*> \verbatim +*> RT1 is DOUBLE PRECISION +*> The eigenvalue of larger absolute value. +*> \endverbatim +*> +*> \param[out] RT2 +*> \verbatim +*> RT2 is DOUBLE PRECISION +*> The eigenvalue of smaller absolute value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> RT1 is accurate to a few ulps barring over/underflow. +*> +*> RT2 may be inaccurate if there is massive cancellation in the +*> determinant A*C-B*B; higher precision or correctly rounded or +*> correctly truncated arithmetic would be needed to compute RT2 +*> accurately in all cases. +*> +*> Overflow is possible only if RT1 is within a factor of 5 of overflow. +*> Underflow is harmless if the input data is 0 or exceeds +*> underflow_threshold / macheps. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLAE2( A, B, C, RT1, RT2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, RT1, RT2 +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION HALF + PARAMETER ( HALF = 0.5D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* +* Compute the eigenvalues +* + SM = A + C + DF = A - C + ADF = ABS( DF ) + TB = B + B + AB = ABS( TB ) + IF( ABS( A ).GT.ABS( C ) ) THEN + ACMX = A + ACMN = C + ELSE + ACMX = C + ACMN = A + END IF + IF( ADF.GT.AB ) THEN + RT = ADF*SQRT( ONE+( AB / ADF )**2 ) + ELSE IF( ADF.LT.AB ) THEN + RT = AB*SQRT( ONE+( ADF / AB )**2 ) + ELSE +* +* Includes case AB=ADF=0 +* + RT = AB*SQRT( TWO ) + END IF + IF( SM.LT.ZERO ) THEN + RT1 = HALF*( SM-RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE IF( SM.GT.ZERO ) THEN + RT1 = HALF*( SM+RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE +* +* Includes case RT1 = RT2 = 0 +* + RT1 = HALF*RT + RT2 = -HALF*RT + END IF + RETURN +* +* End of DLAE2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlaisnan.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlaisnan.f new file mode 100644 index 00000000..58595c5c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlaisnan.f @@ -0,0 +1,91 @@ +*> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN1, DIN2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This routine is not for general use. It exists solely to avoid +*> over-optimization in DISNAN. +*> +*> DLAISNAN checks for NaNs by comparing its two arguments for +*> inequality. NaN is the only floating-point value where NaN != NaN +*> returns .TRUE. To check for NaNs, pass the same variable as both +*> arguments. +*> +*> A compiler must assume that the two arguments are +*> not the same variable, and the test will not be optimized away. +*> Interprocedural or whole-program optimization may delete this +*> test. The ISNAN functions will be replaced by the correct +*> Fortran 03 intrinsic once the intrinsic is widely available. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN1 +*> \verbatim +*> DIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] DIN2 +*> \verbatim +*> DIN2 is DOUBLE PRECISION +*> Two numbers to compare for inequality. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN1, DIN2 +* .. +* +* ===================================================================== +* +* .. Executable Statements .. + DLAISNAN = (DIN1.NE.DIN2) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlamch.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlamch.f new file mode 100644 index 00000000..25c2c8e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlamch.f @@ -0,0 +1,193 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2011 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlanst.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlanst.f new file mode 100644 index 00000000..213b06ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlanst.f @@ -0,0 +1,186 @@ +*> \brief \b DLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm, or the element of largest absolute value of a real symmetric tridiagonal matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLANST + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E ) +* +* .. Scalar Arguments .. +* CHARACTER NORM +* INTEGER N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLANST returns the value of the one norm, or the Frobenius norm, or +*> the infinity norm, or the element of largest absolute value of a +*> real symmetric tridiagonal matrix A. +*> \endverbatim +*> +*> \return DLANST +*> \verbatim +*> +*> DLANST = ( max(abs(A(i,j))), NORM = 'M' or 'm' +*> ( +*> ( norm1(A), NORM = '1', 'O' or 'o' +*> ( +*> ( normI(A), NORM = 'I' or 'i' +*> ( +*> ( normF(A), NORM = 'F', 'f', 'E' or 'e' +*> +*> where norm1 denotes the one norm of a matrix (maximum column sum), +*> normI denotes the infinity norm of a matrix (maximum row sum) and +*> normF denotes the Frobenius norm of a matrix (square root of sum of +*> squares). Note that max(abs(A(i,j))) is not a consistent matrix norm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] NORM +*> \verbatim +*> NORM is CHARACTER*1 +*> Specifies the value to be returned in DLANST as described +*> above. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix A. N >= 0. When N = 0, DLANST is +*> set to zero. +*> \endverbatim +*> +*> \param[in] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> The diagonal elements of A. +*> \endverbatim +*> +*> \param[in] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N-1) +*> The (n-1) sub-diagonal or super-diagonal elements of A. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION ANORM, SCALE, SUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + EXTERNAL LSAME, DISNAN +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* + IF( N.LE.0 ) THEN + ANORM = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + ANORM = ABS( D( N ) ) + DO 10 I = 1, N - 1 + SUM = ABS( D( I ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + SUM = ABS( E( I ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + 10 CONTINUE + ELSE IF( LSAME( NORM, 'O' ) .OR. NORM.EQ.'1' .OR. + $ LSAME( NORM, 'I' ) ) THEN +* +* Find norm1(A). +* + IF( N.EQ.1 ) THEN + ANORM = ABS( D( 1 ) ) + ELSE + ANORM = ABS( D( 1 ) )+ABS( E( 1 ) ) + SUM = ABS( E( N-1 ) )+ABS( D( N ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + DO 20 I = 2, N - 1 + SUM = ABS( D( I ) )+ABS( E( I ) )+ABS( E( I-1 ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + 20 CONTINUE + END IF + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + IF( N.GT.1 ) THEN + CALL DLASSQ( N-1, E, 1, SCALE, SUM ) + SUM = 2*SUM + END IF + CALL DLASSQ( N, D, 1, SCALE, SUM ) + ANORM = SCALE*SQRT( SUM ) + END IF +* + DLANST = ANORM + RETURN +* +* End of DLANST +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlapy2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlapy2.f new file mode 100644 index 00000000..d43b0d5d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlapy2.f @@ -0,0 +1,104 @@ +*> \brief \b DLAPY2 returns sqrt(x2+y2). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAPY2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION X, Y +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary +*> overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] Y +*> \verbatim +*> Y is DOUBLE PRECISION +*> X and Y specify the values x and y. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, Z +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + W = MAX( XABS, YABS ) + Z = MIN( XABS, YABS ) + IF( Z.EQ.ZERO ) THEN + DLAPY2 = W + ELSE + DLAPY2 = W*SQRT( ONE+( Z / W )**2 ) + END IF + RETURN +* +* End of DLAPY2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlascl.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlascl.f new file mode 100644 index 00000000..9b9b33c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlascl.f @@ -0,0 +1,364 @@ +*> \brief \b DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASCL + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER TYPE +* INTEGER INFO, KL, KU, LDA, M, N +* DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASCL multiplies the M by N real matrix A by the real scalar +*> CTO/CFROM. This is done without over/underflow as long as the final +*> result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that +*> A may be full, upper triangular, lower triangular, upper Hessenberg, +*> or banded. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TYPE +*> \verbatim +*> TYPE is CHARACTER*1 +*> TYPE indices the storage type of the input matrix. +*> = 'G': A is a full matrix. +*> = 'L': A is a lower triangular matrix. +*> = 'U': A is an upper triangular matrix. +*> = 'H': A is an upper Hessenberg matrix. +*> = 'B': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the lower +*> half stored. +*> = 'Q': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the upper +*> half stored. +*> = 'Z': A is a band matrix with lower bandwidth KL and upper +*> bandwidth KU. See DGBTRF for storage details. +*> \endverbatim +*> +*> \param[in] KL +*> \verbatim +*> KL is INTEGER +*> The lower bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] KU +*> \verbatim +*> KU is INTEGER +*> The upper bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] CFROM +*> \verbatim +*> CFROM is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] CTO +*> \verbatim +*> CTO is DOUBLE PRECISION +*> +*> The matrix A is multiplied by CTO/CFROM. A(I,J) is computed +*> without over/underflow if the final result CTO*A(I,J)/CFROM +*> can be represented without over/underflow. CFROM must be +*> nonzero. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The matrix to be multiplied by CTO/CFROM. See TYPE for the +*> storage type. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> 0 - successful exit +*> <0 - if INFO = -i, the i-th argument had an illegal value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, KL, KU, LDA, M, N + DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL DONE + INTEGER I, ITYPE, J, K1, K2, K3, K4 + DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH, DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 +* + IF( LSAME( TYPE, 'G' ) ) THEN + ITYPE = 0 + ELSE IF( LSAME( TYPE, 'L' ) ) THEN + ITYPE = 1 + ELSE IF( LSAME( TYPE, 'U' ) ) THEN + ITYPE = 2 + ELSE IF( LSAME( TYPE, 'H' ) ) THEN + ITYPE = 3 + ELSE IF( LSAME( TYPE, 'B' ) ) THEN + ITYPE = 4 + ELSE IF( LSAME( TYPE, 'Q' ) ) THEN + ITYPE = 5 + ELSE IF( LSAME( TYPE, 'Z' ) ) THEN + ITYPE = 6 + ELSE + ITYPE = -1 + END IF +* + IF( ITYPE.EQ.-1 ) THEN + INFO = -1 + ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN + INFO = -4 + ELSE IF( DISNAN(CTO) ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -6 + ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR. + $ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN + INFO = -7 + ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN + INFO = -9 + ELSE IF( ITYPE.GE.4 ) THEN + IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN + INFO = -2 + ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR. + $ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) ) + $ THEN + INFO = -3 + ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR. + $ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR. + $ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN + INFO = -9 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASCL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) + $ RETURN +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM +* + CFROMC = CFROM + CTOC = CTO +* + 10 CONTINUE + CFROM1 = CFROMC*SMLNUM + IF( CFROM1.EQ.CFROMC ) THEN +! CFROMC is an inf. Multiply by a correctly signed zero for +! finite CTOC, or a NaN if CTOC is infinite. + MUL = CTOC / CFROMC + DONE = .TRUE. + CTO1 = CTOC + ELSE + CTO1 = CTOC / BIGNUM + IF( CTO1.EQ.CTOC ) THEN +! CTOC is either 0 or an inf. In both cases, CTOC itself +! serves as the correct multiplication factor. + MUL = CTOC + DONE = .TRUE. + CFROMC = ONE + ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN + MUL = SMLNUM + DONE = .FALSE. + CFROMC = CFROM1 + ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN + MUL = BIGNUM + DONE = .FALSE. + CTOC = CTO1 + ELSE + MUL = CTOC / CFROMC + DONE = .TRUE. + END IF + END IF +* + IF( ITYPE.EQ.0 ) THEN +* +* Full matrix +* + DO 30 J = 1, N + DO 20 I = 1, M + A( I, J ) = A( I, J )*MUL + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( ITYPE.EQ.1 ) THEN +* +* Lower triangular matrix +* + DO 50 J = 1, N + DO 40 I = J, M + A( I, J ) = A( I, J )*MUL + 40 CONTINUE + 50 CONTINUE +* + ELSE IF( ITYPE.EQ.2 ) THEN +* +* Upper triangular matrix +* + DO 70 J = 1, N + DO 60 I = 1, MIN( J, M ) + A( I, J ) = A( I, J )*MUL + 60 CONTINUE + 70 CONTINUE +* + ELSE IF( ITYPE.EQ.3 ) THEN +* +* Upper Hessenberg matrix +* + DO 90 J = 1, N + DO 80 I = 1, MIN( J+1, M ) + A( I, J ) = A( I, J )*MUL + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( ITYPE.EQ.4 ) THEN +* +* Lower half of a symmetric band matrix +* + K3 = KL + 1 + K4 = N + 1 + DO 110 J = 1, N + DO 100 I = 1, MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 100 CONTINUE + 110 CONTINUE +* + ELSE IF( ITYPE.EQ.5 ) THEN +* +* Upper half of a symmetric band matrix +* + K1 = KU + 2 + K3 = KU + 1 + DO 130 J = 1, N + DO 120 I = MAX( K1-J, 1 ), K3 + A( I, J ) = A( I, J )*MUL + 120 CONTINUE + 130 CONTINUE +* + ELSE IF( ITYPE.EQ.6 ) THEN +* +* Band matrix +* + K1 = KL + KU + 2 + K2 = KL + 1 + K3 = 2*KL + KU + 1 + K4 = KL + KU + 1 + M + DO 150 J = 1, N + DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 140 CONTINUE + 150 CONTINUE +* + END IF +* + IF( .NOT.DONE ) + $ GO TO 10 +* + RETURN +* +* End of DLASCL +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlasrt.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlasrt.f new file mode 100644 index 00000000..f5d0e6cd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlasrt.f @@ -0,0 +1,303 @@ +*> \brief \b DLASRT sorts numbers in increasing or decreasing order. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASRT + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER ID +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Sort the numbers in D in increasing order (if ID = 'I') or +*> in decreasing order (if ID = 'D' ). +*> +*> Use Quick Sort, reverting to Insertion sort on arrays of +*> size <= 20. Dimension of STACK limits N to about 2**32. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ID +*> \verbatim +*> ID is CHARACTER*1 +*> = 'I': sort D in increasing order; +*> = 'D': sort D in decreasing order. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The length of the array D. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the array to be sorted. +*> On exit, D has been sorted into increasing order +*> (D(1) <= ... <= D(N) ) or into decreasing order +*> (D(1) >= ... >= D(N) ), depending on ID. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 + RETURN +* +* End of DLASRT +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlassq.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlassq.f new file mode 100644 index 00000000..c7c4087e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dlassq.f @@ -0,0 +1,155 @@ +*> \brief \b DLASSQ updates a sum of squares represented in scaled form. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASSQ + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ ) +* +* .. Scalar Arguments .. +* INTEGER INCX, N +* DOUBLE PRECISION SCALE, SUMSQ +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASSQ returns the values scl and smsq such that +*> +*> ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq, +*> +*> where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is +*> assumed to be non-negative and scl returns the value +*> +*> scl = max( scale, abs( x( i ) ) ). +*> +*> scale and sumsq must be supplied in SCALE and SUMSQ and +*> scl and smsq are overwritten on SCALE and SUMSQ respectively. +*> +*> The routine makes only one pass through the vector x. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of elements to be used from the vector X. +*> \endverbatim +*> +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION array, dimension (N) +*> The vector for which a scaled sum of squares is computed. +*> x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> The increment between successive values of the vector X. +*> INCX > 0. +*> \endverbatim +*> +*> \param[in,out] SCALE +*> \verbatim +*> SCALE is DOUBLE PRECISION +*> On entry, the value scale in the equation above. +*> On exit, SCALE is overwritten with scl , the scaling factor +*> for the sum of squares. +*> \endverbatim +*> +*> \param[in,out] SUMSQ +*> \verbatim +*> SUMSQ is DOUBLE PRECISION +*> On entry, the value sumsq in the equation above. +*> On exit, SUMSQ is overwritten with smsq , the basic sum of +*> squares from which scl has been factored out. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION SCALE, SUMSQ +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER IX + DOUBLE PRECISION ABSXI +* .. +* .. External Functions .. + LOGICAL DISNAN + EXTERNAL DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* + IF( N.GT.0 ) THEN + DO 10 IX = 1, 1 + ( N-1 )*INCX, INCX + ABSXI = ABS( X( IX ) ) + IF( ABSXI.GT.ZERO.OR.DISNAN( ABSXI ) ) THEN + IF( SCALE.LT.ABSXI ) THEN + SUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2 + SCALE = ABSXI + ELSE + SUMSQ = SUMSQ + ( ABSXI / SCALE )**2 + END IF + END IF + 10 CONTINUE + END IF + RETURN +* +* End of DLASSQ +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dsterf.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dsterf.f new file mode 100644 index 00000000..43395cc7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/dsterf.f @@ -0,0 +1,448 @@ +*> \brief \b DSTERF +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DSTERF + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DSTERF( N, D, E, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DSTERF computes all eigenvalues of a symmetric tridiagonal matrix +*> using the Pal-Walker-Kahan variant of the QL or QR algorithm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the n diagonal elements of the tridiagonal matrix. +*> On exit, if INFO = 0, the eigenvalues in ascending order. +*> \endverbatim +*> +*> \param[in,out] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N-1) +*> On entry, the (n-1) subdiagonal elements of the tridiagonal +*> matrix. +*> On exit, E has been destroyed. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> > 0: the algorithm failed to find all of the eigenvalues in +*> a total of 30*N iterations; if INFO = i, then i +*> elements of E have not converged to zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DSTERF( N, D, E, INFO ) +* +* -- LAPACK computational routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO, THREE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, + $ THREE = 3.0D0 ) + INTEGER MAXIT + PARAMETER ( MAXIT = 30 ) +* .. +* .. Local Scalars .. + INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M, + $ NMAXIT + DOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC, + $ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN, + $ SIGMA, SSFMAX, SSFMIN, RMAX +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLANST, DLAPY2 + EXTERNAL DLAMCH, DLANST, DLAPY2 +* .. +* .. External Subroutines .. + EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 +* +* Quick return if possible +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DSTERF', -INFO ) + RETURN + END IF + IF( N.LE.1 ) + $ RETURN +* +* Determine the unit roundoff for this environment. +* + EPS = DLAMCH( 'E' ) + EPS2 = EPS**2 + SAFMIN = DLAMCH( 'S' ) + SAFMAX = ONE / SAFMIN + SSFMAX = SQRT( SAFMAX ) / THREE + SSFMIN = SQRT( SAFMIN ) / EPS2 + RMAX = DLAMCH( 'O' ) +* +* Compute the eigenvalues of the tridiagonal matrix. +* + NMAXIT = N*MAXIT + SIGMA = ZERO + JTOT = 0 +* +* Determine where the matrix splits and choose QL or QR iteration +* for each block, according to whether top or bottom diagonal +* element is smaller. +* + L1 = 1 +* + 10 CONTINUE + print *, "l1 = ", l1 + IF( L1.GT.N ) THEN + print *, "going to 170" + GO TO 170 + end if + IF( L1.GT.1 ) + $ E( L1-1 ) = ZERO + DO 20 M = L1, N - 1 + IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+ + $ 1 ) ) ) )*EPS ) THEN + E( M ) = ZERO + GO TO 30 + END IF + 20 CONTINUE + M = N +* + 30 CONTINUE + print *, "30, d" + print *, d(1:n) + L = L1 + LSV = L + LEND = M + LENDSV = LEND + L1 = M + 1 + IF( LEND.EQ.L ) + $ GO TO 10 +* +* Scale submatrix in rows and columns L to LEND +* + ANORM = DLANST( 'M', LEND-L+1, D( L ), E( L ) ) + ISCALE = 0 + IF( ANORM.EQ.ZERO ) + $ GO TO 10 + IF( (ANORM.GT.SSFMAX) ) THEN + ISCALE = 1 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N, + $ INFO ) + ELSE IF( ANORM.LT.SSFMIN ) THEN + ISCALE = 2 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N, + $ INFO ) + END IF +* + DO 40 I = L, LEND - 1 + E( I ) = E( I )**2 + 40 CONTINUE +* +* Choose between QL and QR iteration +* + IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN + LEND = LSV + L = LENDSV + END IF +* + IF( LEND.GE.L ) THEN + print *, "ql, d" + print *, d(1:n) +* +* QL Iteration +* +* Look for small subdiagonal element. +* + 50 CONTINUE + IF( L.NE.LEND ) THEN + DO 60 M = L, LEND - 1 + IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) ) + $ GO TO 70 + 60 CONTINUE + END IF + M = LEND +* + 70 CONTINUE + IF( M.LT.LEND ) + $ E( M ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 90 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L+1 ) THEN + RTE = SQRT( E( L ) ) + CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 ) + D( L ) = RT1 + D( L+1 ) = RT2 + E( L ) = ZERO + L = L + 2 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L ) ) + SIGMA = ( D( L+1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + print *, "inner loop d before" + print *, d(1:n) + + DO 80 I = M - 1, L, -1 + print *, "inner loop" + print *, "ei", e(i) + BB = E( I ) + R = P + BB + print *, "bb,p,r" + print *, bb,p,r + IF( I.NE.M-1 ) THEN + print *, s,r + E( I+1 ) = S*R + end if + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + print *, "di", d(i) + ALPHA = D( I ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + print *,"og, a, ga", OLDGAM, ALPHA, GAMMA + D( I+1 ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + print *, "p, gamma = ", p,GAMMA + 80 CONTINUE +* + E( L ) = S*P + D( L ) = SIGMA + GAMMA + + print *, "inner loop d after" + print *, d(1:n) + GO TO 50 +* +* Eigenvalue found. +* + 90 CONTINUE + D( L ) = P +* + L = L + 1 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 +* + ELSE +* +* QR Iteration +* +* Look for small superdiagonal element. +* + 100 CONTINUE + DO 110 M = L, LEND + 1, -1 + IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) ) + $ GO TO 120 + 110 CONTINUE + M = LEND +* + 120 CONTINUE + IF( M.GT.LEND ) + $ E( M-1 ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 140 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L-1 ) THEN + RTE = SQRT( E( L-1 ) ) + CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 ) + D( L ) = RT1 + D( L-1 ) = RT2 + E( L-1 ) = ZERO + L = L - 2 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L-1 ) ) + SIGMA = ( D( L-1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + DO 130 I = M, L - 1 + BB = E( I ) + R = P + BB + IF( I.NE.M ) + $ E( I-1 ) = S*R + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + ALPHA = D( I+1 ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + D( I ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + 130 CONTINUE +* + E( L-1 ) = S*P + D( L ) = SIGMA + GAMMA + GO TO 100 +* +* Eigenvalue found. +* + 140 CONTINUE + D( L ) = P +* + L = L - 1 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 +* + END IF +* +* Undo scaling if necessary +* + 150 CONTINUE + IF( ISCALE.EQ.1 ) + $ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) + IF( ISCALE.EQ.2 ) + $ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) +* +* Check for no convergence to an eigenvalue after a total +* of N*MAXIT iterations. +* + IF( JTOT.LT.NMAXIT ) + $ GO TO 10 + DO 160 I = 1, N - 1 + IF( E( I ).NE.ZERO ) + $ INFO = INFO + 1 + 160 CONTINUE + GO TO 180 +* +* Sort eigenvalues in increasing order. +* + 170 CONTINUE + CALL DLASRT( 'I', N, D, INFO ) +* + 180 CONTINUE + RETURN +* +* End of DSTERF +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/lsame.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/testdsterf.f90 b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/testdsterf.f90 new file mode 100644 index 00000000..8373f512 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/testdsterf.f90 @@ -0,0 +1,15 @@ +program testdsterf +implicit none +integer, parameter :: n = 4 +real(kind=8), dimension(n) :: d +real(kind=8), dimension(n-1) :: e +integer :: info,i + +d(1:4) = (/1D+00, 3D+00, 4D+00, 6D+00/) +e(1:3) = (/2D+00, 4D+00, 5D+00/) + +call dsterf(n,d,e,info) +DO i = 1, n + print *, d(i) +end do +end \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/xerbla.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/xerbla.f new file mode 100644 index 00000000..3e93bc4e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/dsterftest/xerbla.f @@ -0,0 +1,99 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download XERBLA + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/daxpy.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/daxpy.f new file mode 100644 index 00000000..64a02d68 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/daxpy.f @@ -0,0 +1,115 @@ +*> \brief \b DAXPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DA +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DAXPY constant times a vector plus a vector. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DA + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (DA.EQ.0.0d0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,4) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DY(I) + DA*DX(I) + END DO + END IF + IF (N.LT.4) RETURN + MP1 = M + 1 + DO I = MP1,N,4 + DY(I) = DY(I) + DA*DX(I) + DY(I+1) = DY(I+1) + DA*DX(I+1) + DY(I+2) = DY(I+2) + DA*DX(I+2) + DY(I+3) = DY(I+3) + DA*DX(I+3) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DY(IY) + DA*DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dcopy.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dcopy.f new file mode 100644 index 00000000..d9d5ac7a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dcopy.f @@ -0,0 +1,115 @@ +*> \brief \b DCOPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DCOPY copies a vector, x, to a vector, y. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,7) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DX(I) + END DO + IF (N.LT.7) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,7 + DY(I) = DX(I) + DY(I+1) = DX(I+1) + DY(I+2) = DX(I+2) + DY(I+3) = DX(I+3) + DY(I+4) = DX(I+4) + DY(I+5) = DX(I+5) + DY(I+6) = DX(I+6) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemm.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemm.f new file mode 100644 index 00000000..4bae243a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemm.f @@ -0,0 +1,384 @@ +*> \brief \b DGEMM +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA,BETA +* INTEGER K,LDA,LDB,LDC,M,N +* CHARACTER TRANSA,TRANSB +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DGEMM performs one of the matrix-matrix operations +*> +*> C := alpha*op( A )*op( B ) + beta*C, +*> +*> where op( X ) is one of +*> +*> op( X ) = X or op( X ) = X**T, +*> +*> alpha and beta are scalars, and A, B and C are matrices, with op( A ) +*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TRANSA +*> \verbatim +*> TRANSA is CHARACTER*1 +*> On entry, TRANSA specifies the form of op( A ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSA = 'N' or 'n', op( A ) = A. +*> +*> TRANSA = 'T' or 't', op( A ) = A**T. +*> +*> TRANSA = 'C' or 'c', op( A ) = A**T. +*> \endverbatim +*> +*> \param[in] TRANSB +*> \verbatim +*> TRANSB is CHARACTER*1 +*> On entry, TRANSB specifies the form of op( B ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSB = 'N' or 'n', op( B ) = B. +*> +*> TRANSB = 'T' or 't', op( B ) = B**T. +*> +*> TRANSB = 'C' or 'c', op( B ) = B**T. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of the matrix +*> op( A ) and of the matrix C. M must be at least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of the matrix +*> op( B ) and the number of columns of the matrix C. N must be +*> at least zero. +*> \endverbatim +*> +*> \param[in] K +*> \verbatim +*> K is INTEGER +*> On entry, K specifies the number of columns of the matrix +*> op( A ) and the number of rows of the matrix op( B ). K must +*> be at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is +*> k when TRANSA = 'N' or 'n', and is m otherwise. +*> Before entry with TRANSA = 'N' or 'n', the leading m by k +*> part of the array A must contain the matrix A, otherwise +*> the leading k by m part of the array A must contain the +*> matrix A. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. When TRANSA = 'N' or 'n' then +*> LDA must be at least max( 1, m ), otherwise LDA must be at +*> least max( 1, k ). +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is +*> n when TRANSB = 'N' or 'n', and is k otherwise. +*> Before entry with TRANSB = 'N' or 'n', the leading k by n +*> part of the array B must contain the matrix B, otherwise +*> the leading n by k part of the array B must contain the +*> matrix B. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> On entry, LDB specifies the first dimension of B as declared +*> in the calling (sub) program. When TRANSB = 'N' or 'n' then +*> LDB must be at least max( 1, k ), otherwise LDB must be at +*> least max( 1, n ). +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION. +*> On entry, BETA specifies the scalar beta. When BETA is +*> supplied as zero then C need not be set on input. +*> \endverbatim +*> +*> \param[in,out] C +*> \verbatim +*> C is DOUBLE PRECISION array of DIMENSION ( LDC, n ). +*> Before entry, the leading m by n part of the array C must +*> contain the matrix C, except when beta is zero, in which +*> case C need not be set on entry. +*> On exit, the array C is overwritten by the m by n matrix +*> ( alpha*op( A )*op( B ) + beta*C ). +*> \endverbatim +*> +*> \param[in] LDC +*> \verbatim +*> LDC is INTEGER +*> On entry, LDC specifies the first dimension of C as declared +*> in the calling (sub) program. LDC must be at least +*> max( 1, m ). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup double_blas_level3 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 3 Blas routine. +*> +*> -- Written on 8-February-1989. +*> Jack Dongarra, Argonne National Laboratory. +*> Iain Duff, AERE Harwell. +*> Jeremy Du Croz, Numerical Algorithms Group Ltd. +*> Sven Hammarling, Numerical Algorithms Group Ltd. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) +* +* -- Reference BLAS level3 routine (version 3.6.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER K,LDA,LDB,LDC,M,N + CHARACTER TRANSA,TRANSB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB + LOGICAL NOTA,NOTB +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* transposed and set NROWA, NCOLA and NROWB as the number of rows +* and columns of A and the number of rows of B respectively. +* + NOTA = LSAME(TRANSA,'N') + NOTB = LSAME(TRANSB,'N') + IF (NOTA) THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF (NOTB) THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF ((.NOT.NOTA) .AND. (.NOT.LSAME(TRANSA,'C')) .AND. + + (.NOT.LSAME(TRANSA,'T'))) THEN + INFO = 1 + ELSE IF ((.NOT.NOTB) .AND. (.NOT.LSAME(TRANSB,'C')) .AND. + + (.NOT.LSAME(TRANSB,'T'))) THEN + INFO = 2 + ELSE IF (M.LT.0) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (K.LT.0) THEN + INFO = 5 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 8 + ELSE IF (LDB.LT.MAX(1,NROWB)) THEN + INFO = 10 + ELSE IF (LDC.LT.MAX(1,M)) THEN + INFO = 13 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DGEMM ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((M.EQ.0) .OR. (N.EQ.0) .OR. + + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN +* +* And if alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + IF (BETA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,M + C(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40 J = 1,N + DO 30 I = 1,M + C(I,J) = BETA*C(I,J) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF (NOTB) THEN + IF (NOTA) THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 50 I = 1,M + C(I,J) = ZERO + 50 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 60 I = 1,M + C(I,J) = BETA*C(I,J) + 60 CONTINUE + END IF + DO 80 L = 1,K + TEMP = ALPHA*B(L,J) + DO 70 I = 1,M + C(I,J) = C(I,J) + TEMP*A(I,L) + 70 CONTINUE + 80 CONTINUE + 90 CONTINUE + ELSE +* +* Form C := alpha*A**T*B + beta*C +* + DO 120 J = 1,N + DO 110 I = 1,M + TEMP = ZERO + DO 100 L = 1,K + TEMP = TEMP + A(L,I)*B(L,J) + 100 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 110 CONTINUE + 120 CONTINUE + END IF + ELSE + IF (NOTA) THEN +* +* Form C := alpha*A*B**T + beta*C +* + DO 170 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 130 I = 1,M + C(I,J) = ZERO + 130 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 140 I = 1,M + C(I,J) = BETA*C(I,J) + 140 CONTINUE + END IF + DO 160 L = 1,K + TEMP = ALPHA*B(J,L) + DO 150 I = 1,M + C(I,J) = C(I,J) + TEMP*A(I,L) + 150 CONTINUE + 160 CONTINUE + 170 CONTINUE + ELSE +* +* Form C := alpha*A**T*B**T + beta*C +* + DO 200 J = 1,N + DO 190 I = 1,M + TEMP = ZERO + DO 180 L = 1,K + TEMP = TEMP + A(L,I)*B(J,L) + 180 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 190 CONTINUE + 200 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMM . +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemv.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemv.f new file mode 100644 index 00000000..e04cc07c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dgemv.f @@ -0,0 +1,330 @@ +*> \brief \b DGEMV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA,BETA +* INTEGER INCX,INCY,LDA,M,N +* CHARACTER TRANS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),X(*),Y(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DGEMV performs one of the matrix-vector operations +*> +*> y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, +*> +*> where alpha and beta are scalars, x and y are vectors and A is an +*> m by n matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TRANS +*> \verbatim +*> TRANS is CHARACTER*1 +*> On entry, TRANS specifies the operation to be performed as +*> follows: +*> +*> TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +*> +*> TRANS = 'T' or 't' y := alpha*A**T*x + beta*y. +*> +*> TRANS = 'C' or 'c' y := alpha*A**T*x + beta*y. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of the matrix A. +*> M must be at least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of the matrix A. +*> N must be at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, n ). +*> Before entry, the leading m by n part of the array A must +*> contain the matrix of coefficients. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. LDA must be at least +*> max( 1, m ). +*> \endverbatim +*> +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION array of DIMENSION at least +*> ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +*> and at least +*> ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +*> Before entry, the incremented array X must contain the +*> vector x. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> On entry, INCX specifies the increment for the elements of +*> X. INCX must not be zero. +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION. +*> On entry, BETA specifies the scalar beta. When BETA is +*> supplied as zero then Y need not be set on input. +*> \endverbatim +*> +*> \param[in,out] Y +*> \verbatim +*> Y is DOUBLE PRECISION array of DIMENSION at least +*> ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +*> and at least +*> ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +*> Before entry with BETA non-zero, the incremented array Y +*> must contain the vector y. On exit, Y is overwritten by the +*> updated vector y. +*> \endverbatim +*> +*> \param[in] INCY +*> \verbatim +*> INCY is INTEGER +*> On entry, INCY specifies the increment for the elements of +*> Y. INCY must not be zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup double_blas_level2 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 2 Blas routine. +*> The vector and matrix arguments are not referenced when N = 0, or M = 0 +*> +*> -- Written on 22-October-1986. +*> Jack Dongarra, Argonne National Lab. +*> Jeremy Du Croz, Nag Central Office. +*> Sven Hammarling, Nag Central Office. +*> Richard Hanson, Sandia National Labs. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +* +* -- Reference BLAS level2 routine (version 3.6.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER INCX,INCY,LDA,M,N + CHARACTER TRANS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),X(*),Y(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,IX,IY,J,JX,JY,KX,KY,LENX,LENY +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 1 + ELSE IF (M.LT.0) THEN + INFO = 2 + ELSE IF (N.LT.0) THEN + INFO = 3 + ELSE IF (LDA.LT.MAX(1,M)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + ELSE IF (INCY.EQ.0) THEN + INFO = 11 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DGEMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((M.EQ.0) .OR. (N.EQ.0) .OR. + + ((ALPHA.EQ.ZERO).AND. (BETA.EQ.ONE))) RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF (LSAME(TRANS,'N')) THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF (INCX.GT.0) THEN + KX = 1 + ELSE + KX = 1 - (LENX-1)*INCX + END IF + IF (INCY.GT.0) THEN + KY = 1 + ELSE + KY = 1 - (LENY-1)*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF (BETA.NE.ONE) THEN + IF (INCY.EQ.1) THEN + IF (BETA.EQ.ZERO) THEN + DO 10 I = 1,LENY + Y(I) = ZERO + 10 CONTINUE + ELSE + DO 20 I = 1,LENY + Y(I) = BETA*Y(I) + 20 CONTINUE + END IF + ELSE + IY = KY + IF (BETA.EQ.ZERO) THEN + DO 30 I = 1,LENY + Y(IY) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40 I = 1,LENY + Y(IY) = BETA*Y(IY) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF (ALPHA.EQ.ZERO) RETURN + IF (LSAME(TRANS,'N')) THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF (INCY.EQ.1) THEN + DO 60 J = 1,N + TEMP = ALPHA*X(JX) + DO 50 I = 1,M + Y(I) = Y(I) + TEMP*A(I,J) + 50 CONTINUE + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80 J = 1,N + TEMP = ALPHA*X(JX) + IY = KY + DO 70 I = 1,M + Y(IY) = Y(IY) + TEMP*A(I,J) + IY = IY + INCY + 70 CONTINUE + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A**T*x + y. +* + JY = KY + IF (INCX.EQ.1) THEN + DO 100 J = 1,N + TEMP = ZERO + DO 90 I = 1,M + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + Y(JY) = Y(JY) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120 J = 1,N + TEMP = ZERO + IX = KX + DO 110 I = 1,M + TEMP = TEMP + A(I,J)*X(IX) + IX = IX + INCX + 110 CONTINUE + Y(JY) = Y(JY) + ALPHA*TEMP + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMV . +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlabad.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlabad.f new file mode 100644 index 00000000..da412633 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlabad.f @@ -0,0 +1,105 @@ +*> \brief \b DLABAD +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLABAD + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLABAD( SMALL, LARGE ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION LARGE, SMALL +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLABAD takes as input the values computed by DLAMCH for underflow and +*> overflow, and returns the square root of each of these values if the +*> log of LARGE is sufficiently large. This subroutine is intended to +*> identify machines with a large exponent range, such as the Crays, and +*> redefine the underflow and overflow limits to be the square roots of +*> the values computed by DLAMCH. This subroutine is needed because +*> DLAMCH does not compensate for poor arithmetic in the upper half of +*> the exponent range, as is found on a Cray. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in,out] SMALL +*> \verbatim +*> SMALL is DOUBLE PRECISION +*> On entry, the underflow threshold as computed by DLAMCH. +*> On exit, if LOG10(LARGE) is sufficiently large, the square +*> root of SMALL, otherwise unchanged. +*> \endverbatim +*> +*> \param[in,out] LARGE +*> \verbatim +*> LARGE is DOUBLE PRECISION +*> On entry, the overflow threshold as computed by DLAMCH. +*> On exit, if LOG10(LARGE) is sufficiently large, the square +*> root of LARGE, otherwise unchanged. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLABAD( SMALL, LARGE ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION LARGE, SMALL +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LOG10, SQRT +* .. +* .. Executable Statements .. +* +* If it looks like we're on a Cray, take the square root of +* SMALL and LARGE to avoid overflow and underflow problems. +* +* IF( LOG10( LARGE ).GT.2000.D0 ) THEN +* SMALL = SQRT( SMALL ) +* LARGE = SQRT( LARGE ) +* END IF +* + RETURN +* +* End of DLABAD +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlacpy.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlacpy.f new file mode 100644 index 00000000..a9a23c94 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlacpy.f @@ -0,0 +1,156 @@ +*> \brief \b DLACPY copies all or part of one two-dimensional array to another. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLACPY + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER LDA, LDB, M, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLACPY copies all or part of a two-dimensional matrix A to another +*> matrix B. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> Specifies the part of the matrix A to be copied to B. +*> = 'U': Upper triangular part +*> = 'L': Lower triangular part +*> Otherwise: All of the matrix A +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The m by n matrix A. If UPLO = 'U', only the upper triangle +*> or trapezoid is accessed; if UPLO = 'L', only the lower +*> triangle or trapezoid is accessed. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] B +*> \verbatim +*> B is DOUBLE PRECISION array, dimension (LDB,N) +*> On exit, B = A in the locations specified by UPLO. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> The leading dimension of the array B. LDB >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, LDB, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN + DO 20 J = 1, N + DO 10 I = 1, MIN( J, M ) + B( I, J ) = A( I, J ) + 10 CONTINUE + 20 CONTINUE + ELSE IF( LSAME( UPLO, 'L' ) ) THEN + DO 40 J = 1, N + DO 30 I = J, M + B( I, J ) = A( I, J ) + 30 CONTINUE + 40 CONTINUE + ELSE + DO 60 J = 1, N + DO 50 I = 1, M + B( I, J ) = A( I, J ) + 50 CONTINUE + 60 CONTINUE + END IF + RETURN +* +* End of DLACPY +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlahr2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlahr2.f new file mode 100644 index 00000000..9d15979c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlahr2.f @@ -0,0 +1,326 @@ +*> \brief \b DLAHR2 reduces the specified number of first columns of a general rectangular matrix A so that elements below the specified subdiagonal are zero, and returns auxiliary matrices which are needed to apply the transformation to the unreduced part of A. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAHR2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) +* +* .. Scalar Arguments .. +* INTEGER K, LDA, LDT, LDY, N, NB +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), +* $ Y( LDY, NB ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1) +*> matrix A so that elements below the k-th subdiagonal are zero. The +*> reduction is performed by an orthogonal similarity transformation +*> Q**T * A * Q. The routine returns the matrices V and T which determine +*> Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. +*> +*> This is an auxiliary routine called by DGEHRD. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix A. +*> \endverbatim +*> +*> \param[in] K +*> \verbatim +*> K is INTEGER +*> The offset for the reduction. Elements below the k-th +*> subdiagonal in the first NB columns are reduced to zero. +*> K < N. +*> \endverbatim +*> +*> \param[in] NB +*> \verbatim +*> NB is INTEGER +*> The number of columns to be reduced. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N-K+1) +*> On entry, the n-by-(n-k+1) general matrix A. +*> On exit, the elements on and above the k-th subdiagonal in +*> the first NB columns are overwritten with the corresponding +*> elements of the reduced matrix; the elements below the k-th +*> subdiagonal, with the array TAU, represent the matrix Q as a +*> product of elementary reflectors. The other columns of A are +*> unchanged. See Further Details. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,N). +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION array, dimension (NB) +*> The scalar factors of the elementary reflectors. See Further +*> Details. +*> \endverbatim +*> +*> \param[out] T +*> \verbatim +*> T is DOUBLE PRECISION array, dimension (LDT,NB) +*> The upper triangular matrix T. +*> \endverbatim +*> +*> \param[in] LDT +*> \verbatim +*> LDT is INTEGER +*> The leading dimension of the array T. LDT >= NB. +*> \endverbatim +*> +*> \param[out] Y +*> \verbatim +*> Y is DOUBLE PRECISION array, dimension (LDY,NB) +*> The n-by-nb matrix Y. +*> \endverbatim +*> +*> \param[in] LDY +*> \verbatim +*> LDY is INTEGER +*> The leading dimension of the array Y. LDY >= N. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> The matrix Q is represented as a product of nb elementary reflectors +*> +*> Q = H(1) H(2) . . . H(nb). +*> +*> Each H(i) has the form +*> +*> H(i) = I - tau * v * v**T +*> +*> where tau is a real scalar, and v is a real vector with +*> v(1:i+k-1) = 0, v(i+k) = 1; v(i+k+1:n) is stored on exit in +*> A(i+k+1:n,i), and tau in TAU(i). +*> +*> The elements of the vectors v together form the (n-k+1)-by-nb matrix +*> V which is needed, with T and Y, to apply the transformation to the +*> unreduced part of the matrix, using an update of the form: +*> A := (I - V*T*V**T) * (A - Y*V**T). +*> +*> The contents of A on exit are illustrated by the following example +*> with n = 7, k = 3 and nb = 2: +*> +*> ( a a a a a ) +*> ( a a a a a ) +*> ( a a a a a ) +*> ( h h a a a ) +*> ( v1 h a a a ) +*> ( v1 v2 a a a ) +*> ( v1 v2 a a a ) +*> +*> where a denotes an element of the original matrix A, h denotes a +*> modified element of the upper Hessenberg matrix H, and vi denotes an +*> element of the vector defining H(i). +*> +*> This subroutine is a slight modification of LAPACK-3.0's DLAHRD +*> incorporating improvements proposed by Quintana-Orti and Van de +*> Gejin. Note that the entries of A(1:K,2:NB) differ from those +*> returned by the original LAPACK-3.0's DLAHRD routine. (This +*> subroutine is not backward compatible with LAPACK-3.0's DLAHRD.) +*> \endverbatim +* +*> \par References: +* ================ +*> +*> Gregorio Quintana-Orti and Robert van de Geijn, "Improving the +*> performance of reduction to Hessenberg form," ACM Transactions on +*> Mathematical Software, 32(2):180-194, June 2006. +*> +* ===================================================================== + SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER K, LDA, LDT, LDY, N, NB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), + $ Y( LDY, NB ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, + $ ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION EI +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DGEMM, DGEMV, DLACPY, + $ DLARFG, DSCAL, DTRMM, DTRMV +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + DO 10 I = 1, NB + IF( I.GT.1 ) THEN +* +* Update A(K+1:N,I) +* +* Update I-th column of A - Y * V**T +* + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, Y(K+1,1), LDY, + $ A( K+I-1, 1 ), LDA, ONE, A( K+1, I ), 1 ) +* +* Apply I - V * T**T * V**T to this column (call it b) from the +* left, using the last column of T as workspace +* +* Let V = ( V1 ) and b = ( b1 ) (first I-1 rows) +* ( V2 ) ( b2 ) +* +* where V1 is unit lower triangular +* +* w := V1**T * b1 +* + CALL DCOPY( I-1, A( K+1, I ), 1, T( 1, NB ), 1 ) + CALL DTRMV( 'Lower', 'Transpose', 'UNIT', + $ I-1, A( K+1, 1 ), + $ LDA, T( 1, NB ), 1 ) +* +* w := w + V2**T * b2 +* + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), + $ LDA, A( K+I, I ), 1, ONE, T( 1, NB ), 1 ) +* +* w := T**T * w +* + CALL DTRMV( 'Upper', 'Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, NB ), 1 ) +* +* b2 := b2 - V2*w +* + CALL DGEMV( 'NO TRANSPOSE', N-K-I+1, I-1, -ONE, + $ A( K+I, 1 ), + $ LDA, T( 1, NB ), 1, ONE, A( K+I, I ), 1 ) +* +* b1 := b1 - V1*w +* + CALL DTRMV( 'Lower', 'NO TRANSPOSE', + $ 'UNIT', I-1, + $ A( K+1, 1 ), LDA, T( 1, NB ), 1 ) + CALL DAXPY( I-1, -ONE, T( 1, NB ), 1, A( K+1, I ), 1 ) +* + A( K+I-1, I-1 ) = EI + END IF +* +* Generate the elementary reflector H(I) to annihilate +* A(K+I+1:N,I) +* + CALL DLARFG( N-K-I+1, A( K+I, I ), A( MIN( K+I+1, N ), I ), 1, + $ TAU( I ) ) + EI = A( K+I, I ) + A( K+I, I ) = ONE +* +* Compute Y(K+1:N,I) +* + CALL DGEMV( 'NO TRANSPOSE', N-K, N-K-I+1, + $ ONE, A( K+1, I+1 ), + $ LDA, A( K+I, I ), 1, ZERO, Y( K+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), LDA, + $ A( K+I, I ), 1, ZERO, T( 1, I ), 1 ) + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, + $ Y( K+1, 1 ), LDY, + $ T( 1, I ), 1, ONE, Y( K+1, I ), 1 ) + CALL DSCAL( N-K, TAU( I ), Y( K+1, I ), 1 ) +* +* Compute T(1:I,I) +* + CALL DSCAL( I-1, -TAU( I ), T( 1, I ), 1 ) + CALL DTRMV( 'Upper', 'No Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, I ), 1 ) + T( I, I ) = TAU( I ) +* + 10 CONTINUE + A( K+NB, NB ) = EI +* +* Compute Y(1:K,1:NB) +* + CALL DLACPY( 'ALL', K, NB, A( 1, 2 ), LDA, Y, LDY ) + CALL DTRMM( 'RIGHT', 'Lower', 'NO TRANSPOSE', + $ 'UNIT', K, NB, + $ ONE, A( K+1, 1 ), LDA, Y, LDY ) + IF( N.GT.K+NB ) + $ CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', K, + $ NB, N-K-NB, ONE, + $ A( 1, 2+NB ), LDA, A( K+1+NB, 1 ), LDA, ONE, Y, + $ LDY ) + CALL DTRMM( 'RIGHT', 'Upper', 'NO TRANSPOSE', + $ 'NON-UNIT', K, NB, + $ ONE, T, LDT, Y, LDY ) +* + RETURN +* +* End of DLAHR2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlamch.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlamch.f new file mode 100644 index 00000000..22a16218 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlamch.f @@ -0,0 +1,189 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2015 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlapy2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlapy2.f new file mode 100644 index 00000000..d43b0d5d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlapy2.f @@ -0,0 +1,104 @@ +*> \brief \b DLAPY2 returns sqrt(x2+y2). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAPY2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION X, Y +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary +*> overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] Y +*> \verbatim +*> Y is DOUBLE PRECISION +*> X and Y specify the values x and y. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, Z +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + W = MAX( XABS, YABS ) + Z = MIN( XABS, YABS ) + IF( Z.EQ.ZERO ) THEN + DLAPY2 = W + ELSE + DLAPY2 = W*SQRT( ONE+( Z / W )**2 ) + END IF + RETURN +* +* End of DLAPY2 +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr1.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr1.f new file mode 100644 index 00000000..df4fb68b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr1.f @@ -0,0 +1,179 @@ +*> \brief \b DLAQR1 sets a scalar multiple of the first column of the product of 2-by-2 or 3-by-3 matrix H and specified shifts. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAQR1 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION SI1, SI2, SR1, SR2 +* INTEGER LDH, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION H( LDH, * ), V( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Given a 2-by-2 or 3-by-3 matrix H, DLAQR1 sets v to a +*> scalar multiple of the first column of the product +*> +*> (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) +*> +*> scaling to avoid overflows and most underflows. It +*> is assumed that either +*> +*> 1) sr1 = sr2 and si1 = -si2 +*> or +*> 2) si1 = si2 = 0. +*> +*> This is useful for starting double implicit shift bulges +*> in the QR algorithm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is integer +*> Order of the matrix H. N must be either 2 or 3. +*> \endverbatim +*> +*> \param[in] H +*> \verbatim +*> H is DOUBLE PRECISION array of dimension (LDH,N) +*> The 2-by-2 or 3-by-3 matrix H in (*). +*> \endverbatim +*> +*> \param[in] LDH +*> \verbatim +*> LDH is integer +*> The leading dimension of H as declared in +*> the calling procedure. LDH.GE.N +*> \endverbatim +*> +*> \param[in] SR1 +*> \verbatim +*> SR1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SI1 +*> \verbatim +*> SI1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SR2 +*> \verbatim +*> SR2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SI2 +*> \verbatim +*> SI2 is DOUBLE PRECISION +*> The shifts in (*). +*> \endverbatim +*> +*> \param[out] V +*> \verbatim +*> V is DOUBLE PRECISION array of dimension N +*> A scalar multiple of the first column of the +*> matrix K in (*). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Contributors: +* ================== +*> +*> Karen Braman and Ralph Byers, Department of Mathematics, +*> University of Kansas, USA +*> +* ===================================================================== + SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION SI1, SI2, SR1, SR2 + INTEGER LDH, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), V( * ) +* .. +* +* ================================================================ +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION H21S, H31S, S +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. + IF( N.EQ.2 ) THEN + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + V( 1 ) = H21S*H( 1, 2 ) + ( H( 1, 1 )-SR1 )* + $ ( ( H( 1, 1 )-SR2 ) / S ) - SI1*( SI2 / S ) + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + END IF + ELSE + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + + $ ABS( H( 3, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + V( 3 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + H31S = H( 3, 1 ) / S + V( 1 ) = ( H( 1, 1 )-SR1 )*( ( H( 1, 1 )-SR2 ) / S ) - + $ SI1*( SI2 / S ) + H( 1, 2 )*H21S + H( 1, 3 )*H31S + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + + $ H( 2, 3 )*H31S + V( 3 ) = H31S*( H( 1, 1 )+H( 3, 3 )-SR1-SR2 ) + + $ H21S*H( 3, 2 ) + END IF + END IF + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr5.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr5.f new file mode 100644 index 00000000..37ce6f6b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaqr5.f @@ -0,0 +1,921 @@ +*> \brief \b DLAQR5 performs a single small-bulge multi-shift QR sweep. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAQR5 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, +* SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, +* LDU, NV, WV, LDWV, NH, WH, LDWH ) +* +* .. Scalar Arguments .. +* INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, +* $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV +* LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. +* DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), +* $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), +* $ Z( LDZ, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAQR5, called by DLAQR0, performs a +*> single small-bulge multi-shift QR sweep. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] WANTT +*> \verbatim +*> WANTT is logical scalar +*> WANTT = .true. if the quasi-triangular Schur factor +*> is being computed. WANTT is set to .false. otherwise. +*> \endverbatim +*> +*> \param[in] WANTZ +*> \verbatim +*> WANTZ is logical scalar +*> WANTZ = .true. if the orthogonal Schur factor is being +*> computed. WANTZ is set to .false. otherwise. +*> \endverbatim +*> +*> \param[in] KACC22 +*> \verbatim +*> KACC22 is integer with value 0, 1, or 2. +*> Specifies the computation mode of far-from-diagonal +*> orthogonal updates. +*> = 0: DLAQR5 does not accumulate reflections and does not +*> use matrix-matrix multiply to update far-from-diagonal +*> matrix entries. +*> = 1: DLAQR5 accumulates reflections and uses matrix-matrix +*> multiply to update the far-from-diagonal matrix entries. +*> = 2: DLAQR5 accumulates reflections, uses matrix-matrix +*> multiply to update the far-from-diagonal matrix entries, +*> and takes advantage of 2-by-2 block structure during +*> matrix multiplies. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is integer scalar +*> N is the order of the Hessenberg matrix H upon which this +*> subroutine operates. +*> \endverbatim +*> +*> \param[in] KTOP +*> \verbatim +*> KTOP is integer scalar +*> \endverbatim +*> +*> \param[in] KBOT +*> \verbatim +*> KBOT is integer scalar +*> These are the first and last rows and columns of an +*> isolated diagonal block upon which the QR sweep is to be +*> applied. It is assumed without a check that +*> either KTOP = 1 or H(KTOP,KTOP-1) = 0 +*> and +*> either KBOT = N or H(KBOT+1,KBOT) = 0. +*> \endverbatim +*> +*> \param[in] NSHFTS +*> \verbatim +*> NSHFTS is integer scalar +*> NSHFTS gives the number of simultaneous shifts. NSHFTS +*> must be positive and even. +*> \endverbatim +*> +*> \param[in,out] SR +*> \verbatim +*> SR is DOUBLE PRECISION array of size (NSHFTS) +*> \endverbatim +*> +*> \param[in,out] SI +*> \verbatim +*> SI is DOUBLE PRECISION array of size (NSHFTS) +*> SR contains the real parts and SI contains the imaginary +*> parts of the NSHFTS shifts of origin that define the +*> multi-shift QR sweep. On output SR and SI may be +*> reordered. +*> \endverbatim +*> +*> \param[in,out] H +*> \verbatim +*> H is DOUBLE PRECISION array of size (LDH,N) +*> On input H contains a Hessenberg matrix. On output a +*> multi-shift QR sweep with shifts SR(J)+i*SI(J) is applied +*> to the isolated diagonal block in rows and columns KTOP +*> through KBOT. +*> \endverbatim +*> +*> \param[in] LDH +*> \verbatim +*> LDH is integer scalar +*> LDH is the leading dimension of H just as declared in the +*> calling procedure. LDH.GE.MAX(1,N). +*> \endverbatim +*> +*> \param[in] ILOZ +*> \verbatim +*> ILOZ is INTEGER +*> \endverbatim +*> +*> \param[in] IHIZ +*> \verbatim +*> IHIZ is INTEGER +*> Specify the rows of Z to which transformations must be +*> applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N +*> \endverbatim +*> +*> \param[in,out] Z +*> \verbatim +*> Z is DOUBLE PRECISION array of size (LDZ,IHI) +*> If WANTZ = .TRUE., then the QR Sweep orthogonal +*> similarity transformation is accumulated into +*> Z(ILOZ:IHIZ,ILO:IHI) from the right. +*> If WANTZ = .FALSE., then Z is unreferenced. +*> \endverbatim +*> +*> \param[in] LDZ +*> \verbatim +*> LDZ is integer scalar +*> LDA is the leading dimension of Z just as declared in +*> the calling procedure. LDZ.GE.N. +*> \endverbatim +*> +*> \param[out] V +*> \verbatim +*> V is DOUBLE PRECISION array of size (LDV,NSHFTS/2) +*> \endverbatim +*> +*> \param[in] LDV +*> \verbatim +*> LDV is integer scalar +*> LDV is the leading dimension of V as declared in the +*> calling procedure. LDV.GE.3. +*> \endverbatim +*> +*> \param[out] U +*> \verbatim +*> U is DOUBLE PRECISION array of size +*> (LDU,3*NSHFTS-3) +*> \endverbatim +*> +*> \param[in] LDU +*> \verbatim +*> LDU is integer scalar +*> LDU is the leading dimension of U just as declared in the +*> in the calling subroutine. LDU.GE.3*NSHFTS-3. +*> \endverbatim +*> +*> \param[in] NH +*> \verbatim +*> NH is integer scalar +*> NH is the number of columns in array WH available for +*> workspace. NH.GE.1. +*> \endverbatim +*> +*> \param[out] WH +*> \verbatim +*> WH is DOUBLE PRECISION array of size (LDWH,NH) +*> \endverbatim +*> +*> \param[in] LDWH +*> \verbatim +*> LDWH is integer scalar +*> Leading dimension of WH just as declared in the +*> calling procedure. LDWH.GE.3*NSHFTS-3. +*> \endverbatim +*> +*> \param[in] NV +*> \verbatim +*> NV is integer scalar +*> NV is the number of rows in WV agailable for workspace. +*> NV.GE.1. +*> \endverbatim +*> +*> \param[out] WV +*> \verbatim +*> WV is DOUBLE PRECISION array of size +*> (LDWV,3*NSHFTS-3) +*> \endverbatim +*> +*> \param[in] LDWV +*> \verbatim +*> LDWV is integer scalar +*> LDWV is the leading dimension of WV as declared in the +*> in the calling subroutine. LDWV.GE.NV. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Contributors: +* ================== +*> +*> Karen Braman and Ralph Byers, Department of Mathematics, +*> University of Kansas, USA +* +*> \par References: +* ================ +*> +*> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +*> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 +*> Performance, SIAM Journal of Matrix Analysis, volume 23, pages +*> 929--947, 2002. +*> +* ===================================================================== + SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, + $ SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, + $ LDU, NV, WV, LDWV, NH, WH, LDWH ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, + $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), + $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), + $ Z( LDZ, * ) +* .. +* +* ================================================================ +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, BETA, H11, H12, H21, H22, REFSUM, + $ SAFMAX, SAFMIN, SCL, SMLNUM, SWAP, TST1, TST2, + $ ULP + INTEGER I, I2, I4, INCOL, J, J2, J4, JBOT, JCOL, JLEN, + $ JROW, JTOP, K, K1, KDU, KMS, KNZ, KRCOL, KZS, + $ M, M22, MBOT, MEND, MSTART, MTOP, NBMPS, NDCOL, + $ NS, NU + LOGICAL ACCUM, BLK22, BMP22 +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. +* + INTRINSIC ABS, DBLE, MAX, MIN, MOD +* .. +* .. Local Arrays .. + DOUBLE PRECISION VT( 3 ) +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DLABAD, DLACPY, DLAQR1, DLARFG, DLASET, + $ DTRMM +* .. +* .. Executable Statements .. +* +* ==== If there are no shifts, then there is nothing to do. ==== +* + IF( NSHFTS.LT.2 ) + $ RETURN +* +* ==== If the active block is empty or 1-by-1, then there +* . is nothing to do. ==== +* + IF( KTOP.GE.KBOT ) + $ RETURN +* +* ==== Shuffle shifts into pairs of real shifts and pairs +* . of complex conjugate shifts assuming complex +* . conjugate shifts are already adjacent to one +* . another. ==== +* + DO 10 I = 1, NSHFTS - 2, 2 + IF( SI( I ).NE.-SI( I+1 ) ) THEN +* + SWAP = SR( I ) + SR( I ) = SR( I+1 ) + SR( I+1 ) = SR( I+2 ) + SR( I+2 ) = SWAP +* + SWAP = SI( I ) + SI( I ) = SI( I+1 ) + SI( I+1 ) = SI( I+2 ) + SI( I+2 ) = SWAP + END IF + 10 CONTINUE +* +* ==== NSHFTS is supposed to be even, but if it is odd, +* . then simply reduce it by one. The shuffle above +* . ensures that the dropped shift is real and that +* . the remaining shifts are paired. ==== +* + NS = NSHFTS - MOD( NSHFTS, 2 ) +* +* ==== Machine constants for deflation ==== +* + SAFMIN = DLAMCH( 'SAFE MINIMUM' ) + SAFMAX = ONE / SAFMIN + CALL DLABAD( SAFMIN, SAFMAX ) + ULP = DLAMCH( 'PRECISION' ) + SMLNUM = SAFMIN*( DBLE( N ) / ULP ) +* +* ==== Use accumulated reflections to update far-from-diagonal +* . entries ? ==== +* + ACCUM = ( KACC22.EQ.1 ) .OR. ( KACC22.EQ.2 ) +* +* ==== If so, exploit the 2-by-2 block structure? ==== +* + BLK22 = ( NS.GT.2 ) .AND. ( KACC22.EQ.2 ) +* +* ==== clear trash ==== +* + IF( KTOP+2.LE.KBOT ) + $ H( KTOP+2, KTOP ) = ZERO +* +* ==== NBMPS = number of 2-shift bulges in the chain ==== +* + NBMPS = NS / 2 +* +* ==== KDU = width of slab ==== +* + KDU = 6*NBMPS - 3 +* +* ==== Create and chase chains of NBMPS bulges ==== +* + DO 220 INCOL = 3*( 1-NBMPS ) + KTOP - 1, KBOT - 2, 3*NBMPS - 2 + NDCOL = INCOL + KDU + IF( ACCUM ) + $ CALL DLASET( 'ALL', KDU, KDU, ZERO, ONE, U, LDU ) +* +* ==== Near-the-diagonal bulge chase. The following loop +* . performs the near-the-diagonal part of a small bulge +* . multi-shift QR sweep. Each 6*NBMPS-2 column diagonal +* . chunk extends from column INCOL to column NDCOL +* . (including both column INCOL and column NDCOL). The +* . following loop chases a 3*NBMPS column long chain of +* . NBMPS bulges 3*NBMPS-2 columns to the right. (INCOL +* . may be less than KTOP and and NDCOL may be greater than +* . KBOT indicating phantom columns from which to chase +* . bulges before they are actually introduced or to which +* . to chase bulges beyond column KBOT.) ==== +* + DO 150 KRCOL = INCOL, MIN( INCOL+3*NBMPS-3, KBOT-2 ) +* +* ==== Bulges number MTOP to MBOT are active double implicit +* . shift bulges. There may or may not also be small +* . 2-by-2 bulge, if there is room. The inactive bulges +* . (if any) must wait until the active bulges have moved +* . down the diagonal to make room. The phantom matrix +* . paradigm described above helps keep track. ==== +* + MTOP = MAX( 1, ( ( KTOP-1 )-KRCOL+2 ) / 3+1 ) + MBOT = MIN( NBMPS, ( KBOT-KRCOL ) / 3 ) + M22 = MBOT + 1 + BMP22 = ( MBOT.LT.NBMPS ) .AND. ( KRCOL+3*( M22-1 ) ).EQ. + $ ( KBOT-2 ) +* +* ==== Generate reflections to chase the chain right +* . one column. (The minimum value of K is KTOP-1.) ==== +* + DO 20 M = MTOP, MBOT + K = KRCOL + 3*( M-1 ) + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 3, H( KTOP, KTOP ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ V( 1, M ) ) + ALPHA = V( 1, M ) + CALL DLARFG( 3, ALPHA, V( 2, M ), 1, V( 1, M ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M ) = H( K+2, K ) + V( 3, M ) = H( K+3, K ) + CALL DLARFG( 3, BETA, V( 2, M ), 1, V( 1, M ) ) +* +* ==== A Bulge may collapse because of vigilant +* . deflation or destructive underflow. In the +* . underflow case, try the two-small-subdiagonals +* . trick to try to reinflate the bulge. ==== +* + IF( H( K+3, K ).NE.ZERO .OR. H( K+3, K+1 ).NE. + $ ZERO .OR. H( K+3, K+2 ).EQ.ZERO ) THEN +* +* ==== Typical case: not collapsed (yet). ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Atypical case: collapsed. Attempt to +* . reintroduce ignoring H(K+1,K) and H(K+2,K). +* . If the fill resulting from the new +* . reflector is too large, then abandon it. +* . Otherwise, use the new one. ==== +* + CALL DLAQR1( 3, H( K+1, K+1 ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ VT ) + ALPHA = VT( 1 ) + CALL DLARFG( 3, ALPHA, VT( 2 ), 1, VT( 1 ) ) + REFSUM = VT( 1 )*( H( K+1, K )+VT( 2 )* + $ H( K+2, K ) ) +* + IF( ABS( H( K+2, K )-REFSUM*VT( 2 ) )+ + $ ABS( REFSUM*VT( 3 ) ).GT.ULP* + $ ( ABS( H( K, K ) )+ABS( H( K+1, + $ K+1 ) )+ABS( H( K+2, K+2 ) ) ) ) THEN +* +* ==== Starting a new bulge here would +* . create non-negligible fill. Use +* . the old one with trepidation. ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Stating a new bulge here would +* . create only negligible fill. +* . Replace the old reflector with +* . the new one. ==== +* + H( K+1, K ) = H( K+1, K ) - REFSUM + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + V( 1, M ) = VT( 1 ) + V( 2, M ) = VT( 2 ) + V( 3, M ) = VT( 3 ) + END IF + END IF + END IF + 20 CONTINUE +* +* ==== Generate a 2-by-2 reflection, if needed. ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 2, H( K+1, K+1 ), LDH, SR( 2*M22-1 ), + $ SI( 2*M22-1 ), SR( 2*M22 ), SI( 2*M22 ), + $ V( 1, M22 ) ) + BETA = V( 1, M22 ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M22 ) = H( K+2, K ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + END IF + END IF +* +* ==== Multiply H by reflections from the left ==== +* + IF( ACCUM ) THEN + JBOT = MIN( NDCOL, KBOT ) + ELSE IF( WANTT ) THEN + JBOT = N + ELSE + JBOT = KBOT + END IF + DO 40 J = MAX( KTOP, KRCOL ), JBOT + MEND = MIN( MBOT, ( J-KRCOL+2 ) / 3 ) + DO 30 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*( H( K+1, J )+V( 2, M )* + $ H( K+2, J )+V( 3, M )*H( K+3, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M ) + H( K+3, J ) = H( K+3, J ) - REFSUM*V( 3, M ) + 30 CONTINUE + 40 CONTINUE + IF( BMP22 ) THEN + K = KRCOL + 3*( M22-1 ) + DO 50 J = MAX( K+1, KTOP ), JBOT + REFSUM = V( 1, M22 )*( H( K+1, J )+V( 2, M22 )* + $ H( K+2, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M22 ) + 50 CONTINUE + END IF +* +* ==== Multiply H by reflections from the right. +* . Delay filling in the last row until the +* . vigilant deflation check is complete. ==== +* + IF( ACCUM ) THEN + JTOP = MAX( KTOP, INCOL ) + ELSE IF( WANTT ) THEN + JTOP = 1 + ELSE + JTOP = KTOP + END IF + DO 90 M = MTOP, MBOT + IF( V( 1, M ).NE.ZERO ) THEN + K = KRCOL + 3*( M-1 ) + DO 60 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M )*( H( J, K+1 )+V( 2, M )* + $ H( J, K+2 )+V( 3, M )*H( J, K+3 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M ) + H( J, K+3 ) = H( J, K+3 ) - REFSUM*V( 3, M ) + 60 CONTINUE +* + IF( ACCUM ) THEN +* +* ==== Accumulate U. (If necessary, update Z later +* . with with an efficient matrix-matrix +* . multiply.) ==== +* + KMS = K - INCOL + DO 70 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M )*( U( J, KMS+1 )+V( 2, M )* + $ U( J, KMS+2 )+V( 3, M )*U( J, KMS+3 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - REFSUM*V( 2, M ) + U( J, KMS+3 ) = U( J, KMS+3 ) - REFSUM*V( 3, M ) + 70 CONTINUE + ELSE IF( WANTZ ) THEN +* +* ==== U is not accumulated, so update Z +* . now by multiplying by reflections +* . from the right. ==== +* + DO 80 J = ILOZ, IHIZ + REFSUM = V( 1, M )*( Z( J, K+1 )+V( 2, M )* + $ Z( J, K+2 )+V( 3, M )*Z( J, K+3 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M ) + Z( J, K+3 ) = Z( J, K+3 ) - REFSUM*V( 3, M ) + 80 CONTINUE + END IF + END IF + 90 CONTINUE +* +* ==== Special case: 2-by-2 reflection (if needed) ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF ( V( 1, M22 ).NE.ZERO ) THEN + DO 100 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M22 )*( H( J, K+1 )+V( 2, M22 )* + $ H( J, K+2 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M22 ) + 100 CONTINUE +* + IF( ACCUM ) THEN + KMS = K - INCOL + DO 110 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M22 )*( U( J, KMS+1 )+ + $ V( 2, M22 )*U( J, KMS+2 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - + $ REFSUM*V( 2, M22 ) + 110 CONTINUE + ELSE IF( WANTZ ) THEN + DO 120 J = ILOZ, IHIZ + REFSUM = V( 1, M22 )*( Z( J, K+1 )+V( 2, M22 )* + $ Z( J, K+2 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M22 ) + 120 CONTINUE + END IF + END IF + END IF +* +* ==== Vigilant deflation check ==== +* + MSTART = MTOP + IF( KRCOL+3*( MSTART-1 ).LT.KTOP ) + $ MSTART = MSTART + 1 + MEND = MBOT + IF( BMP22 ) + $ MEND = MEND + 1 + IF( KRCOL.EQ.KBOT-2 ) + $ MEND = MEND + 1 + DO 130 M = MSTART, MEND + K = MIN( KBOT-1, KRCOL+3*( M-1 ) ) +* +* ==== The following convergence test requires that +* . the tradition small-compared-to-nearby-diagonals +* . criterion and the Ahues & Tisseur (LAWN 122, 1997) +* . criteria both be satisfied. The latter improves +* . accuracy in some examples. Falling back on an +* . alternate convergence criterion when TST1 or TST2 +* . is zero (as done here) is traditional but probably +* . unnecessary. ==== +* + IF( H( K+1, K ).NE.ZERO ) THEN + TST1 = ABS( H( K, K ) ) + ABS( H( K+1, K+1 ) ) + IF( TST1.EQ.ZERO ) THEN + IF( K.GE.KTOP+1 ) + $ TST1 = TST1 + ABS( H( K, K-1 ) ) + IF( K.GE.KTOP+2 ) + $ TST1 = TST1 + ABS( H( K, K-2 ) ) + IF( K.GE.KTOP+3 ) + $ TST1 = TST1 + ABS( H( K, K-3 ) ) + IF( K.LE.KBOT-2 ) + $ TST1 = TST1 + ABS( H( K+2, K+1 ) ) + IF( K.LE.KBOT-3 ) + $ TST1 = TST1 + ABS( H( K+3, K+1 ) ) + IF( K.LE.KBOT-4 ) + $ TST1 = TST1 + ABS( H( K+4, K+1 ) ) + END IF + IF( ABS( H( K+1, K ) ).LE.MAX( SMLNUM, ULP*TST1 ) ) + $ THEN + H12 = MAX( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H21 = MIN( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H11 = MAX( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + H22 = MIN( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + SCL = H11 + H12 + TST2 = H22*( H11 / SCL ) +* + IF( TST2.EQ.ZERO .OR. H21*( H12 / SCL ).LE. + $ MAX( SMLNUM, ULP*TST2 ) )H( K+1, K ) = ZERO + END IF + END IF + 130 CONTINUE +* +* ==== Fill in the last row of each bulge. ==== +* + MEND = MIN( NBMPS, ( KBOT-KRCOL-1 ) / 3 ) + DO 140 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*V( 3, M )*H( K+4, K+3 ) + H( K+4, K+1 ) = -REFSUM + H( K+4, K+2 ) = -REFSUM*V( 2, M ) + H( K+4, K+3 ) = H( K+4, K+3 ) - REFSUM*V( 3, M ) + 140 CONTINUE +* +* ==== End of near-the-diagonal bulge chase. ==== +* + 150 CONTINUE +* +* ==== Use U (if accumulated) to update far-from-diagonal +* . entries in H. If required, use U to update Z as +* . well. ==== +* + IF( ACCUM ) THEN + IF( WANTT ) THEN + JTOP = 1 + JBOT = N + ELSE + JTOP = KTOP + JBOT = KBOT + END IF + IF( ( .NOT.BLK22 ) .OR. ( INCOL.LT.KTOP ) .OR. + $ ( NDCOL.GT.KBOT ) .OR. ( NS.LE.2 ) ) THEN +* +* ==== Updates not exploiting the 2-by-2 block +* . structure of U. K1 and NU keep track of +* . the location and size of U in the special +* . cases of introducing bulges and chasing +* . bulges off the bottom. In these special +* . cases and in case the number of shifts +* . is NS = 2, there is no 2-by-2 block +* . structure to exploit. ==== +* + K1 = MAX( 1, KTOP-INCOL ) + NU = ( KDU-MAX( 0, NDCOL-KBOT ) ) - K1 + 1 +* +* ==== Horizontal Multiply ==== +* + DO 160 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) + CALL DGEMM( 'C', 'N', NU, JLEN, NU, ONE, U( K1, K1 ), + $ LDU, H( INCOL+K1, JCOL ), LDH, ZERO, WH, + $ LDWH ) + CALL DLACPY( 'ALL', NU, JLEN, WH, LDWH, + $ H( INCOL+K1, JCOL ), LDH ) + 160 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 170 JROW = JTOP, MAX( KTOP, INCOL ) - 1, NV + JLEN = MIN( NV, MAX( KTOP, INCOL )-JROW ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ H( JROW, INCOL+K1 ), LDH, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ H( JROW, INCOL+K1 ), LDH ) + 170 CONTINUE +* +* ==== Z multiply (also vertical) ==== +* + IF( WANTZ ) THEN + DO 180 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ Z( JROW, INCOL+K1 ), LDZ, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ Z( JROW, INCOL+K1 ), LDZ ) + 180 CONTINUE + END IF + ELSE +* +* ==== Updates exploiting U's 2-by-2 block structure. +* . (I2, I4, J2, J4 are the last rows and columns +* . of the blocks.) ==== +* + I2 = ( KDU+1 ) / 2 + I4 = KDU + J2 = I4 - I2 + J4 = KDU +* +* ==== KZS and KNZ deal with the band of zeros +* . along the diagonal of one of the triangular +* . blocks. ==== +* + KZS = ( J4-J2 ) - ( NS+1 ) + KNZ = NS + 1 +* +* ==== Horizontal multiply ==== +* + DO 190 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) +* +* ==== Copy bottom of H to top+KZS of scratch ==== +* (The first KZS rows get multiplied by zero.) ==== +* + CALL DLACPY( 'ALL', KNZ, JLEN, H( INCOL+1+J2, JCOL ), + $ LDH, WH( KZS+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DLASET( 'ALL', KZS, JLEN, ZERO, ZERO, WH, LDWH ) + CALL DTRMM( 'L', 'U', 'C', 'N', KNZ, JLEN, ONE, + $ U( J2+1, 1+KZS ), LDU, WH( KZS+1, 1 ), + $ LDWH ) +* +* ==== Multiply top of H by U11**T ==== +* + CALL DGEMM( 'C', 'N', I2, JLEN, J2, ONE, U, LDU, + $ H( INCOL+1, JCOL ), LDH, ONE, WH, LDWH ) +* +* ==== Copy top of H to bottom of WH ==== +* + CALL DLACPY( 'ALL', J2, JLEN, H( INCOL+1, JCOL ), LDH, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DTRMM( 'L', 'L', 'C', 'N', J2, JLEN, ONE, + $ U( 1, I2+1 ), LDU, WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'C', 'N', I4-I2, JLEN, J4-J2, ONE, + $ U( J2+1, I2+1 ), LDU, + $ H( INCOL+1+J2, JCOL ), LDH, ONE, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', KDU, JLEN, WH, LDWH, + $ H( INCOL+1, JCOL ), LDH ) + 190 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 200 JROW = JTOP, MAX( INCOL, KTOP ) - 1, NV + JLEN = MIN( NV, MAX( INCOL, KTOP )-JROW ) +* +* ==== Copy right of H to scratch (the first KZS +* . columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, H( JROW, INCOL+1+J2 ), + $ LDH, WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ H( JROW, INCOL+1 ), LDH, U, LDU, ONE, WV, + $ LDWV ) +* +* ==== Copy left of H to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, H( JROW, INCOL+1 ), LDH, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ H( JROW, INCOL+1+J2 ), LDH, + $ U( J2+1, I2+1 ), LDU, ONE, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ H( JROW, INCOL+1 ), LDH ) + 200 CONTINUE +* +* ==== Multiply Z (also vertical) ==== +* + IF( WANTZ ) THEN + DO 210 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) +* +* ==== Copy right of Z to left of scratch (first +* . KZS columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U12 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, + $ LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ Z( JROW, INCOL+1 ), LDZ, U, LDU, ONE, + $ WV, LDWV ) +* +* ==== Copy left of Z to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, Z( JROW, INCOL+1 ), + $ LDZ, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ U( J2+1, I2+1 ), LDU, ONE, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Copy the result back to Z ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ Z( JROW, INCOL+1 ), LDZ ) + 210 CONTINUE + END IF + END IF + END IF + 220 CONTINUE +* +* ==== End of DLAQR5 ==== +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlarfg.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlarfg.f new file mode 100644 index 00000000..ce91d33c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlarfg.f @@ -0,0 +1,196 @@ +*> \brief \b DLARFG generates an elementary reflector (Householder matrix). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLARFG + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU ) +* +* .. Scalar Arguments .. +* INTEGER INCX, N +* DOUBLE PRECISION ALPHA, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLARFG generates a real elementary reflector H of order n, such +*> that +*> +*> H * ( alpha ) = ( beta ), H**T * H = I. +*> ( x ) ( 0 ) +*> +*> where alpha and beta are scalars, and x is an (n-1)-element real +*> vector. H is represented in the form +*> +*> H = I - tau * ( 1 ) * ( 1 v**T ) , +*> ( v ) +*> +*> where tau is a real scalar and v is a real (n-1)-element +*> vector. +*> +*> If the elements of x are all zero, then tau = 0 and H is taken to be +*> the unit matrix. +*> +*> Otherwise 1 <= tau <= 2. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the elementary reflector. +*> \endverbatim +*> +*> \param[in,out] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION +*> On entry, the value alpha. +*> On exit, it is overwritten with the value beta. +*> \endverbatim +*> +*> \param[in,out] X +*> \verbatim +*> X is DOUBLE PRECISION array, dimension +*> (1+(N-2)*abs(INCX)) +*> On entry, the vector x. +*> On exit, it is overwritten with the vector v. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> The increment between elements of X. INCX > 0. +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> The value tau. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION ALPHA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER J, KNT + DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2 + EXTERNAL DLAMCH, DLAPY2, DNRM2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN +* .. +* .. External Subroutines .. + EXTERNAL DSCAL +* .. +* .. Executable Statements .. +* + IF( N.LE.1 ) THEN + TAU = ZERO + RETURN + END IF +* + XNORM = DNRM2( N-1, X, INCX ) +* + IF( XNORM.EQ.ZERO ) THEN +* +* H = I +* + TAU = ZERO + ELSE +* +* general case +* + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' ) + KNT = 0 + IF( ABS( BETA ).LT.SAFMIN ) THEN +* +* XNORM, BETA may be inaccurate; scale X and recompute them +* + RSAFMN = ONE / SAFMIN + 10 CONTINUE + KNT = KNT + 1 + CALL DSCAL( N-1, RSAFMN, X, INCX ) + BETA = BETA*RSAFMN + ALPHA = ALPHA*RSAFMN + IF( ABS( BETA ).LT.SAFMIN ) + $ GO TO 10 +* +* New BETA is at most 1, at least SAFMIN +* + XNORM = DNRM2( N-1, X, INCX ) + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + END IF + TAU = ( BETA-ALPHA ) / BETA + CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX ) +* +* If ALPHA is subnormal, it may lose relative accuracy +* + DO 20 J = 1, KNT + BETA = BETA*SAFMIN + 20 CONTINUE + ALPHA = BETA + END IF +* + RETURN +* +* End of DLARFG +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaset.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaset.f new file mode 100644 index 00000000..d3bb9456 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dlaset.f @@ -0,0 +1,184 @@ +*> \brief \b DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASET + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER LDA, M, N +* DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASET initializes an m-by-n matrix A to BETA on the diagonal and +*> ALPHA on the offdiagonals. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> Specifies the part of the matrix A to be set. +*> = 'U': Upper triangular part is set; the strictly lower +*> triangular part of A is not changed. +*> = 'L': Lower triangular part is set; the strictly upper +*> triangular part of A is not changed. +*> Otherwise: All of the matrix A is set. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION +*> The constant to which the offdiagonal elements are to be set. +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION +*> The constant to which the diagonal elements are to be set. +*> \endverbatim +*> +*> \param[out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> On exit, the leading m-by-n submatrix of A is set as follows: +*> +*> if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n, +*> if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n, +*> otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j, +*> +*> and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n). +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, M, N + DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Set the strictly upper triangular or trapezoidal part of the +* array to ALPHA. +* + DO 20 J = 2, N + DO 10 I = 1, MIN( J-1, M ) + A( I, J ) = ALPHA + 10 CONTINUE + 20 CONTINUE +* + ELSE IF( LSAME( UPLO, 'L' ) ) THEN +* +* Set the strictly lower triangular or trapezoidal part of the +* array to ALPHA. +* + DO 40 J = 1, MIN( M, N ) + DO 30 I = J + 1, M + A( I, J ) = ALPHA + 30 CONTINUE + 40 CONTINUE +* + ELSE +* +* Set the leading m-by-n submatrix to ALPHA. +* + DO 60 J = 1, N + DO 50 I = 1, M + A( I, J ) = ALPHA + 50 CONTINUE + 60 CONTINUE + END IF +* +* Set the first min(M,N) diagonal elements to BETA. +* + DO 70 I = 1, MIN( M, N ) + A( I, I ) = BETA + 70 CONTINUE +* + RETURN +* +* End of DLASET +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dnrm2.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dnrm2.f new file mode 100644 index 00000000..5ea257a2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dnrm2.f @@ -0,0 +1,112 @@ +*> \brief \b DNRM2 +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX) +* +* .. Scalar Arguments .. +* INTEGER INCX,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DNRM2 returns the euclidean norm of a vector via the function +*> name, so that +*> +*> DNRM2 := sqrt( x'*x ) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> -- This version written on 25-October-1982. +*> Modified on 14-October-1993 to inline the call to DLASSQ. +*> Sven Hammarling, Nag Ltd. +*> \endverbatim +*> +* ===================================================================== + DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION X(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ABSXI,NORM,SCALE,SSQ + INTEGER IX +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS,SQRT +* .. + IF (N.LT.1 .OR. INCX.LT.1) THEN + NORM = ZERO + ELSE IF (N.EQ.1) THEN + NORM = ABS(X(1)) + ELSE + SCALE = ZERO + SSQ = ONE +* The following loop is equivalent to this call to the LAPACK +* auxiliary routine: +* CALL DLASSQ( N, X, INCX, SCALE, SSQ ) +* + DO 10 IX = 1,1 + (N-1)*INCX,INCX + IF (X(IX).NE.ZERO) THEN + ABSXI = ABS(X(IX)) + IF (SCALE.LT.ABSXI) THEN + SSQ = ONE + SSQ* (SCALE/ABSXI)**2 + SCALE = ABSXI + ELSE + SSQ = SSQ + (ABSXI/SCALE)**2 + END IF + END IF + 10 CONTINUE + NORM = SCALE*SQRT(SSQ) + END IF +* + DNRM2 = NORM + RETURN +* +* End of DNRM2. +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dscal.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dscal.f new file mode 100644 index 00000000..3337de8e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dscal.f @@ -0,0 +1,110 @@ +*> \brief \b DSCAL +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DSCAL(N,DA,DX,INCX) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DA +* INTEGER INCX,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DSCAL scales a vector by a constant. +*> uses unrolled loops for increment equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 3/93 to return if incx .le. 0. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DSCAL(N,DA,DX,INCX) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DA + INTEGER INCX,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,M,MP1,NINCX +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0 .OR. INCX.LE.0) RETURN + IF (INCX.EQ.1) THEN +* +* code for increment equal to 1 +* +* +* clean-up loop +* + M = MOD(N,5) + IF (M.NE.0) THEN + DO I = 1,M + DX(I) = DA*DX(I) + END DO + IF (N.LT.5) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,5 + DX(I) = DA*DX(I) + DX(I+1) = DA*DX(I+1) + DX(I+2) = DA*DX(I+2) + DX(I+3) = DA*DX(I+3) + DX(I+4) = DA*DX(I+4) + END DO + ELSE +* +* code for increment not equal to 1 +* + NINCX = N*INCX + DO I = 1,NINCX,INCX + DX(I) = DA*DX(I) + END DO + END IF + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmm.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmm.f new file mode 100644 index 00000000..cbd5ce70 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmm.f @@ -0,0 +1,415 @@ +*> \brief \b DTRMM +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA +* INTEGER LDA,LDB,M,N +* CHARACTER DIAG,SIDE,TRANSA,UPLO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),B(LDB,*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DTRMM performs one of the matrix-matrix operations +*> +*> B := alpha*op( A )*B, or B := alpha*B*op( A ), +*> +*> where alpha is a scalar, B is an m by n matrix, A is a unit, or +*> non-unit, upper or lower triangular matrix and op( A ) is one of +*> +*> op( A ) = A or op( A ) = A**T. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SIDE +*> \verbatim +*> SIDE is CHARACTER*1 +*> On entry, SIDE specifies whether op( A ) multiplies B from +*> the left or right as follows: +*> +*> SIDE = 'L' or 'l' B := alpha*op( A )*B. +*> +*> SIDE = 'R' or 'r' B := alpha*B*op( A ). +*> \endverbatim +*> +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> On entry, UPLO specifies whether the matrix A is an upper or +*> lower triangular matrix as follows: +*> +*> UPLO = 'U' or 'u' A is an upper triangular matrix. +*> +*> UPLO = 'L' or 'l' A is a lower triangular matrix. +*> \endverbatim +*> +*> \param[in] TRANSA +*> \verbatim +*> TRANSA is CHARACTER*1 +*> On entry, TRANSA specifies the form of op( A ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSA = 'N' or 'n' op( A ) = A. +*> +*> TRANSA = 'T' or 't' op( A ) = A**T. +*> +*> TRANSA = 'C' or 'c' op( A ) = A**T. +*> \endverbatim +*> +*> \param[in] DIAG +*> \verbatim +*> DIAG is CHARACTER*1 +*> On entry, DIAG specifies whether or not A is unit triangular +*> as follows: +*> +*> DIAG = 'U' or 'u' A is assumed to be unit triangular. +*> +*> DIAG = 'N' or 'n' A is not assumed to be unit +*> triangular. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of B. M must be at +*> least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of B. N must be +*> at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. When alpha is +*> zero then A is not referenced and B need not be set before +*> entry. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m +*> when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +*> Before entry with UPLO = 'U' or 'u', the leading k by k +*> upper triangular part of the array A must contain the upper +*> triangular matrix and the strictly lower triangular part of +*> A is not referenced. +*> Before entry with UPLO = 'L' or 'l', the leading k by k +*> lower triangular part of the array A must contain the lower +*> triangular matrix and the strictly upper triangular part of +*> A is not referenced. +*> Note that when DIAG = 'U' or 'u', the diagonal elements of +*> A are not referenced either, but are assumed to be unity. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. When SIDE = 'L' or 'l' then +*> LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +*> then LDA must be at least max( 1, n ). +*> \endverbatim +*> +*> \param[in,out] B +*> \verbatim +*> B is DOUBLE PRECISION array of DIMENSION ( LDB, n ). +*> Before entry, the leading m by n part of the array B must +*> contain the matrix B, and on exit is overwritten by the +*> transformed matrix. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> On entry, LDB specifies the first dimension of B as declared +*> in the calling (sub) program. LDB must be at least +*> max( 1, m ). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level3 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 3 Blas routine. +*> +*> -- Written on 8-February-1989. +*> Jack Dongarra, Argonne National Laboratory. +*> Iain Duff, AERE Harwell. +*> Jeremy Du Croz, Numerical Algorithms Group Ltd. +*> Sven Hammarling, Numerical Algorithms Group Ltd. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +* +* -- Reference BLAS level3 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA + INTEGER LDA,LDB,M,N + CHARACTER DIAG,SIDE,TRANSA,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),B(LDB,*) +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,J,K,NROWA + LOGICAL LSIDE,NOUNIT,UPPER +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Test the input parameters. +* + LSIDE = LSAME(SIDE,'L') + IF (LSIDE) THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME(DIAG,'N') + UPPER = LSAME(UPLO,'U') +* + INFO = 0 + IF ((.NOT.LSIDE) .AND. (.NOT.LSAME(SIDE,'R'))) THEN + INFO = 1 + ELSE IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN + INFO = 2 + ELSE IF ((.NOT.LSAME(TRANSA,'N')) .AND. + + (.NOT.LSAME(TRANSA,'T')) .AND. + + (.NOT.LSAME(TRANSA,'C'))) THEN + INFO = 3 + ELSE IF ((.NOT.LSAME(DIAG,'U')) .AND. (.NOT.LSAME(DIAG,'N'))) THEN + INFO = 4 + ELSE IF (M.LT.0) THEN + INFO = 5 + ELSE IF (N.LT.0) THEN + INFO = 6 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 9 + ELSE IF (LDB.LT.MAX(1,M)) THEN + INFO = 11 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DTRMM ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (M.EQ.0 .OR. N.EQ.0) RETURN +* +* And when alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,M + B(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF (LSIDE) THEN + IF (LSAME(TRANSA,'N')) THEN +* +* Form B := alpha*A*B. +* + IF (UPPER) THEN + DO 50 J = 1,N + DO 40 K = 1,M + IF (B(K,J).NE.ZERO) THEN + TEMP = ALPHA*B(K,J) + DO 30 I = 1,K - 1 + B(I,J) = B(I,J) + TEMP*A(I,K) + 30 CONTINUE + IF (NOUNIT) TEMP = TEMP*A(K,K) + B(K,J) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80 J = 1,N + DO 70 K = M,1,-1 + IF (B(K,J).NE.ZERO) THEN + TEMP = ALPHA*B(K,J) + B(K,J) = TEMP + IF (NOUNIT) B(K,J) = B(K,J)*A(K,K) + DO 60 I = K + 1,M + B(I,J) = B(I,J) + TEMP*A(I,K) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*A**T*B. +* + IF (UPPER) THEN + DO 110 J = 1,N + DO 100 I = M,1,-1 + TEMP = B(I,J) + IF (NOUNIT) TEMP = TEMP*A(I,I) + DO 90 K = 1,I - 1 + TEMP = TEMP + A(K,I)*B(K,J) + 90 CONTINUE + B(I,J) = ALPHA*TEMP + 100 CONTINUE + 110 CONTINUE + ELSE + DO 140 J = 1,N + DO 130 I = 1,M + TEMP = B(I,J) + IF (NOUNIT) TEMP = TEMP*A(I,I) + DO 120 K = I + 1,M + TEMP = TEMP + A(K,I)*B(K,J) + 120 CONTINUE + B(I,J) = ALPHA*TEMP + 130 CONTINUE + 140 CONTINUE + END IF + END IF + ELSE + IF (LSAME(TRANSA,'N')) THEN +* +* Form B := alpha*B*A. +* + IF (UPPER) THEN + DO 180 J = N,1,-1 + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = 1,M + B(I,J) = TEMP*B(I,J) + 150 CONTINUE + DO 170 K = 1,J - 1 + IF (A(K,J).NE.ZERO) THEN + TEMP = ALPHA*A(K,J) + DO 160 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + ELSE + DO 220 J = 1,N + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 190 I = 1,M + B(I,J) = TEMP*B(I,J) + 190 CONTINUE + DO 210 K = J + 1,N + IF (A(K,J).NE.ZERO) THEN + TEMP = ALPHA*A(K,J) + DO 200 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 200 CONTINUE + END IF + 210 CONTINUE + 220 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A**T. +* + IF (UPPER) THEN + DO 260 K = 1,N + DO 240 J = 1,K - 1 + IF (A(J,K).NE.ZERO) THEN + TEMP = ALPHA*A(J,K) + DO 230 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 230 CONTINUE + END IF + 240 CONTINUE + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(K,K) + IF (TEMP.NE.ONE) THEN + DO 250 I = 1,M + B(I,K) = TEMP*B(I,K) + 250 CONTINUE + END IF + 260 CONTINUE + ELSE + DO 300 K = N,1,-1 + DO 280 J = K + 1,N + IF (A(J,K).NE.ZERO) THEN + TEMP = ALPHA*A(J,K) + DO 270 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 270 CONTINUE + END IF + 280 CONTINUE + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(K,K) + IF (TEMP.NE.ONE) THEN + DO 290 I = 1,M + B(I,K) = TEMP*B(I,K) + 290 CONTINUE + END IF + 300 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMM . +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmv.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmv.f new file mode 100644 index 00000000..71459fe7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/dtrmv.f @@ -0,0 +1,342 @@ +*> \brief \b DTRMV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* +* .. Scalar Arguments .. +* INTEGER INCX,LDA,N +* CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),X(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DTRMV performs one of the matrix-vector operations +*> +*> x := A*x, or x := A**T*x, +*> +*> where x is an n element vector and A is an n by n unit, or non-unit, +*> upper or lower triangular matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> On entry, UPLO specifies whether the matrix is an upper or +*> lower triangular matrix as follows: +*> +*> UPLO = 'U' or 'u' A is an upper triangular matrix. +*> +*> UPLO = 'L' or 'l' A is a lower triangular matrix. +*> \endverbatim +*> +*> \param[in] TRANS +*> \verbatim +*> TRANS is CHARACTER*1 +*> On entry, TRANS specifies the operation to be performed as +*> follows: +*> +*> TRANS = 'N' or 'n' x := A*x. +*> +*> TRANS = 'T' or 't' x := A**T*x. +*> +*> TRANS = 'C' or 'c' x := A**T*x. +*> \endverbatim +*> +*> \param[in] DIAG +*> \verbatim +*> DIAG is CHARACTER*1 +*> On entry, DIAG specifies whether or not A is unit +*> triangular as follows: +*> +*> DIAG = 'U' or 'u' A is assumed to be unit triangular. +*> +*> DIAG = 'N' or 'n' A is not assumed to be unit +*> triangular. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the order of the matrix A. +*> N must be at least zero. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, n ). +*> Before entry with UPLO = 'U' or 'u', the leading n by n +*> upper triangular part of the array A must contain the upper +*> triangular matrix and the strictly lower triangular part of +*> A is not referenced. +*> Before entry with UPLO = 'L' or 'l', the leading n by n +*> lower triangular part of the array A must contain the lower +*> triangular matrix and the strictly upper triangular part of +*> A is not referenced. +*> Note that when DIAG = 'U' or 'u', the diagonal elements of +*> A are not referenced either, but are assumed to be unity. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. LDA must be at least +*> max( 1, n ). +*> \endverbatim +*> +*> \param[in,out] X +*> \verbatim +*> X is DOUBLE PRECISION array of dimension at least +*> ( 1 + ( n - 1 )*abs( INCX ) ). +*> Before entry, the incremented array X must contain the n +*> element vector x. On exit, X is overwritten with the +*> tranformed vector x. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> On entry, INCX specifies the increment for the elements of +*> X. INCX must not be zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level2 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 2 Blas routine. +*> The vector and matrix arguments are not referenced when N = 0, or M = 0 +*> +*> -- Written on 22-October-1986. +*> Jack Dongarra, Argonne National Lab. +*> Jeremy Du Croz, Nag Central Office. +*> Sven Hammarling, Nag Central Office. +*> Richard Hanson, Sandia National Labs. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* +* -- Reference BLAS level2 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,LDA,N + CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),X(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER (ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,IX,J,JX,KX + LOGICAL NOUNIT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN + INFO = 1 + ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 2 + ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,N)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DTRMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (N.EQ.0) RETURN +* + NOUNIT = LSAME(DIAG,'N') +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF (INCX.LE.0) THEN + KX = 1 - (N-1)*INCX + ELSE IF (INCX.NE.1) THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form x := A*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 20 J = 1,N + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 10 I = 1,J - 1 + X(I) = X(I) + TEMP*A(I,J) + 10 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 20 CONTINUE + ELSE + JX = KX + DO 40 J = 1,N + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 30 I = 1,J - 1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX + INCX + 30 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX + INCX + 40 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 60 J = N,1,-1 + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 50 I = N,J + 1,-1 + X(I) = X(I) + TEMP*A(I,J) + 50 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 60 CONTINUE + ELSE + KX = KX + (N-1)*INCX + JX = KX + DO 80 J = N,1,-1 + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 70 I = N,J + 1,-1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX - INCX + 70 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX - INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := A**T*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 100 J = N,1,-1 + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 90 I = J - 1,1,-1 + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + X(J) = TEMP + 100 CONTINUE + ELSE + JX = KX + (N-1)*INCX + DO 120 J = N,1,-1 + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 110 I = J - 1,1,-1 + IX = IX - INCX + TEMP = TEMP + A(I,J)*X(IX) + 110 CONTINUE + X(JX) = TEMP + JX = JX - INCX + 120 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 140 J = 1,N + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 130 I = J + 1,N + TEMP = TEMP + A(I,J)*X(I) + 130 CONTINUE + X(J) = TEMP + 140 CONTINUE + ELSE + JX = KX + DO 160 J = 1,N + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = J + 1,N + IX = IX + INCX + TEMP = TEMP + A(I,J)*X(IX) + 150 CONTINUE + X(JX) = TEMP + JX = JX + INCX + 160 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMV . +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/lsame.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/netlib.go b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/netlib.go new file mode 100644 index 00000000..182e074a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/netlib.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum 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 netlib + +// void dlahr2_(int* n, int* k, int* nb, double* a, int* lda, double* tau, double* t, int* ldt, double* y, int* ldy); +// +// void dlaqr5_(int* wantt, int* wantz, int* kacc22, int* n, int* ktop, int* kbot, int* nshfts, +// double* sr, double* si, double* h, int* ldh, int* iloz, int* ihiz, +// double* z, int* ldz, double* v, int* ldv, double* u, int* ldu, +// int* nv, double* wv, int* ldwv, int* nh, double* wh, int* ldwh); +import "C" + +func Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { + func() { + n := C.int(n) + k := C.int(k) + nb := C.int(nb) + lda := C.int(lda) + ldt := C.int(ldt) + ldy := C.int(ldy) + C.dlahr2_((*C.int)(&n), (*C.int)(&k), (*C.int)(&nb), + (*C.double)(&a[0]), (*C.int)(&lda), + (*C.double)(&tau[0]), + (*C.double)(&t[0]), (*C.int)(&ldt), + (*C.double)(&y[0]), (*C.int)(&ldy)) + }() +} + +func Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot int, nshfts int, sr, si []float64, h []float64, + ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, + u []float64, ldu int, nh int, wh []float64, ldwh int, nv int, wv []float64, ldwv int) { + func() { + wt := C.int(0) + if wantt { + wt = 1 + } + wz := C.int(0) + if wantz { + wz = 1 + } + kacc22 := C.int(kacc22) + n := C.int(n) + ktop := C.int(ktop) + kbot := C.int(kbot) + nshfts := C.int(nshfts) + ldh := C.int(ldh) + iloz := C.int(iloz) + ihiz := C.int(ihiz) + ldz := C.int(ldz) + ldv := C.int(ldv) + ldu := C.int(ldu) + nh := C.int(nh) + ldwh := C.int(ldwh) + nv := C.int(nv) + ldwv := C.int(ldwv) + C.dlaqr5_((*C.int)(&wt), (*C.int)(&wz), (*C.int)(&kacc22), + (*C.int)(&n), (*C.int)(&ktop), (*C.int)(&kbot), + (*C.int)(&nshfts), (*C.double)(&sr[0]), (*C.double)(&si[0]), + (*C.double)(&h[0]), (*C.int)(&ldh), + (*C.int)(&iloz), (*C.int)(&ihiz), (*C.double)(&z[0]), (*C.int)(&ldz), + (*C.double)(&v[0]), (*C.int)(&ldv), + (*C.double)(&u[0]), (*C.int)(&ldu), + (*C.int)(&nh), (*C.double)(&wh[0]), (*C.int)(&ldwh), + (*C.int)(&nv), (*C.double)(&wv[0]), (*C.int)(&ldwv)) + }() +} diff --git a/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/xerbla.f b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/xerbla.f new file mode 100644 index 00000000..eb1c037d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/internal/testdata/netlib/xerbla.f @@ -0,0 +1,89 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup aux_blas +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack.go b/vendor/gonum.org/v1/gonum/lapack/lapack.go new file mode 100644 index 00000000..c78d19c8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/lapack.go @@ -0,0 +1,188 @@ +// Copyright ©2015 The gonum 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 lapack // import "gonum.org/v1/gonum/lapack" + +import "gonum.org/v1/gonum/blas" + +const None = 'N' + +type Job byte + +type Comp byte + +// Complex128 defines the public complex128 LAPACK API supported by gonum/lapack. +type Complex128 interface{} + +// Float64 defines the public float64 LAPACK API supported by gonum/lapack. +type Float64 interface { + Dgecon(norm MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 + Dgeev(jobvl LeftEVJob, jobvr RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) + Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool + Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dgesvd(jobU, jobVT SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) + Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) + Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) + Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) + Dggsvd3(jobU, jobV, jobQ GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) + Dlantr(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 + Dlange(norm MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 + Dlansy(norm MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 + Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) + Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 + Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) + Dsyev(jobz EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) + Dtrcon(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 + Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) + Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) +} + +// Direct specifies the direction of the multiplication for the Householder matrix. +type Direct byte + +const ( + Forward Direct = 'F' // Reflectors are right-multiplied, H_0 * H_1 * ... * H_{k-1}. + Backward Direct = 'B' // Reflectors are left-multiplied, H_{k-1} * ... * H_1 * H_0. +) + +// Sort is the sorting order. +type Sort byte + +const ( + SortIncreasing Sort = 'I' + SortDecreasing Sort = 'D' +) + +// StoreV indicates the storage direction of elementary reflectors. +type StoreV byte + +const ( + ColumnWise StoreV = 'C' // Reflector stored in a column of the matrix. + RowWise StoreV = 'R' // Reflector stored in a row of the matrix. +) + +// MatrixNorm represents the kind of matrix norm to compute. +type MatrixNorm byte + +const ( + MaxAbs MatrixNorm = 'M' // max(abs(A(i,j))) ('M') + MaxColumnSum MatrixNorm = 'O' // Maximum column sum (one norm) ('1', 'O') + MaxRowSum MatrixNorm = 'I' // Maximum row sum (infinity norm) ('I', 'i') + NormFrob MatrixNorm = 'F' // Frobenius norm (sqrt of sum of squares) ('F', 'f', E, 'e') +) + +// MatrixType represents the kind of matrix represented in the data. +type MatrixType byte + +const ( + General MatrixType = 'G' // A dense matrix (like blas64.General). + UpperTri MatrixType = 'U' // An upper triangular matrix. + LowerTri MatrixType = 'L' // A lower triangular matrix. +) + +// Pivot specifies the pivot type for plane rotations +type Pivot byte + +const ( + Variable Pivot = 'V' + Top Pivot = 'T' + Bottom Pivot = 'B' +) + +type DecompUpdate byte + +const ( + ApplyP DecompUpdate = 'P' + ApplyQ DecompUpdate = 'Q' +) + +// SVDJob specifies the singular vector computation type for SVD. +type SVDJob byte + +const ( + SVDAll SVDJob = 'A' // Compute all singular vectors + SVDInPlace SVDJob = 'S' // Compute the first singular vectors and store them in provided storage. + SVDOverwrite SVDJob = 'O' // Compute the singular vectors and store them in input matrix + SVDNone SVDJob = 'N' // Do not compute singular vectors +) + +// GSVDJob specifies the singular vector computation type for Generalized SVD. +type GSVDJob byte + +const ( + GSVDU GSVDJob = 'U' // Compute orthogonal matrix U + GSVDV GSVDJob = 'V' // Compute orthogonal matrix V + GSVDQ GSVDJob = 'Q' // Compute orthogonal matrix Q + GSVDUnit GSVDJob = 'I' // Use unit-initialized matrix + GSVDNone GSVDJob = 'N' // Do not compute orthogonal matrix +) + +// EVComp specifies how eigenvectors are computed. +type EVComp byte + +const ( + // OriginalEV specifies to compute the eigenvectors of the original + // matrix. + OriginalEV EVComp = 'V' + // TridiagEV specifies to compute both the eigenvectors of the input + // tridiagonal matrix. + TridiagEV EVComp = 'I' + // HessEV specifies to compute both the eigenvectors of the input upper + // Hessenberg matrix. + HessEV EVComp = 'I' + + // UpdateSchur specifies that the matrix of Schur vectors will be + // updated by Dtrexc. + UpdateSchur EVComp = 'V' +) + +// Job types for computation of eigenvectors. +type ( + EVJob byte + LeftEVJob byte + RightEVJob byte +) + +// Job constants for computation of eigenvectors. +const ( + ComputeEV EVJob = 'V' // Compute eigenvectors in Dsyev. + ComputeLeftEV LeftEVJob = 'V' // Compute left eigenvectors. + ComputeRightEV RightEVJob = 'V' // Compute right eigenvectors. +) + +// Jobs for Dgebal. +const ( + Permute Job = 'P' + Scale Job = 'S' + PermuteScale Job = 'B' +) + +// Job constants for Dhseqr. +const ( + EigenvaluesOnly EVJob = 'E' + EigenvaluesAndSchur EVJob = 'S' +) + +// EVSide specifies what eigenvectors will be computed. +type EVSide byte + +// EVSide constants for Dtrevc3. +const ( + RightEV EVSide = 'R' // Compute right eigenvectors only. + LeftEV EVSide = 'L' // Compute left eigenvectors only. + RightLeftEV EVSide = 'B' // Compute both right and left eigenvectors. +) + +// HowMany specifies which eigenvectors will be computed. +type HowMany byte + +// HowMany constants for Dhseqr. +const ( + AllEV HowMany = 'A' // Compute all right and/or left eigenvectors. + AllEVMulQ HowMany = 'B' // Compute all right and/or left eigenvectors multiplied by an input matrix. + SelectedEV HowMany = 'S' // Compute selected right and/or left eigenvectors. +) diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go b/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go new file mode 100644 index 00000000..07071df8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go @@ -0,0 +1,20 @@ +// Copyright ©2017 The gonum 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 lapack64 provides a set of convenient wrapper functions for LAPACK +// calls, as specified in the netlib standard (www.netlib.org). +// +// The native Go routines are used by default, and the Use function can be used +// to set an alternative implementation. +// +// If the type of matrix (General, Symmetric, etc.) is known and fixed, it is +// used in the wrapper signature. In many cases, however, the type of the matrix +// changes during the call to the routine, for example the matrix is symmetric on +// entry and is triangular on exit. In these cases the correct types should be checked +// in the documentation. +// +// The full set of Lapack functions is very large, and it is not clear that a +// full implementation is desirable, let alone feasible. Please open up an issue +// if there is a specific function you need and/or are willing to implement. +package lapack64 // import "gonum.org/v1/gonum/lapack/lapack64" diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go b/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go new file mode 100644 index 00000000..f93e9207 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go @@ -0,0 +1,545 @@ +// Copyright ©2015 The gonum 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 lapack64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/gonum" +) + +var lapack64 lapack.Float64 = gonum.Implementation{} + +// Use sets the LAPACK float64 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(l lapack.Float64) { + lapack64 = l +} + +// Potrf computes the Cholesky factorization of a. +// The factorization has the form +// A = U^T * U if a.Uplo == blas.Upper, or +// A = L * L^T if a.Uplo == blas.Lower, +// where U is an upper triangular matrix and L is lower triangular. +// The triangular matrix is returned in t, and the underlying data between +// a and t is shared. The returned bool indicates whether a is positive +// definite and the factorization could be finished. +func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) { + ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, a.Stride) + t.Uplo = a.Uplo + t.N = a.N + t.Data = a.Data + t.Stride = a.Stride + t.Diag = blas.NonUnit + return +} + +// Gecon estimates the reciprocal of the condition number of the n×n matrix A +// given the LU decomposition of the matrix. The condition number computed may +// be based on the 1-norm or the ∞-norm. +// +// a contains the result of the LU decomposition of A as computed by Getrf. +// +// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 4*n and Gecon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Gecon will panic otherwise. +func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float64, iwork []int) float64 { + return lapack64.Dgecon(norm, a.Cols, a.Data, a.Stride, anorm, work, iwork) +} + +// Gels finds a minimum-norm solution based on the matrices A and B using the +// QR or LQ factorization. Gels returns false if the matrix +// A is singular, and true if this solution was successfully found. +// +// The minimization problem solved depends on the input parameters. +// +// 1. If m >= n and trans == blas.NoTrans, Gels finds X such that || A*X - B||_2 +// is minimized. +// 2. If m < n and trans == blas.NoTrans, Gels finds the minimum norm solution of +// A * X = B. +// 3. If m >= n and trans == blas.Trans, Gels finds the minimum norm solution of +// A^T * X = B. +// 4. If m < n and trans == blas.Trans, Gels finds X such that || A*X - B||_2 +// is minimized. +// Note that the least-squares solutions (cases 1 and 3) perform the minimization +// per column of B. This is not the same as finding the minimum-norm matrix. +// +// The matrix A is a general matrix of size m×n and is modified during this call. +// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, +// the elements of b specify the input matrix B. B has size m×nrhs if +// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the +// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, +// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic +// otherwise. A longer work will enable blocked algorithms to be called. +// In the special case that lwork == -1, work[0] will be set to the optimal working +// length. +func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) bool { + return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, a.Stride, b.Data, b.Stride, work, lwork) +} + +// Geqrf computes the QR factorization of the m×n matrix A using a blocked +// algorithm. A is modified to contain the information to construct Q and R. +// The upper triangle of a contains the matrix R. The lower triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length at least min(m,n), and +// this function will panic otherwise. +// +// The ith elementary reflector can be explicitly constructed by first extracting +// the +// v[j] = 0 j < i +// v[j] = 1 j == i +// v[j] = a[j*lda+i] j > i +// and computing H_i = I - tau[i] * v * v^T. +// +// The orthonormal matrix Q can be constucted from a product of these elementary +// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m and this function will panic otherwise. +// Geqrf is a blocked QR factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Geqrf, +// the optimal work length will be stored into work[0]. +func Geqrf(a blas64.General, tau, work []float64, lwork int) { + lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork) +} + +// Gelqf computes the LQ factorization of the m×n matrix A using a blocked +// algorithm. A is modified to contain the information to construct L and Q. The +// lower triangle of a contains the matrix L. The elements above the diagonal +// and the slice tau represent the matrix Q. tau is modified to contain the +// reflector scales. tau must have length at least min(m,n), and this function +// will panic otherwise. +// +// See Geqrf for a description of the elementary reflectors and orthonormal +// matrix Q. Q is constructed as a product of these elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m and this function will panic otherwise. +// Gelqf is a blocked LQ factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Gelqf, +// the optimal work length will be stored into work[0]. +func Gelqf(a blas64.General, tau, work []float64, lwork int) { + lapack64.Dgelqf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork) +} + +// Gesvd computes the singular value decomposition of the input matrix A. +// +// The singular value decomposition is +// A = U * Sigma * V^T +// where Sigma is an m×n diagonal matrix containing the singular values of A, +// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first +// min(m,n) columns of U and V are the left and right singular vectors of A +// respectively. +// +// jobU and jobVT are options for computing the singular vectors. The behavior +// is as follows +// jobU == lapack.SVDAll All m columns of U are returned in u +// jobU == lapack.SVDInPlace The first min(m,n) columns are returned in u +// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a +// jobU == lapack.SVDNone The columns of U are not computed. +// The behavior is the same for jobVT and the rows of V^T. At most one of jobU +// and jobVT can equal lapack.SVDOverwrite, and Gesvd will panic otherwise. +// +// On entry, a contains the data for the m×n matrix A. During the call to Gesvd +// the data is overwritten. On exit, A contains the appropriate singular vectors +// if either job is lapack.SVDOverwrite. +// +// s is a slice of length at least min(m,n) and on exit contains the singular +// values in decreasing order. +// +// u contains the left singular vectors on exit, stored columnwise. If +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is +// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is +// not used. +// +// vt contains the left singular vectors on exit, stored rowwise. If +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is +// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is +// not used. +// +// work is a slice for storing temporary memory, and lwork is the usable size of +// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). +// If lwork == -1, instead of performing Gesvd, the optimal work length will be +// stored into work[0]. Gesvd will panic if the working memory has insufficient +// storage. +// +// Gesvd returns whether the decomposition successfully completed. +func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64, lwork int) (ok bool) { + return lapack64.Dgesvd(jobU, jobVT, a.Rows, a.Cols, a.Data, a.Stride, s, u.Data, u.Stride, vt.Data, vt.Stride, work, lwork) +} + +// Getrf computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of A into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Getrf is the blocked version of the algorithm. +// +// Getrf returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func Getrf(a blas64.General, ipiv []int) bool { + return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, a.Stride, ipiv) +} + +// Getri computes the inverse of the matrix A using the LU factorization computed +// by Getrf. On entry, a contains the PLU decomposition of A as computed by +// Getrf and on exit contains the reciprocal of the original matrix. +// +// Getri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= n and this function will panic otherwise. +// Getri is a blocked inversion, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Getri, +// the optimal work length will be stored into work[0]. +func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) { + return lapack64.Dgetri(a.Cols, a.Data, a.Stride, ipiv, work, lwork) +} + +// Getrs solves a system of equations using an LU factorization. +// The system of equations solved is +// A * X = B if trans == blas.Trans +// A^T * X = B if trans == blas.NoTrans +// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. +// +// On entry b contains the elements of the matrix B. On exit, b contains the +// elements of X, the solution to the system of equations. +// +// a and ipiv contain the LU factorization of A and the permutation indices as +// computed by Getrf. ipiv is zero-indexed. +func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) { + lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, a.Stride, ipiv, b.Data, b.Stride) +} + +// Ggsvd3 computes the generalized singular value decomposition (GSVD) +// of an m×n matrix A and p×n matrix B: +// U^T*A*Q = D1*[ 0 R ] +// +// V^T*B*Q = D2*[ 0 R ] +// where U, V and Q are orthogonal matrices. +// +// Ggsvd3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and +// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following +// structures, respectively: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// Ggsvd3 computes C, S, R, and optionally the orthogonal transformation +// matrices U, V and Q. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// alpha and beta must have length n or Ggsvd3 will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, iwork contains the permutation required to sort alpha descending. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than n, otherwise Ggsvd3 will panic. If +// lwork is -1, work[0] holds the optimal lwork on return, but Ggsvd3 does +// not perform the GSVD. +func Ggsvd3(jobU, jobV, jobQ lapack.GSVDJob, a, b blas64.General, alpha, beta []float64, u, v, q blas64.General, work []float64, lwork int, iwork []int) (k, l int, ok bool) { + return lapack64.Dggsvd3(jobU, jobV, jobQ, a.Rows, a.Cols, b.Rows, a.Data, a.Stride, b.Data, b.Stride, alpha, beta, u.Data, u.Stride, v.Data, v.Stride, q.Data, q.Stride, work, lwork, iwork) +} + +// Lange computes the matrix norm of the general m×n matrix A. The input norm +// specifies the norm computed. +// lapack.MaxAbs: the maximum absolute value of an element. +// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. +// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. +// lapack.Frobenius: the square root of the sum of the squares of the entries. +// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 { + return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, a.Stride, work) +} + +// Lansy computes the specified norm of an n×n symmetric matrix. If +// norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length +// at least n and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func Lansy(norm lapack.MatrixNorm, a blas64.Symmetric, work []float64) float64 { + return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, a.Stride, work) +} + +// Lantr computes the specified norm of an m×n trapezoidal matrix A. If +// norm == lapack.MaxColumnSum work must have length at least n and this function +// will panic otherwise. There are no restrictions on work for the other matrix norms. +func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 { + return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, a.Stride, work) +} + +// Lapmt rearranges the columns of the m×n matrix X as specified by the +// permutation k_0, k_1, ..., k_{n-1} of the integers 0, ..., n-1. +// +// If forward is true a forward permutation is performed: +// +// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. +// +// otherwise a backward permutation is performed: +// +// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. +// +// k must have length n, otherwise Lapmt will panic. k is zero-indexed. +func Lapmt(forward bool, x blas64.General, k []int) { + lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, x.Stride, k) +} + +// Ormlq multiplies the matrix C by the othogonal matrix Q defined by +// A and tau. A and tau are as returned from Gelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right +// A is of size k×n. This uses a blocked algorithm. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, +// and this function will panic otherwise. +// Ormlq uses a block algorithm, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Ormlq, +// the optimal work length will be stored into work[0]. +// +// Tau contains the Householder scales and must have length at least k, and +// this function will panic otherwise. +func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { + lapack64.Dormlq(side, trans, c.Rows, c.Cols, a.Rows, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork) +} + +// Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as +// C = Q * C, if side == blas.Left and trans == blas.NoTrans, +// C = Q^T * C, if side == blas.Left and trans == blas.Trans, +// C = C * Q, if side == blas.Right and trans == blas.NoTrans, +// C = C * Q^T, if side == blas.Right and trans == blas.Trans, +// where Q is defined as the product of k elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1}. +// +// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. +// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. +// The ith column of A contains the vector which defines the elementary +// reflector H_i and tau[i] contains its scalar factor. tau must have length k +// and Ormqr will panic otherwise. Geqrf returns A and tau in the required +// form. +// +// work must have length at least max(1,lwork), and lwork must be at least n if +// side == blas.Left and at least m if side == blas.Right, otherwise Ormqr will +// panic. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= m if side == blas.Left and lwork >= n if side == +// blas.Right, and this function will panic otherwise. Larger values of lwork +// will generally give better performance. On return, work[0] will contain the +// optimal value of lwork. +// +// If lwork is -1, instead of performing Ormqr, the optimal workspace size will +// be stored into work[0]. +func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { + lapack64.Dormqr(side, trans, c.Rows, c.Cols, a.Cols, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork) +} + +// Pocon estimates the reciprocal of the condition number of a positive-definite +// matrix A given the Cholesky decmposition of A. The condition number computed +// is based on the 1-norm and the ∞-norm. +// +// anorm is the 1-norm and the ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 3*n and Pocon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Pocon will panic otherwise. +func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float64 { + return lapack64.Dpocon(a.Uplo, a.N, a.Data, a.Stride, anorm, work, iwork) +} + +// Syev computes all eigenvalues and, optionally, the eigenvectors of a real +// symmetric matrix A. +// +// w contains the eigenvalues in ascending order upon return. w must have length +// at least n, and Syev will panic otherwise. +// +// On entry, a contains the elements of the symmetric matrix A in the triangular +// portion specified by uplo. If jobz == lapack.ComputeEV a contains the +// orthonormal eigenvectors of A on exit, otherwise on exit the specified +// triangular region is overwritten. +// +// Work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 3*n-1, and Syev will panic otherwise. The amount of blocking is +// limited by the usable length. If lwork == -1, instead of computing Syev the +// optimal work length is stored into work[0]. +func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) (ok bool) { + return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, a.Stride, w, work, lwork) +} + +// Trcon estimates the reciprocal of the condition number of a triangular matrix A. +// The condition number computed may be based on the 1-norm or the ∞-norm. +// +// work is a temporary data slice of length at least 3*n and Trcon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Trcon will panic otherwise. +func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork []int) float64 { + return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, a.Stride, work, iwork) +} + +// Trtri computes the inverse of a triangular matrix, storing the result in place +// into a. +// +// Trtri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +func Trtri(a blas64.Triangular) (ok bool) { + return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, a.Stride) +} + +// Trtrs solves a triangular system of the form A * X = B or A^T * X = B. Trtrs +// returns whether the solve completed successfully. If A is singular, no solve is performed. +func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool) { + return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, a.Stride, b.Data, b.Stride) +} + +// Geev computes the eigenvalues and, optionally, the left and/or right +// eigenvectors for an n×n real nonsymmetric matrix A. +// +// The right eigenvector v_j of A corresponding to an eigenvalue λ_j +// is defined by +// A v_j = λ_j v_j, +// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by +// u_j^H A = λ_j u_j^H, +// where u_j^H is the conjugate transpose of u_j. +// +// On return, A will be overwritten and the left and right eigenvectors will be +// stored, respectively, in the columns of the n×n matrices VL and VR in the +// same order as their eigenvalues. If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV, +// otherwise jobvl must be lapack.None. +// Right eigenvectors will be computed only if jobvr == lapack.ComputeRightEV, +// otherwise jobvr must be lapack.None. +// For other values of jobvl and jobvr Geev will panic. +// +// On return, wr and wi will contain the real and imaginary parts, respectively, +// of the computed eigenvalues. Complex conjugate pairs of eigenvalues appear +// consecutively with the eigenvalue having the positive imaginary part first. +// wr and wi must have length n, and Geev will panic otherwise. +// +// work must have length at least lwork and lwork must be at least max(1,4*n) if +// the left or right eigenvectors are computed, and at least max(1,3*n) if no +// eigenvectors are computed. For good performance, lwork must generally be +// larger. On return, optimal value of lwork will be stored in work[0]. +// +// If lwork == -1, instead of performing Geev, the function only calculates the +// optimal vaule of lwork and stores it into work[0]. +// +// On return, first will be the index of the first valid eigenvalue. +// If first == 0, all eigenvalues and eigenvectors have been computed. +// If first is positive, Geev failed to compute all the eigenvalues, no +// eigenvectors have been computed and wr[first:] and wi[first:] contain those +// eigenvalues which have converged. +func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, wi []float64, vl, vr blas64.General, work []float64, lwork int) (first int) { + n := a.Rows + if a.Cols != n { + panic("lapack64: matrix not square") + } + if jobvl == lapack.ComputeLeftEV && (vl.Rows != n || vl.Cols != n) { + panic("lapack64: bad size of VL") + } + if jobvr == lapack.ComputeRightEV && (vr.Rows != n || vr.Cols != n) { + panic("lapack64: bad size of VR") + } + return lapack64.Dgeev(jobvl, jobvr, n, a.Data, a.Stride, wr, wi, vl.Data, vl.Stride, vr.Data, vr.Stride, work, lwork) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dbdsqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dbdsqr.go new file mode 100644 index 00000000..e52fd9dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dbdsqr.go @@ -0,0 +1,198 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dbdsqrer interface { + Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) (ok bool) +} + +func DbdsqrTest(t *testing.T, impl Dbdsqrer) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + _ = bi + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, ncvt, nru, ncc, ldvt, ldu, ldc int + }{ + {5, 5, 5, 5, 0, 0, 0}, + {10, 10, 10, 10, 0, 0, 0}, + {10, 11, 12, 13, 0, 0, 0}, + {20, 13, 12, 11, 0, 0, 0}, + + {5, 5, 5, 5, 6, 7, 8}, + {10, 10, 10, 10, 30, 40, 50}, + {10, 12, 11, 13, 30, 40, 50}, + {20, 12, 13, 11, 30, 40, 50}, + + {130, 130, 130, 500, 900, 900, 500}, + } { + for cas := 0; cas < 10; cas++ { + n := test.n + ncvt := test.ncvt + nru := test.nru + ncc := test.ncc + ldvt := test.ldvt + ldu := test.ldu + ldc := test.ldc + if ldvt == 0 { + ldvt = ncvt + } + if ldu == 0 { + ldu = n + } + if ldc == 0 { + ldc = ncc + } + + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + eCopy := make([]float64, len(e)) + copy(eCopy, e) + work := make([]float64, 4*n) + for i := range work { + work[i] = rnd.NormFloat64() + } + + // First test the decomposition of the bidiagonal matrix. Set + // pt and u equal to I with the correct size. At the result + // of Dbdsqr, p and u will contain the data of P^T and Q, which + // will be used in the next step to test the multiplication + // with Q and VT. + + q := make([]float64, n*n) + ldq := n + pt := make([]float64, n*n) + ldpt := n + for i := 0; i < n; i++ { + q[i*ldq+i] = 1 + } + for i := 0; i < n; i++ { + pt[i*ldpt+i] = 1 + } + + ok := impl.Dbdsqr(uplo, n, n, n, 0, d, e, pt, ldpt, q, ldq, nil, 0, work) + + isUpper := uplo == blas.Upper + errStr := fmt.Sprintf("isUpper = %v, n = %v, ncvt = %v, nru = %v, ncc = %v", isUpper, n, ncvt, nru, ncc) + if !ok { + t.Errorf("Unexpected Dbdsqr failure: %s", errStr) + } + + bMat := constructBidiagonal(uplo, n, dCopy, eCopy) + sMat := constructBidiagonal(uplo, n, d, e) + + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + ansMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, q, ldq, sMat.Data, sMat.Stride, 0, tmp.Data, tmp.Stride) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, tmp.Data, tmp.Stride, pt, ldpt, 0, ansMat.Data, ansMat.Stride) + + same := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(ansMat.Data[i*ansMat.Stride+j], bMat.Data[i*bMat.Stride+j], 1e-8, 1e-8) { + same = false + } + } + } + if !same { + t.Errorf("Bidiagonal mismatch. %s", errStr) + } + if !sort.IsSorted(sort.Reverse(sort.Float64Slice(d))) { + t.Errorf("D is not sorted. %s", errStr) + } + + // The above computed the real P and Q. Now input data for V^T, + // U, and C to check that the multiplications happen properly. + dAns := make([]float64, len(d)) + copy(dAns, d) + eAns := make([]float64, len(e)) + copy(eAns, e) + + u := make([]float64, nru*ldu) + for i := range u { + u[i] = rnd.NormFloat64() + } + uCopy := make([]float64, len(u)) + copy(uCopy, u) + vt := make([]float64, n*ldvt) + for i := range vt { + vt[i] = rnd.NormFloat64() + } + vtCopy := make([]float64, len(vt)) + copy(vtCopy, vt) + c := make([]float64, n*ldc) + for i := range c { + c[i] = rnd.NormFloat64() + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + // Reset input data + copy(d, dCopy) + copy(e, eCopy) + impl.Dbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work) + + // Check result. + if !floats.EqualApprox(d, dAns, 1e-14) { + t.Errorf("D mismatch second time. %s", errStr) + } + if !floats.EqualApprox(e, eAns, 1e-14) { + t.Errorf("E mismatch second time. %s", errStr) + } + ans := make([]float64, len(vtCopy)) + copy(ans, vtCopy) + ldans := ldvt + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, ncvt, n, 1, pt, ldpt, vtCopy, ldvt, 0, ans, ldans) + if !floats.EqualApprox(ans, vt, 1e-10) { + t.Errorf("Vt result mismatch. %s", errStr) + } + ans = make([]float64, len(uCopy)) + copy(ans, uCopy) + ldans = ldu + bi.Dgemm(blas.NoTrans, blas.NoTrans, nru, n, n, 1, uCopy, ldu, q, ldq, 0, ans, ldans) + if !floats.EqualApprox(ans, u, 1e-10) { + t.Errorf("U result mismatch. %s", errStr) + } + ans = make([]float64, len(cCopy)) + copy(ans, cCopy) + ldans = ldc + bi.Dgemm(blas.Trans, blas.NoTrans, n, ncc, n, 1, q, ldq, cCopy, ldc, 0, ans, ldans) + if !floats.EqualApprox(ans, c, 1e-10) { + t.Errorf("C result mismatch. %s", errStr) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebak.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebak.go new file mode 100644 index 00000000..7d1030a4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebak.go @@ -0,0 +1,110 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dgebaker interface { + Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) +} + +func DgebakTest(t *testing.T, impl Dgebaker) { + rnd := rand.New(rand.NewSource(1)) + + for _, job := range []lapack.Job{lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale} { + for _, side := range []lapack.EVSide{lapack.LeftEV, lapack.RightEV} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 100; cas++ { + m := rnd.Intn(n + 1) + v := randomGeneral(n, m, m+extra, rnd) + var ilo, ihi int + if v.Rows > 0 { + ihi = rnd.Intn(n) + ilo = rnd.Intn(ihi + 1) + } else { + ihi = -1 + } + testDgebak(t, impl, job, side, ilo, ihi, v, rnd) + } + } + } + } + } +} + +func testDgebak(t *testing.T, impl Dgebaker, job lapack.Job, side lapack.EVSide, ilo, ihi int, v blas64.General, rnd *rand.Rand) { + const tol = 1e-15 + n := v.Rows + m := v.Cols + extra := v.Stride - v.Cols + + // Create D and D^{-1} by generating random scales between ilo and ihi. + d := eye(n, n) + dinv := eye(n, n) + scale := nanSlice(n) + if job == lapack.Scale || job == lapack.PermuteScale { + if ilo == ihi { + scale[ilo] = 1 + } else { + for i := ilo; i <= ihi; i++ { + scale[i] = 2 * rnd.Float64() + d.Data[i*d.Stride+i] = scale[i] + dinv.Data[i*dinv.Stride+i] = 1 / scale[i] + } + } + } + + // Create P by generating random column swaps. + p := eye(n, n) + if job == lapack.Permute || job == lapack.PermuteScale { + // Make up some random permutations. + for i := n - 1; i > ihi; i-- { + scale[i] = float64(rnd.Intn(i + 1)) + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[i:]}, + blas64.Vector{p.Stride, p.Data[int(scale[i]):]}) + } + for i := 0; i < ilo; i++ { + scale[i] = float64(i + rnd.Intn(ihi-i+1)) + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[i:]}, + blas64.Vector{p.Stride, p.Data[int(scale[i]):]}) + } + } + + got := cloneGeneral(v) + impl.Dgebak(job, side, n, ilo, ihi, scale, m, got.Data, got.Stride) + + prefix := fmt.Sprintf("Case job=%v, side=%v, n=%v, ilo=%v, ihi=%v, m=%v, extra=%v", + job, side, n, ilo, ihi, m, extra) + + if !generalOutsideAllNaN(got) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, got.Data) + } + + // Compute D*V or D^{-1}*V and store into dv. + dv := zeros(n, m, m) + if side == lapack.RightEV { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d, v, 0, dv) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, dinv, v, 0, dv) + } + // Compute P*D*V or P*D^{-1}*V and store into want. + want := zeros(n, m, m) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, p, dv, 0, want) + + if !equalApproxGeneral(want, got, tol) { + t.Errorf("%v: unexpected value of V", prefix) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebal.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebal.go new file mode 100644 index 00000000..b07ababf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebal.go @@ -0,0 +1,175 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dgebaler interface { + Dgebal(job lapack.Job, n int, a []float64, lda int, scale []float64) (int, int) +} + +func DgebalTest(t *testing.T, impl Dgebaler) { + rnd := rand.New(rand.NewSource(1)) + + for _, job := range []lapack.Job{lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 10, 18, 31, 53, 100} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 100; cas++ { + a := unbalancedSparseGeneral(n, n, n+extra, 2*n, rnd) + testDgebal(t, impl, job, a) + } + } + } + } +} + +func testDgebal(t *testing.T, impl Dgebaler, job lapack.Job, a blas64.General) { + const tol = 1e-14 + + n := a.Rows + extra := a.Stride - n + + var scale []float64 + if n > 0 { + scale = nanSlice(n) + } + + want := cloneGeneral(a) + + ilo, ihi := impl.Dgebal(job, n, a.Data, a.Stride, scale) + + prefix := fmt.Sprintf("Case job=%v, n=%v, extra=%v", job, n, extra) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + + if n == 0 { + if ilo != 0 { + t.Errorf("%v: unexpected ilo when n=0. Want 0, got %v", prefix, ilo) + } + if ihi != -1 { + t.Errorf("%v: unexpected ihi when n=0. Want -1, got %v", prefix, ihi) + } + return + } + + if job == lapack.None { + if ilo != 0 { + t.Errorf("%v: unexpected ilo when job=None. Want 0, got %v", prefix, ilo) + } + if ihi != n-1 { + t.Errorf("%v: unexpected ihi when job=None. Want %v, got %v", prefix, n-1, ihi) + } + k := -1 + for i := range scale { + if scale[i] != 1 { + k = i + break + } + } + if k != -1 { + t.Errorf("%v: unexpected scale[%v] when job=None. Want 1, got %v", prefix, k, scale[k]) + } + if !equalApproxGeneral(a, want, 0) { + t.Errorf("%v: unexpected modification of A when job=None", prefix) + } + return + } + + if ilo < 0 || ihi < ilo || n <= ihi { + t.Errorf("%v: invalid ordering of ilo=%v and ihi=%v", prefix, ilo, ihi) + } + + if ilo >= 2 && !isUpperTriangular(blas64.General{ilo - 1, ilo - 1, a.Stride, a.Data}) { + t.Errorf("%v: T1 is not upper triangular", prefix) + } + m := n - ihi - 1 // Order of T2. + k := ihi + 1 + if m >= 2 && !isUpperTriangular(blas64.General{m, m, a.Stride, a.Data[k*a.Stride+k:]}) { + t.Errorf("%v: T2 is not upper triangular", prefix) + } + + if job == lapack.Permute || job == lapack.PermuteScale { + // Check that all rows in [ilo:ihi+1] have at least one nonzero + // off-diagonal element. + zeroRow := -1 + for i := ilo; i <= ihi; i++ { + onlyZeros := true + for j := ilo; j <= ihi; j++ { + if i != j && a.Data[i*a.Stride+j] != 0 { + onlyZeros = false + break + } + } + if onlyZeros { + zeroRow = i + break + } + } + if zeroRow != -1 && ilo != ihi { + t.Errorf("%v: row %v has only zero off-diagonal elements, ilo=%v, ihi=%v", prefix, zeroRow, ilo, ihi) + } + // Check that all columns in [ilo:ihi+1] have at least one nonzero + // off-diagonal element. + zeroCol := -1 + for j := ilo; j <= ihi; j++ { + onlyZeros := true + for i := ilo; i <= ihi; i++ { + if i != j && a.Data[i*a.Stride+j] != 0 { + onlyZeros = false + break + } + } + if onlyZeros { + zeroCol = j + break + } + } + if zeroCol != -1 && ilo != ihi { + t.Errorf("%v: column %v has only zero off-diagonal elements, ilo=%v, ihi=%v", prefix, zeroCol, ilo, ihi) + } + + // Create the permutation matrix P. + p := eye(n, n) + for j := n - 1; j > ihi; j-- { + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[j:]}, + blas64.Vector{p.Stride, p.Data[int(scale[j]):]}) + } + for j := 0; j < ilo; j++ { + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[j:]}, + blas64.Vector{p.Stride, p.Data[int(scale[j]):]}) + } + // Compute P^T*A*P and store into want. + ap := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, want, p, 0, ap) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, p, ap, 0, want) + } + if job == lapack.Scale || job == lapack.PermuteScale { + // Modify want by D and D^{-1}. + d := eye(n, n) + dinv := eye(n, n) + for i := ilo; i <= ihi; i++ { + d.Data[i*d.Stride+i] = scale[i] + dinv.Data[i*dinv.Stride+i] = 1 / scale[i] + } + ad := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, want, d, 0, ad) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, dinv, ad, 0, want) + } + if !equalApproxGeneral(want, a, tol) { + t.Errorf("%v: unexpected value of A, ilo=%v, ihi=%v", prefix, ilo, ihi) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebd2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebd2.go new file mode 100644 index 00000000..f122c407 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebd2.go @@ -0,0 +1,54 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" +) + +type Dgebd2er interface { + Dgebd2(m, n int, a []float64, lda int, d, e, tauq, taup, work []float64) +} + +func Dgebd2Test(t *testing.T, impl Dgebd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {3, 4, 0}, + {4, 3, 0}, + {3, 4, 10}, + {4, 3, 10}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + nb := min(m, n) // 'nb' name parallel with Dlabrd code. + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + d := nanSlice(nb) + e := nanSlice(nb - 1) + tauP := nanSlice(nb) + tauQ := nanSlice(nb) + work := nanSlice(max(m, n)) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgebd2(m, n, a, lda, d, e, tauQ, tauP, work) + if m >= n && nb == n { + tauP[n-1] = 0 + } + if m < n && nb == m { + tauQ[m-1] = 0 + } + + checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebrd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebrd.go new file mode 100644 index 00000000..0bbba460 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgebrd.go @@ -0,0 +1,151 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgebrder interface { + Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) + Dgebd2er +} + +func DgebrdTest(t *testing.T, impl Dgebrder) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {100, 100, 0}, + {100, 150, 0}, + {150, 100, 0}, + {100, 100, 200}, + {100, 150, 200}, + {150, 100, 200}, + + {300, 300, 0}, + {300, 400, 0}, + {400, 300, 0}, + {300, 300, 500}, + {300, 400, 500}, + {300, 400, 500}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + minmn := min(m, n) + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + d := make([]float64, minmn) + e := make([]float64, minmn-1) + tauP := make([]float64, minmn) + tauQ := make([]float64, minmn) + work := make([]float64, max(m, n)) + for i := range work { + work[i] = math.NaN() + } + + // Store a. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Compute the true answer with the unblocked algorithm. + impl.Dgebd2(m, n, a, lda, d, e, tauQ, tauP, work) + aAns := make([]float64, len(a)) + copy(aAns, a) + dAns := make([]float64, len(d)) + copy(dAns, d) + eAns := make([]float64, len(e)) + copy(eAns, e) + tauQAns := make([]float64, len(tauQ)) + copy(tauQAns, tauQ) + tauPAns := make([]float64, len(tauP)) + copy(tauPAns, tauP) + + // Test with optimal work. + lwork := -1 + copy(a, aCopy) + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + work = make([]float64, int(work[0])) + lwork = len(work) + for i := range work { + work[i] = math.NaN() + } + for i := range d { + d[i] = math.NaN() + } + for i := range e { + e[i] = math.NaN() + } + for i := range tauQ { + tauQ[i] = math.NaN() + } + for i := range tauP { + tauP[i] = math.NaN() + } + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + + // Test answers + if !floats.EqualApprox(a, aAns, 1e-10) { + t.Errorf("a mismatch") + } + if !floats.EqualApprox(d, dAns, 1e-10) { + t.Errorf("d mismatch") + } + if !floats.EqualApprox(e, eAns, 1e-10) { + t.Errorf("e mismatch") + } + if !floats.EqualApprox(tauQ, tauQAns, 1e-10) { + t.Errorf("tauQ mismatch") + } + if !floats.EqualApprox(tauP, tauPAns, 1e-10) { + t.Errorf("tauP mismatch") + } + + // Test with shorter than optimal work. + lwork-- + copy(a, aCopy) + for i := range d { + d[i] = 0 + } + for i := range e { + e[i] = 0 + } + for i := range tauP { + tauP[i] = 0 + } + for i := range tauQ { + tauQ[i] = 0 + } + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + + // Test answers + if !floats.EqualApprox(a, aAns, 1e-10) { + t.Errorf("a mismatch") + } + if !floats.EqualApprox(d, dAns, 1e-10) { + t.Errorf("d mismatch") + } + if !floats.EqualApprox(e, eAns, 1e-10) { + t.Errorf("e mismatch") + } + if !floats.EqualApprox(tauQ, tauQAns, 1e-10) { + t.Errorf("tauQ mismatch") + } + if !floats.EqualApprox(tauP, tauPAns, 1e-10) { + t.Errorf("tauP mismatch") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgecon.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgecon.go new file mode 100644 index 00000000..bbb76284 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgecon.go @@ -0,0 +1,97 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "log" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgeconer interface { + Dlanger + Dgetrfer + Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 +} + +func DgeconTest(t *testing.T, impl Dgeconer) { + for _, test := range []struct { + m int + n int + a []float64 + condOne float64 + condInf float64 + }{ + { + a: []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }, + m: 3, + n: 3, + condOne: 3.0 / 16, + condInf: 3.0 / 16, + }, + { + a: []float64{ + 2, 9, 3, 2, + 10, 9, 9, 3, + 1, 1, 5, 2, + 8, 4, 10, 2, + }, + m: 4, + n: 4, + condOne: 0.024740155174938, + condInf: 0.012034465570035, + }, + // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. + { + a: []float64{ + 2.9995576045549965, -2.0898894566158663, 3.965560740124006, + -2.0898894566158663, 1.9634729526261008, -2.8681002706874104, + 3.965560740124006, -2.8681002706874104, 5.502416670471008, + }, + m: 3, + n: 3, + condOne: 0.024054837369015203, + condInf: 0.024054837369015203, + }, + } { + m := test.m + n := test.n + lda := n + a := make([]float64, len(test.a)) + copy(a, test.a) + ipiv := make([]int, min(m, n)) + + // Find the norms of the original matrix. + work := make([]float64, 4*n) + oneNorm := impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) + infNorm := impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) + + // Compute LU factorization of a. + impl.Dgetrf(m, n, a, lda, ipiv) + + // Compute the condition number + iwork := make([]int, n) + condOne := impl.Dgecon(lapack.MaxColumnSum, n, a, lda, oneNorm, work, iwork) + condInf := impl.Dgecon(lapack.MaxRowSum, n, a, lda, infNorm, work, iwork) + + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e0, 1e0) { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) + } else if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e-14, 1e-14) { + log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condOne, condOne) + } + if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e0, 1e0) { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condInf, condInf) + } else if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e-14, 1e-14) { + log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condInf, condInf) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev.go new file mode 100644 index 00000000..3ad86c1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev.go @@ -0,0 +1,735 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "strconv" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgeever interface { + Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, + wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) int +} + +type dgeevTest struct { + a blas64.General + evWant []complex128 // If nil, the eigenvalues are not known. + valTol float64 // Tolerance for eigenvalue checks. + vecTol float64 // Tolerance for eigenvector checks. +} + +func DgeevTest(t *testing.T, impl Dgeever) { + rnd := rand.New(rand.NewSource(1)) + + for i, test := range []dgeevTest{ + { + a: A123{}.Matrix(), + evWant: A123{}.Eigenvalues(), + }, + + dgeevTestForAntisymRandom(10, rnd), + dgeevTestForAntisymRandom(11, rnd), + dgeevTestForAntisymRandom(50, rnd), + dgeevTestForAntisymRandom(51, rnd), + dgeevTestForAntisymRandom(100, rnd), + dgeevTestForAntisymRandom(101, rnd), + + { + a: Circulant(2).Matrix(), + evWant: Circulant(2).Eigenvalues(), + }, + { + a: Circulant(3).Matrix(), + evWant: Circulant(3).Eigenvalues(), + }, + { + a: Circulant(4).Matrix(), + evWant: Circulant(4).Eigenvalues(), + }, + { + a: Circulant(5).Matrix(), + evWant: Circulant(5).Eigenvalues(), + }, + { + a: Circulant(10).Matrix(), + evWant: Circulant(10).Eigenvalues(), + }, + { + a: Circulant(15).Matrix(), + evWant: Circulant(15).Eigenvalues(), + valTol: 1e-12, + }, + { + a: Circulant(30).Matrix(), + evWant: Circulant(30).Eigenvalues(), + valTol: 1e-11, + vecTol: 1e-12, + }, + { + a: Circulant(50).Matrix(), + evWant: Circulant(50).Eigenvalues(), + valTol: 1e-11, + vecTol: 1e-12, + }, + { + a: Circulant(101).Matrix(), + evWant: Circulant(101).Eigenvalues(), + valTol: 1e-10, + vecTol: 1e-11, + }, + { + a: Circulant(150).Matrix(), + evWant: Circulant(150).Eigenvalues(), + valTol: 1e-9, + vecTol: 1e-10, + }, + + { + a: Clement(2).Matrix(), + evWant: Clement(2).Eigenvalues(), + }, + { + a: Clement(3).Matrix(), + evWant: Clement(3).Eigenvalues(), + }, + { + a: Clement(4).Matrix(), + evWant: Clement(4).Eigenvalues(), + }, + { + a: Clement(5).Matrix(), + evWant: Clement(5).Eigenvalues(), + }, + { + a: Clement(10).Matrix(), + evWant: Clement(10).Eigenvalues(), + }, + { + a: Clement(15).Matrix(), + evWant: Clement(15).Eigenvalues(), + }, + { + a: Clement(30).Matrix(), + evWant: Clement(30).Eigenvalues(), + valTol: 1e-11, + }, + { + a: Clement(50).Matrix(), + evWant: Clement(50).Eigenvalues(), + valTol: 1e-7, + vecTol: 1e-11, + }, + + { + a: Creation(2).Matrix(), + evWant: Creation(2).Eigenvalues(), + }, + { + a: Creation(3).Matrix(), + evWant: Creation(3).Eigenvalues(), + }, + { + a: Creation(4).Matrix(), + evWant: Creation(4).Eigenvalues(), + }, + { + a: Creation(5).Matrix(), + evWant: Creation(5).Eigenvalues(), + }, + { + a: Creation(10).Matrix(), + evWant: Creation(10).Eigenvalues(), + }, + { + a: Creation(15).Matrix(), + evWant: Creation(15).Eigenvalues(), + }, + { + a: Creation(30).Matrix(), + evWant: Creation(30).Eigenvalues(), + }, + { + a: Creation(50).Matrix(), + evWant: Creation(50).Eigenvalues(), + }, + { + a: Creation(101).Matrix(), + evWant: Creation(101).Eigenvalues(), + }, + { + a: Creation(150).Matrix(), + evWant: Creation(150).Eigenvalues(), + }, + + { + a: Diagonal(0).Matrix(), + evWant: Diagonal(0).Eigenvalues(), + }, + { + a: Diagonal(10).Matrix(), + evWant: Diagonal(10).Eigenvalues(), + }, + { + a: Diagonal(50).Matrix(), + evWant: Diagonal(50).Eigenvalues(), + }, + { + a: Diagonal(151).Matrix(), + evWant: Diagonal(151).Eigenvalues(), + }, + + { + a: Downshift(2).Matrix(), + evWant: Downshift(2).Eigenvalues(), + }, + { + a: Downshift(3).Matrix(), + evWant: Downshift(3).Eigenvalues(), + }, + { + a: Downshift(4).Matrix(), + evWant: Downshift(4).Eigenvalues(), + }, + { + a: Downshift(5).Matrix(), + evWant: Downshift(5).Eigenvalues(), + }, + { + a: Downshift(10).Matrix(), + evWant: Downshift(10).Eigenvalues(), + }, + { + a: Downshift(15).Matrix(), + evWant: Downshift(15).Eigenvalues(), + }, + { + a: Downshift(30).Matrix(), + evWant: Downshift(30).Eigenvalues(), + }, + { + a: Downshift(50).Matrix(), + evWant: Downshift(50).Eigenvalues(), + }, + { + a: Downshift(101).Matrix(), + evWant: Downshift(101).Eigenvalues(), + }, + { + a: Downshift(150).Matrix(), + evWant: Downshift(150).Eigenvalues(), + }, + + { + a: Fibonacci(2).Matrix(), + evWant: Fibonacci(2).Eigenvalues(), + }, + { + a: Fibonacci(3).Matrix(), + evWant: Fibonacci(3).Eigenvalues(), + }, + { + a: Fibonacci(4).Matrix(), + evWant: Fibonacci(4).Eigenvalues(), + }, + { + a: Fibonacci(5).Matrix(), + evWant: Fibonacci(5).Eigenvalues(), + }, + { + a: Fibonacci(10).Matrix(), + evWant: Fibonacci(10).Eigenvalues(), + }, + { + a: Fibonacci(15).Matrix(), + evWant: Fibonacci(15).Eigenvalues(), + }, + { + a: Fibonacci(30).Matrix(), + evWant: Fibonacci(30).Eigenvalues(), + }, + { + a: Fibonacci(50).Matrix(), + evWant: Fibonacci(50).Eigenvalues(), + }, + { + a: Fibonacci(101).Matrix(), + evWant: Fibonacci(101).Eigenvalues(), + }, + { + a: Fibonacci(150).Matrix(), + evWant: Fibonacci(150).Eigenvalues(), + }, + + { + a: Gear(2).Matrix(), + evWant: Gear(2).Eigenvalues(), + }, + { + a: Gear(3).Matrix(), + evWant: Gear(3).Eigenvalues(), + }, + { + a: Gear(4).Matrix(), + evWant: Gear(4).Eigenvalues(), + valTol: 1e-7, + }, + { + a: Gear(5).Matrix(), + evWant: Gear(5).Eigenvalues(), + }, + { + a: Gear(10).Matrix(), + evWant: Gear(10).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(15).Matrix(), + evWant: Gear(15).Eigenvalues(), + }, + { + a: Gear(30).Matrix(), + evWant: Gear(30).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(50).Matrix(), + evWant: Gear(50).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(101).Matrix(), + evWant: Gear(101).Eigenvalues(), + }, + { + a: Gear(150).Matrix(), + evWant: Gear(150).Eigenvalues(), + valTol: 1e-8, + }, + + { + a: Grcar{N: 10, K: 3}.Matrix(), + evWant: Grcar{N: 10, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 10, K: 7}.Matrix(), + evWant: Grcar{N: 10, K: 7}.Eigenvalues(), + }, + { + a: Grcar{N: 11, K: 7}.Matrix(), + evWant: Grcar{N: 11, K: 7}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 3}.Matrix(), + evWant: Grcar{N: 50, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 51, K: 3}.Matrix(), + evWant: Grcar{N: 51, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 10}.Matrix(), + evWant: Grcar{N: 50, K: 10}.Eigenvalues(), + }, + { + a: Grcar{N: 51, K: 10}.Matrix(), + evWant: Grcar{N: 51, K: 10}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 30}.Matrix(), + evWant: Grcar{N: 50, K: 30}.Eigenvalues(), + }, + { + a: Grcar{N: 150, K: 2}.Matrix(), + evWant: Grcar{N: 150, K: 2}.Eigenvalues(), + }, + { + a: Grcar{N: 150, K: 148}.Matrix(), + evWant: Grcar{N: 150, K: 148}.Eigenvalues(), + }, + + { + a: Hanowa{N: 6, Alpha: 17}.Matrix(), + evWant: Hanowa{N: 6, Alpha: 17}.Eigenvalues(), + }, + { + a: Hanowa{N: 50, Alpha: -1}.Matrix(), + evWant: Hanowa{N: 50, Alpha: -1}.Eigenvalues(), + }, + { + a: Hanowa{N: 100, Alpha: -1}.Matrix(), + evWant: Hanowa{N: 100, Alpha: -1}.Eigenvalues(), + }, + + { + a: Lesp(2).Matrix(), + evWant: Lesp(2).Eigenvalues(), + }, + { + a: Lesp(3).Matrix(), + evWant: Lesp(3).Eigenvalues(), + }, + { + a: Lesp(4).Matrix(), + evWant: Lesp(4).Eigenvalues(), + }, + { + a: Lesp(5).Matrix(), + evWant: Lesp(5).Eigenvalues(), + }, + { + a: Lesp(10).Matrix(), + evWant: Lesp(10).Eigenvalues(), + }, + { + a: Lesp(15).Matrix(), + evWant: Lesp(15).Eigenvalues(), + }, + { + a: Lesp(30).Matrix(), + evWant: Lesp(30).Eigenvalues(), + }, + { + a: Lesp(50).Matrix(), + evWant: Lesp(50).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + { + a: Lesp(101).Matrix(), + evWant: Lesp(101).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + { + a: Lesp(150).Matrix(), + evWant: Lesp(150).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + + { + a: Rutis{}.Matrix(), + evWant: Rutis{}.Eigenvalues(), + }, + + { + a: Tris{N: 74, X: 1, Y: -2, Z: 1}.Matrix(), + evWant: Tris{N: 74, X: 1, Y: -2, Z: 1}.Eigenvalues(), + }, + { + a: Tris{N: 74, X: 1, Y: 2, Z: -3}.Matrix(), + evWant: Tris{N: 74, X: 1, Y: 2, Z: -3}.Eigenvalues(), + }, + { + a: Tris{N: 75, X: 1, Y: 2, Z: -3}.Matrix(), + evWant: Tris{N: 75, X: 1, Y: 2, Z: -3}.Eigenvalues(), + }, + + { + a: Wilk4{}.Matrix(), + evWant: Wilk4{}.Eigenvalues(), + }, + { + a: Wilk12{}.Matrix(), + evWant: Wilk12{}.Eigenvalues(), + valTol: 1e-8, + }, + { + a: Wilk20(0).Matrix(), + evWant: Wilk20(0).Eigenvalues(), + }, + { + a: Wilk20(1e-10).Matrix(), + evWant: Wilk20(1e-10).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + + { + a: Zero(1).Matrix(), + evWant: Zero(1).Eigenvalues(), + }, + { + a: Zero(10).Matrix(), + evWant: Zero(10).Eigenvalues(), + }, + { + a: Zero(50).Matrix(), + evWant: Zero(50).Eigenvalues(), + }, + { + a: Zero(100).Matrix(), + evWant: Zero(100).Eigenvalues(), + }, + } { + for _, jobvl := range []lapack.LeftEVJob{lapack.ComputeLeftEV, lapack.None} { + for _, jobvr := range []lapack.RightEVJob{lapack.ComputeRightEV, lapack.None} { + for _, extra := range []int{0, 11} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + testDgeev(t, impl, strconv.Itoa(i), test, jobvl, jobvr, extra, wl) + } + } + } + } + } + + for _, n := range []int{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, 50, 51, 100, 101} { + for _, jobvl := range []lapack.LeftEVJob{lapack.ComputeLeftEV, lapack.None} { + for _, jobvr := range []lapack.RightEVJob{lapack.ComputeRightEV, lapack.None} { + for cas := 0; cas < 10; cas++ { + // Create a block diagonal matrix with + // random eigenvalues of random multiplicity. + ev := make([]complex128, n) + tmat := zeros(n, n, n) + for i := 0; i < n; { + re := rnd.NormFloat64() + if i == n-1 || rnd.Float64() < 0.5 { + // Real eigenvalue. + nb := rnd.Intn(min(4, n-i)) + 1 + for k := 0; k < nb; k++ { + tmat.Data[i*tmat.Stride+i] = re + ev[i] = complex(re, 0) + i++ + } + continue + } + // Complex eigenvalue. + im := rnd.NormFloat64() + nb := rnd.Intn(min(4, (n-i)/2)) + 1 + for k := 0; k < nb; k++ { + // 2×2 block for the complex eigenvalue. + tmat.Data[i*tmat.Stride+i] = re + tmat.Data[(i+1)*tmat.Stride+i+1] = re + tmat.Data[(i+1)*tmat.Stride+i] = -im + tmat.Data[i*tmat.Stride+i+1] = im + ev[i] = complex(re, im) + ev[i+1] = complex(re, -im) + i += 2 + } + } + + // Compute A = Q T Q^T where Q is an + // orthogonal matrix. + q := randomOrthogonal(n, rnd) + tq := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.Trans, 1, tmat, q, 0, tq) + a := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, tq, 0, a) + + test := dgeevTest{ + a: a, + evWant: ev, + valTol: 1e-12, + vecTol: 1e-8, + } + testDgeev(t, impl, "random", test, jobvl, jobvr, 0, optimumWork) + } + } + } + } +} + +func testDgeev(t *testing.T, impl Dgeever, tc string, test dgeevTest, jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, extra int, wl worklen) { + const defaultTol = 1e-13 + valTol := test.valTol + if valTol == 0 { + valTol = defaultTol + } + vecTol := test.vecTol + if vecTol == 0 { + vecTol = defaultTol + } + + a := cloneGeneral(test.a) + n := a.Rows + + var vl blas64.General + if jobvl == lapack.ComputeLeftEV { + vl = nanGeneral(n, n, n) + } + + var vr blas64.General + if jobvr == lapack.ComputeRightEV { + vr = nanGeneral(n, n, n) + } + + wr := make([]float64, n) + wi := make([]float64, n) + + var lwork int + switch wl { + case minimumWork: + if jobvl == lapack.ComputeLeftEV || jobvr == lapack.ComputeRightEV { + lwork = max(1, 4*n) + } else { + lwork = max(1, 3*n) + } + case mediumWork: + work := make([]float64, 1) + impl.Dgeev(jobvl, jobvr, n, nil, 1, nil, nil, nil, 1, nil, 1, work, -1) + if jobvl == lapack.ComputeLeftEV || jobvr == lapack.ComputeRightEV { + lwork = (int(work[0]) + 4*n) / 2 + } else { + lwork = (int(work[0]) + 3*n) / 2 + } + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dgeev(jobvl, jobvr, n, nil, 1, nil, nil, nil, 1, nil, 1, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + first := impl.Dgeev(jobvl, jobvr, n, a.Data, a.Stride, wr, wi, + vl.Data, vl.Stride, vr.Data, vr.Stride, work, len(work)) + + prefix := fmt.Sprintf("Case #%v: n=%v, jobvl=%v, jobvr=%v, extra=%v, work=%v", + tc, n, jobvl, jobvr, extra, wl) + + if !generalOutsideAllNaN(vl) { + t.Errorf("%v: out-of-range write to VL", prefix) + } + if !generalOutsideAllNaN(vr) { + t.Errorf("%v: out-of-range write to VR", prefix) + } + + if first > 0 { + t.Logf("%v: all eigenvalues haven't been computed, first=%v", prefix, first) + } + + // Check that conjugate pair eigevalues are ordered correctly. + for i := first; i < n; { + if wi[i] == 0 { + i++ + continue + } + if wr[i] != wr[i+1] { + t.Errorf("%v: real parts of %vth conjugate pair not equal", prefix, i) + } + if wi[i] < 0 || wi[i+1] > 0 { + t.Errorf("%v: unexpected ordering of %vth conjugate pair", prefix, i) + } + i += 2 + } + + // Check the computed eigenvalues against provided known eigenvalues. + if test.evWant != nil { + used := make([]bool, n) + for i := first; i < n; i++ { + evGot := complex(wr[i], wi[i]) + idx := -1 + for k, evWant := range test.evWant { + if !used[k] && cmplx.Abs(evWant-evGot) < valTol { + idx = k + used[k] = true + break + } + } + if idx == -1 { + t.Errorf("%v: unexpected eigenvalue %v", prefix, evGot) + } + } + } + + if first > 0 || (jobvl == lapack.None && jobvr == lapack.None) { + // No eigenvectors have been computed. + return + } + + // Check that the columns of VL and VR are eigenvectors that correspond + // to the computed eigenvalues. + for k := 0; k < n; { + if wi[k] == 0 { + if jobvl == lapack.ComputeLeftEV { + ev := columnOf(vl, k) + if !isLeftEigenvectorOf(test.a, ev, nil, complex(wr[k], 0), vecTol) { + t.Errorf("%v: VL[:,%v] is not left real eigenvector", + prefix, k) + } + + norm := floats.Norm(ev, 2) + if math.Abs(norm-1) >= defaultTol { + t.Errorf("%v: norm of left real eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + if jobvr == lapack.ComputeRightEV { + ev := columnOf(vr, k) + if !isRightEigenvectorOf(test.a, ev, nil, complex(wr[k], 0), vecTol) { + t.Errorf("%v: VR[:,%v] is not right real eigenvector", + prefix, k) + } + + norm := floats.Norm(ev, 2) + if math.Abs(norm-1) >= defaultTol { + t.Errorf("%v: norm of right real eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + k++ + } else { + if jobvl == lapack.ComputeLeftEV { + evre := columnOf(vl, k) + evim := columnOf(vl, k+1) + if !isLeftEigenvectorOf(test.a, evre, evim, complex(wr[k], wi[k]), vecTol) { + t.Errorf("%v: VL[:,%v:%v] is not left complex eigenvector", + prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isLeftEigenvectorOf(test.a, evre, evim, complex(wr[k+1], wi[k+1]), vecTol) { + t.Errorf("%v: VL[:,%v:%v] is not left complex eigenvector", + prefix, k, k+1) + } + + norm := math.Hypot(floats.Norm(evre, 2), floats.Norm(evim, 2)) + if math.Abs(norm-1) > defaultTol { + t.Errorf("%v: norm of left complex eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + if jobvr == lapack.ComputeRightEV { + evre := columnOf(vr, k) + evim := columnOf(vr, k+1) + if !isRightEigenvectorOf(test.a, evre, evim, complex(wr[k], wi[k]), vecTol) { + t.Errorf("%v: VR[:,%v:%v] is not right complex eigenvector", + prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isRightEigenvectorOf(test.a, evre, evim, complex(wr[k+1], wi[k+1]), vecTol) { + t.Errorf("%v: VR[:,%v:%v] is not right complex eigenvector", + prefix, k, k+1) + } + + norm := math.Hypot(floats.Norm(evre, 2), floats.Norm(evim, 2)) + if math.Abs(norm-1) > defaultTol { + t.Errorf("%v: norm of right complex eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + // We don't test whether the largest component is real + // because checking it is flaky due to rounding errors. + + k += 2 + } + } +} + +func dgeevTestForAntisymRandom(n int, rnd *rand.Rand) dgeevTest { + a := NewAntisymRandom(n, rnd) + return dgeevTest{ + a: a.Matrix(), + evWant: a.Eigenvalues(), + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev_bench.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev_bench.go new file mode 100644 index 00000000..177807de --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeev_bench.go @@ -0,0 +1,63 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +var resultGeneral blas64.General + +func DgeevBenchmark(b *testing.B, impl Dgeever) { + rnd := rand.New(rand.NewSource(1)) + benchmarks := []struct { + name string + a blas64.General + }{ + {"AntisymRandom3", NewAntisymRandom(3, rnd).Matrix()}, + {"AntisymRandom4", NewAntisymRandom(4, rnd).Matrix()}, + {"AntisymRandom5", NewAntisymRandom(5, rnd).Matrix()}, + {"AntisymRandom10", NewAntisymRandom(10, rnd).Matrix()}, + {"AntisymRandom50", NewAntisymRandom(50, rnd).Matrix()}, + {"AntisymRandom100", NewAntisymRandom(100, rnd).Matrix()}, + {"AntisymRandom200", NewAntisymRandom(200, rnd).Matrix()}, + {"AntisymRandom500", NewAntisymRandom(500, rnd).Matrix()}, + {"Circulant3", Circulant(3).Matrix()}, + {"Circulant4", Circulant(4).Matrix()}, + {"Circulant5", Circulant(5).Matrix()}, + {"Circulant10", Circulant(10).Matrix()}, + {"Circulant50", Circulant(50).Matrix()}, + {"Circulant100", Circulant(100).Matrix()}, + {"Circulant200", Circulant(200).Matrix()}, + {"Circulant500", Circulant(500).Matrix()}, + } + for _, bm := range benchmarks { + n := bm.a.Rows + a := zeros(n, n, n) + vl := zeros(n, n, n) + vr := zeros(n, n, n) + wr := make([]float64, n) + wi := make([]float64, n) + work := make([]float64, 1) + impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, nil, n, nil, nil, nil, n, nil, n, work, -1) + work = make([]float64, int(work[0])) + b.Run(bm.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + copyGeneral(a, bm.a) + b.StartTimer() + impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, a.Data, a.Stride, wr, wi, + vl.Data, vl.Stride, vr.Data, vr.Stride, work, len(work)) + } + resultGeneral = a + }) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehd2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehd2.go new file mode 100644 index 00000000..5b7e8309 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehd2.go @@ -0,0 +1,196 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgehd2er interface { + Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) +} + +func Dgehd2Test(t *testing.T, impl Dgehd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 30} { + for _, extra := range []int{0, 1, 13} { + for cas := 0; cas < 100; cas++ { + testDgehd2(t, impl, n, extra, rnd) + } + } + } +} + +func testDgehd2(t *testing.T, impl Dgehd2er, n, extra int, rnd *rand.Rand) { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + + tau := nanSlice(n - 1) + work := nanSlice(n) + + a := randomGeneral(n, n, n+extra, rnd) + // NaN out elements under the diagonal except + // for the [ilo:ihi,ilo:ihi] block. + for i := 1; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + a.Data[i*a.Stride+j] = math.NaN() + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + a.Data[i*a.Stride+j] = math.NaN() + } + } + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + + impl.Dgehd2(n, ilo, ihi, a.Data, a.Stride, tau, work) + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v", n, ilo, ihi, extra) + + // Check any invalid modifications of a. + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + for i := ilo; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + if !math.IsNaN(a.Data[i*a.Stride+j]) { + t.Errorf("%v: expected NaN at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + if !math.IsNaN(a.Data[i*a.Stride+j]) { + t.Errorf("%v: expected NaN at A[%v,%v]", prefix, i, j) + } + } + } + for i := 0; i <= ilo; i++ { + for j := i; j < ilo+1; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + for j := ihi + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := i; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + + // Check that tau has been assigned properly. + for i, v := range tau { + if i < ilo || i >= ihi { + if !math.IsNaN(v) { + t.Errorf("%v: expected NaN at tau[%v]", prefix, i) + } + } else { + if math.IsNaN(v) { + t.Errorf("%v: unexpected NaN at tau[%v]", prefix, i) + } + } + } + + // Extract Q and check that it is orthogonal. + q := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < q.Rows; i++ { + q.Data[i*q.Stride+i] = 1 + } + qCopy := q + qCopy.Data = make([]float64, len(q.Data)) + for j := ilo; j < ihi; j++ { + h := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < h.Rows; i++ { + h.Data[i*h.Stride+i] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal\nQ=%v", prefix, q) + } + + // Overwrite NaN elements of aCopy with zeros + // (we will multiply with it below). + for i := 1; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + aCopy.Data[i*aCopy.Stride+j] = 0 + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy.Data[i*aCopy.Stride+j] = 0 + } + } + + // Construct Q^T * AOrig * Q and check that it is + // equal to A from Dgehd2. + aq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, q, 0, aq) + qaq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aq, 0, qaq) + for i := ilo; i <= ihi; i++ { + for j := ilo; j <= ihi; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + if j < i-1 { + if math.Abs(qaqij) > 1e-14 { + t.Errorf("%v: Q^T*A*Q is not upper Hessenberg, [%v,%v]=%v", prefix, i, j, qaqij) + } + continue + } + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-14 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehrd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehrd.go new file mode 100644 index 00000000..012b8707 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgehrd.go @@ -0,0 +1,209 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgehrder interface { + Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) + + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgehrdTest(t *testing.T, impl Dgehrder) { + rnd := rand.New(rand.NewSource(1)) + + // Randomized tests for small matrix sizes that will most likely + // use the unblocked algorithm. + for _, n := range []int{1, 2, 3, 4, 5, 10, 34} { + for _, extra := range []int{0, 13} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 10; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDgehrd(t, impl, n, ilo, ihi, extra, optwork, rnd) + } + } + } + } + + // These are selected tests for larger matrix sizes to test the blocked + // algorithm. Use sizes around several powers of two because that is + // where the blocked path will most likely start to be taken. For + // example, at present the blocked algorithm is used for sizes larger + // than 129. + for _, test := range []struct { + n, ilo, ihi int + }{ + {0, 0, -1}, + + {68, 0, 63}, + {68, 0, 64}, + {68, 0, 65}, + {68, 0, 66}, + {68, 0, 67}, + + {132, 2, 129}, + {132, 1, 129}, // Size = 129, unblocked. + {132, 0, 129}, // Size = 130, blocked. + {132, 1, 130}, + {132, 0, 130}, + {132, 1, 131}, + {132, 0, 131}, + + {260, 2, 257}, + {260, 1, 257}, + {260, 0, 257}, + {260, 0, 258}, + {260, 0, 259}, + } { + for _, extra := range []int{0, 13} { + for _, optwork := range []bool{true, false} { + testDgehrd(t, impl, test.n, test.ilo, test.ihi, extra, optwork, rnd) + } + } + } +} + +func testDgehrd(t *testing.T, impl Dgehrder, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + a := randomGeneral(n, n, n+extra, rnd) + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + + var tau []float64 + if n > 1 { + tau = nanSlice(n - 1) + } + + var work []float64 + if optwork { + work = nanSlice(1) + impl.Dgehrd(n, ilo, ihi, nil, a.Stride, nil, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, n)) + } + + impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + if n == 0 { + // Just make sure there is no panic. + return + } + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v", n, ilo, ihi, extra) + + // Check any invalid modifications of a. + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + for i := ilo; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification of A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification of A[%v,%v]", prefix, i, j) + } + } + } + for i := 0; i <= ilo; i++ { + for j := i; j < ilo+1; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + for j := ihi + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := i; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + + // Check that tau has been assigned properly. + for i, v := range tau { + if math.IsNaN(v) { + t.Errorf("%v: unexpected NaN at tau[%v]", prefix, i) + } + } + + // Extract Q and check that it is orthogonal. + q := eye(n, n) + if ilo != ihi { + for i := ilo + 2; i <= ihi; i++ { + for j := ilo + 1; j < ihi; j++ { + q.Data[i*q.Stride+j] = a.Data[i*a.Stride+j-1] + } + } + nh := ihi - ilo + impl.Dorgqr(nh, nh, nh, q.Data[(ilo+1)*q.Stride+ilo+1:], q.Stride, tau[ilo:ihi], work, len(work)) + } + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal\nQ=%v", prefix, q) + } + + // Construct Q^T * AOrig * Q and check that it is upper Hessenberg. + aq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, q, 0, aq) + qaq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aq, 0, qaq) + for i := 0; i <= ilo; i++ { + for j := ilo + 1; j <= ihi; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } + for i := ilo + 1; i <= ihi; i++ { + for j := ilo; j < n; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + if j < i-1 { + if math.Abs(qaqij) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q is not upper Hessenberg, [%v,%v]=%v", prefix, i, j, qaqij) + } + continue + } + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelq2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelq2.go new file mode 100644 index 00000000..20f95717 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelq2.go @@ -0,0 +1,113 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgelq2er interface { + Dgelq2(m, n int, a []float64, lda int, tau, work []float64) +} + +func Dgelq2Test(t *testing.T, impl Dgelq2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {1, 12, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {1, 12, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + a := make([]float64, m*lda) + for i := 0; i < m*lda; i++ { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgelq2(m, n, a, lda, tau, work) + + Q := constructQ("LQ", m, n, a, lda, tau) + + // Check that Q is orthonormal + for i := 0; i < Q.Rows; i++ { + nrm := blas64.Nrm2(Q.Cols, blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}) + if math.Abs(nrm-1) > 1e-14 { + t.Errorf("Q not normal. Norm is %v", nrm) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(Q.Rows, + blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}, + blas64.Vector{Inc: 1, Data: Q.Data[j*Q.Stride:]}, + ) + if math.Abs(dot) > 1e-14 { + t.Errorf("Q not orthogonal. Dot is %v", dot) + } + } + } + + L := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + L.Data[i*L.Stride+j] = a[i*lda+j] + } + } + + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(ans.Data, aCopy) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, L, Q, 0, ans) + if !floats.EqualApprox(aCopy, ans.Data, 1e-14) { + t.Errorf("Case %v, LQ mismatch. Want %v, got %v.", c, aCopy, ans.Data) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelqf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelqf.go new file mode 100644 index 00000000..5bbe7312 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgelqf.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgelqfer interface { + Dgelq2er + Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgelqfTest(t *testing.T, impl Dgelqfer) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {200, 200, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 30}, + {5, 10, 30}, + {10, 10, 30}, + {300, 5, 500}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = rnd.Float64() + } + } + tau := make([]float64, n) + for i := 0; i < n; i++ { + tau[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ans := make([]float64, len(a)) + copy(ans, a) + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + // Compute unblocked QR. + impl.Dgelq2(m, n, ans, lda, tau, work) + // Compute blocked QR with small work. + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch small work.", c) + } + // Try the full length of work. + impl.Dgelqf(m, n, a, lda, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + copy(a, aCopy) + impl.Dgelqf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + + // Try a slightly smaller version of work to test blocking code. + if len(work) <= m { + continue + } + work = work[1:] + lwork-- + copy(a, aCopy) + impl.Dgelqf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgels.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgels.go new file mode 100644 index 00000000..9b49a54c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgels.go @@ -0,0 +1,182 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgelser interface { + Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool +} + +func DgelsTest(t *testing.T, impl Dgelser) { + rnd := rand.New(rand.NewSource(1)) + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + m, n, nrhs, lda, ldb int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 10, 20}, + {3, 5, 4, 10, 20}, + {4, 3, 5, 10, 20}, + {4, 5, 3, 10, 20}, + {5, 3, 4, 10, 20}, + {5, 4, 3, 10, 20}, + {3, 4, 5, 20, 10}, + {3, 5, 4, 20, 10}, + {4, 3, 5, 20, 10}, + {4, 5, 3, 20, 10}, + {5, 3, 4, 20, 10}, + {5, 4, 3, 20, 10}, + {200, 300, 400, 0, 0}, + {200, 400, 300, 0, 0}, + {300, 200, 400, 0, 0}, + {300, 400, 200, 0, 0}, + {400, 200, 300, 0, 0}, + {400, 300, 200, 0, 0}, + {200, 300, 400, 500, 600}, + {200, 400, 300, 500, 600}, + {300, 200, 400, 500, 600}, + {300, 400, 200, 500, 600}, + {400, 200, 300, 500, 600}, + {400, 300, 200, 500, 600}, + {200, 300, 400, 600, 500}, + {200, 400, 300, 600, 500}, + {300, 200, 400, 600, 500}, + {300, 400, 200, 600, 500}, + {400, 200, 300, 600, 500}, + {400, 300, 200, 600, 500}, + } { + m := test.m + n := test.n + nrhs := test.nrhs + + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Size of b is the same trans or no trans, because the number of rows + // has to be the max of (m,n). + mb := max(m, n) + nb := nrhs + ldb := test.ldb + if ldb == 0 { + ldb = nb + } + b := make([]float64, mb*ldb) + for i := range b { + b[i] = rnd.Float64() + } + bCopy := make([]float64, len(b)) + copy(bCopy, b) + + // Find optimal work length. + work := make([]float64, 1) + impl.Dgels(trans, m, n, nrhs, a, lda, b, ldb, work, -1) + + // Perform linear solve + work = make([]float64, int(work[0])) + lwork := len(work) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dgels(trans, m, n, nrhs, a, lda, b, ldb, work, lwork) + + // Check that the answer is correct by comparing to the normal equations. + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, len(aCopy)), + } + copy(aMat.Data, aCopy) + szAta := n + if trans == blas.Trans { + szAta = m + } + aTA := blas64.General{ + Rows: szAta, + Cols: szAta, + Stride: szAta, + Data: make([]float64, szAta*szAta), + } + + // Compute A^T * A if notrans and A * A^T otherwise. + if trans == blas.NoTrans { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, aMat, aMat, 0, aTA) + } else { + blas64.Gemm(blas.NoTrans, blas.Trans, 1, aMat, aMat, 0, aTA) + } + + // Multiply by X. + X := blas64.General{ + Rows: szAta, + Cols: nrhs, + Stride: ldb, + Data: b, + } + ans := blas64.General{ + Rows: aTA.Rows, + Cols: X.Cols, + Stride: X.Cols, + Data: make([]float64, aTA.Rows*X.Cols), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aTA, X, 0, ans) + + B := blas64.General{ + Rows: szAta, + Cols: nrhs, + Stride: ldb, + Data: make([]float64, len(bCopy)), + } + + copy(B.Data, bCopy) + var ans2 blas64.General + if trans == blas.NoTrans { + ans2 = blas64.General{ + Rows: aMat.Cols, + Cols: B.Cols, + Stride: B.Cols, + Data: make([]float64, aMat.Cols*B.Cols), + } + } else { + ans2 = blas64.General{ + Rows: aMat.Rows, + Cols: B.Cols, + Stride: B.Cols, + Data: make([]float64, aMat.Rows*B.Cols), + } + } + + // Compute A^T B if Trans or A * B otherwise + if trans == blas.NoTrans { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, aMat, B, 0, ans2) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, B, 0, ans2) + } + if !floats.EqualApprox(ans.Data, ans2.Data, 1e-12) { + t.Errorf("Normal equations not satisfied") + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeql2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeql2.go new file mode 100644 index 00000000..0ff6a930 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeql2.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgeql2er interface { + Dgeql2(m, n int, a []float64, lda int, tau, work []float64) +} + +func Dgeql2Test(t *testing.T, impl Dgeql2er) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Add tests for m < n. + for _, test := range []struct { + m, n, lda int + }{ + {5, 5, 0}, + {5, 3, 0}, + {5, 4, 0}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + tau := nanSlice(min(m, n)) + work := nanSlice(n) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgeql2(m, n, a, lda, tau, work) + + k := min(m, n) + // Construct Q. + q := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + q.Data[i*q.Stride+i] = 1 + } + for i := 0; i < k; i++ { + h := blas64.General{Rows: m, Cols: m, Stride: m, Data: make([]float64, m*m)} + for j := 0; j < m; j++ { + h.Data[j*h.Stride+j] = 1 + } + v := blas64.Vector{Inc: 1, Data: make([]float64, m)} + v.Data[m-k+i] = 1 + for j := 0; j < m-k+i; j++ { + v.Data[j] = a[j*lda+n-k+i] + } + blas64.Ger(-tau[i], v, v, h) + qTmp := blas64.General{Rows: q.Rows, Cols: q.Cols, Stride: q.Stride, Data: make([]float64, len(q.Data))} + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qTmp, 0, q) + } + if !isOrthonormal(q) { + t.Errorf("Q is not orthonormal") + } + l := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + if m >= n { + for i := m - n; i < m; i++ { + for j := 0; j <= min(i-(m-n), n-1); j++ { + l.Data[i*l.Stride+j] = a[i*lda+j] + } + } + } else { + panic("untested") + } + ans := blas64.General{Rows: m, Cols: n, Stride: lda, Data: make([]float64, len(a))} + copy(ans.Data, a) + + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, l, 0, ans) + if !floats.EqualApprox(ans.Data, aCopy, 1e-10) { + t.Errorf("Reconstruction mismatch: m = %v, n = %v", m, n) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqp3.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqp3.go new file mode 100644 index 00000000..54e30bf5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqp3.go @@ -0,0 +1,135 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgeqp3er interface { + Dlapmter + Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) +} + +func Dgeqp3Test(t *testing.T, impl Dgeqp3er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + {129, 256, 0}, + {256, 129, 0}, + {129, 256, 266}, + {256, 129, 266}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + const ( + all = iota + some + none + ) + for _, free := range []int{all, some, none} { + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + jpvt := make([]int, n) + for j := range jpvt { + switch free { + case all: + jpvt[j] = -1 + case some: + jpvt[j] = rnd.Intn(2) - 1 + case none: + jpvt[j] = 0 + default: + panic("bad freedom") + } + } + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, 1) + impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, lwork) + + // Test that the QR factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("QR", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < m; i++ { + nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A * P = Q * R + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a[i*lda+j] + } + } + got := nanGeneral(m, n, lda) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := blas64.General{Rows: m, Cols: n, Stride: lda, Data: aCopy} + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpvt) + if !equalApproxGeneral(got, want, 1e-13) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", c, got, want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqr2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqr2.go new file mode 100644 index 00000000..f9ebf694 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqr2.go @@ -0,0 +1,111 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgeqr2er interface { + Dgeqr2(m, n int, a []float64, lda int, tau []float64, work []float64) +} + +func Dgeqr2Test(t *testing.T, impl Dgeqr2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, n) + for i := range work { + work[i] = rnd.Float64() + } + copy(aCopy, a) + impl.Dgeqr2(m, n, a, lda, tau, work) + + // Test that the QR factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("QR", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < m; i++ { + nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}) + if math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = Q * R + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a[i*lda+j] + } + } + atmp := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(atmp.Data, a) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, atmp) + if !floats.EqualApprox(atmp.Data, aCopy, 1e-14) { + t.Errorf("Q*R != a") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqrf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqrf.go new file mode 100644 index 00000000..60386c08 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgeqrf.go @@ -0,0 +1,95 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgeqrfer interface { + Dgeqr2er + Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgeqrfTest(t *testing.T, impl Dgeqrfer) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {200, 200, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 20}, + {5, 10, 20}, + {10, 10, 20}, + {300, 5, 400}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = rnd.Float64() + } + } + tau := make([]float64, n) + for i := 0; i < n; i++ { + tau[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ans := make([]float64, len(a)) + copy(ans, a) + work := make([]float64, n) + // Compute unblocked QR. + impl.Dgeqr2(m, n, ans, lda, tau, work) + // Compute blocked QR with small work. + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch small work.", c) + } + // Try the full length of work. + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + copy(a, aCopy) + impl.Dgeqrf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + + // Try a slightly smaller version of work to test blocking. + if len(work) <= n { + continue + } + work = work[1:] + lwork-- + copy(a, aCopy) + impl.Dgeqrf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerq2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerq2.go new file mode 100644 index 00000000..ec0dde2a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerq2.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgerq2er interface { + Dgerq2(m, n int, a []float64, lda int, tau []float64, work []float64) +} + +func Dgerq2Test(t *testing.T, impl Dgerq2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + copy(aCopy, a) + impl.Dgerq2(m, n, a, lda, tau, work) + + // Test that the RQ factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("RQ", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < q.Rows; i++ { + nrm := blas64.Nrm2(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}) + if math.IsNaN(nrm) || math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}) + if math.IsNaN(dot) || math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = R * Q + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + off := m - n + for j := max(0, i-off); j < n; j++ { + r.Data[i*r.Stride+j] = a[i*lda+j] + } + } + + got := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, r, q, 0, got) + want := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: aCopy, + } + if !equalApproxGeneral(got, want, 1e-14) { + t.Errorf("Case %d, R*Q != a\ngot: %+v\nwant:%+v", c, got, want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerqf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerqf.go new file mode 100644 index 00000000..b6e24126 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgerqf.go @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgerqfer interface { + Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgerqfTest(t *testing.T, impl Dgerqfer) { + const tol = 1e-13 + + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {200, 180, 0}, + {180, 200, 0}, + {200, 200, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + {200, 180, 220}, + {180, 200, 220}, + {200, 200, 220}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := []float64{0} + impl.Dgerqf(m, n, a, lda, tau, work, -1) + lwkopt := int(work[0]) + for _, wk := range []struct { + name string + length int + }{ + {name: "short", length: m}, + {name: "medium", length: lwkopt - 1}, + {name: "long", length: lwkopt}, + } { + if wk.length < max(1, m) { + continue + } + lwork := wk.length + work = make([]float64, lwork) + for i := range work { + work[i] = rnd.Float64() + } + copy(a, aCopy) + impl.Dgerqf(m, n, a, lda, tau, work, lwork) + + // Test that the RQ factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("RQ", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < q.Rows; i++ { + nrm := blas64.Nrm2(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}) + if math.IsNaN(nrm) || math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}) + if math.IsNaN(dot) || math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = R * Q + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + off := m - n + for j := max(0, i-off); j < n; j++ { + r.Data[i*r.Stride+j] = a[i*lda+j] + } + } + + got := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, r, q, 0, got) + want := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: aCopy, + } + if !equalApproxGeneral(got, want, tol) { + t.Errorf("Case %d, R*Q != a %s\ngot: %+v\nwant:%+v", c, wk.name, got, want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgesvd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgesvd.go new file mode 100644 index 00000000..8c317993 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgesvd.go @@ -0,0 +1,286 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgesvder interface { + Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) +} + +func DgesvdTest(t *testing.T, impl Dgesvder) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Add tests for all of the cases when the SVD implementation + // is finished. + // TODO(btracey): Add tests for m > mnthr and n > mnthr when other SVD + // conditions are implemented. Right now mnthr is 5,000,000 which is too + // large to create a square matrix of that size. + for _, test := range []struct { + m, n, lda, ldu, ldvt int + }{ + {5, 5, 0, 0, 0}, + {5, 6, 0, 0, 0}, + {6, 5, 0, 0, 0}, + {5, 9, 0, 0, 0}, + {9, 5, 0, 0, 0}, + + {5, 5, 10, 11, 12}, + {5, 6, 10, 11, 12}, + {6, 5, 10, 11, 12}, + {5, 5, 10, 11, 12}, + {5, 9, 10, 11, 12}, + {9, 5, 10, 11, 12}, + + {300, 300, 0, 0, 0}, + {300, 400, 0, 0, 0}, + {400, 300, 0, 0, 0}, + {300, 600, 0, 0, 0}, + {600, 300, 0, 0, 0}, + + {300, 300, 400, 450, 460}, + {300, 400, 500, 550, 560}, + {400, 300, 550, 550, 560}, + {300, 600, 700, 750, 760}, + {600, 300, 700, 750, 760}, + } { + jobU := lapack.SVDAll + jobVT := lapack.SVDAll + + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldvt := test.ldvt + if ldvt == 0 { + ldvt = n + } + + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + u := make([]float64, m*ldu) + for i := range u { + u[i] = rnd.NormFloat64() + } + + vt := make([]float64, n*ldvt) + for i := range vt { + vt[i] = rnd.NormFloat64() + } + + uAllOrig := make([]float64, len(u)) + copy(uAllOrig, u) + vtAllOrig := make([]float64, len(vt)) + copy(vtAllOrig, vt) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + s := make([]float64, min(m, n)) + + work := make([]float64, 1) + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, -1) + + if !floats.Equal(a, aCopy) { + t.Errorf("a changed during call to get work length") + } + + work = make([]float64, int(work[0])) + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, len(work)) + + errStr := fmt.Sprintf("m = %v, n = %v, lda = %v, ldu = %v, ldv = %v", m, n, lda, ldu, ldvt) + svdCheck(t, false, errStr, m, n, s, a, u, ldu, vt, ldvt, aCopy, lda) + svdCheckPartial(t, impl, lapack.SVDAll, errStr, uAllOrig, vtAllOrig, aCopy, m, n, a, lda, s, u, ldu, vt, ldvt, work, false) + + // Test InPlace + jobU = lapack.SVDInPlace + jobVT = lapack.SVDInPlace + copy(a, aCopy) + copy(u, uAllOrig) + copy(vt, vtAllOrig) + + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, len(work)) + svdCheck(t, true, errStr, m, n, s, a, u, ldu, vt, ldvt, aCopy, lda) + svdCheckPartial(t, impl, lapack.SVDInPlace, errStr, uAllOrig, vtAllOrig, aCopy, m, n, a, lda, s, u, ldu, vt, ldvt, work, false) + } +} + +// svdCheckPartial checks that the singular values and vectors are computed when +// not all of them are computed. +func svdCheckPartial(t *testing.T, impl Dgesvder, job lapack.SVDJob, errStr string, uAllOrig, vtAllOrig, aCopy []float64, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, shortWork bool) { + rnd := rand.New(rand.NewSource(1)) + jobU := job + jobVT := job + // Compare the singular values when computed with {SVDNone, SVDNone.} + sCopy := make([]float64, len(s)) + copy(sCopy, s) + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + tmp1 := make([]float64, 1) + tmp2 := make([]float64, 1) + jobU = lapack.SVDNone + jobVT = lapack.SVDNone + + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, tmp2, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork := len(work) + if shortWork { + lwork-- + } + ok := impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, tmp2, ldvt, work, lwork) + if !ok { + t.Errorf("Dgesvd did not complete successfully") + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when singular vectors not computed: %s", errStr) + } + // Check that the singular vectors are correctly computed when the other + // is none. + uAll := make([]float64, len(u)) + copy(uAll, u) + vtAll := make([]float64, len(vt)) + copy(vtAll, vt) + + // Copy the original vectors so the data outside the matrix bounds is the same. + copy(u, uAllOrig) + copy(vt, vtAllOrig) + + jobU = job + jobVT = lapack.SVDNone + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, tmp2, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + if shortWork { + lwork-- + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, tmp2, ldvt, work, len(work)) + if !floats.EqualApprox(uAll, u, 1e-10) { + t.Errorf("U mismatch when VT is not computed: %s", errStr) + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when U computed VT not") + } + jobU = lapack.SVDNone + jobVT = job + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, vt, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + if shortWork { + lwork-- + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, vt, ldvt, work, len(work)) + if !floats.EqualApprox(vtAll, vt, 1e-10) { + t.Errorf("VT mismatch when U is not computed: %s", errStr) + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when VT computed U not") + } +} + +// svdCheck checks that the singular value decomposition correctly multiplies back +// to the original matrix. +func svdCheck(t *testing.T, thin bool, errStr string, m, n int, s, a, u []float64, ldu int, vt []float64, ldvt int, aCopy []float64, lda int) { + sigma := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < min(m, n); i++ { + sigma.Data[i*sigma.Stride+i] = s[i] + } + + uMat := blas64.General{ + Rows: m, + Cols: m, + Stride: ldu, + Data: u, + } + vTMat := blas64.General{ + Rows: n, + Cols: n, + Stride: ldvt, + Data: vt, + } + if thin { + sigma.Rows = min(m, n) + sigma.Cols = min(m, n) + uMat.Cols = min(m, n) + vTMat.Rows = min(m, n) + } + + tmp := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(ans.Data, a) + + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uMat, sigma, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, vTMat, 0, ans) + + if !floats.EqualApprox(ans.Data, aCopy, 1e-8) { + t.Errorf("Decomposition mismatch. Trim = %v, %s", thin, errStr) + } + + if !thin { + // Check that U and V are orthogonal. + for i := 0; i < uMat.Rows; i++ { + for j := i + 1; j < uMat.Rows; j++ { + dot := blas64.Dot(uMat.Cols, + blas64.Vector{Inc: 1, Data: uMat.Data[i*uMat.Stride:]}, + blas64.Vector{Inc: 1, Data: uMat.Data[j*uMat.Stride:]}, + ) + if dot > 1e-8 { + t.Errorf("U not orthogonal %s", errStr) + } + } + } + for i := 0; i < vTMat.Rows; i++ { + for j := i + 1; j < vTMat.Rows; j++ { + dot := blas64.Dot(vTMat.Cols, + blas64.Vector{Inc: 1, Data: vTMat.Data[i*vTMat.Stride:]}, + blas64.Vector{Inc: 1, Data: vTMat.Data[j*vTMat.Stride:]}, + ) + if dot > 1e-8 { + t.Errorf("V not orthogonal %s", errStr) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetf2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetf2.go new file mode 100644 index 00000000..7cb155e9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetf2.go @@ -0,0 +1,195 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgetf2er interface { + Dgetf2(m, n int, a []float64, lda int, ipiv []int) bool +} + +func Dgetf2Test(t *testing.T, impl Dgetf2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {10, 10, 0}, + {10, 5, 0}, + {10, 5, 0}, + + {10, 10, 20}, + {5, 10, 20}, + {10, 5, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + mn := min(m, n) + ipiv := make([]int, mn) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + ok := impl.Dgetf2(m, n, a, lda, ipiv) + checkPLU(t, ok, m, n, lda, ipiv, a, aCopy, 1e-14, true) + } + + // Test with singular matrices (random matrices are almost surely non-singular). + for _, test := range []struct { + m, n, lda int + a []float64 + }{ + { + m: 2, + n: 2, + lda: 2, + a: []float64{ + 1, 0, + 0, 0, + }, + }, + { + m: 2, + n: 2, + lda: 2, + a: []float64{ + 1, 5, + 2, 10, + }, + }, + { + m: 3, + n: 3, + lda: 3, + // row 3 = row1 + 2 * row2 + a: []float64{ + 1, 5, 7, + 2, 10, -3, + 5, 25, 1, + }, + }, + { + m: 3, + n: 4, + lda: 4, + // row 3 = row1 + 2 * row2 + a: []float64{ + 1, 5, 7, 9, + 2, 10, -3, 11, + 5, 25, 1, 31, + }, + }, + } { + if impl.Dgetf2(test.m, test.n, test.a, test.lda, make([]int, min(test.m, test.n))) { + t.Log("Returned ok with singular matrix.") + } + } +} + +// checkPLU checks that the PLU factorization contained in factorize matches +// the original matrix contained in original. +func checkPLU(t *testing.T, ok bool, m, n, lda int, ipiv []int, factorized, original []float64, tol float64, print bool) { + var hasZeroDiagonal bool + for i := 0; i < min(m, n); i++ { + if factorized[i*lda+i] == 0 { + hasZeroDiagonal = true + break + } + } + if hasZeroDiagonal && ok { + t.Error("Has a zero diagonal but returned ok") + } + if !hasZeroDiagonal && !ok { + t.Error("Non-zero diagonal but returned !ok") + } + + // Check that the LU decomposition is correct. + mn := min(m, n) + l := make([]float64, m*mn) + ldl := mn + u := make([]float64, mn*n) + ldu := n + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + v := factorized[i*lda+j] + switch { + case i == j: + l[i*ldl+i] = 1 + u[i*ldu+i] = v + case i > j: + l[i*ldl+j] = v + case i < j: + u[i*ldu+j] = v + } + } + } + + LU := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + U := blas64.General{ + Rows: mn, + Cols: n, + Stride: ldu, + Data: u, + } + L := blas64.General{ + Rows: m, + Cols: mn, + Stride: ldl, + Data: l, + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, L, U, 0, LU) + + p := make([]float64, m*m) + ldp := m + for i := 0; i < m; i++ { + p[i*ldp+i] = 1 + } + for i := len(ipiv) - 1; i >= 0; i-- { + v := ipiv[i] + blas64.Swap(m, blas64.Vector{Inc: 1, Data: p[i*ldp:]}, blas64.Vector{Inc: 1, Data: p[v*ldp:]}) + } + P := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: p, + } + aComp := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(aComp.Data, factorized) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, P, LU, 0, aComp) + if !floats.EqualApprox(aComp.Data, original, tol) { + if print { + t.Errorf("PLU multiplication does not match original matrix.\nWant: %v\nGot: %v", original, aComp.Data) + return + } + t.Error("PLU multiplication does not match original matrix.") + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrf.go new file mode 100644 index 00000000..1c9c6e45 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrf.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" +) + +type Dgetrfer interface { + Dgetrf(m, n int, a []float64, lda int, ipiv []int) bool +} + +func DgetrfTest(t *testing.T, impl Dgetrfer) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {4, 5, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 20}, + {5, 10, 20}, + {10, 10, 20}, + {300, 5, 400}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + mn := min(m, n) + ipiv := make([]int, mn) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + + // Cannot compare the outputs of Dgetrf and Dgetf2 because the pivoting may + // happen differently. Instead check that the LPQ factorization is correct. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ok := impl.Dgetrf(m, n, a, lda, ipiv) + checkPLU(t, ok, m, n, lda, ipiv, a, aCopy, 1e-10, false) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetri.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetri.go new file mode 100644 index 00000000..fd79df2a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetri.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgetrier interface { + Dgetrfer + Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) bool +} + +func DgetriTest(t *testing.T, impl Dgetrier) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, test := range []struct { + n, lda int + }{ + {5, 0}, + {5, 8}, + {45, 0}, + {45, 50}, + {65, 0}, + {65, 70}, + {150, 0}, + {150, 250}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + // Generate a random well conditioned matrix + perm := rnd.Perm(n) + a := make([]float64, n*lda) + for i := 0; i < n; i++ { + a[i*lda+perm[i]] = 1 + } + for i := range a { + a[i] += 0.01 * rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ipiv := make([]int, n) + // Compute LU decomposition. + impl.Dgetrf(n, n, a, lda, ipiv) + // Compute inverse. + work := make([]float64, 1) + impl.Dgetri(n, a, lda, ipiv, work, -1) + work = make([]float64, int(work[0])) + lwork := len(work) + + ok := impl.Dgetri(n, a, lda, ipiv, work, lwork) + if !ok { + t.Errorf("Unexpected singular matrix.") + } + + // Check that A(inv) * A = I. + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, aCopy, lda, a, lda, 0, ans, lda) + isEye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + // This tolerance is so high because computing matrix inverses + // is very unstable. + if math.Abs(ans[i*lda+j]-1) > 5e-2 { + isEye = false + } + } else { + if math.Abs(ans[i*lda+j]) > 5e-2 { + isEye = false + } + } + } + } + if !isEye { + t.Errorf("Inv(A) * A != I. n = %v, lda = %v", n, lda) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrs.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrs.go new file mode 100644 index 00000000..edc6d502 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dgetrs.go @@ -0,0 +1,113 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgetrser interface { + Dgetrfer + Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) +} + +func DgetrsTest(t *testing.T, impl Dgetrser) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Put more thought into creating more regularized matrices + // and what correct tolerances should be. Consider also seeding the random + // number in this test to make it more robust to code changes in other + // parts of the suite. + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + n, nrhs, lda, ldb int + tol float64 + }{ + {3, 3, 0, 0, 1e-12}, + {3, 5, 0, 0, 1e-12}, + {5, 3, 0, 0, 1e-12}, + + {3, 3, 8, 10, 1e-12}, + {3, 5, 8, 10, 1e-12}, + {5, 3, 8, 10, 1e-12}, + + {300, 300, 0, 0, 1e-8}, + {300, 500, 0, 0, 1e-8}, + {500, 300, 0, 0, 1e-6}, + + {300, 300, 700, 600, 1e-8}, + {300, 500, 700, 600, 1e-8}, + {500, 300, 700, 600, 1e-6}, + } { + n := test.n + nrhs := test.nrhs + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = nrhs + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + b := make([]float64, n*ldb) + for i := range b { + b[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + bCopy := make([]float64, len(b)) + copy(bCopy, b) + + ipiv := make([]int, n) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + + // Compute the LU factorization. + impl.Dgetrf(n, n, a, lda, ipiv) + // Solve the system of equations given the result. + impl.Dgetrs(trans, n, nrhs, a, lda, ipiv, b, ldb) + + // Check that the system of equations holds. + A := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: aCopy, + } + B := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: bCopy, + } + X := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: b, + } + tmp := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: make([]float64, n*ldb), + } + copy(tmp.Data, bCopy) + blas64.Gemm(trans, blas.NoTrans, 1, A, X, 0, B) + if !floats.EqualApprox(tmp.Data, bCopy, test.tol) { + t.Errorf("Linear solve mismatch. trans = %v, n = %v, nrhs = %v, lda = %v, ldb = %v", trans, n, nrhs, lda, ldb) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvd3.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvd3.go new file mode 100644 index 00000000..0a4af656 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvd3.go @@ -0,0 +1,173 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dggsvd3er interface { + Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) +} + +func Dggsvd3Test(t *testing.T, impl Dggsvd3er) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, lda, ldb, ldu, ldv, ldq int + + ok bool + }{ + {m: 3, p: 3, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + } { + m := test.m + p := test.p + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := randomGeneral(m, n, lda, rnd) + aCopy := cloneGeneral(a) + b := randomGeneral(p, n, ldb, rnd) + bCopy := cloneGeneral(b) + + alpha := make([]float64, n) + beta := make([]float64, n) + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + iwork := make([]int, n) + + work := []float64{0} + impl.Dggsvd3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, n, p, + a.Data, a.Stride, + b.Data, b.Stride, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work, -1, iwork) + + lwork := int(work[0]) + work = make([]float64, lwork) + + k, l, ok := impl.Dggsvd3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, n, p, + a.Data, a.Stride, + b.Data, b.Stride, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work, lwork, iwork) + + if !ok { + if test.ok { + t.Errorf("test %d unexpectedly did not converge", cas) + } + continue + } + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + // Check C^2 + S^2 = I. + var elements []float64 + if m-k-l >= 0 { + elements = alpha[k : k+l] + } else { + elements = alpha[k:m] + } + for i := range elements { + i += k + d := alpha[i]*alpha[i] + beta[i]*beta[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("test %d: alpha_%d^2 + beta_%d^2 != 1: got: %v", cas, i, i, d) + } + } + + zeroR, d1, d2 := constructGSVDresults(n, p, m, k, l, a, b, alpha, beta) + + // Check U^T*A*Q = D1*[ 0 R ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + d10r := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d1, zeroR, 0, d10r) + + if !equalApproxGeneral(uAns, d10r, 1e-14) { + t.Errorf("test %d: U^T*A*Q != D1*[ 0 R ]\nU^T*A*Q:\n%+v\nD1*[ 0 R ]:\n%+v", + cas, uAns, d10r) + } + + // Check V^T*B*Q = D2*[ 0 R ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + d20r := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d2, zeroR, 0, d20r) + + if !equalApproxGeneral(vAns, d20r, 1e-14) { + t.Errorf("test %d: V^T*B*Q != D2*[ 0 R ]\nV^T*B*Q:\n%+v\nD2*[ 0 R ]:\n%+v", + cas, vAns, d20r) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvp3.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvp3.go new file mode 100644 index 00000000..23111518 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dggsvp3.go @@ -0,0 +1,146 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dggsvp3er interface { + Dlanger + Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) +} + +func Dggsvp3Test(t *testing.T, impl Dggsvp3er) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, lda, ldb, ldu, ldv, ldq int + }{ + {m: 3, p: 3, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20}, + } { + m := test.m + p := test.p + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := randomGeneral(m, n, lda, rnd) + aCopy := cloneGeneral(a) + b := randomGeneral(p, n, ldb, rnd) + bCopy := cloneGeneral(b) + + tola := float64(max(m, n)) * impl.Dlange(lapack.NormFrob, m, n, a.Data, a.Stride, nil) * dlamchE + tolb := float64(max(p, n)) * impl.Dlange(lapack.NormFrob, p, n, b.Data, b.Stride, nil) * dlamchE + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + iwork := make([]int, n) + tau := make([]float64, n) + + work := []float64{0} + impl.Dggsvp3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, p, n, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + iwork, tau, + work, -1) + + lwork := int(work[0]) + work = make([]float64, lwork) + + k, l := impl.Dggsvp3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, p, n, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + iwork, tau, + work, lwork) + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + zeroA, zeroB := constructGSVPresults(n, p, m, k, l, a, b) + + // Check U^T*A*Q = [ 0 RA ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + if !equalApproxGeneral(uAns, zeroA, 1e-14) { + t.Errorf("test %d: U^T*A*Q != [ 0 RA ]\nU^T*A*Q:\n%+v\n[ 0 RA ]:\n%+v", + cas, uAns, zeroA) + } + + // Check V^T*B*Q = [ 0 RB ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + if !equalApproxGeneral(vAns, zeroB, 1e-14) { + t.Errorf("test %d: V^T*B*Q != [ 0 RB ]\nV^T*B*Q:\n%+v\n[ 0 RB ]:\n%+v", + cas, vAns, zeroB) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dhseqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dhseqr.go new file mode 100644 index 00000000..85ae5234 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dhseqr.go @@ -0,0 +1,861 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dhseqrer interface { + Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, + z []float64, ldz int, work []float64, lwork int) int +} + +type dhseqrTest struct { + n int + ilo int + ihi int + h []float64 + tol float64 + + evWant []complex128 +} + +func DhseqrTest(t *testing.T, impl Dhseqrer) { + for i, tc := range dhseqrTests { + for _, job := range []lapack.EVJob{lapack.EigenvaluesOnly, lapack.EigenvaluesAndSchur} { + for _, wantz := range []bool{false, true} { + for _, extra := range []int{0, 11} { + testDhseqr(t, impl, i, tc, job, wantz, extra, true) + testDhseqr(t, impl, i, tc, job, wantz, extra, false) + } + } + } + } +} + +func testDhseqr(t *testing.T, impl Dhseqrer, i int, test dhseqrTest, job lapack.EVJob, wantz bool, extra int, optwork bool) { + const tol = 1e-14 + evTol := test.tol + if evTol == 0 { + evTol = tol + } + + n := test.n + ihi := test.ihi + ilo := test.ilo + h := zeros(n, n, n+extra) + copyGeneral(h, blas64.General{Rows: n, Cols: n, Stride: max(1, n), Data: test.h}) + hCopy := cloneGeneral(h) + + var compz lapack.EVComp = lapack.None + z := blas64.General{Stride: max(1, n)} + if wantz { + // First, let Dhseqr initialize Z to the identity matrix. + compz = lapack.HessEV + z = nanGeneral(n, n, n+extra) + } + + wr := nanSlice(n) + wi := nanSlice(n) + + work := nanSlice(max(1, n)) + if optwork { + impl.Dhseqr(job, lapack.HessEV, n, ilo, ihi, nil, h.Stride, nil, nil, nil, z.Stride, work, -1) + work = nanSlice(int(work[0])) + } + + unconverged := impl.Dhseqr(job, compz, n, ilo, ihi, h.Data, h.Stride, wr, wi, z.Data, z.Stride, work, len(work)) + prefix := fmt.Sprintf("Case %v: job=%v, compz=%v, n=%v, ilo=%v, ihi=%v, extra=%v, optwk=%v", + i, job, compz, n, ilo, ihi, extra, optwork) + if unconverged > 0 { + t.Logf("%v: Dhseqr did not compute all eigenvalues. unconverged=%v", prefix, unconverged) + if unconverged <= ilo { + t.Fatalf("%v: 0 < unconverged <= ilo", prefix) + } + } + + // Check that wr and wi have been assigned completely. + if floats.HasNaN(wr) { + t.Errorf("%v: wr has NaN elements", prefix) + } + if floats.HasNaN(wi) { + t.Errorf("%v: wi has NaN elements", prefix) + } + + // Check that complex eigenvalues are stored in consecutive elements as + // complex conjugate pairs. + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + if wi[i] == 0 { + // Real eigenvalue. + i++ + continue + } + // Complex conjugate pair. + if wr[i] != wr[i+1] { + t.Errorf("%v: conjugate pair has real parts unequal", prefix) + } + if wi[i] < 0 { + t.Errorf("%v: first in conjugate pair has negative imaginary part", prefix) + } + if wi[i+1] != -wi[i] { + t.Errorf("%v: complex pair is not conjugate", prefix) + } + i += 2 + } + + // Check that H contains the Schur form T. + if job == lapack.EigenvaluesAndSchur { + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + if wi[i] == 0 { + // Real eigenvalue. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: T not in Schur form (real eigenvalue not on diagonal)", prefix) + } + i++ + continue + } + // Complex conjugate pair. + im := math.Sqrt(math.Abs(h.Data[(i+1)*h.Stride+i])) * math.Sqrt(math.Abs(h.Data[i*h.Stride+i+1])) + if wr[i] != h.Data[i*h.Stride+i] || wr[i] != h.Data[(i+1)*h.Stride+i+1] || + math.Abs(wi[i]-im) > tol { + t.Errorf("%v: conjugate pair and 2×2 diagonal block don't correspond", prefix) + } + i += 2 + } + } + + // Check that all the found eigenvalues are really eigenvalues. + foundEV := make([]bool, len(test.evWant)) + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + ev := complex(wr[i], wi[i]) + // Use problem-specific tolerance for testing eigenvalues. + found, index := containsComplex(test.evWant, ev, evTol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } else { + foundEV[index] = true + } + i++ + } + if unconverged == 0 { + // Check that all eigenvalues have been found. + // This simple check assumes that all eigenvalues are + // sufficiently separated from each other at least by evTol. + for i := range foundEV { + if !foundEV[i] { + t.Errorf("%v: %vth eigenvalue not found", prefix, i) + } + } + } + + if !wantz { + return + } + + // Z must be orthogonal. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + + if job == lapack.EigenvaluesAndSchur { + tz := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.Trans, 1, h, z, 0, tz) + ztz := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, z, tz, 0, ztz) + if !equalApproxGeneral(ztz, hCopy, evTol) { + t.Errorf("%v: H != Z T Z^T", prefix) + } + } + + // Restore H. + copyGeneral(h, hCopy) + // Call Dhseqr again with the identity matrix given explicitly in Q. + q := eye(n, n+extra) + impl.Dhseqr(job, lapack.OriginalEV, n, ilo, ihi, h.Data, h.Stride, wr, wi, q.Data, q.Stride, work, len(work)) + if !equalApproxGeneral(z, q, 0) { + t.Errorf("%v: Z and Q are not equal", prefix) + } +} + +var dhseqrTests = []dhseqrTest{ + { + n: 0, + ilo: 0, + ihi: -1, + }, + { + n: 1, + ilo: 0, + ihi: 0, + h: []float64{0}, + evWant: []complex128{0}, + }, + { + n: 1, + ilo: 0, + ihi: 0, + h: []float64{7.09965484086874e-1}, + evWant: []complex128{7.09965484086874e-1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{0, 0, 0, 0}, + evWant: []complex128{0}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 1, 0, + 0, 1, + }, + evWant: []complex128{1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 0, -1, + 1, 0, + }, + evWant: []complex128{1i, -1i}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + n: 4, + ilo: 1, + ihi: 2, + h: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 2, + }, + evWant: []complex128{1, 2, 9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + n: 5, + ilo: 0, + ihi: 4, + h: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + { + // BFW62A matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix small (n <= 75). + n: 62, + ilo: 0, + ihi: 61, + tol: 1e-12, + h: []float64{ + 0.7610708, -0.71474042262732, -1.03373461417302e-17, 8.218284875369092e-18, -4.39003777724509e-18, -7.633870714681998e-18, -9.951525116511751e-18, -6.538760279193677e-18, -1.656240811786753e-18, -4.915424973452908e-18, -7.590492820502813e-18, -4.532592864746854e-18, 1.137360639223451e-18, -2.088794138001457e-18, 4.330727699351238e-18, 4.88172964159538e-18, -6.438459345602974e-18, 7.414402965763168e-18, 8.592387304092668e-19, 2.905505475188102e-18, -5.210204793418634e-18, 2.377023457149656e-18, -1.958364175388968e-18, -8.746122759061733e-20, 1.839015672758814e-18, 3.097454207400904e-18, 1.545856657360309e-18, 1.713923049773744e-21, 1.333951071201153e-18, -1.256151066318485e-18, 5.489655201308922e-19, -2.191335276195054e-18, 3.211054779957158e-18, -4.585099368362507e-19, 4.064807180521144e-18, -3.621561583390336e-18, 4.638803832189033e-19, 1.306132013406548e-18, 7.71710094138792e-19, 2.320760977517361e-18, -6.538298612520761e-19, -3.498839827985687e-18, 2.699116500378558e-18, -1.653627855476782e-18, 7.006984532830204e-19, -2.829108657299736e-18, -5.260772120044258e-18, 1.014346572590618e-18, -1.751563831849658e-18, -1.850186018112724e-19, 2.870415308417256e-18, -8.423700664162806e-19, 3.498345394735042e-19, 1.448350507022323e-18, -3.119800500343431e-18, 4.170966784863917e-18, -4.413795207992463e-19, -2.550853151356032e-18, 2.058575286932081e-18, 1.11609155804576e-18, -2.819648393130598e-18, -2.691434041700446e-19, + -0.71474042262732, 1.938395745278447, -1.179041092366627, 2.994496337305918e-17, -1.886890458028042e-17, -1.696051150581149e-17, -1.066654178739982e-17, -6.29828959344471e-18, -3.017613522337327e-18, -6.087774183044001e-18, -1.623722797471356e-17, -1.609066043798334e-17, 1.1222991062801e-17, -1.199415856132727e-17, 3.254808477409891e-17, 3.032574771313234e-17, -2.950307698970009e-17, 3.390164991463985e-17, 3.580652213399182e-17, -1.363239170451582e-17, 5.318959619432346e-19, -2.094826370136215e-17, 2.503105756608372e-17, 1.02172885473953e-17, 2.072365201436764e-17, 5.419721687057681e-17, 2.946627912791419e-17, -1.348815353957071e-17, -6.109538294302727e-18, 8.919596400140564e-19, -4.965011212156456e-18, -8.892555328798407e-18, -8.533370652960768e-18, 2.670935841220357e-17, 6.294143735482237e-17, -6.631964574578866e-17, 1.610888675267686e-17, -1.914212496162892e-17, 7.491989417296875e-17, 2.433601037912241e-17, -3.471972221532949e-17, 1.239231453972595e-18, 8.477927675716922e-17, 1.832368873558869e-17, -3.15614722379294e-17, -3.481308523858143e-17, 8.753655535825511e-17, -2.311094913977048e-17, -1.97736043621337e-17, -4.591312368362259e-18, -4.090767028097941e-17, 9.630744841167777e-17, 6.376373378245906e-17, 3.517117740157962e-18, -4.504796150838874e-17, 7.517908631343054e-17, 5.08947280115584e-17, -1.382149857389238e-17, -2.198919507523352e-18, 7.280187019637593e-18, -4.195544216643798e-17, -1.69351463438629e-16, + 0, -1.179041092366627, 1.770797890903813, 0.9251612011433773, 0.003661446613681521, -0.005110479724841567, 0.0005014497289028411, 0.00268637752732762, -0.003137790817099964, 0.0001251340392028716, 0.005236816389348038, -0.007596537304410319, -0.003216883293048434, 0.002836879838039065, 0.006069520262676079, 0.002668518333518884, 0.009131523505676264, 0.004626632495050776, 0.00181579510454105, 0.001123900611304629, 0.001677485377614088, 0.00363754391761903, -0.0007470406844762735, 0.002833257933303097, -0.0002375815340930377, -0.002849024657372476, -0.0002629124003065383, -0.0009435052243060314, -0.001501677820905836, 0.0007867717317979819, -0.003255814847476796, 0.0001229596171032013, 0.001899497807037465, 0.001586135347885108, -0.002155598204409179, -0.004095921626627291, -0.004749259183184092, -0.0003901939289968589, -0.00126397970751315, 0.001155644134671306, 0.000291837164140963, -0.0008540793573406925, 0.0005498493646965147, -0.000512747881346778, 0.001308619245804509, -0.001057469234737898, 8.364932352209563e-05, -0.0004759538737373512, 0.0002832407173157385, -2.502295625364179e-05, -0.001116422235449543, 0.0008744887175767913, -0.001577030646119032, 0.0006630051771088335, 0.0008174386956312274, 0.0005885600522543514, -0.000529324123745168, 0.0006462360717703873, -0.0005292503950906053, -0.0008409757119361148, 0.001179292096398777, -7.042243897656571e-05, + 0, 0, 0.9256234889252499, 2.188661152704918, -1.116554836905615, -0.02243454666837822, 0.001818477623431723, 0.01031345522542573, -0.02255181751639313, 0.01064389372187288, 0.02644236613167033, -0.03711341885334873, -0.01368507023909662, 0.005876976997280983, 0.04065670610764593, 0.01666467627475975, 0.04720670725274503, 0.02074371568474985, 0.02492606640786733, -0.0007477579555839802, 0.008780018993769038, 0.02228545976823896, -0.001309713708470288, 0.02515283874752867, -0.002695437114195642, -0.03058898397162627, -0.004721936411831751, -0.01112709820777293, 0.005156744291122814, 0.001266520229863774, -0.0173310067274492, 0.006032177243961209, 0.01546906824241716, 0.004122912475005991, -0.01457685983271352, -0.02472315268907353, -0.0146012575743626, 0.01613627552485761, -0.03570849487210562, 0.009634392591632741, 0.01396210133689555, -0.01085301942984549, 0.02308071799914048, -0.01534806641683973, 0.007461896675297811, 0.001678793578211992, -0.004550709803423801, -0.003543952787451961, 0.01328644094056202, 0.01722933205866279, -0.01604068924890588, 0.01061524273934986, -0.01948663408394128, 0.02488657490054273, 0.002560204204893632, -0.007049942019567433, -0.005861737475764968, 0.007063905438215945, -0.01302170441839208, -0.01452116548010346, 0.008856002952171451, 0.003352799875293177, + 0, 0, 0, -1.131565669446545, 3.458875937128813, -2.92300025604371, 0.0004977656856497978, 0.006279968970473544, 0.0775979532222543, -0.07809248806636047, -0.04323656216106807, 0.05001022064587737, 0.003864067108285046, 0.04141643188583877, -0.1284617838883834, -0.04493800214431209, -0.07456343090218126, -0.01563872481200422, -0.1339020629421785, 0.04186908269102881, -0.01575262227867954, -0.05122401589211525, -0.01356095585891559, -0.1061570482803366, 0.01819813598371521, 0.1481253462698246, 0.02550194602547843, 0.04637287461870648, -0.07444378895306285, 0.01361958240422481, 0.04035022896181466, -0.04232248915252568, -0.06075940528348658, 0.027263798939883, 0.03953143432541723, 0.06518841156851282, -0.03410646432627348, -0.1414076406563496, 0.2323217246349602, -0.03415439789233707, -0.1031903658536844, 0.06725801721048928, -0.1560521418148311, 0.1014900809050588, -0.02098771321982528, -0.03982159107235207, 0.03695361299827822, 0.01067293209294729, -0.09426629859219736, -0.1345822610538289, 0.09362330513280395, -0.05670709861587474, 0.1059566486421828, -0.1760916487632087, 0.003702764511325265, 0.07422105386227762, 0.02742567045198715, -0.03734725575689604, 0.08146131944298318, 0.09081980084945049, -0.03823012624212198, -0.02882941691361127, + 0, 0, 0, 0, -2.935177932025793, 5.590160898106907, -2.264162462726681, -0.02411424982833118, -0.1133643811701465, 0.1104837624251364, 0.05106708784671347, -0.03981053811687705, -0.02554107703230142, -0.06918772930550876, 0.1627330379332113, 0.0515325563326872, 0.0562468014393183, 0.0339155492439978, 0.1634368483167388, -0.06785129040640099, 0.04039982620620088, 0.04044710731973533, 0.0285518510842595, 0.1485759249940305, -0.0304537251951914, -0.2009213484930713, -0.05273834253818357, -0.03107458918212595, 0.09792748883617711, -0.0337039884304953, -0.06657284881035327, 0.04914327832710783, 0.07368372187446774, -0.0404082088678178, -0.04421178865717079, -0.0709487906769288, 0.048430647567918, 0.1864479159285081, -0.3079556699470428, 0.01491993158702447, 0.1333753802314968, -0.09591074161204663, 0.1894696359177905, -0.1319027537070656, 0.03081270942006841, 0.04847952392626505, -0.04816809266890478, -0.0008101823853040729, 0.1149477702272877, 0.1970244006374306, -0.1184305631819092, 0.07656633356645355, -0.140928669738484, 0.2423845347140408, -0.01430733985161339, -0.0967298709856266, -0.03791764167457073, 0.04501910433428818, -0.09499757971636948, -0.1139200858550714, 0.04630019674988028, 0.03975991363586522, + 0, 0, 0, 0, 0, -2.266072850070115, 4.40758227065786, -2.187592801167079, 0.04541318743325212, -0.0292500337966509, -0.02398663294591961, -0.0298607436249778, 0.0765927452101913, 0.03477459705241919, -0.0257224121936686, 0.001477537977391887, 0.04674868179804328, -0.07030659618878905, 0.0114383223715982, 0.04039500147294157, -0.06165490536387656, 0.03052165142437121, -0.03151343169646251, -0.04567511071619659, 0.01389646864038026, 0.03406059858329889, 0.07777247587370216, -0.05562215591676438, -0.02972304398764038, 0.04553302018172632, 0.04905358098395964, 0.02540110963535692, 0.00741827563880251, -0.02406479350578768, 0.00798549007761889, -0.02127832597347739, 0.01170084494509563, 0.002383029926628291, 0.02969332847749644, 0.07478610531483831, 0.01311741704707942, 0.004853415796376565, 0.02254889573704177, -0.0008058983249759786, -0.01674237970384834, 0.007747220993838389, 0.001741724814996781, -0.02678508693786828, 0.03009097476646124, -0.06933693587488159, -0.006894177513041368, -0.003212920179243059, 0.006244662438662574, -0.03261491350065344, 0.03016960268159134, -0.001128724172713099, 0.01002372353957473, 0.01549185843206932, -0.01638802914727083, -0.02186759059889685, 0.02607807397124053, -0.01433672343290503, + 0, 0, 0, 0, 0, 0, -2.208506791141428, 5.240066122406224, -2.182709291422287, -0.04831719550093321, -0.03858222961310988, 0.07090414091109702, 0.07618344970454043, 0.01210977758298604, -0.08775997916346844, -0.04209238321226993, -0.08158937930535407, -0.0691978468647506, -0.0718486976078294, 0.004433709126950578, -0.06338689200675134, -0.03622650750929987, -0.007019326939737634, -0.1038169299762074, -0.003664296783585897, 0.1260404715508425, 0.01449365280740196, 0.02152866502194497, -0.04579662426484265, 0.02137306190373941, 0.02841535413798802, -0.04356497460133966, -0.04882163279365745, 0.0002663261307664017, 0.04049595350038757, 0.05101584504101733, 0.02365749339968924, -0.05799471679730656, 0.1571971147245405, -0.01838060269733261, -0.05301211904637573, 0.02796283933445018, -0.0827747400120639, 0.0826539872568238, -0.004639853234141812, -0.03415100337915269, 0.02043301459221876, -0.01420687321749558, -0.07938788384250468, -0.06984431882951091, 0.01979778686221181, -0.05267713009695951, 0.05803585434476307, -0.1172598583231236, 0.01085942096095348, 0.03045318026097962, 0.03931707061762502, -0.0233260419792624, 0.02886660013519448, 0.03861548107303825, -0.03415507841094348, 0.008098200304311437, + 0, 0, 0, 0, 0, 0, 0, -2.279082737682327, 4.179202389209161, 2.014339592778223, -0.04255211810632337, 0.2215228709530191, 0.04554891291433198, -0.1776754857264893, 0.008167590360928265, -0.03396600462822136, -0.2424067171263278, -0.04982603310212124, 0.08199335145408625, -0.1620942794258422, 0.002338101300086993, -0.07021142224421691, 0.09194811379254013, 0.06141720296344315, -0.04343138202962209, -0.07659354927119244, -0.1361105641705367, 0.04365095033370017, 0.1736465880725596, -0.08740865081391179, -0.01477028109128357, -0.0188999323841316, -0.01077877669937425, -0.04294670860685663, 0.01729899060655344, 0.08739236799944389, 0.182034549192379, 0.1742753783161974, -0.2051811283512857, -0.09696129832199611, 0.08343537923840838, -0.04957366782909829, 0.1265093425463374, -0.07142635715461459, 0.03516617105992843, 0.0383997617140459, -0.04104973319490962, 0.02037353120337982, 0.04757894980296348, 0.2227131172970346, -0.07280127948445575, 0.01933448054625989, -0.05548809149836405, 0.2093056702150173, -0.07255565470500472, -0.123599084041237, -0.01537223729308192, 0.002577573950277644, -0.0733551734670323, -0.03190494711187865, -0.03967527247234395, 0.07966579792866824, + 0, 0, 0, 0, 0, 0, 0, 0, 1.903931035374501, 3.824975942360571, -1.918381148171332, -0.1657229385793016, -0.1612950026821678, 0.06698675826395525, 0.126725548868686, 0.05262161401229534, 0.1736974825351408, 0.1645930486922778, -0.008218244683807857, 0.0481824748986632, 0.1029912224929829, 0.04100531176584442, -0.05027752034197176, 0.03600703924093035, -0.03107821795488815, -0.09759422490480313, -0.04354787932553194, 0.08526304164417117, -0.05355786578034339, -0.0210819410892414, -0.1122497139926173, -0.02837719853579051, 0.02149997813969711, 0.06803627465540676, -0.0458177019216118, -0.09920218030202725, -0.1651400777956252, -0.0455277713939929, 0.003337830551949452, -0.06755253724103881, -0.07801076584667281, -0.04572759847378299, -0.02963338925321968, 0.07597836187621793, 0.01430341925034608, -0.02647305556934371, 0.0228555845523007, 0.01546873666210535, -0.03908905892485317, -0.01513876665871793, 0.0042446623219113, 0.03015387459510092, -0.02120400053387252, -0.03598829734362344, 0.004724005614895581, 0.07940598065515762, 0.01643813194117675, 0.005515400875796831, 0.03057541214871107, -0.01882273722478993, 0.001668026830005827, -0.02913002540516653, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.035489145812599, 3.958195998136282, -2.415518953202652, -0.1018252839623988, 0.09113791429521235, -0.143125166149266, -0.02308820648298807, 0.007900495974597297, 0.0891936029052371, -0.191496963455834, 0.08058392972181647, 0.05211306893716722, -0.02786699591928707, 0.007523375632267236, -0.05648289516476343, 0.06927000214275245, 0.1738730341952659, 0.04931088211870207, 0.03078035118979117, -0.09569654581650394, 0.01335103593932622, 0.06192961771791639, -0.02060940913305214, -0.05414923078827102, 0.06346107123244546, 0.02052335161999402, 0.0759441214578726, -0.1238298106880246, -0.2507681676381417, 0.3220100931816501, -0.01147160193974397, -0.1324548043218159, 0.1477869911354369, -0.2406607672124291, 0.06431201000607845, -0.01766450147458312, -0.0548904673124562, 0.05157233284634812, 0.04488059690309322, -0.06177517133954061, -0.23112183069299, 0.2080819465459902, -0.05619520043449243, 0.1795452492137158, -0.204269300276831, -0.01430899089131678, 0.08951777845217569, -0.02653873178692821, -0.04665500591425999, 0.1362175927592773, 0.1872861054389846, -0.02109220243469613, -0.07237982467321609, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.387825495222564, 5.631333594127314, 1.792900160009439, -0.1292562242890975, 0.1708356554410346, 0.04950951151168896, -0.009914110552264667, 0.1304655891154234, 0.1609748354747077, -0.08607480442007164, 0.1610516858008479, 0.006346254683211893, 0.02530117908848513, 0.2023262116291442, -0.04991598539162005, -0.3298986278194697, -0.1487726465103999, 0.04799870466505981, 0.1882318445518781, -0.1206769872912393, -0.09574976849564885, 0.04601707138105179, 0.0715991702971735, 0.0110319870997898, -0.07468722751312951, -0.06360236467100627, 0.03066807997062939, 0.1978804308092757, -0.4403223814664722, -0.09064370852004526, 0.08638179820445273, -0.1181221434581026, 0.2272147516466281, -0.1254616867610615, -0.0001501123827163629, 0.1032892317050803, -0.05195565185717236, 0.04689531008365307, 0.1236167395644631, 0.2849021718663459, -0.08639934992977449, 0.1211622058496298, -0.1593293433814323, 0.2959939998820938, -0.06193112020165896, -0.06245227757105343, -0.04632893647720479, 0.03583128970774434, -0.07735153068129821, -0.1215213155769518, 0.01117363777162431, 0.01224071348068845, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.970568498833333, 3.432745918572068, -2.179945131289983, 0.1549422681053906, 0.02156733618947362, -0.1743403098753009, 0.04884260166424702, 0.161193984588502, -0.2174611110448761, 0.05521624891494294, -0.05887323587614037, 0.1328019445063764, 0.150653877491827, -0.06531521571304157, -0.1543822385517836, -0.2043044123070031, 0.1255799677545108, 0.1951365223394271, -0.1233664137625445, -0.1191855712864921, -0.04903904444926842, 0.01721465629147372, -0.04824417949824886, -0.001809247060549745, 0.04683387964790045, 0.1406402447048902, 0.2582634735034707, -0.2591765142026595, -0.1617309876246061, 0.1040899633433518, -0.09204034179968526, 0.1659716858767694, -0.07258217699057123, 0.1238542047814545, -0.005315457299413418, -0.04888221850509963, 0.02889824196206881, 0.07250335907166307, 0.3039398127688065, -0.1278843615154275, 0.03794117583347663, -0.08815038995197073, 0.3363118210052076, -0.1106312150714128, -0.1943873573646721, -0.03270119577811206, 0.02061769160692044, -0.1147396461667833, -0.04432517129006736, -0.03624512007085111, 0.1372685073992675, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.971094433373163, 3.959369702740928, 1.887120354843997, -0.05026461165000308, -0.1399839889203879, -0.185627397808518, -0.04596340870656163, 0.008956420059669758, -0.1381531838530755, -0.06179826475610644, 0.03260995306247771, -0.0962297246933979, 0.05268169622571128, 0.2046211566675452, 0.1296024872478153, -0.05109478171641717, -0.06816393508471544, 0.06908783957203835, 0.1203829447316026, 0.01720249086925636, -0.03678250120900584, -0.09954728921499965, 0.08400427932827997, 0.09706474262764897, 0.1099658716687498, -0.02055867348093135, 0.1883358420037133, 0.09179573472650564, 0.0428976892444284, 0.06904499115717885, -0.07352106561747025, -0.01527177851177849, 0.007127245592600535, -0.03478704421611469, 0.003011747710224133, -0.02349766354391826, 0.01004232793292505, -0.1176867876164139, 0.02626695914041232, -0.06316783433824909, 0.07753431035296164, -0.05772959109292543, 0.01954926232340906, -0.06086028308842151, -0.003104675370067428, -0.004923780276110752, 0.008718170992460231, 0.05506074746847181, 0.02126352510068548, 0.02026026825978836, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.051962095286209, 4.783354200058216, -2.891753406247233, 0.1494225282409022, 0.212321254452782, -0.2121415539790813, 0.02466897820188111, 0.06733336624204075, 0.013113247694252, 0.1066584296274234, 0.08752061927245192, 0.07922179944730777, 0.2365701476731576, 0.007588213043408364, -0.05416415411776607, -0.2020969955640969, 0.06349969928685602, -0.06132787289740503, -0.03422718627771316, -0.01952915873386353, 0.0644213739673787, 0.002115696634784188, 0.06255822113535302, -0.199371510170398, -0.3230384741719209, 0.3808208705549075, 0.04071272810763353, -0.01872027971165153, 0.175074940224908, -0.3802378821499527, -0.06108501582393667, 0.06646559313315525, -0.1623676411929772, 0.03990883781119187, 0.04487902512075174, -0.1419408834211026, -0.1568779206082137, 0.1763292664552807, -0.09481989476682466, 0.1344530334023877, -0.1823509060475661, 0.01993854821358784, 0.06058475613302417, -0.08882610769003915, -0.07025689205542202, 0.1720722409076721, 0.2549799182126544, 0.01962928250874243, -0.01708969300024939, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.90166412025067, 5.683663549106058, 1.9210862649828, 0.003584348132213356, -0.04815067261613367, 0.08879292199376522, -0.005675898744132862, 0.03588291164670374, -0.1637463265891401, -0.2197707557186419, -0.08857402261688128, -0.04780383765954515, 0.007843151524149466, 0.1770531910307867, -0.01723997302062695, -0.02612834699223629, -0.00540746785723896, -0.0705490796246758, -0.04457806266766569, 0.06473113864983282, 0.006275761834464256, -0.08950765677362392, -0.1005085571651238, -0.009712772636099888, 0.1241037651167948, -0.1243232786387127, -0.2285046949724745, -0.09330919844079147, 0.05061721851550809, 0.2874490693586184, -0.03620828558028133, 0.009836453811605826, 0.06478449995192533, -0.01171663894787422, 0.006410086373602496, -0.2000108983272982, 0.03916914746487668, 0.03329096249389659, 0.07559233782463498, -0.1503685986635421, -0.006365422116363463, 0.1204026175721976, 0.125722416995956, 0.03865674591865399, -0.0001228620998850972, -0.06816612415831065, -0.03365741691324027, -0.07613321112893839, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.851490093348759, 5.320051320277479, 2.417643700741916, -0.1995237653475895, 0.07621645201183533, -0.1771833255682829, -0.01078146896182771, -0.06438976299009525, -0.2876178310323119, -0.006303714018374637, 0.356885069902641, 0.07024283797935846, 0.01881395860270091, -0.2092513663311028, 0.109718092264327, 0.02854685307727969, -0.1312757974509329, -0.1108285734230257, 0.05182740468109521, 0.07233132504659899, 0.05030539452868459, -0.06059975102985716, -0.2297336103700467, 0.5045083042485633, -0.0004325173131309776, -0.1784693418735473, 0.08394922707081144, -0.2680843663012994, 0.2671400195308918, -0.001793550843300997, -0.1325105555633781, 0.07300804882966573, -0.06897110118534086, -0.2665451791081322, -0.2630899900703882, 0.04369816343226968, -0.156643286665005, 0.1549466071737415, -0.4145076724124122, 0.07488318920361078, 0.1419270611119949, 0.1219043619914908, -0.06378625947413261, 0.08917372812331978, 0.1038377550424948, -0.08072252702869862, 0.009394294196957323, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.53934911433842, 3.08124689760215, -1.480395561682393, 0.2462776680494332, 0.01710234467080554, -0.01750922521427385, -0.08464899612469672, -0.08513339146210799, 0.1497690941692451, 0.2003583687026345, 0.229975304279735, -0.06773544482684146, -0.212962762165994, 0.100805918257745, 0.1387021642494545, 0.05756587177820099, -0.02342135307890196, 0.0413142771758164, 0.01012070144816604, 0.009465626383560421, -0.1768890665508353, -0.3114326451294799, 0.334908331740353, 0.1454336469709651, -0.1253099733433882, 0.187117750616515, -0.2556659183272817, 0.05828504568732875, -0.09923486906264152, -0.01295943412712868, 0.04742766192450461, 0.002467967102260226, -0.09546651038888934, -0.3163510329005083, 0.1861927610821425, -0.06672987133018268, 0.1437750260846377, -0.3332140898455062, 0.07302040974957998, 0.1701107028641413, -0.01658898261297759, -0.05269690883993056, 0.1563566521838276, 0.1337720630335788, 0.01368561538114742, -0.1213888256015452, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.307203302598592, 2.885610538012057, 2.250703368751336, 0.07975315762421138, 0.09370441866373114, -0.1923654024839493, -0.1853398422580131, -0.201205128559576, -0.2125042330970577, -0.1602582952706193, 0.3093660817821342, 0.01852414315637842, -0.09255035727223564, -0.1924195495982953, -0.1559361270247578, -0.02917817624329287, 0.1447862761755991, -0.04690491601291951, -0.1960912348494043, -0.2042284966615884, 0.05841637536106218, 0.02291485689303238, -0.2827174856981686, -0.2943255892311636, -0.2215807563938077, 0.1152617438267267, 0.3936419107039491, 0.02096945169954771, -0.02252698024658075, 0.07773344380322408, -0.006443114230257507, -0.03639999246001423, -0.09084547229099375, -0.0397561686169364, 0.07701104659075265, 0.005605523155556855, -0.09348135695481166, -0.03124263128081152, 0.1542717927672431, 0.175465847613986, 0.0572413755901381, -0.03334819451365621, -0.1404348146594518, -0.06481871409417514, -0.04848557273226619, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.221221516792545, 4.982054100250426, 2.183210516233156, 0.0908360095708884, -0.3019054223643021, -0.5366128211639946, -0.3196918354703204, -0.1253970246067154, -0.02164532399684936, 0.2556280160777759, 0.08182827430850881, -0.03680716913431671, 0.03290225595516987, -0.1262131502004158, -0.09569394699109128, -0.005709824337923843, 0.0821878342740492, -0.1407748396690034, 0.09719614879475127, 0.2301897192422586, 0.04576646414789445, -0.2184893983754594, -0.2792745493536102, -0.363844809151781, 0.3257684950525028, 0.4790184968677053, -0.07652744991329491, 0.06377373985106835, 0.09437678117499698, -0.06131442314952967, 0.1635757313451941, -0.2796573282080887, -0.05643997532345108, 0.1152912068418917, 0.05000521333406865, -0.1112720969259657, 0.0037148809503484, 0.1093948420140112, 0.2980235424512261, 0.1525445958488788, -0.1264302662462978, -0.2913624335279468, -0.003113019822754165, -0.1134308899923566, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.400474057942684, 3.406090954274398, 1.166212384143174, -0.2629422439993046, -0.2702044042321645, -0.06636757078595552, -0.08446798536159737, 0.1313648786119294, 0.1193846426124598, -0.07246210384479049, 0.01554276290017705, 0.07103237282021825, 0.00101034194025556, -0.02392135193032525, 0.06952201574673418, -0.007400528848880757, -0.1551607153718201, -0.1651416045393484, -0.0721038672300459, 0.1237766596982622, -0.03361356917856322, -0.2622129829975602, -0.09615056687603316, 0.06891513871408637, 0.2914707059926323, -0.1250888357080352, 0.06761344442133146, 0.0799843533260796, -0.01371538646021322, 0.07103228925121174, -0.3405952917653196, 0.09927170088586629, 0.07489758155119226, 0.08314980277563824, -0.2366684526630883, 0.04202882159469431, 0.2074629307377897, 0.133356144785867, 0.0637264741453499, 0.0308975379082297, -0.1084379405587302, 0.02099441886765496, -0.1808400593316885, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.086464017862694, 5.114621438496568, 1.930881617131408, 0.1620245301097141, 0.1255287200617495, 0.3368622640783234, -0.07183251945541429, -0.3012926287551759, -0.1116975660537743, 0.113190686135744, -0.04910476738177835, -0.0465386985036234, -0.01788084091497165, 0.06748386592535341, -0.02381369375912231, 0.1493221788544871, 0.02579249903686181, -0.2497357621560777, 0.1787366301893779, 0.1598754145183457, 0.1674188524026742, 0.2477399099122946, -0.3340328954217437, -0.2111911479084411, 0.05086712720251271, -0.1292081829605008, -0.04302551258734066, -0.04971415251604733, -0.3610534332063385, 0.1892568833309398, -0.04472498978753213, -0.2065739236157566, -0.02046944574279112, -0.1756213338724003, 0.07793636245748489, 0.001237377976353086, -0.09033779335999018, -0.160410772384528, 0.08626890948440605, 0.2182749871373348, -0.0838793833068209, 0.1464287335113856, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.723745364788649, 3.894040171351998, -1.604023474297945, 0.3564682842321129, -0.068601028463067, 0.2723514789823699, 0.1226064004710703, -0.1014104100043627, -0.01893991862852569, 0.08732928681306741, 0.1555840779063216, 0.08897747453791588, -0.05848831483689518, -0.0484062742636184, -0.01943252555803195, -0.1897987807964078, -0.04208301117450661, -0.05303588371252462, 0.1133610703860842, -0.02273323404597872, 0.2540238415394855, -0.07855533407962875, -0.06507240945437587, -0.005499676266161271, 0.06537585217565781, -0.04778965574559299, 0.03306331390850831, -0.03674334203422738, 0.03096742123062764, 0.01763537013767625, -0.02727086473016628, -0.003088168719969086, 0.0435625544938414, -0.03476926734733601, -0.03196005989505435, -0.1419829052022682, -0.06959993690169985, 0.04835942714075128, 0.06791350727690673, -0.02769231996290041, 0.02869640238709043, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.887735910703242, 2.376861553923156, -2.059488107339375, -0.1636149309402013, 0.4041266030614025, 0.3896070591189961, -0.2297552131134549, -0.01184707906318158, 0.07039303277467518, 0.09925344398529366, 0.06695981045037805, -0.008491592697259171, -0.04552531630716806, -0.2274274932314481, -0.4148399842074417, -0.04458879883972757, 0.1297363092206598, 0.006733546690957063, -0.3384389296777096, 0.1168946778492827, -0.005399720520138511, 0.3552679244548678, -0.05369187330796665, 0.07272949240516048, 0.04205583963833656, -0.003676655566636833, -0.02270378608066365, -0.2966711461982461, 0.02934135424925877, 0.02865469879716708, 0.06673230222014637, -0.1838317311908014, -0.004436962897364399, 0.1509614176408774, 0.03376168246202512, 0.0005117826261220852, 0.04498835681575293, -0.07866868520578868, -0.0334252458798712, -0.08545921183065397, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.342190295905557, 4.675687708808497, -2.268183880250829, 0.2090893331762786, 0.4578770822708127, -0.01884304914244323, -0.07920602266213114, 0.05860045842795304, -0.009411964143128677, -0.009484130845488712, -0.03376087164847531, 0.01728654546382909, -0.2136063948857168, -0.1250583122943451, 0.2295451258972967, -0.06031125891810103, -0.1745972831925295, -0.3612966512867564, -0.1696417690184429, 0.2894160200659208, 0.5167644047563161, -0.08805909441951841, 0.1382094329850753, 0.05099565505493066, -0.04533499187369815, 0.05797820328595679, -0.1922533222149581, -0.1102035618550493, 0.09431486137300341, -0.001494148493882944, -0.09571326182532253, -0.0247601912770405, 0.1256667582306468, 0.2120425181347171, 0.07968400246820299, -0.09760118083265475, -0.2941239252154335, -0.07105438440442044, -0.06896304227007152, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.005975891768637, 3.352830695220589, -1.754960054860547, 0.1623709029576712, -0.01686728241632605, -0.03827200221784547, 0.1561794350456731, 0.1402911103849665, 0.03386692126036084, -0.2383508690881479, 0.08335746314476074, 0.1222986332072196, 0.1365597783993524, 0.1833332391744543, -0.1153402862359182, 0.06132285746330645, 0.103916564083423, 0.1352942358705118, 0.03751837000428822, -0.09780641373392215, 0.01802532012439729, 0.07461290579154131, -0.07340909507755823, 0.0263628669211833, 0.05634194666559207, 0.1326983203399266, -0.07526750794049826, -0.0255602869082238, -0.03079487759048528, 0.2087632832461296, -0.06368900481673745, -0.1885028988850317, -0.09938432303399658, -0.02813603601003281, -0.03116773548046878, -0.01139744596335172, -0.007527417596076127, 0.09996642926056981, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.005352340672642, 4.225811150115511, 2.31447703108509, 0.2404320758625818, -0.1026845105793418, 0.09323203523714457, -0.07188013661735847, -0.04900547068951503, -0.01143900704943617, 0.03127208944683336, -0.1422425637959582, 0.1223555755457385, 0.3629752163517811, -0.1439880981371962, -0.2053548592359871, -0.2670448469719894, -0.2854950646499647, 0.4890836381626159, 0.4252198149550604, -0.04903353665384676, 0.1440097216561384, 0.05263434485402999, -0.05654435812537717, 0.2744897997285071, -0.1869384630385859, -0.0801988284405884, 0.1415754714387316, 0.0461903176790022, 0.07292418854739299, -0.07749396692418822, -0.01197157575397448, 0.2335354584093252, 0.1565196693950396, -0.2175672539551863, -0.294898244011832, -0.04250817996099358, -0.06254226634319582, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.023207199521003, 3.695034404904957, -1.278828575213463, -0.09576460539931182, 0.01293341047109737, -0.1025508423146749, -0.09879959800395338, 0.1293868360344177, 0.02661187351571312, -0.03208813036911215, 0.102284173268301, 0.01897487699556174, -4.171607187027272e-05, -0.2343929177751728, -0.1591895912128799, -0.3479923586821921, 0.2266119442104414, 0.1369767045914879, -0.093264948471121, 0.05584513287015452, 0.1113848723095114, 0.07805629549261404, 0.385159500396428, -0.315090514425508, 0.2619076486635123, 0.2100336864909587, 0.1489157028437222, 0.01899500010404414, -0.05839538028607237, 0.1065294735286251, 0.1429581389759609, 0.1768187396519744, -0.0107077164022975, -0.07184487656799306, 0.1053566314912159, -0.2656344309369447, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.535179041441933, 2.927516278644585, 1.069440149410428, -0.1940154888240462, -0.06435827084629098, 0.03118119256124731, 0.2144814653940334, -0.1459984300204726, -0.01884883111449459, -0.0996859848375896, -0.1929505482810151, -0.142915066638186, 0.04595119246484281, 0.09181030791542119, 0.1046793740137302, -0.1631714112553374, -0.1533173188313381, -0.008178614876768846, -0.03838516939058051, -0.04628352128726964, -0.04001834958725597, -0.3727398948175817, 0.349654467351177, -0.113952499262497, -0.101339746891288, -0.1603850568927218, -0.1309942015965596, 0.07772040042527674, 0.1275463112280693, -0.04252979249843156, -0.1408252690486143, 0.05191953638235136, 0.07165159166941262, -0.1158826338243819, 0.09369294636414835, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.042176179125399, 2.455373013093171, -1.298065125007905, 0.02028671121404909, 0.003306962463612291, -0.1036220220710941, 0.0481345337164661, 0.03315299260062861, 0.04992516180471544, 0.09592872957586211, 0.03096020094331417, 0.009903127869262564, 0.01875056235671545, 0.03272160535846057, 0.01927852349784328, 0.02325854762506147, 0.04608264369572843, -0.009983430343303928, -0.01609838886434818, -0.01003965210423024, 0.02113424938210403, 0.005924265966984703, -0.05179857793569453, -0.0244630676591391, 0.01057802494355381, 0.0691716202360271, -0.02554792020429601, -0.09556309673821282, -0.01109440159507958, 0.002795432770742045, -0.03608009327148794, -0.009904492448746673, -0.004701473084555832, 0.06319402826809284, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.341422080029597, 2.641177760807674, 1.591936295305328, 0.005262995989819829, 0.05712969006064635, -0.05864522459107201, -0.06744950477663363, 0.1271503047471045, 0.2094260695099903, -0.3057531846245879, -0.04037395011724824, -0.02967432474543921, -0.09059292764118339, 0.2862509429106201, 0.1048474566793039, -0.04995247127231636, 0.1184570436074571, -0.03693842645635304, -0.08306079853122639, -0.04945597334476677, 0.2089393586111927, -0.2028924047636768, 0.01499186002602688, -0.1284371246539898, 0.04369426140288886, 0.001107629872198076, 0.002549707872053236, 0.1030701664382734, 0.002039801798898688, -0.1568979174791054, -0.1881891997896287, -0.1100556548512126, 0.06948313266853789, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.629047221760682, 3.633220763136687, 1.407673550411567, 0.0339033673171226, -0.0440877649168133, -0.1309350154964067, -0.05292438726218229, 0.1243733326688556, -0.09611554125353661, -0.01801557361391788, -0.1394535956650391, -0.04800585756898997, 0.2092817652566071, 0.1937706427881193, -0.0316202819028252, 0.08185853657036937, 0.008847184587817514, -0.05390183527194951, 0.0500718698457836, -0.06277970709250076, -0.07596180328240805, 0.04008159730086977, -0.0124923156950488, -0.01841127788787308, -0.008904456301771634, 0.02894837811492813, 0.08379155755674296, 0.038658741027786, -0.1013410184828959, -0.1363862936525638, -0.04609547972146647, -0.01057837708981668, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.387217368144026, 2.728722184696696, 1.424749145313089, -0.01601470906433309, -0.07512459959692018, -0.101188344036713, -0.003441549977747002, 0.06449001937611275, -0.03196276224536809, -0.1213336580505604, -0.009099515848609243, 0.02592480117875633, 0.1486227237292286, -0.00133150660633606, 0.001532054214242922, 0.02645122343613796, -0.01679939752946042, -0.006472860460697598, -0.1046070432475455, 0.002013525317899786, 0.007407876301716394, 0.03426066213629017, -0.07238247076893806, -0.002515176653231992, 0.04897218815805249, 0.04708726516482133, 0.01321800810118652, -0.0106268999083793, -0.03069342204089823, -0.02184119543907794, -0.02064865378574994, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.391700331330132, 3.10873390469995, -1.005261568422076, 0.07033689862768554, -0.01130536743091839, -0.2012624886845097, 0.1894945671077086, 0.07933080126112255, 0.075305885120587, 0.07607468793519609, -0.2915128232499786, -0.05359107726226209, -0.0167141837673077, -0.09941630815355153, -0.003665007998583435, -0.0299234883671778, -0.3018441136613871, 0.06749072049202193, -0.04549007934188216, -0.1272169539451481, -0.04604367173781738, -0.2292387384782596, 0.1104667012348132, 0.1037443269592589, 0.003358877836343526, -0.09748118788274351, 0.1190372958872585, 0.07594840982846023, -0.02118200682737069, 0.04505746778768557, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.040421536922372, 2.090179325079248, 1.054133848546223, 0.1016135668098681, 0.1058908215655909, -0.1395436464948118, -0.0005843093291569908, 0.06576578822426617, -0.01954438761767608, 0.1340460322034086, -0.1079153000090457, 0.008558237228615952, 0.05442003661392834, -0.01948493437734833, 0.03204864462372618, 0.1899187419163797, 0.02651889944688371, 0.04143699821901681, 0.06155302263071664, 0.01361677379827648, 0.1864345911285355, -0.06057118267116334, -0.1079059175548875, -0.04926446070686546, 0.04450551753882914, -0.05461151981988153, -0.001886612406799282, 0.0366915411934175, -0.01306027401322379, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.017217105119183, 2.057885109672617, 1.717830826909398, 0.08026860099733665, -0.229664599517274, 0.08592953162584042, 0.07113555573927616, 0.1205711964241209, 0.06034607492733832, -0.1241960272046997, -0.02576402132560143, 0.100546870611732, -0.06664178017945782, 0.01551828302018928, 0.01075203286396453, 0.1648555544266941, -0.06180621835112392, 0.00904698466380283, -0.08614048879659969, 0.1377785336580386, -0.02458732719586508, -0.06527069420169623, -0.09919539357362668, -0.0371614630248139, -0.01956332576116701, -0.02610087976547117, -0.01636500296481732, 0.04290323999519369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.73126542682124, 3.177372305562633, 1.069892746405991, -0.3373448837554265, 0.04914183280708707, 0.2222099960511715, 0.1000273467845214, 0.02495153836835336, -0.2988822213671982, 0.09070115558214502, 0.006890792477648951, -0.09774415864582336, 0.01733122536241725, -0.06539161565511441, 0.4180846670181008, -0.1348357420052125, -0.01486736897403777, -0.1707564509631871, 0.275788236310813, -0.03928409265616119, -0.1437568066337482, -0.159713937527644, -0.06441082113320754, -0.04838713636560495, 0.03935472474969938, -0.03034455737023176, 0.1502866267461562, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9860332560182929, 2.457690638088044, 0.7585454975233088, -0.1838919851966072, -0.04382890538941454, -0.140552844264958, 0.09130507944212898, 0.001128260213507534, 0.06804648176327489, -0.03968302808799389, 0.02820745088433483, 0.03697025018803624, 0.06358690037762478, 0.08600302483044212, 0.04484515559448902, 0.08149618479019373, -0.008400294556984093, 0.1073491700579635, -0.06306885174166355, 0.02287587454966997, 0.01464609607772943, 0.03996572206258068, -0.03555777800156044, 0.01763122405260091, -0.01550330692085902, -0.021886735564678, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.8854567164260388, 3.24250422074227, -0.9209580946507911, 0.06835402983935927, 0.05640958121017869, 0.1025591786485125, -0.08943334614410312, -0.06811365067010508, 0.1109007141056824, -0.02177056785348171, 0.03875431100769289, 0.2363367275176182, -0.09273940436583276, 0.1105048998268415, 0.01324218642906586, 0.1204923454912281, 0.1300264818238509, -0.07418265989085007, -0.160155156583538, -0.03336518282890372, 0.03274839794300601, -0.02988917934624772, 0.0313012656489897, 0.02783060486964485, -0.03014058011457086, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.9647900465381067, 1.776310496646176, -1.171438051631132, 0.05140489138825926, 0.1299377347834004, 0.2201816497369831, 0.02994176320228855, 0.04558225788991847, -0.02505795321566107, -0.07354754829932028, -0.07990068462027206, 0.03705853127225793, -0.1892721965231484, -0.0414104999094905, -0.04365760163266805, 0.004082206348271171, -0.01640857151771855, -0.04917783956511107, 0.05677253037720179, -0.01538028417587433, -0.1057997510635607, -0.1262079630007641, -0.09383731776836683, 0.1119867440818691, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.059667715135062, 2.869444516413392, -0.768053436705612, -0.01982926570738622, -0.05898277292649027, 0.08032989813585734, 0.02430925291918696, -0.05541157112738762, 0.01387900032498306, 0.005672434099991189, 0.05365330433412881, -0.04355934883978447, -0.02337398496984892, -0.01686799971841361, 0.1422537288231567, -0.05666452598379437, -0.1164424129736735, -0.154242271156826, -0.04516863877735287, -0.01545725267339097, 0.05268933296374621, -0.01791535900714333, 0.08893369086218253, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.006637453830663, 1.684689844069783, 0.9123803878361401, 0.3537494043954367, -0.0934425457654232, 0.125950163184819, 0.0008929568569579045, -0.05163443135049815, -0.1076491218622526, -0.0453578935139585, -0.1495191189316716, 0.0001415820705124262, -0.05006551799497391, -0.128789667082152, 0.01100316880829279, 0.1037355563583926, 0.1230844198081173, -0.01355995466456035, -0.04069963982836227, -0.2068443754239467, -0.100425014495166, 0.005750041723483063, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7847696566083294, 2.188950883712381, -0.6166420348084849, 0.05427293688357122, -0.09172120702478551, 0.01394828380275868, -0.04214925628047594, -0.2002409114863903, 0.2374547253440619, -0.07586414645695061, -0.02243126761233804, -0.09086994858618591, -0.06440645239833823, 0.02923240705539655, 0.1008328000734136, 0.0681346127852103, -0.03404818684407405, -0.03418035480719885, 0.02177303810889437, -0.08932854185081496, 0.05516897717457826, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.5961213393185251, 2.487671728233433, 0.9779431494823534, -0.08808252008539449, 0.07346845556012158, 0.03791477768403206, 0.1133987101884693, -0.04867168124335965, 0.1007529815412284, 0.07012067318801543, 0.04686393658752402, -0.007976030601315085, 0.009647274715336393, 0.04388047564013912, 0.1448956828911585, 0.09593976527370232, 0.01772056425810449, -0.01920422214800561, 0.07683802973941063, -0.09812807079543846, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.990432056210743, 2.774709587520062, -0.9402258848421475, 0.01395715665576621, 0.05464370856162152, 0.05969855937401768, -0.09840756262028037, 0.1283282686407038, 0.01393286908802421, 0.0953055258318351, 0.007548139187554635, -0.05906283649224034, -0.0006153285921519075, -0.05497497151651637, -0.008769303020395835, 0.05051213594154082, 0.09095589353294919, -0.006367749500199228, -0.04367472066475442, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.9556547348028801, 2.802801220763579, -1.059088183997589, -0.06046741386547052, -0.109550403372664, 0.1079992883617651, -0.1303209308383404, 0.005273660747274722, -0.103872667440789, -0.06600322769700166, 0.05217402045757749, 0.08518450366824531, 0.09805210958705181, 0.003600709399162004, -0.05665622206864503, -0.1159528275969711, -0.04404155725184447, 0.02203210385909037, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.063540216854957, 1.744535368562572, 0.7905163601870416, 0.02656379893207305, -0.007035839152219695, 0.04085917849823771, -0.009245974538993987, 0.0249953312582957, -0.003223257434620091, 0.005723442767043741, -0.01704173254774269, -0.006825269002180425, 0.001391384124621517, 0.005712500889522121, 0.03850120618331365, 0.01404973463460888, -0.01209325063900243, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.788177934248775, 1.912200014248186, -0.7537507368298558, -0.0661262783848291, 0.05943707989564052, 0.02061524812146071, 0.02585592085441167, -0.02083197113611205, 0.003987942029650998, 0.02210665757083753, -0.02360486919891839, 0.005051227537696999, -0.0006754747654496297, 0.01013804196323632, 0.01058372156918393, -0.05401144478196152, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.8186713915600072, 1.708711700739236, 0.6332443934946002, 0.0347014944537665, -0.01300019502207845, 0.01605786260146845, -0.02637192977655575, -0.02304218343188766, 0.02296628976143508, -0.01424547177831386, -0.03972717940911979, -0.1167021874016301, 0.06633764648895558, -0.1293541599290803, 0.004742672723613311, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5157633499563469, 1.976352201317751, 0.6234503597941091, 0.01391296633390046, -0.07272602653366068, 0.0140570704220571, 0.01336752650183375, 0.05902767787103762, -0.08819062077742636, -0.02551451255772886, 0.1312142929003566, 0.01369744243814129, 0.06473360298498254, 0.01231850487143263, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6533080656351744, 1.758802439425837, 0.4318871049206415, -0.003082957500133511, -0.09814169758462682, 0.04175539354758488, 0.0235289164184994, -0.01629543995009982, -0.05231016932343414, -0.03672204848733453, 0.009389336932342413, -0.06142381433250257, -0.01010858967311151, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4817927293509213, 1.408851322535897, -0.7676055176021872, -0.04505523423060897, 0.01813562786331449, 0.03138728238085502, 0.0007373169379419269, 0.001847667170281647, -0.01640431370966648, 0.04696818974656805, -0.004393748298759055, -0.02848496648956977, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7883892138973269, 1.746055173045302, 0.4846783430365095, -0.0003922243062844435, 0.01186867835550373, 0.01648380387048428, -0.03174672656471393, -0.03627511739090696, -0.004853687188112606, -0.06885884936290802, -0.004917829299265958, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5208363315616994, 2.037277859382022, 0.5232085356010402, 0.07175407188317283, -0.07019064479939288, -0.02385694223436976, -0.00819063541887864, 0.07192359009199149, -0.06656167507443485, -0.04927759893361527, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5819314677010843, 2.130167978098713, 0.5667361680393177, -0.01053764587057425, 0.01592751856907668, -0.01111604356574088, -0.004404610058468247, 0.03850545663289814, 0.04729794670040405, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6488904808178829, 1.974426530381294, -0.2820471741701222, 0.02456494941736511, 0.03486280653024869, -0.01809831529884736, 0.08408521068644187, -0.006474401058818371, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.3312307167387429, 1.235934836863219, -0.2452582871525679, 0.01878427096720662, 0.04975840840483642, 0.05672553943361373, 0.01742942062643791, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.2654365696129733, 2.208256891929066, 0.3360201888498769, 0.06660725081463706, -0.01286437627536736, -0.002070231898763094, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.3639062481633207, 2.248588741393716, -0.1889980205327704, 0.05688507493685012, -0.04579504315826421, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.1624755988486198, 1.590085647221482, 0.1168533202179821, 0.005293082667091636, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.173908380119132, 1.450043378319349, 0.02765965035599782, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02984095753646376, 1.759629990218614, + }, + evWant: []complex128{ + -0.01716884621227793, + -0.1844331609734137, + 0.05200651487352193, + 0.1336851109127556, + 0.2020936631953806, + 0.3566470363060668, + 0.3627207699831158, + 0.4388555152488943, + 0.4776853636435153, + 0.5598821450074998, + 0.6249350549980947, + 0.6791310689291772, + 0.985877008147705 + 0.01929363300192029i, + 0.985877008147705 - 0.01929363300192029i, + 0.9908483217835712, + 1.011990761364073, + 1.130046345264462, + 1.323698071765709, + 1.348598229483672, + 1.363190626641638 + 0.05400660173350781i, + 1.363190626641638 - 0.05400660173350781i, + 1.632832316477256, + 1.646239548684271, + 1.742738908029794, + 1.763069014878969, + 1.789601126186348, + 1.945228042429256, + 1.946373262056993, + 1.997152389795002, + 2.261322781594966, + 2.286944100979884, + 2.447712649969029, + 2.557857506923634, + 2.608379034892128, + 2.653335615965549, + 2.675270309760236, + 2.964219802766918 + 0.01767482509567778i, + 2.964219802766918 - 0.01767482509567778i, + 3.014604817775139, + 3.158289371199042, + 3.311794215710077, + 3.389894197376214, + 3.553333074879877, + 3.641274442796651, + 3.857556223000175, + 4.045817381029103, + 4.330901939363569, + 4.337313647767939, + 4.527400487637496, + 4.917229128467305, + 4.985609414964091, + 5.687686849958608, + 5.79422309012183, + 5.997813119506478, + 6.732426637899077, + 6.957609338485607, + 7.529842664573327, + 7.609108287806763, + 7.761261355516287, + 8.311941758006698, + 9.07053741884884, + 9.217944588000314, + }, + }, + { + // TOLS90 matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix big (n > 75). + n: 90, + ilo: 0, + ihi: 89, + tol: 1e-12, + h: []float64{ + 0, 15.87097792952162, -0.08018778146407576, 1.923854288576926, 0.2308884192434597, 0.3394611053158814, -0.137843056509317, 0.08273319299962868, 0.09094485832017182, -0.1932984706702652, 0.1180502933247899, -0.2497600660136686, 0.05058238526630414, 0.1559958264692184, -0.1159258671363344, 0.009240657808439554, -0.07576925270220009, -0.08136563335139357, 0.03812188405626555, 0.08890970810264923, 0.03109600803532232, -0.01649595143487545, -0.03210884292964193, -0.06264912164116895, 0.02576130685189339, 0.07030469513274047, -0.03577429596420342, -0.06755584096587573, -0.01609449751643862, -0.034609250889499, -0.006417485131372289, -0.03097242984568944, 0.009636702832094541, 0.03557221482377193, 0.03197869740177413, 0.006433398911967483, -0.01135683279223704, 0.005555822920782794, 0.005082647305173025, 0.009385366191684759, 0.008128896608623586, -0.02296712755081439, -0.003777413820214802, 0.005123235117691023, -0.001849213959133196, -0.02340110883416673, 0.03713005378535863, 0.001732375396842803, -0.002750608017025007, -0.008067437745595896, 0.007330916864526544, -0.002616316716217023, -0.006297132815168344, -0.005559964495164493, -0.009996463242082429, 0.005115046921377182, 0.001491016327339477, -0.000957347151456719, 0.006745577006930539, -0.004544035710017501, -0.004411949528299773, -0.006799740101884459, 0.0005344071027975155, 0.0004690847920096184, -0.004718575501368472, -0.002540214169642457, 0.00357159293854215, -0.003314789809413553, -0.003402372051470523, 0.0006527769815598059, -0.002716170091878954, -0.001540321517093821, 0.001756589868588563, -0.001379260966541515, 2.681259838616508e-05, -0.004307760317855304, -0.001109087032949234, -0.0001659937040461595, -0.0002235436314482387, -0.00119569899683125, 0.0005623327348935116, -0.0006320070189143994, 0.001043573892153891, -0.0008750118344396425, 0.0005348270042878935, 0.0008273143853381587, -0.0006622544067919339, -0.0008492128694001077, -0.0007986665099336194, -0.0009015882205421384, + -12.61872336344661, -0.7232497785660141, 7.609159226285555, 0.3870426982100038, 5.924856640096555, 0.6102682886559223, -0.1693535996869482, -1.919018099340693, -0.2138609560373459, 0.8042623392399718, 0.8674124147325857, 1.331963567449537, -1.782290696158441, -0.8346237530841022, -1.552156412468403, -0.6151273144224881, -0.7391936693539152, 0.9311934770410842, 0.6166024938842418, -1.54644771695033, -1.776481997993627, -0.934164018650274, 1.955449870926906, -2.082936149197492, -0.222464503236819, 0.1331142802435182, -0.7633944660137448, -0.8176194198678164, 0.2746498608375185, -0.1119720547510174, -0.3046093297897633, 0.093708523663493, -0.1254384253653835, -0.3826156782538976, 0.9720657328245648, 0.4435611080311743, -0.002705519800257373, 0.4068502033494004, 0.8228026417475635, 1.898141183528268, -2.19419418629088, -2.26250233043472, 1.169369389476936, -2.320900757809857, 1.963641620262248, -0.9292511308866737, 1.20566753941007, -3.909359844030778, -1.745106869690986, -0.1674293744185332, 1.824325508201922, -0.611032518780414, -0.8172751651339325, -0.379367811436249, -1.118039132172379, -2.1156899896767, 0.6317312221182597, 1.675601832555065, -0.1958681401344015, 3.202902011360347, 0.2083144054490269, 1.651454396883902, -1.879950006164014, 1.114962429097019, -3.728120039552464, 2.115800549383747, 1.993994934513307, 1.036800346894651, 2.843012388647532, 2.665528597975866, -0.08443708961414848, -1.658265513220315, 2.825691629937317, 1.163068598831327, 1.032612155987785, -0.3464359914213002, -0.7374155713124153, -0.009825846309687306, -1.878310233217088, 1.038183449333641, 0.8683442149070821, 0.2096953654957043, 1.097533010763627, -1.40566207568186, 1.539718090250373, -0.3057191046244732, 0.9596910019319377, 0.4410690813618931, -0.01734977865916698, -0.7028527205475527, + 0, -21.14096588949502, -11.77071611766029, 91.38817973790069, 24.01994594814793, 7.139034668143506, -7.77684013545977, 11.8189112903465, 4.350214240774185, -13.41161300072837, 0.8429515510200203, -0.1960485971162483, -1.892239827255886, -2.481138864200454, -4.993335484535367, -1.462743953230215, -1.649744938703439, -3.306123402194819, 0.6299802354863298, 0.006312776908129815, 0.7029217322720615, 0.1969979096896496, 0.6484394805159026, 0.4612739081461551, 1.218623710778157, 1.937283920899595, -4.274393204137636, -1.417028232311232, 1.761975679896983, -1.207846701077455, -2.947009378633724, -1.111456928119195, 2.001483835367479, -0.3273985739357373, 1.27142153234808, 2.470518283440578, -0.497592748085565, -1.01776837453108, 0.1736631347448449, 0.2170284795451557, -1.102797734602059, -0.8983239378242805, 0.8376082516437703, -1.015605628895311, 1.888662040615523, -1.813946159105028, 3.745871277192266, -1.691058864813766, 0.5544744103796291, -0.95962769863539, 1.495178118153111, 0.1369976805376806, -3.134133785033962, -1.134766199832475, -2.142472928604951, 0.4360359463007911, 1.080773790484485, 0.9136687613609559, 1.421868877932455, -0.4939788885367615, 0.01579620756278606, -0.4041188740514539, -0.3370957888349073, 0.4032844546374829, -1.281049156842126, 1.334866305935072, -0.4288161314791398, -0.4076960827986253, 0.8975402184760907, 0.008483305617251051, -0.02300021991545602, -0.4779200297205075, 0.8640559542693361, 0.6740166979504152, 1.271173988705413, -0.125268363712917, -0.02783785192682384, -0.7952831181002197, -0.1834134462936435, -0.3033906534395994, -0.1842466257842833, 0.3294577790658342, 0.4265858101126394, -1.050551059782219, 0.5557053448408287, -0.07549099980078718, 0.4485085972651929, 0.604772326452039, 0.02668915155289681, -0.35958437456048, + 0, 0, -71.67241414253803, -12.6925239065222, -58.51026881403752, -9.923972440030834, -18.08337737101079, 23.73437311293314, 10.42624729020936, -7.39628437264571, 6.93334510855383, -16.20186028661058, 19.09098951338167, 7.231158491837533, 25.86051183536314, 4.692849852643402, 13.50562601772541, -23.8959783279092, 10.46795736800158, 26.42552249365325, 25.55147405605497, 30.98455252329583, -38.26426057779729, 41.72459242758727, 14.01187370572939, -9.227025126956866, 17.69341876066779, 17.7058942448478, -13.2182156659012, 3.273277215940703, 7.82096407961303, -6.540134857551783, 5.302726399754003, 21.6168229759513, -35.45773268931614, -39.5771763658349, 16.91907564224343, 16.55810765769962, 10.84170890675409, 4.539182245882841, 5.966139065523301, 10.43624249585104, -6.306944364017387, 25.11309378553394, -23.98463112536712, -3.253554932408899, -26.20327820737005, 34.95346757431584, -22.06848426488626, 0.3787905650745691, 12.79793983153946, -15.15662916810503, 30.10820985389998, 17.18239253486946, 26.44238280127885, -17.53916820777098, -21.59984930800645, -20.89069843604591, -10.62614963929214, -4.16861219455282, -15.8281632392319, -15.45413424684084, 7.28126264287692, -17.30978445489622, 25.83878482866339, -18.20409699627451, 1.341279973912325, 6.060701390094514, -0.9930555858249585, -0.4770067839263625, -8.050723322366107, 15.00633993006825, -10.12301020599794, -15.02267685265745, -28.87546819977945, -4.887384695963816, 3.812851132430744, 19.10682316350844, 7.478580657962908, -7.486104775378393, 8.24517564743228, -7.51905558097683, -6.644004835040043, 16.04319982377311, -12.24015636297471, -0.4152718733052826, -15.37260980717165, -14.36579932723399, -1.30513875795791, 5.356894027365968, + 0, 0, 0, 88.73441744471468, -9.667604704172753, -22.84943872004879, 5.044285909895449, -2.76004875036668, 0.3050715430090338, 2.281066203460998, -3.081685045157843, 5.563173468318147, 1.196920824152984, 0.7508125732458136, 3.261490552895722, -0.1915889730517104, 2.178042983750966, -5.719722606964433, -0.808717831824074, 3.567750315780947, 4.405620166473985, 8.068713509838501, -3.974147763943233, 4.024558504483837, 1.343369353638846, -1.554164148226279, 1.397410693322202, 1.549071510171349, -0.6861822032616559, -0.03144220974090741, -1.503375319686877, -1.213563509509453, 1.485658175240746, 1.102628808733887, -2.836353822887371, -2.651198571403894, 1.944770277514162, 1.800720538730825, 2.925044559436877, 2.489394773406274, -3.99962439548742, -1.365153890760246, 1.729186611640552, 0.90732580595284, 0.02970965138899272, -9.802670261550649, -3.377885239589956, 3.311681996737421, -2.102890043550365, -2.752571666784161, 7.725320034635699, -0.8099349955071451, 0.5680350525364315, 2.461090824551101, 1.671002962178604, -4.651796111745832, -3.019627268376409, -1.456848301794733, 0.6765376227892419, -2.208873565004413, -2.755468168868538, -2.723938546851782, 1.844529360647301, -1.962817053181678, 2.77164872022158, -0.6312645341808628, 0.9959732581947718, -0.01141276076056162, -1.047045912982139, 0.9659655272370172, -1.069371622104567, -0.564318267120407, -0.9606489624515147, -0.3731646049074267, -0.4361324066751411, -1.228953081985217, 2.112718903093324, 3.774673462225595, 2.038526286226191, -2.037134562294253, -0.6272498215703869, -0.9130826952549337, -0.5356753186936942, 1.739354952287502, -2.607676632661601, 1.167128690015535, -3.643945638175477, -2.247788469333459, 0.4447578257714688, 0.8814188227164721, + 0, 0, 0, 0, 35.22951028609684, -22.61691132174376, 97.10536643650998, -3.714742139430975, 10.06500336745724, -16.35785983037913, 8.78437693523264, 1.985132974393485, -1.609800726068471, 10.55631691645605, 9.224290477011534, 4.722637143581605, 4.125150731568718, -5.396683914299057, 6.364591301561367, 8.24526687743292, 4.911724566872895, 6.542687463438916, -9.348997687795265, 14.18011100433374, 5.720905431367072, -1.582673805208176, 3.789638114574857, 6.440267872588953, -4.901278147004489, 0.421175984045115, 3.797008789173352, 0.2579925025997163, -1.093437933585557, -1.126991905684307, -4.4057666178694, -6.4297958780832, 4.918610437583255, 4.893900733343752, 7.627382484342153, 6.943539836193181, -10.22700285291435, -5.21717606135954, 5.635670539663245, -0.61979670671329, 1.025327494294112, -29.98298952616265, -10.87852244502099, 6.724183768213139, -5.415447368170939, -9.131548344141406, 25.08685243604318, -0.5163094225162969, 5.436141320006754, 5.254969244047728, 5.189340308692745, -14.05566775803058, -3.790558233978546, -2.867451571946585, -2.265074057881479, -13.27098968249704, -6.419573660857155, -2.44809433119093, 5.262803237338727, -6.396156300345669, 12.9332727436708, -2.828158861124294, 6.494893307712784, -4.900718840392307, -12.17623988734707, 2.132680032576169, -4.239391092443586, -4.723934051879516, -6.984654958110764, -2.787156581230434, 4.744573069448925, -7.311973630803457, 14.86842763617212, 11.70461213488476, 10.92665646005423, -8.812367256417245, -1.725823238463376, -0.599065820210566, -2.268141253505947, 2.588966312561057, -7.560432899806777, 4.711500915754516, -11.63409451724343, -3.784667325499409, 0.9845255581998278, 2.917504056968942, + 0, 0, 0, 0, 0, -116.0630192746665, 5.887300060633501, -55.36418027265255, -2.470006763999332, 13.03531089357281, 0.1172864444746298, 2.336301687054243, 4.34928920056458, 9.106206444726951, -0.8318917014102636, 2.753642271658936, -4.563539972366368, 5.616802475300401, -0.4836767449615566, -6.113950704235537, -7.384788928153566, -6.850835642415652, 4.436028327150289, -4.972441466665182, -5.074617872073305, 2.249115729647296, -1.27635805087233, -1.815933433231301, 2.59978300016936, -0.5676863289525813, 1.704036354039219, 1.966949252223741, -2.742379099660473, -5.759265103182953, 6.226978264278319, 6.392620681348136, -0.2885756166938758, -0.2986490248004344, 5.021918870709579, 7.495865991102269, -15.19741578062141, -10.52747112766237, 9.21669911214595, -12.00882240945578, 9.449065100345695, -22.03792558203701, -5.042603937347324, -5.034444931509023, 3.887859743790752, -4.92423649287837, 15.14459404442214, 4.709447859501895, -10.68403398232012, 2.785222602001631, -3.955139727592788, -10.90921547327889, -3.836568621330626, 5.465232651370832, 4.568243480001632, -2.511523602459496, -0.9621054122709324, -0.6044291916789493, 6.467023010391031, 2.662510020284552, -3.203951737691022, 7.315143747841559, 0.2986491524564562, 0.04345879316587933, -0.3120127984400304, 4.715818739144954, -0.3713148742857386, -7.592585985711748, 1.251675665881772, 5.563320889185214, 8.934186230540199, -1.034540314919822, 1.499762588438347, 3.648805772901489, 1.867765342642769, -3.856064394520797, -4.257325323439929, 0.9065282321682452, 0.9958862297862445, -2.214139637816267, -1.516486450508368, 2.326410461051852, -3.227358821350026, -0.4749483061012461, 2.179821376672413, 0.1114550663371978, + 0, 0, 0, 0, 0, 0, 53.90645393584658, -20.01147603384238, 68.25945706992877, -2.001388852130252, -0.6303875033830074, 7.681723436887633, -2.793396522752484, -3.849646005163192, 7.47502807954784, -2.524396627852584, -1.112160063163965, -0.4457759133018216, -5.425351770541893, -7.213840725579055, -0.6234582007920942, -0.3045445372121888, -1.838748235944519, -3.05429610717454, -5.218058811930899, -0.3089178689448414, -0.07503528649101057, 0.1630591210001797, 2.58742687436071, 0.8589336965724809, 0.3026886986297957, 0.0616540381895139, -1.743768523575526, 2.75507802571559, -2.587808530052548, -1.25512695563184, 3.800814529165174, 3.132593897658502, 9.751967320860086, 12.09676139406092, -18.96514427687867, -10.33529268364038, 9.423861340153673, -8.118494925333524, 6.455831882458702, -13.89851030432216, -5.253096745704963, 1.482474561585576, -0.7990859267629726, -0.1919859569182034, 14.99486076662231, 0.8403897566592956, -9.631758825484061, 7.546859017133015, 1.761650219269993, -14.8002789790671, -12.03184495751378, 1.278761976352118, -1.043958743156598, -6.425946785515577, -5.130193263963021, -8.943747092721882, 6.884559516868113, 0.02054820847870697, 1.622114564484586, 8.27790706580309, -0.4201537658318323, 6.949197674374433, 6.109317458173291, 7.745771202714325, -4.383777284917787, -5.023236465266974, 3.152075902042714, 1.185720299074054, -2.570558625807648, -2.575936989524232, 0.7822876332433506, 11.50350236141349, 2.541100031822599, -6.266519860892538, 5.220802309799155, -2.7113287362323, -0.0782755292810481, -1.306667606835813, 0.9121698644456847, 0.07469182002148761, -4.645428950155893, -1.074584465997386, 0.6604539390114011, -0.1666067442015038, + 0, 0, 0, 0, 0, 0, 0, -85.98674061062438, 1.162623410299333, -104.1491535027204, 7.969764337327856, -6.932488858320204, -6.767747448265724, -7.331077471298601, -1.288550484452708, -5.088257375240862, 2.763979746955463, 2.528081478578727, -2.575430737963284, -6.921068854524492, -4.018385524701809, -1.579042698955484, -0.7534247768022768, -5.324588385519177, -4.241013196984152, -2.113061191594958, 1.678130424336868, -0.2888364599120758, -2.575220703265352, 3.435198525295604, 4.161688539607654, 4.731385858073858, -4.276207990137705, -6.32017796521583, 6.190217309330307, 4.183836067935781, 1.849953972589691, 2.606132984461453, 10.00029158683688, 12.0615055907306, -22.12319815923896, -13.94593423436807, 13.56355336723619, -14.73390655737362, 8.504539865599947, -39.98652916386596, -13.54021158220439, -0.05790828602008728, 3.121363813023208, -10.26329339936837, 29.60358127644879, 5.640693459787456, -6.225202166414575, 8.49263970223689, 1.111516509579903, -18.45973622662288, -10.78955835552373, 3.866537233352727, 8.114971974287389, -7.188761733179074, -3.287441529549332, 5.156604610165261, 10.80793451072269, -1.239076505166311, 4.628996155335966, 5.792922582124358, 2.03417264625456, -4.707373530409962, -9.448778191150614, 6.51155292021117, -3.19382039380789, -7.177226661410774, -6.832018005921634, 3.442244659675745, 10.77505720982952, -1.609927625466521, 4.733127783256045, 7.444153456927645, 6.065657625755138, -7.768628874694797, -8.73223505289636, 1.578394964028069, -0.8054671616028769, 0.5972200288905033, -8.68273678581243, 5.453422469912097, -8.723308411603904, -3.656294698422601, 3.713788968458369, 2.245164999387903, + 0, 0, 0, 0, 0, 0, 0, 0, 82.30322830941419, -13.16495817094656, -40.37221874531644, -7.156146024985344, 6.407626256610186, -3.070719411573423, -1.248781274591569, -0.09188094231426196, -0.14791454863577, 10.46460085885971, 2.511645220965021, -7.306021862635426, -8.821036218813667, -11.27778024004047, 8.299073644975818, -2.786388825153335, -1.404614079695401, 1.895971545970186, -2.374603998420206, -1.895908635885413, 0.4177297064772442, 0.3179694660965782, 2.847483353627781, 2.28314647154709, -4.251315293192437, -7.351627496507233, 8.45101495879304, 6.656324309408108, 0.05811442721379975, 0.352210596662256, 7.158242198776926, 9.604014490962273, -19.05916411574244, -13.48053537548751, 11.11056501341958, -13.44816425524262, 13.03794734916214, -23.56660744892662, -3.179691183297922, -4.31381647439135, 9.383878541906311, -8.241547161602726, 15.17745487655014, 10.50533207581469, -12.3496460656361, 8.196225745083185, -0.03575510420729201, -7.579890340619093, -0.7363093925300244, 8.756813214260761, 11.93727799717407, 0.3635376217139206, 0.4603703423631014, 5.507079480435261, 9.421116342576116, 5.29496740123859, -3.941393949093798, 8.749586295075376, -3.842933870553052, -3.434396636354037, 0.7496949834113942, 5.050293641980197, -2.449146742066287, -0.1213669699610963, -2.640456287197764, 5.565782021620873, 8.693308402974377, 2.307206522787629, -4.138693274221668, -6.245432457269187, 0.202505673386626, -6.566863879917412, -11.74280124769381, 5.642870396242308, -0.659648816152216, -1.690565064770402, -5.93672734719091, 4.422450101243651, -0.7271854445212377, 0.7895970235545322, 3.96205972546395, 0.3762898199575608, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52.18436402228633, -1.17071077050581, -78.74014811145696, -2.436421299700726, -6.158177326953696, -12.84920002328411, -13.40821294858424, -5.273362519386561, -6.872625202393317, -7.634332724591617, 1.036587235099262, 6.207608782298316, 3.391369867457635, -7.524695482267034, -4.223994548482144, 1.005090702038289, -2.66480555032824, 4.646608362152693, 2.243089562166944, -3.34529856305617, 5.740218757228164, 2.12882450346135, 2.939738798956252, -0.03146392010752049, 3.38958622345852, -0.2577487623574973, -3.051389295629871, -0.697296699287094, 0.6189380855708414, -2.814647546822989, -5.010744640386618, 10.8659101121065, 7.550151766381041, -5.138398331003744, 5.941882913285983, -6.24020929364107, 6.192495406215602, -0.1393925926206985, 3.522667688918142, -0.4029078058202559, -1.086721958116794, -9.106949733745292, 1.080723194973581, 12.43512076939469, -1.559991201757955, 2.834826471699229, 10.91592518979253, 10.14280540179991, -0.4312954736361566, 0.1698301469389144, 5.224021770744672, 1.399356722825569, 3.824858056231203, 1.187505521773207, -1.25027597821317, 3.154667536052018, -8.777523547457038, 1.485334722226234, -4.846848932499968, -5.331464798306308, -2.935610863284922, 2.146754442305868, 3.916678542801113, -5.097848412152915, -1.684939990487824, 2.003333243800943, -2.22594720641393, 4.656849950049951, -5.745353345757918, 0.6044487182322886, 1.596087705639433, -5.155786671036686, 3.16998966590795, -2.175693288642318, 2.801445787424951, -3.130319162400883, 2.85020826323644, 0.1640583474231081, -0.214298568273029, -0.1740891639628268, 1.273833756482144, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70.09446168050651, -11.26895002135244, -48.54705040053749, 4.118431277865748, 10.84591029041512, -0.6748674802174282, -3.045053711060402, 2.014682374966249, 2.306026198573233, -1.350656230483865, -2.329953831978132, -9.588390292055525, 3.269359204435148, 9.980505686658566, 1.082807022265471, 6.273567735324175, -5.719240792932494, -2.503890374538294, 5.253867760378612, -7.368019321193995, -5.092315009287605, -5.608336565960785, 7.85433697392239, 13.05231727795986, -10.24473853042492, -6.497760170002005, 0.7720864098024787, -0.9464942766836045, -5.75736090996403, -6.449685187648799, 14.67091581503414, 7.752227657052853, -8.313707502058552, 7.618733560061307, -10.26315766622777, 49.66932226344804, 9.396595252505557, 4.646105097651882, -1.000511699400161, 17.50139800181348, -24.58127340300144, -11.80138366202307, -5.227433380710831, -10.13287460063552, -3.337359409768342, 12.99698337996271, 3.068027046277927, -1.951738372661316, -7.666145241687218, 6.9088789851311, 0.2649618535564444, -15.99488743024383, -0.7701348417963114, 1.505671187381852, -5.323669521268157, 0.5338896728895715, -6.748253910318381, 14.64352852958436, 23.40931931143844, 4.375219426823375, -1.811045463489342, 4.773508381777763, 10.818209698722, -5.294039411650939, -18.70264738152938, -4.975296365083204, -2.600819681501243, 3.308632477674194, -6.40160106179316, 2.538884420020582, 18.76233248591015, -4.114557081532237, 0.5111695455673799, -4.794755383844113, 16.67507540569322, -6.886183084140394, 7.719834159396155, 4.933410312388084, -6.089459478292116, -3.503666218213469, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66.6637247212457, -0.5663386193537134, 86.66019711942882, -15.20175735117943, 4.314620867702222, -19.41396340483079, -15.38151259581058, -4.248235572512307, -2.600133694847515, 4.086685275316547, 6.543863987851957, -3.556770106796698, -8.862927415679744, 0.5940920961482564, 0.2891990484420937, 1.2985992187588, 0.6463973107839561, -0.1897507095552844, 4.999681085896536, -0.6439357872831064, 2.066718921953054, -0.1085645365015185, 0.1070768393458224, 3.026109517007545, 1.481907260983705, 0.1499047456480452, 0.9514718442208902, 3.068093096347056, 2.714461903454389, -3.99786212133959, -1.490015954498088, 3.704196600400429, -3.084024872438948, 1.383157275632034, -16.26579452857151, -7.173167896042849, 2.321998416940817, 2.275237906163105, -6.307537188875993, 6.209730858735038, 4.018421456135293, 0.9621119492629135, 1.945276954758256, 0.4126375340548999, -3.009694590378986, -2.629957817671035, 1.384131483830782, 5.687116562672569, 1.212032906758187, 0.4457093459378468, 5.044411045879187, 2.653766535846431, 0.2411195122877111, -1.543285991977046, 0.8571968890482712, -2.832787648800616, -6.089862603942122, -4.243058413925725, -0.2712347348375778, -0.7571525905438323, -0.1391757644986091, -3.374311051582727, 0.7719310852064701, 3.726864797116653, -0.7589171772472043, 1.688124623456514, -0.06145796388713081, 2.035112211335303, -1.275417314028715, -6.847693700987137, -1.324382865895411, 1.215308587453588, 3.389389718245654, -4.298340356096036, 3.252289347232091, -3.54897896652072, -2.583331482537173, 1.391546454632447, 1.526078993538325, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -76.15771433854052, -11.99852507214444, 27.62893281995865, -8.886170208363085, -9.022500867915554, -6.483908690769347, -6.478797015907496, 5.436632960504888, 10.11648415512398, 11.05236551506778, -6.555078182021158, 0.9926522830872675, 7.012674375514302, -3.958653565895998, 11.89784449953233, 4.997490823792532, -11.71308595491765, 7.473858613545575, 4.526049765812032, 2.627760851429408, -3.543040309678986, -0.6545512958150839, -1.975237359166213, -9.752416598897163, 0.1746629230980583, 3.764199942242819, -3.523765142660245, -6.526579460908251, 12.86892013415631, 9.636987335709112, -7.71437307352219, 9.374585571980461, -10.09888573625552, 2.627000532523575, -14.35239184493451, 17.7934680232572, 12.24617038938174, -6.2027891597684, -2.117824121844527, 2.304085371600412, 14.52899092304767, -1.375604453625678, 9.300885546968621, 18.94646416924206, 20.59266172433305, 2.716897787405002, 14.41056423737162, 4.669781485892746, 2.929418504934519, 8.242335741048715, 5.40876543323668, 2.002902940983452, 5.6098816375921, -14.20093255834947, 3.901682718637671, -7.337643713401271, -8.218284944457553, 3.072811403558771, -2.292798328406445, 10.69584853135417, -9.650335290149327, -4.330515729410567, 0.5204595970152146, -1.624267060418924, 8.140164084847148, -15.7637122001724, 2.453007028561554, -4.499820926337408, -18.34001755668463, 9.796120126023718, -6.012926560200856, 4.434295362280665, -9.67082400790736, 10.4548835691208, -1.769628011664158, 0.4768710210096864, 0.3854758620192356, 3.320903327037195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -43.98223406015142, -5.032665049120959, 63.89171973078309, -17.03607126733364, -11.37762317554949, -1.901161248292645, -0.8260131144255914, 12.01428472457645, 5.352225349608783, -0.3266225326728286, -15.64216660863595, 0.3825939195623905, -1.494103371722206, -5.375511858816146, -1.862194375089014, 5.63824583310378, 5.360101148587418, -5.696506781095095, -2.080871954585809, -0.7829130324044875, 6.783149785809925, -0.3661710817347401, 2.462769544154133, -0.8126745345164752, -2.507928414100153, -0.7896746658950899, -0.4314818025686951, 3.924872737975131, 3.720963560907183, -0.9854313103876566, 0.5600582865792041, -1.688187106864158, 17.44248034254651, 7.56859337644358, -2.163244623250694, -0.7929207133815144, 6.398869750639878, -6.091736851159077, -4.728849132755795, -2.854085872325754, -4.826855364681831, -3.30106640664588, 0.2719713238103212, 0.2298412502409825, -0.853005758672194, -3.263371003058645, -1.287397261994707, 0.6221723886323094, -3.488369011339807, -1.414828169574871, 0.07717807180754992, -2.684195273815242, 0.2613139899890946, -4.206641018599038, 2.982830136882203, 6.657239919946693, -2.518089625188537, -0.4552654704803235, 2.298800483965624, 2.494983397734763, -1.284395189604125, -4.238400338443188, -0.6366063645353051, -3.325393279736908, -1.764225755959617, -1.813359309843393, -0.2947559613727277, 6.320461175365693, -1.048130219904732, 1.69129533904847, -2.336845279584976, 5.580341689077066, -4.541654669729592, 3.817079261725959, 1.972729191142582, -1.594128333779149, -1.535735104483785, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -59.46738063214526, -16.09510211169977, 75.92651854229776, -6.959588443327999, -2.809913552100682, -9.062449485347019, 2.929935910954824, -6.516445771274741, 5.618312537880061, 9.794206647467506, 10.44206520884292, 1.504143210681085, -1.194672878944117, -1.206412082832246, -1.592792412630419, -0.8713955483970806, -0.4430245993565414, 2.114713938914445, -0.3808503381452496, -0.3361054648766276, 1.810321218052103, 0.06324533489118153, -3.207697984086771, -1.888840647774234, -6.337450722394116, -7.051669943095036, 10.24163394168822, 4.591682020148506, -5.157620119910969, 1.350695165969617, 0.7792033958582947, -0.8363399401868995, 0.8398917333791918, -5.122390663285614, -0.589942253467838, 0.1140765360111759, -8.180634436361872, 0.782695084020231, -0.4316505953196415, -4.677604739058501, -3.371394391221965, 6.790122165196175, 5.900302157317789, -1.138518787666086, -2.696524630738898, 13.39780057844131, 4.194434073284752, 5.363099243116376, 4.110197934071277, -2.070985188896846, -1.165572235840805, -1.241624822428416, -7.086628398680193, -7.575672638929711, -1.486981977191632, -2.042873730189658, 5.495814100326541, 1.841533297055732, -6.033390059069625, 1.625951790058254, 5.031090908642416, -5.215840389266634, 1.850639244782789, 2.092351976481545, -1.480623358531872, 5.911569449582607, -1.869423525406329, -0.8096475091606794, -1.000819809262052, 1.841395444723725, 1.081170909224551, 2.284559473058704, -0.6250480378852277, -1.559903447023968, -1.853970655342937, 1.547744137147876, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -96.3647680893793, 1.199043513223026, 17.60420974833172, -13.06773608748545, -13.86009320666351, 0.1767817722626665, -0.5124263274350351, -16.26448243634644, -7.14143348503811, -14.24141019732697, 2.26049840163611, -0.5232284569456099, -1.920838853591793, 4.846489507057715, 3.042770898035555, 1.294385928313621, 3.262620434881149, -2.270944593759149, -1.408453286683619, 4.497236785795636, 5.977793107223872, 0.1340518117987963, -0.6905643209085197, 4.805322551598841, 6.502377969783907, -10.47261184903601, -4.131639902258459, 5.974051724377973, -4.360075843426007, 4.73500504926485, -9.718847270507625, -2.119804026495935, -5.657677043459689, -2.856025773969369, 1.756942740498222, 1.717927994018707, 2.836097818243513, -4.425043948906356, 4.283315817519375, -2.059940986323201, -6.307828936261935, -11.44715911847551, 0.3006681108636347, -5.507293839810647, 1.536345859738123, -2.26452399462477, -4.716331237978856, -1.255956886329029, 0.7042206945918659, -2.667007107490436, 6.672978852425663, 3.262254896828355, 5.937155133580987, 1.948386865395799, 4.552963709305849, 1.788332867713114, -10.63067323751173, 5.26892419774046, 3.167593513248493, 1.170780576616151, 1.205868492329382, -0.3777966262231325, 12.93219596919667, -1.629499482312095, 5.270759888996531, 6.75414771239083, -5.680238880370791, 1.763910811059415, 0.2558270515454605, 2.632569608785784, -0.6147023174800583, -1.873856188681823, -1.734814810908174, 0.7079064341945942, -0.9150650771583158, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -23.02913191459475, -22.68355714527637, -71.45920181332552, -7.335069133951983, 6.88897969406801, 14.22303129604287, -5.713578960023669, 15.25375807101405, 7.31607076966181, -22.97972556461536, 1.773867719140929, -10.21928707943674, 1.424895097068828, -6.202938372907802, -3.564833182189926, 2.874044501828823, 8.685525653278034, -6.81311188053174, 2.764368126088952, -1.051923578466305, -0.9476817080611526, 1.161644143534287, 0.8923143965210864, -1.986614015969402, -4.795152281813358, -4.571219954943216, 1.206804637019736, 1.189134886949103, -3.389219761826265, -1.403036249676163, 0.1159085048840897, 0.8722638450337192, 0.6308893671254719, 4.417698737007038, -3.617011218574619, -1.59415231672244, -0.4094009736543018, -4.615708070111476, -5.105781556006933, 7.165268502604309, -10.27990343205298, -2.449496798762735, 1.740806437896727, -1.676699767804021, 0.4392602027266447, -2.822535542169061, -7.693191637559086, -0.9799315922761813, -5.464041140223222, 1.890629379194414, -2.234640399497272, -0.9456666715392037, 0.997606186316458, -3.110634577331055, 1.532640947608809, -6.76298600927938, 1.926980466393365, -0.3975761625796731, -0.1074936397088645, 1.428032551521818, -0.2307372170405339, 10.50672618228523, -1.043253387292014, 7.351732297170027, 4.654268870350594, -10.97263974298692, 6.22881607660602, 5.315813011291942, 1.976388766185981, -1.590375718577871, -1.91368371633717, -4.647761418706064, -1.035563975020433, 0.1409584860123588, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75.07192855828178, 12.10308470349448, 73.0310118247737, -9.646003904806241, 4.932961189760345, 1.718589369927463, -15.44305085297956, -19.92076242236019, 1.289853308008594, 19.44625320979492, 4.210588674471425, -2.579319144988436, 2.410104964471558, -3.865247564242535, 0.826851006847084, -3.631426466227551, -2.842039660907502, 2.249433450127177, -3.309261383458769, 0.6757720427689214, 2.35903348697973, 2.568255552039278, -0.321803303996427, -1.108091120089183, -1.412785938851775, 1.785124078160854, 2.573232078948616, -2.076416085393783, -9.312869029610674, -4.310360243055708, 0.07839735762587302, -0.4810908104630088, 0.9952395155647055, -3.886794543907047, 2.525965274526253, 3.540664673781963, -2.704864111340364, -3.864627721141978, 4.457179505634837, -6.813519964253322, -2.007416166791153, -1.607611533013739, 10.38000897763594, -0.3046634977924537, -2.266871922238326, 2.573731821774683, -2.979571190380482, -2.320864784735163, -1.500209869827327, -5.106748863521393, -3.950957911975269, 0.7340374884876252, 1.73889407335216, 2.182641990536762, -6.356098593894809, -5.93055977994974, -0.6040135105288104, 3.029168613692871, -5.042929510576918, 5.833709461846172, 15.29860079283752, -1.235961351707758, 9.34323445595332, 3.785951093156088, -10.34177459105045, 2.911648799971752, 9.281014378066164, -0.4941493880528656, 3.071779513490743, -4.517815603760604, -6.192250219969715, -0.3317883573330157, 1.349445179208848, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -63.45021054279741, -15.82766767521525, 41.22915354775575, 4.664008353213778, -1.654066901130316, -23.18254021974398, -12.84906013980607, -0.9626027911697629, 3.41433891445458, -0.06961595567794145, -1.096971305807928, 0.8698295584855787, 3.772196521299375, 6.631293883425417, -7.052125668571361, -3.200823343555333, 3.814349784726156, 4.941784929229768, 0.6315537523938005, -0.01802357802850369, 3.141620177813325, 3.10250469485239, -4.155135005432694, 1.701739006290255, 1.540814933013846, 0.7387665729315541, -5.311958621040922, -13.02405885670838, -4.942498894115073, 2.149572755504388, 3.341124951208096, 3.870026706159178, -2.46509460954075, 0.4769961681706392, 6.604145321870847, -4.15894453283208, -3.374029939123039, 6.807566765521488, -11.58698328431105, -2.80185415106152, -0.002148524464262543, 7.754192162202266, 0.5225981165001614, 2.195290230986459, -5.408948531637178, 0.1049214015983932, -8.924285492967401, -2.350089393085131, -0.5423255417785425, -3.219609856555158, -4.390973896320624, -1.269742631984241, 4.051212063679165, -10.36139506901704, 0.3230350713187323, 1.674998606949747, 3.540984566900865, 1.18972973091647, 2.057607076615883, 13.40112401714828, -1.748763782836714, 13.13716409027571, -0.2243177932456299, -12.24721484928519, 5.87773220153188, 9.74466077242022, -0.8896869572089892, 2.189477242908632, -5.208603883097037, -8.105641911969411, -0.7300180023457923, 2.022265831725371, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -52.66687486179152, -3.101783038688906, 62.54840137160225, 9.616670950233983, -12.50481143141205, -28.04924352555032, 18.7558503771284, 14.97634693290006, 5.851320122566384, -0.1677270839150571, -2.409084137352026, -9.845991621034058, -3.801336162247693, -0.9907297274053595, -4.664351290089362, 4.309633797495072, 0.6048954669030202, 1.543984136643211, 0.7189536403742964, 5.611415033458477, 2.487672542609962, -8.621934168449286, -10.05094063299714, 8.742063873037001, -3.490157247009134, 2.066460908332703, -4.477586251672978, -5.332933548411357, -5.713234560480118, -8.240059969073409, -3.364164696488402, 6.227061542811854, 0.1791896591361718, -2.507565879175399, 3.698854501954176, -1.007279474702307, -5.481898046206347, -1.72805442027048, 1.655718519783813, -4.101110323704863, 3.320297978932387, -3.684641982534487, -2.130960673414645, 9.904486582652764, -2.376262647862093, 2.148900292669743, 4.759998469058096, -13.36944502872464, -7.978751527858369, 6.863214185815936, -1.882367548219069, -2.561088530514321, 4.873981502571982, -7.579320197588544, -1.497679078782172, 2.35834379567061, -8.385645880902972, 4.09880893561949, 4.828417395745121, 2.282140125429291, -4.833463519506268, 2.913845215609183, -1.612937226837221, -0.5525869262187749, 0.6145753612090259, -1.089608686377456, -0.3258113829684524, -2.210223671018175, -0.8097847014254713, 1.266046990796156, -0.1222971055896021, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -62.97383455884989, -15.72156846847342, -50.52987429444124, -5.821406791941631, -6.271938286848207, -28.08098151092815, 2.368560549147725, -14.39710551246207, 7.569330972477777, -13.4264330861926, 2.75461801976173, 2.688711269115824, 2.764732074458091, 8.408341398358559, -10.04776489918815, -7.396363378028368, -1.149416203511894, -1.054301083542792, -10.04596380901379, -11.69408823775871, 17.38686456253957, 8.299516226227814, -13.25762288717717, 7.349031579684647, -4.534835890890477, 25.89116419268924, -0.01992743860632668, 7.982099277597088, -0.04160883712533649, 2.573520590529096, -11.35149838346194, -4.227617111120538, 0.2168974914804734, -1.795362046493738, 5.631764300285649, 6.008575066010116, 15.72428788595154, -1.842254414189587, -0.5382261085672077, -9.552315485913649, 3.675875209168321, -2.602166724352801, 1.859610651661533, -1.895505270339744, 11.52276237353004, -6.239279748413804, -0.1297742740578715, 0.6991046300254831, -0.4208529689673289, -5.060072193399457, -1.906088726339328, 12.62054139647468, -5.130598829626098, -6.128474594316537, -7.690481592824534, -2.247055264194942, -1.447577869543198, -12.36316455006643, 2.732894276344731, -10.27755222960528, 0.5243468721916534, 9.047719038239586, -4.383971076616716, -4.842518948484556, 1.125600151566935, -1.90225576696169, 4.722031005971605, 5.306544131294808, -1.877228890927751, -0.1571777681548308, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62.52508007922609, -5.719488295515556, -63.28854566104216, -24.50023292372474, -1.974567606587724, 15.49864632949223, 6.998409457393456, -5.489144318408908, -0.6799511450744802, 0.6168873226031361, 7.888491941073679, -11.5213969968209, -12.02867471563315, 7.763694194348873, 8.334853365418969, -2.380451302943409, 0.09020014258787826, 2.3486772567884, 5.673982771176749, -11.02127409093227, -3.603461078419621, 3.167170753763195, -9.711383410279849, 4.723995107208117, -25.16138896067726, -12.23741325241211, -5.007012002050583, 2.190640446078525, -2.216636720328977, -0.5859489793413336, 8.233471386988535, 3.365237643930874, 4.189743657652521, -1.395157859959696, 0.3920210029284703, -7.056426817934152, 2.580560567814978, -2.128975130545938, 4.242435652432224, 2.235031188314527, 3.444275519482045, -0.7064127681508054, 3.521919688523948, -2.59915922665114, 2.796011561611334, 7.213677229286767, -0.2401477293445469, -9.239236230514949, 6.250101954381679, 6.220350851430839, -13.83625185491088, -1.200037472412707, 6.659714118020979, 11.18894360817651, 1.029186325547049, 3.013890675288255, 11.33035543805201, -0.7441654641054523, 9.147248359723497, -2.626393685016684, -5.110468073117602, -0.06530067048820608, 4.76431701962415, -2.253412642242864, 6.519983245052911, -3.976542599366748, -2.604614469192844, 2.348858737245175, 1.219946438299759, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71.32602496514716, -8.756876217814053, 35.04911984263231, 11.85596450877738, 3.138232705310344, -2.194824321913857, -2.176583710259183, -3.343478177638568, -4.236563157562049, -1.392674203474749, -10.32262876392589, -11.63217516576671, 6.360303917047404, 5.478160154717675, -1.373379667953706, 0.1222360308529321, 5.92992964189494, 6.968285486207656, -22.24412202832642, -14.08200805003572, 5.255065130840872, -9.647401891006457, 11.00321233823368, -26.63174562751841, -2.523162844598605, -6.145124307805637, 6.022273738346928, -2.926653347515803, 8.133925760802793, 8.591428362280888, -6.013423802818253, 5.249342941582124, -3.970400887670635, -1.748951928295462, -11.28492868937306, 3.683276522805945, 2.775813620317148, -1.942462052184175, 0.8891846150120821, 1.129690076778026, -5.55530433211887, 6.228804252833361, -6.493720150589822, 9.095196357844529, 8.099379043388204, 3.282276517555831, -3.970254131193375, 7.47529332111375, 3.579752526867083, -14.72795586609742, 5.127558963939634, 7.483150275119841, 8.143770403634198, 5.638865762472385, -1.070704874835951, 9.665581065265565, -1.166404516592552, 7.118528213260745, -2.114185083787445, -6.481345817022934, 2.439165766212086, 1.688770678506234, -1.42208740458422, 3.736908500476163, -2.52099822967916, -1.096365312903943, 3.115453100212649, -0.09261316039995293, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -53.91482041296031, -6.195234141533248, -84.22720528023089, -8.228357964869858, -5.335191448255144, 5.056702938346606, -7.464695583224544, 11.90761078244647, 13.09090097966719, 0.6578496842921259, -10.92616341315019, 13.03744853784803, 12.44023007567226, -1.161373459354644, -1.087744561840636, 5.932731979531396, 9.315732460781408, -21.37551613946766, -11.96248596464901, 13.63024808396517, -9.288714959320243, 7.289554080422293, -28.16285634112625, -9.571761912856207, -12.95118012023273, -3.750611197225868, -3.922432347873787, 6.124510964031026, 8.396222723906581, 0.6148965037770432, 5.13355621975811, -5.15138967657882, -8.114413035924995, -14.85090329064167, 3.39729299292902, -2.657124865451653, 11.34942261680844, -2.606547131090628, 0.1623880304796317, 0.3049177006141654, 1.35635227366094, -6.653050626870728, 8.073015458686122, 4.32132583894199, 2.212964809408603, -2.184076048165147, 9.799834020565784, 5.96606727639304, -17.42599122311193, 2.990347710352649, 8.359376262684071, 11.42371296595421, 0.9821035082629358, 3.26846258160433, 16.37981065781434, -2.885803722420936, 10.97059625603291, 1.611945735717845, -7.260237552742894, 0.9012561107562547, 4.615303611480527, -0.2799207674436057, 5.037467804678709, -4.682042101547799, -3.881526357472375, 2.728902770049329, -0.06849225345413945, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75.12896070864572, -14.55114803420073, -25.88520658421626, 0.3634408911932056, -5.749148081032294, -3.987054468607347, 3.605389714269859, 18.07840198100762, -7.822123425494485, 2.924157083708025, 1.962703760694055, -2.860064629683554, 2.959145172069614, 3.93868226857773, 6.366668810634879, 5.288829466990348, -4.294038560170033, -0.08801626773445168, 5.250702110881997, -0.3152641291658385, 2.199002653107061, -17.67833947760999, -5.045964490505647, 1.211048049454066, 2.421824405506, -4.376451661909966, 6.241973769898392, 4.290964226801218, 5.969309505771088, 0.8555684941579085, -2.217790960392097, -1.35718576281381, -1.746727805108543, 0.5254608653917869, 0.8086186851967726, 5.293064595586645, -0.3599247004146829, 1.959101109902374, 8.947006788222373, -2.378495602576101, 2.723709987744103, -2.329120911932814, -11.05882331472708, -13.0794383091978, -3.452514320213396, -1.512851055243775, 0.1639755205493351, 0.0825479539228451, -15.39065507630122, -3.091131632830409, 5.338329408636449, -8.829569668743607, 8.153591122859282, 9.18321870067153, 3.77411909040066, -0.7259214307321555, -2.707742728847757, -6.070142253582127, 0.8961401710073812, 9.291034725859165, -5.172620787510649, 5.77739330996065, -5.938409073064742, -5.68284811156704, 2.213899420332612, 2.230741101606077, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40.51083229358659, -6.657401086597119, 46.1651355827067, 3.571126140204381, -16.51018529197995, -18.81764925681962, -3.560003960730173, 1.069143039257071, 7.841419461017695, -7.426825297086943, 3.636227586276667, -2.832840975189855, -4.226091127266264, -10.32558071350056, -5.423718841813621, 7.898975963852462, 9.110182036344748, -4.818572270232188, 7.517064129930646, -3.069225466093795, 13.58082569251052, 1.95336044171603, 5.706764456088048, 5.029792791510202, 3.178869494747695, -5.047323754409704, -2.736438120770565, 1.426807143702085, -1.920567914619038, 3.428205422463726, 5.74585589697081, 5.382153677222462, -0.8865556423886194, 3.914778289385668, -6.604066141662078, 3.391876836068548, 3.169728760425306, -4.677156167446953, -1.155070546015535, 3.061191481464817, -3.13123995748959, 6.494562114793292, 3.376621926659731, -4.587404098548453, -4.277527442893002, 1.474886961462322, 3.323795372963384, 5.401089673065682, 0.3253871348814484, -2.369066423960044, 3.865796037257022, -1.638291040075763, -9.722922494527154, 0.5238103099430581, -1.203361374442151, -3.74503959737966, 4.569457144757759, -0.4965825177245843, -2.765019233250034, 0.2829604726448859, -1.146952017594104, 2.265032786536537, 2.680700571952246, -1.255503266954519, 0.1637658162738065, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -45.71426451969628, 0.3451233465733878, -42.83879591649266, -9.652152512053839, 2.943077049148836, 3.595807131194814, 12.07618358595724, 7.583721776261375, -2.798504129600953, 0.3493125113412846, -0.3060685650112926, -1.969954034839694, -2.226643423419492, 0.2775817976926701, 6.61252070570618, 0.2026442823847165, -1.756653814676166, 1.358336152476414, -2.953213341300402, 5.767247508163317, 4.576452080845395, -5.48265868666933, -5.584394192816982, 5.087476338922126, -3.141525913674985, -6.275099033613296, 5.577549390317852, -4.816802787505703, -2.484144702930381, -5.941817033794925, -10.3264911173429, -5.364557843392888, -7.843223405124702, -0.5283376840825795, -0.9570442251031415, -5.24883614050029, -7.185962189820855, -2.977003550332989, 1.181048111506568, -2.173863203462683, 4.403509726183693, 5.789771709589788, -3.251326838177565, 0.833293737507765, 2.197330074627189, -6.70359339703703, 2.969866449959098, -1.167049442438063, -0.3088855619701391, 2.234922153742612, -0.8743490423992627, 9.838111926343993, -3.681537357431789, 6.247482122998323, 10.24712337154277, -4.61734564949215, -0.06307486749200926, 1.334451074280191, 5.336299550216522, -2.297158597383811, -1.096756988788949, -2.950656621747207, -1.793982883674879, -1.379935304922622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58.4305528833414, -10.93080151481084, -73.47222018485503, 1.299575050569214, 18.14449108892977, -6.050719753243367, 0.5840217211940599, 1.960086594084849, -4.368421952540212, 1.788116554787903, 2.164491069701282, 2.358970020887192, 1.093569678019126, 1.989649218755819, -1.28823196621902, -0.5313187250208743, -0.5624844430654856, -1.907667575555907, 6.909040860485212, 2.408127751390964, 0.4215555707913529, -2.780873876588656, 1.85248203975166, 3.135639744664483, -4.380299973926649, -3.921426250428929, 1.495099382458397, 2.622560565964388, 0.2177544811958763, -0.04339424448668048, -0.2214592105458387, -2.06944907992863, 0.1763703512794778, -2.846732426447117, -0.4639421303306322, 1.287390331822631, 0.6533086995560746, -2.425549690664099, 3.088053892492399, -1.130817472618208, 1.485446373139376, 4.380685859773039, -2.57028748480229, -2.127967029034677, 3.41369029366427, 7.568188803198317, 0.496744282104129, -3.964473757500087, 0.0282299427440213, -1.96849998024905, -3.553514188828535, 0.9438074995728989, -3.104500825703638, 1.724858829778236, 1.800147082209048, 0.224333685578572, -3.291601313990126, 1.370577599850704, -3.565441527576292, 1.823418080577437, 1.52484990001091, -0.828729219973382, -1.06107451712335, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60.4551144650917, -1.112031735605267, 40.52296759779913, -2.279357391039372, 4.563291267943169, 8.295632041224566, -3.939508280061141, 1.942114905022437, 3.077992623697353, 0.6979345603294407, 6.071625856395872, 9.832923870768321, -8.720411873028274, -8.458375209728874, 7.032936679862646, -3.660503707293801, 5.13609182864828, -3.763326595416756, -3.646534951906556, 3.175402986994713, 1.020866860271357, -3.886824646779147, 8.218325748247384, 3.32404792165843, -9.200062655640144, 6.295889066677559, 3.845719933212995, -3.43351185274513, 5.438009428491434, 6.112353772294139, 1.228860655027741, 1.024037136509394, -2.139240304739709, 1.532357918757432, 10.1079544033704, 4.044497472104775, -1.295614976235356, 9.473469973585541, -8.029083475961539, -4.343462366128194, 10.84815682088869, 1.011633882504112, -7.169231098330976, 8.133704565655293, 2.691632282997318, 0.8507816064460101, -3.282652921494739, -4.061244378839357, 0.05112572018852947, -3.547751950024609, 5.30365786223212, -9.690997968552335, -1.734557454096158, 2.931578504521047, -0.5834918591113373, -4.496448398993238, -3.031542637377464, -2.036988448519847, 2.154422493546257, 3.299173741623872, 1.162415691741919, -0.5670591291688311, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -70.06613504205954, -9.835478687386175, 48.52214856712762, 11.48136951108488, 5.892721436902954, -3.703795834979923, 0.8429544617402316, 0.6016790749403919, -1.12542788838987, 2.368548605557095, -0.6822772589146743, -4.287688004185707, -2.594460038219845, 1.811391939430363, -3.268064562811219, 1.460904850276689, -2.864974741945764, -1.034841388002912, 1.745241178328566, 2.486796799228639, -0.2269447058580376, 3.439717265105236, 1.02136554408696, -4.705182655489384, 2.499760827621522, 1.840963673652037, 2.953808675230261, 4.276133519908038, 2.651957942115774, 0.6355241666252862, 0.57194650441768, -0.1440454915229704, 2.242291193237154, 3.579445219558762, 2.752322997747827, -2.639308831991975, 2.4577698710486, -4.752199390601385, -3.863233755634323, 3.10435637509681, -3.028301690338678, -1.02478741743191, 2.754261908266995, 0.03535310362791887, 0.6383262792814937, 0.4368852433821509, -1.380097243200454, 0.281051180629981, -3.521710925389415, 2.247365619297284, -3.14338177048046, -3.302250573466052, 2.012036598405328, 0.1368976717018865, -1.193536497653941, -2.112322112549731, 0.1388066012915721, 0.8364226293226722, 1.307996121331485, 0.8916481210688338, 0.4828704628796113, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -48.35160025190098, -2.541971211171999, -40.68153564873732, 9.207954361446687, -5.556985583068949, -2.844696785788164, 2.796718046185394, 2.464041987072172, 1.893613270308423, 4.028977435880829, 1.580350980861052, -1.926871386712014, 1.936201877177753, 0.03605266371746324, 2.628195057996384, -4.803264934471255, 0.1432706764330213, 0.1079385572562689, 2.678825585163418, -1.064180917349414, -0.5008460410343695, 2.882130267316084, -0.15398049667585, -1.581309397233642, -3.437020133996731, 1.265459202748218, 1.117834225134362, 0.1360954343911673, 0.9375505319888843, 3.243740457337423, 2.092675870695559, 0.04783544042641906, 4.765463295666528, -0.4641437505818906, -0.4785294697426362, 0.9696458103026435, -8.685566793141595, -7.008778621407876, 1.595549810231035, 0.3128462080006037, -1.324425648748344, 1.053200285772633, -9.359526652432077, -1.580936494199254, 3.673447578818254, -5.544913965708159, 2.361010918728093, 4.208995052675768, 0.06177199204784918, -0.7315046900899178, -0.358711190997884, -4.578123417453783, 2.050322078756102, 3.974849259098512, -0.7452561049821164, 1.594734714218798, -1.737806196971752, -2.031916066155333, 0.5613088668818109, 0.7078249129938057, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51.98712898798419, -10.91279555750407, 16.5116520014062, 7.070082094300194, 7.316626743402702, -4.062538962997873, -0.7405273411971364, -2.403988646588473, 4.735499624487429, -2.288345916874214, 1.710004157792464, 0.7759293763857303, 2.319801872864849, 3.523736483172671, -4.063099150658085, -2.492051000480119, 4.11448548909593, 7.129988646336227, -2.243669991226699, -0.01638383640626986, 5.035870505157345, -0.9263294558811588, 2.097755508212908, 1.321512562673401, 3.748642620543865, 3.497629889280451, 2.535560833332076, 6.70155773507767, -2.222025277278504, 3.745469454508642, 4.860671405997067, 1.247993743903351, 1.366709222748014, 0.15728611894614, 2.359412737808513, 2.228713531327038, -1.291887607463255, -2.502446261947766, 0.8576018641230071, 0.2591128365637439, 0.1281550783740285, 1.457088120497456, 2.804040947211357, 3.04089132770398, 0.5933410236497064, 0.5620801447638994, -3.466284049616893, 1.640115928164911, -1.286700740977786, -6.179791106131169, 1.636998061183449, -0.2159342040060719, -0.3846813123879876, -3.023642425428129, 2.529816319670621, 0.03264733953770085, 1.353325216772121, 0.7761992320974147, 0.8335576498590705, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25.43514166894322, -8.17729396479627, -9.755663509088453, 19.19784728348034, -4.384048886049747, -7.499153400798601, 4.435169145012178, 2.435444086759126, -9.059597245945259, -5.325657224831133, 5.740599830438042, -2.492050052381312, 4.19796696197511, -4.263587721918892, 1.77146723826956, -0.4935403175135217, 0.8862361772476778, 0.718637930367225, 2.234402910854942, 1.153322927018771, -3.443329198738874, 0.6587212840847486, -0.7054120735100874, -3.07872040612198, -1.371786433350092, 1.271824407901802, -3.947941817835058, -0.8336796717965617, 0.6116519681575391, -3.071696553703523, 4.475454076327929, 0.7609188629051276, 1.92281105267744, 3.40184922477059, -8.810192326908565, -4.590741833410618, 3.734024788110379, -1.509040639411721, -1.529465630170008, 0.9461084686824491, -6.75503144580174, -2.037690055578029, 1.030666583912851, -3.882610283293217, 2.375072374836591, 5.361220748281059, 2.030587685343521, -2.594516437562062, 3.173762351676447, -3.470985476419609, 0.8394945737986235, 1.011387559197422, -0.3451056702610979, -0.5600384586317051, -1.250437490195752, -0.6594046924812333, 1.043095979522655, 0.3317341014295642, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28.99829564612994, -7.919492306918029, 14.05556909884386, 7.925941651982717, 1.30923833477671, 2.711408876410578, 1.61295413285611, -1.556599660832906, -0.8098128328747748, 0.4820136628666691, 1.242144749021579, 2.59270514147219, 1.070695817241087, 0.3750106994386846, 0.1725150645491444, 1.817115818968294, -0.4814506723964737, -1.161742890285604, 1.472007131837003, -3.436966082846573, 0.6982494240111369, -0.3149935878404753, 0.423370074395463, -0.9574295293157908, 0.2421056567329433, -0.5049850377885065, -4.679003799785368, 1.836812379169509, -0.6413835068300918, 2.492048982685315, 1.392871072424903, 1.054456102018222, 1.562804344198468, -0.5360913571726491, 0.2289458184750688, -1.348818559581913, -0.7324130913590041, 0.2525553513400682, -0.719825146825839, -0.6622690818866591, -0.05716678780881196, 0.03985333634237294, -0.3355682149483769, -0.1341481930486313, -0.2245769325773339, 1.701054496016564, -2.071735516197021, 0.7197321751353539, -0.5990693757732555, 0.7461182301273023, -1.28537860516808, -0.1752635447217054, -0.01940763082982118, -0.1985636316510818, 0.9478745916084782, 0.2042482439571948, -0.4223294809395653, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -26.09223882232648, -12.37682729616652, -21.27874182963862, 4.348357266610032, 4.573400992223148, 5.451216191750214, -3.611392020039598, -0.07921190808374405, -0.8260009529279171, -0.8434890069043338, -0.4552052508830591, -0.4528369276968658, 0.485445048833045, 0.7411599447890793, -0.4977249990635382, 1.190184399027994, 0.5973815546085762, -0.787231230010092, 0.03686032549901305, -0.4890816251224443, 0.5247759592075937, -1.879966027178497, 0.7792555164671459, 1.08723712738975, -1.42032534259863, 0.1721744481327533, 0.1056055009830306, -2.005790677375433, 1.016109801476819, -1.242159849121084, 1.243013696198364, 3.432482241304956, -4.523104088240713, -1.568715574671622, 5.119814672065328, 0.3791289530216432, -2.190682514501041, 2.552754170198622, -0.449368385418214, -0.5848836895616387, -0.9128519962622303, -0.9291921116478306, 0.6344008715643001, 1.688400124637569, 0.3633977049284803, -1.575721206061369, 1.961090047103945, -0.6752069375516031, -0.7855465024767947, -0.2102475861881171, 0.6869577789805948, -1.299232189451566, 0.5683367030798885, 0.3130637568892004, 0.1545378225570001, 0.3790410707685513, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.78430083032547, 1.185047939349582, 35.77538180501586, -6.08934280503613, -4.628055061913704, 4.470155638785817, 0.1274755893885796, -4.165150926841093, -2.90227906734488, -0.845111562541671, -1.740136245099567, -0.7946086439652909, 0.165908004480544, -0.6322554553948885, -0.7202811048901517, 0.962291525388159, 0.1867569707618253, 0.7090001464102381, -0.9034980429447981, -0.7997832600818465, 0.1057538227773544, -0.2295775902801903, -0.2167480404571516, -1.707234755317263, 2.041285551224553, -0.7878934898873934, -1.430438536425756, 5.730418488030445, 0.6926510312478421, -4.339109958364433, 6.727134105417382, -5.329326344720556, 0.2090167614184525, 9.514829796739471, 6.99752035864157, -5.726866864790069, 2.796275247427376, 2.891078173635352, 0.5284713674492778, -4.068212458937251, 0.007838785072538627, -1.603613176227203, 2.0145967452931, 0.8759256044597022, -3.80096540098218, 3.215984538447468, -2.552801380633107, 0.554399068571981, -0.3103317501790938, 1.208594964868666, -1.283494125131377, 0.7998967241899251, -0.386450465669298, -1.202893469925367, -1.317846847748221, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -47.41309320362173, -6.902809138581961, 24.68993718840007, -3.13534854977696, 7.054619343395385, 5.577611289513071, -3.877117196513223, -0.705447221487262, -0.8099002262119813, -0.1565635558190763, -1.127616075289359, -0.340714841660406, 0.660945871772091, -1.386755567315061, -0.4584883778560444, 0.9198751662032315, 1.002014450214894, -0.8640902794196041, -0.8777171102898179, 2.14825103785315, 0.989246034616117, -0.007095782785030112, 1.73906114106083, 0.6255059446607256, 0.1889696248858352, 1.03385909422522, 2.226668602394364, 0.1698945168834521, -1.873328492302393, 1.635950747204321, -0.6535224611564427, -0.5212140486619968, 1.003703892471871, 3.059411904595601, -1.892088474084682, 0.9339283828820583, 2.372361621792483, 1.133949816931869, -0.1994699011958669, 0.6535725484050933, -0.9195781603438848, -1.005444925904406, 0.06444426676642491, -0.8098171033672705, -1.318065403781523, 0.229094599479945, -0.1458840598162685, 0.2580570421599906, 0.599654091348747, -0.1055495042899468, 0.8993623666137143, 0.2691782537744015, -0.1099774106379499, 0.2977644683250328, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -24.74429137938651, -3.056148054133861, 19.0056932068058, 16.39870702492764, 4.267138497765569, -7.263096879020432, -2.919011924763906, -0.4167087337896431, -0.8396221408817942, -1.296684951975891, 0.7231090234720337, -0.1375746950653319, 0.4893869484915677, 0.3142640879884956, -0.2220967974170002, -1.109112753429507, 1.837593002510292, 1.479112432032976, -1.096302655894103, -1.964525246159897, -0.3280412024354407, -0.9206324506519383, -3.476018583754276, 0.6640599703563438, 0.3918183916355132, -3.395485381429018, -0.003002004945104059, 3.146782410011682, -5.072333819483568, 5.41257407183969, 0.6517585511003233, -7.269221543477382, -4.056630984171059, 4.210313402070434, -4.078813743290807, -2.25180663054022, -1.292189897325851, 1.427646253569202, -0.02497439324399699, 0.4774218280565992, -0.6503459447009956, 0.2399655638403526, 1.867125503961992, -0.9832308658323502, 0.3873487083709633, 0.05281139747950379, -0.3835529630274041, -1.6917245847278, 1.122860683946538, -1.59095315900844, -0.1293462709264742, 0.744401662451372, 0.550681606700183, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -34.33789589268527, -6.878943247619225, -14.64721261322692, 10.01107177766694, -10.23942535961409, -1.01498039173437, -1.897412320562053, 0.1671533339857628, -0.8712694561978971, -1.083706765312663, -0.8072110203673344, 0.8308152015963188, 0.2147544944441696, -0.5493919968376136, 0.1446575439684376, -0.6832698103437359, -0.3948442858808979, -1.115588657559433, 0.3579803772248178, 1.360983446684671, 1.00664254181845, 0.463405794612902, -0.01621384683534825, -0.8228161891870686, -0.9063503571998639, -1.803563811674677, 1.773734326519576, 0.4302873906114944, -1.04322351848609, -2.826856356023816, -1.324768966730078, -3.650267019006124, 0.4946176831514201, 0.9765254105590534, -2.029801194780261, -0.08501190782368655, 2.178344340984078, -1.920968439027878, 1.468087622744764, 0.7608787750954016, -1.000741195716964, 1.504164739818004, -0.2688678814948808, 0.6600983722848048, -1.220320200367525, 0.2410125647060634, 0.1664703506451447, -0.00850398171402288, 0.147174562643468, -0.02779982278043158, 0.8346719111354661, 1.343056942062318, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24.86877278577309, -16.79318934098175, 7.458488104737861, 9.49827773740922, -2.037264532584139, 1.252205231895099, 0.5394711870719748, 2.195699736074124, -0.06182472637253196, 0.7020281028590925, 0.3258270446041916, 0.1103891416148433, 0.2807839830050392, 0.8324674121995713, -0.07707017579260933, 0.04774101018547401, -0.6651862970621468, 0.5716949794838074, 0.2786641675385044, 0.6522299722084175, 0.9870590659751258, 0.07525858148281402, 0.2573717074126062, -0.8694521708682318, -1.166811640779638, 1.298799293918699, -2.203520860482713, 0.6442208455279349, -1.644267690640131, -2.625903488982017, -2.302992147951265, 1.257444945761727, -0.08416130603880936, -1.270800555411265, -0.7611165428890112, 1.039732198091014, -1.251481617872658, 0.668700121789956, -0.6911166576485717, -0.6139792747015455, 1.608281400168625, -0.2867634337303782, 0.1637144135551453, -0.00432411765221891, 0.07102947638320466, -1.167072230215902, 1.020402395737285, -0.8250836936353415, -0.6010780760217853, 0.1575436581466232, 0.3661602997463697, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25.48744110290001, -0.8196103125693783, -28.12739691634226, -14.66875241082419, -0.615739550477418, 0.7968006490105319, 1.893633537382631, -1.654939455947577, -0.6163475289447353, -1.258986228668871, -0.1685854638534228, 0.3466358666389292, -1.426194843008651, -0.2003994306001548, -1.259905297827965, 1.344072840361883, -0.688819755049539, -1.014480774303581, -0.6295918075499517, 0.1776953465799677, -0.2343489103275878, 1.245580834373049, 0.282925806992274, 0.9010886337902754, -1.886506785726124, -1.464163182582124, 1.060688891787593, 0.9766666550692192, -0.7971522349237924, -0.3026477025841756, 0.1569473405096722, -1.562229392252153, -0.5092349552596337, 0.330008450314712, -0.6335053028536132, 0.4247451599698489, 0.0985199006348359, -0.3513889048599413, 0.06524354177060393, -0.1957245081554103, -0.9317593740728739, 0.1952654121598859, -0.2590026012553117, 0.3001134383078498, 1.986414203689662, -1.071273239462749, 1.253278874165287, 0.33617967896085, 0.7395830923202225, 1.549701849275336, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31.61694956773989, -9.578300913349803, -3.504213982861134, 2.937150834658584, 0.9888020778636044, -1.024980201460239, -0.5118645161888414, -1.146567755798608, -1.444823248641867, 0.119064333528641, -0.4696982483040331, 1.095121262010022, -0.5308991134969057, -0.5197247973700743, 1.05002708888555, 1.818937037971043, -0.464288009797318, 0.6619872266917841, 3.401021092823941, -0.9482749170371739, 2.813315825246367, 1.129476242162393, 0.1981687722797381, -1.019635015614744, -3.307198789311745, -1.432171362179824, -1.184749190478042, -1.044919901810701, -0.6539226010822516, 0.4625979387292016, 0.6826291685753989, -1.87320881210041, -0.02360508954848113, 1.040603087479057, -0.4961300270289009, 1.055913719807241, -2.655638121288787, 0.1835672294990115, -0.2887263743968013, -1.414391072650056, 0.9868620830546826, 0.6374153108068793, 0.1452572712918873, -0.3526782564487305, 0.6972915252755666, -0.01466270301749871, -0.4766248436639112, 0.2560860018610663, 0.5918528531262749, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16.11268891122238, -18.88517791209816, -7.849457648122431, 0.5186009516658268, 0.9174633102810905, -0.4433385845787631, 0.259117803259069, 0.4812800928303352, 0.3809278637536887, 0.1040308979050729, -0.05696819922547338, 0.04177348257977326, -0.19151417247168, -0.9633478211800127, -0.1242642511041362, 0.3111175057895781, -0.0993555030948718, 0.9200983120151756, -0.283630744431747, -0.3768440931992381, 0.2608693517536536, -0.1701114694365957, 0.1657033422918405, 0.5579125426286559, -1.625886334801126, -0.3807035749043056, 0.9640891719563836, -0.1517544113079037, -0.06175882514010688, 0.4876052179200603, -0.1171970532950455, 0.01944444533954101, 0.4490968232071326, -0.4458741922044034, 0.3254420663099036, 0.5282760372591894, -0.05934694150103174, 0.1060201539053977, 0.8283931026778301, -0.4074091722040743, 0.4784701634625882, -0.02952608481148086, -0.1915663172505298, 0.1218560114391382, -0.3518484009580818, -0.2587618544226619, -0.1011116715064274, -0.4008733499435151, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10.28612342841808, -23.92112732279337, 5.771795426117762, -0.8030148991959661, 0.04406286929137412, -0.2462851679259779, -0.0790329685264313, 0.5162614125094603, 0.01081766552358586, -0.3771532498914852, 0.2371657873877063, -0.1121483962706096, -0.598902253817861, -1.018195608367853, -0.01053082672842091, -0.3684877801366509, 0.3508826267234865, -0.2390155682927431, -0.1773909049534708, 0.1757923535233533, 0.2788684363679378, -0.521760862098457, 0.3153403198775502, 0.08909424355874358, 0.3382317489455293, 0.2248194206427477, 0.6112323344458919, -0.05266682106538524, -0.857521487871565, 0.09621919673355192, 0.1820135304582492, -0.03556509270831806, 0.05480383694627229, -0.05236763037981038, 0.9935679652239512, -0.01831786321756342, 0.205863157809067, 0.3066879134775455, -0.5897438503738709, 0.1809856006527006, 0.2304158672123705, 0.1357359363236704, 0.01081706136475033, -0.2019643081867054, -0.2674765180786534, 0.1218826125012657, 0.06599894348285046, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7.508940298192356, -25.92446548490683, 0.8596283612994251, -0.885296785459307, 0.6510912736108546, 0.04489469589179211, 0.1153490121088812, 0.6103383563995985, -0.6314156415588608, 0.01915715564342266, -0.5113720254650198, 0.08321272888636021, 0.2526155635642888, 0.07676680070437664, -0.207069381512334, -0.4238244829828506, 0.1598019632669035, 0.01979690071582769, -0.1131733213057336, 0.1678269137319559, -0.06128460713493483, 0.2950474603493092, -0.05777326473555904, 0.1081544273212701, 0.1350575367841474, -0.1382598662249417, -0.02063619586362458, -0.01748166206219487, 0.1390481463209892, 0.07165704302950053, 0.1349895003361674, 0.06236059106166005, -0.1944785128320574, -0.2787255380331269, 0.01560113047175663, -0.2002320581613433, 0.3115961907926021, 0.1635870368788743, 0.05678294158098499, -0.476018191230865, 0.3068760522389033, -0.3033131104805271, 0.3509349305650783, 0.3398673523876503, -0.02472276597655712, -0.1406202583056918, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.938841061583187, -25.33986700948118, 3.895381103905187, -0.4068328885046618, -1.020248987608946, 1.875210227283616, 0.8326849356539051, 0.3197332657604331, 0.8814021905636888, -0.191597405724302, -1.189763075075068, -1.758874335134983, -0.01899353751647506, 0.0276611350365027, 0.5048267537307356, -0.5806174579955142, -0.02276182921702848, 0.4354081702397676, -0.1913814507405756, -0.1404271457144592, 0.4293939511517911, -0.2455037565707741, -0.6287458194591844, -0.4325390080784384, 0.5663792753160686, 0.06496758462505856, -1.013812891552513, -0.6580075377114708, 0.3012766122553553, 0.7826160029411943, -0.2956334704185347, 0.5829842798108729, 1.888181195419026, 0.2434171191535548, 0.4382404847806721, -0.2260461131572888, -1.002274173244901, 0.1511392353702925, 0.959534113889126, -0.7055427039674402, 0.6121511681849879, -1.070201333103883, -0.85450815461259, 0.3517683076365886, 0.2515058817628869, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.188440162629536, -18.32569924146616, -9.589804523680115, 0.3710427014950839, 0.3218205714481496, -0.2690828162556131, 0.3778764240350382, -0.3074423748293786, 0.005775081556014241, -0.01195607972614768, 0.4411561531339875, -0.03533727446997911, -0.1118188852301485, 0.5245470238731157, -0.01500837976097037, 0.2330462173829136, 0.3097172521421208, -0.1141404752456203, -0.03010554327463865, -0.3053455023961597, -0.568283713910994, -0.4659469523334061, 0.1389552806909783, -0.2547565634519277, -0.08627456156926228, 0.4559236364597809, -0.3852998773859254, -0.2059868514232366, -0.02375049165040808, -0.3131649641419055, 0.1909454021240402, -0.2322739633649241, 0.008020950818914468, -0.08341805591326434, -0.111253448846017, 0.05259516567515898, -0.001122570051102888, 0.1514471161594721, -0.0404691113211848, -0.008872368197677635, 0.0116933627886483, -0.09874720009960319, -0.03877084404075001, 0.05002466574186254, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10.03537283004762, -31.0463181244779, 1.779031435921747, 0.5805779942073915, -0.1697490764077751, -0.01914980853094367, -0.2211539569318829, -0.4216165170128795, -0.6480115775079677, -0.4142538428904219, 0.06564004090328103, -0.4941714579440745, 1.034278660942381, -0.2047718684985376, -0.01268161547420685, 0.517525878890536, -0.1043791000267504, -0.3647396058345162, 0.2111603242370048, -0.9972172123676774, -0.5115981269692284, 0.4959144934872069, 0.04212237503456763, -0.0259339732866725, -0.1242882315804042, -0.4810924645313537, -0.02365156513499566, 0.2627756243130801, -0.5274144495229729, 0.2708662778382719, 0.8165087143124619, -0.1013704061972073, 0.2726522755404825, 0.3850625905291744, -0.5191444285929395, 0.1772802840204757, 0.3334115942202089, 0.1315431110247013, -0.02250684048613707, -0.169616886212142, -0.3125742719244352, 0.04507962853556727, 0.01003848565633635, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.534564874870957, -24.59524017605734, 3.803193767088361, 0.1204388472709394, 0.5761719808045163, -0.1117681261275701, -0.2329370688709992, -0.08102002281001033, 0.1428619986726483, 0.104842791253757, -0.1181730570197248, 0.4589008851142075, -0.1080200483321708, 0.1900878438866454, 0.1999148634974392, -0.1482677353246511, -0.1560253005429775, -0.148698943892873, -0.5439804195128841, -0.4178164555772285, 0.1013788135893234, -0.2170885424796042, -0.02176885122945166, 0.2064156754855712, -0.3206810843761114, -0.04373791424112124, 0.2504839663865664, -0.28090563960889, 0.1385536322071997, -0.08959168523700539, -0.05811267349918002, 0.005219295271455209, -0.0006095068025606334, 0.05188819365042641, 0.05557911001260952, 0.07279423774972828, 0.07138061600398075, -0.03756847423989253, 0.02816926549231814, -0.07480288912090098, -0.006340103202835009, 0.0003644593817090534, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.032984611804681, -27.23593121948949, 10.91195300159838, -0.1955025467061237, -0.3108776615407506, -0.3861125933123738, -0.2335216115611025, -0.9691736965590945, -0.2809799173614512, -0.2879486799582545, 0.2288415268907392, -0.06960881368743468, -0.3354356497684607, -0.3414928741679384, -0.060828537807209, -0.301089195863019, 0.200552261417137, 0.1352398329475678, 0.3340834458703997, 0.07377669861905928, 0.2564987850409935, 0.3238811050529972, -0.7225355496632641, 0.2551257047021489, 0.1771742636853869, 0.06594998613853977, 0.07018408521301191, -0.05587922004114503, 0.9700092972137774, -0.2579283194903866, 0.6519487404137869, 0.5508375252467951, -0.6490234945917377, 0.1447953357975773, 0.2164634615540051, 0.3169200204043436, -0.03463118539302083, -0.151318881732286, -0.2345691835471254, -0.01993158819697678, -0.05040377327442637, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11.4540626253999, -20.77158386493728, 0.8646709228308843, 0.1362724391608822, 0.1719025418456963, -0.2551996740096885, -0.03511714486680503, 0.1843273888070675, 0.1712704953498521, -0.08238211456267275, -0.0278396535204387, 0.09282985085557675, 0.2532178349906294, 0.08197119062309449, 0.0199260300618629, 0.2535665679716856, -0.1152352645199304, -0.1736314115581865, 0.01698268605977707, 0.04658947833988694, -0.1857939567479137, 0.01460595684305768, -0.05830186068372888, 0.03887623804842972, 0.1233901766950485, -0.03958735173141364, 0.07325984287647014, 0.01640653011899173, 0.1584691045459283, -0.2308825423077231, -0.1894450711707396, 0.01097836857891495, 0.04360019357535277, 0.005697416476426774, -0.2056452089585314, 0.04960126421902575, -0.09143466075759629, -0.0152240285154079, 0.07997148646231036, 0.03173856999389955, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.214993452284615, -24.05350963927314, 2.935180686952885, 0.009367576430711424, 0.02897145608792666, 1.037258110070721, 0.1361330302043889, 0.267403438521004, 0.2041268631368911, 0.009677886298345676, 0.4513281035866327, 0.4879183299083247, -0.04366463541582642, 0.1415327697743105, -0.2267638854965378, -0.4997584611277828, -0.6976848080687116, -0.02518594676737141, -0.2588366599642389, -0.2416744762736605, 0.7221885872238599, -0.5539147131834354, -0.1134910123367641, 0.2737448220857051, -0.2927880039131713, 0.2057867576341399, -0.79800324914354, 0.1932584636177841, -0.5035224041067244, -0.5321735749435307, 0.5437275964446536, -0.1399374304829474, -0.07507775144608267, -0.2918402578666227, 0.09771036738785385, 0.1114599184651533, 0.1302712088256483, 0.0519407976536088, 0.06216196476169271, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.947682961146469, -25.70508238397117, -11.46177925662307, -0.3724367020684367, -0.0346498317775926, 0.06864375351559394, 0.07554361694203379, -0.367323229127421, 0.09593202864671034, 0.1377534867847666, 0.1184603670917067, -0.02650248054294359, 0.2092301771249943, -0.009852203175540166, 0.1288173411245062, -0.01556723710218602, -0.2725343716448551, -0.04882125871058738, -0.1164191596901248, -0.01306504969938954, -0.09972247608276598, -0.05244353803868229, 0.08508888288435545, 0.01494712152255306, 0.06488803226510469, -0.1140190552259744, 0.1236269753074166, -0.2360969288917616, -0.1066473633353232, 0.1264867082185493, -0.02483266501799899, -0.04114542787579798, -0.1266313954297545, 0.03448373932480522, -0.05195144188753792, 0.03249420081315806, 0.03713923614715957, 0.01317281111328615, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11.69631299718309, -22.48619259551776, 0.4736607761650089, 0.3364440611411286, 0.001896101447363962, -0.01839142547031177, 0.03683300808928491, 0.04804330923877288, 0.163622475873788, 0.1554000460872887, -0.08113035605009281, 0.0394436822356209, -0.1518190651150113, -0.2391233604051897, -0.1848160862235859, 0.005028918748719988, -0.1738801952717139, -0.1389518165707553, 0.2440059223399533, -0.1912611405349515, -0.1278732887547087, 0.03594552209482393, -0.1239443437214213, 0.07601115720720845, -0.2413170999853679, 0.01830028011033026, -0.1786719142755088, -0.05040746869497416, 0.1855068663687703, -0.01469530719590392, -0.03565818225935036, -0.006393469065442842, -0.02927051217417908, 0.04981431028590561, 0.01896848487153613, -0.02389638792932929, 0.001671298450249839, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7907072650120487, -24.90261765607406, -3.336934808793186, -0.1100561385510806, 0.03806580362882676, -0.9795899124384002, 0.2113562476336533, 0.1210755170917097, -0.5709907672936722, 0.06148724086826907, 0.4281734290575387, -0.1228023758602741, 1.217889711872614, 0.5772065011935688, -0.8854453190120086, -0.02188476051865783, 0.2939683523215479, -0.3364845598685323, 0.4389370528196214, 0.2175645153244334, 0.1003089157346634, 0.5938129566146761, -0.2639007244911475, -0.4694860419564821, 0.0619677643285282, -0.05717000630200545, -0.3202406910706038, 0.378107742758849, -0.14006136421472, -0.248450630677327, -0.1410998107329354, 0.0735235604182249, 0.006870838292283573, 0.1952510899320096, 0.0282675631387419, -0.003424908838937833, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.437730841654131, -33.27385476914327, -6.935734943236623, 0.2090812561111312, 0.3348393450135521, -0.223586923299236, -0.07352664648222718, 0.03785759488211347, -0.1513766386596058, -0.2099960883438794, 0.1017048240174961, 0.04182607962471709, 0.237579420640883, 0.2399067162829091, 0.07523955310772605, 0.05857405848698407, -0.05389473909058243, 0.2636593955046162, 0.1468245947741072, -0.1210583952104068, 0.1524669191535411, -0.214238636532872, -0.03816758506191603, -0.1354966639865573, 0.09316724617238126, -0.01615929313522045, 0.005900244511659499, 0.1042542689707338, 0.02949183866897195, 0.037267365131775, -0.07808591456574898, 0.03857619705636327, -0.07145363560926057, 0.002429628071270416, -0.01721018579426699, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.66333148382885, -14.4614219114703, -0.8464300600479908, 0.2514104375223278, -0.09861658442109786, 0.1691348097352446, 0.1896581102869329, -0.08087907706641626, 0.01174408327349146, -0.04072839225976889, -0.21084119330376, -0.2084820021746563, 0.06459499104581255, -0.07220761842989601, -0.08081244480389148, 0.2770967905223476, -0.1130641379249503, 0.01313709061334511, 0.1053117612678122, -0.08548227871695131, 0.04755230373305874, -0.239808392738221, 0.006594669706792055, -0.1160148635147146, -0.1546465218776207, 0.1797178820270592, -0.03514352886331645, -9.157443953328604e-05, -0.08036793482879778, 0.002475861135144963, 0.05097461589006569, 0.01013677531395254, 0.0105449596442005, 0.01367406076786437, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.019923386108676, -26.76235000723083, -5.231507339253204, 0.176832541192354, 0.3017249373834541, -0.1388443978394047, 0.2312643317132779, -0.04464652755082743, 0.07808084544420522, 0.4313216233613872, 0.3080530810133845, -0.3090015643058375, 0.2364897664214366, 0.06604367687341839, -0.1876613180395572, 0.3146210580156822, 0.1784726037504162, -0.02271540068963666, 0.2342699465461129, -0.1343387528471265, 0.06625828689355771, -0.003273887803178955, 0.1450943895905023, 0.00620258099433276, -0.09380102559767173, 0.01798478433460103, -0.07862806231355808, 0.05631636830032596, -0.0196969615930718, 0.04436104332404119, 0.05354400105458426, -0.02354762170847734, -0.02514305223947428, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.177075859399771, -33.39258164773348, 1.63759177075579, -0.06342533195251419, 0.1411980486906961, -0.1464775848775387, -0.04431760714090424, 0.01154744252601158, 0.1026506579361863, -0.02088412824928649, -0.02902179807556261, 0.01304836720502356, -0.07271697524786641, -0.07325213106164481, 0.03704096648459854, -0.05922855466144863, -0.06262650371609046, -0.03182071956590917, 0.009080904737058308, 0.1354599956171088, -0.012606916831903, 0.03239503119872632, 0.1409587222872537, -0.06002807561785677, 0.04627926839441229, 0.02573135330017627, 0.004605365395089219, -0.08725168654474108, 0.002587419133345108, -0.05185185645936881, -0.005849547735873801, -0.009771554197080978, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.064718113513358, -13.12988850942804, -3.438372519392976, 0.1264586180050162, 0.004883996372652178, -0.04481988503927746, 0.09576485030352094, -0.3955235936343703, -0.2087500394183668, 0.3073328906227044, 0.02068102374422703, -0.1083588810681304, 0.1758168533371591, -0.1756277739685251, -0.07450374022378869, -0.01630094419723318, -0.1914647508380139, 0.08895278495397248, 0.1403814278690517, -0.03489253346297209, 0.01598763641739303, 0.1131830343890914, -0.06699742805657724, 0.00240472634967058, 0.05514166821797546, 0.03884124270426484, -0.01101385248527006, 0.01954817931909242, -0.03459346077345329, -0.01274466093412686, -0.003543141293631806, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.395368558938009, -27.6115795496259, 6.02328924849129, -0.0217949039676702, 0.01713458866911107, 0.1204807990971129, -0.1903985203838578, -0.245494995765684, -0.01567899867737631, -0.0483287391034937, -0.060209365295053, -0.00658859715813279, -0.1748730515278048, -0.1172896416076897, 0.002885900683208647, -0.2725962934388483, 0.1896424602622011, 0.2547718270544993, 0.08930762271234099, -0.05000517893940885, 0.198774168883364, -0.1836169107571341, -0.001441577306058042, 0.02027315191018264, 0.07922510191796643, -0.01081020778347853, -0.05485129878921055, -0.003504265936056936, -0.01741627502898858, -0.004300648475577595, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.881439123068173, -31.86267091719867, 0.3170578648639695, 0.4687236230510464, 0.02662683343011025, -0.3302193472780357, -0.477346463679984, -0.0517454341931882, -0.3336060762108314, 0.09422553730446168, 0.04946779745885752, -0.5432213903814268, -0.2492264416620409, 0.1732279550240386, -0.09454901437534985, 0.243084678749923, 0.184313316080481, 0.110429054715389, -0.03650964419849936, 0.09749969511293206, -0.1326505036247279, 0.05009598527464214, 0.1082240240233409, -0.1489278834552438, -0.08096188906466491, -0.0850388793794887, -0.1125032485965546, 0.05122382376743441, 0.05527189635692931, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7431797386269411, -14.65117500009382, 5.823447882655948, -0.1881157144876831, -0.3008729186775366, -0.2240680575846533, 0.02294923203244657, -0.1328373063914675, 0.01835629292837719, 0.1359000574454446, -0.3469510665265196, -0.1308216630102339, -0.03496464106937285, -0.2440104038689523, 0.04193512042581821, -0.1366336497635793, 0.03231520148337453, -0.1084198723292215, -0.06739647043502352, 0.08740658296680984, -0.05956248732431352, 0.05155443563206404, -0.06543491661245913, 0.06950710262417095, -0.02430554263388206, 0.003834848628751442, 0.03034298318482847, 0.03421651369935733, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.826424710849555, -27.75807925717017, 6.49845414271845, 0.2088222638768245, 0.2567583755247717, 0.1680006630260083, 0.07113722086014379, -0.03228298686790457, -0.1031612528617338, 0.1843360031254731, 0.07332196070209686, -0.01774216015656859, 0.2986364342557484, -0.00134569499401013, 0.05460048981943994, -0.02322575505419388, 0.08264206029436941, 0.08014218496669946, 0.02559186811441928, 0.06346651700418222, -0.0449661723444516, 0.02381879758386176, -0.08682020285221281, 0.08025959489260269, -0.01003292155179478, -0.02340991530415569, -0.02962714897774685, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.435188878061354, -30.23792586523732, 0.4023394954316882, 0.1442634156119251, -0.1020481640743369, 0.2616580251348765, -0.1059180761079543, -0.08743876827521066, 0.2785769450080205, 0.04428252801918474, 0.0202832410441884, 0.04189636473520755, -0.1103209617823084, 0.08801265177191683, -0.06151324254000396, 0.01355502488640757, 0.1011883046619023, 0.01940829963761287, -0.02376145032104872, -0.04253776187455549, 0.1015931898787959, 0.004439366426774084, 0.02720943797022718, 0.03068092663135336, -0.02169503454248668, -0.04815156165797598, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.23475181130263, -25.85002095399512, -9.61072734631551, -0.2587337302523749, -0.2671090327042298, -0.1373193461266922, -0.01686645319925775, 0.1214524395626546, 0.04787321250564932, -0.0102808929635468, -0.1079687161735285, -0.1204158425469933, -0.01370170730210608, 0.03896661385808254, 0.02006408734658718, -0.01957557336743487, 0.02048657847215082, 0.03186441907330201, 0.01437600500970395, -0.07256365762710008, -0.04268726613146586, -0.004291692030780559, -0.02959742701650543, 0.009784658017416398, -0.001361411062570107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.668539275335888, -23.18029209894821, -7.104549227457261, 0.009494835170991586, -0.2155484926554607, -0.05117708716304314, 0.09558257063666828, -0.006204864175755139, -0.0535983098279376, -0.1721078109347795, -0.1292907195966384, 0.04463480683436428, 0.03962458796875007, -0.03394918991811541, 0.0360179426993984, -0.05098248960386708, 0.05421613324558673, 0.006517343947994034, -0.02849867886559621, -0.07880371848866945, 0.02642259523254391, -0.03587610810807455, -0.0153740561986479, -0.01461543749433446, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.000678311567365, -23.41161932249744, 0.1115405160634775, -0.07148023127921439, -0.03829631039398255, 0.4350529946111771, 0.1273341721442011, -0.03309653396004558, 0.07269741094613814, -0.2517627759593927, -0.0916540014643315, -0.09513082346238068, 0.02936404485630485, -0.03887824155586548, 0.03259923092993516, 0.01480224718798229, -0.06089794884744876, 0.04533354466816, -0.04401696277253729, 0.08384757422274537, 0.03447473565697338, -0.03655777066458333, -0.04286881746219928, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.1997455187845329, -23.67906930857953, 3.298493240502194, -0.1847467985210671, 0.1243176781235989, -0.02243375998252476, -0.0004203531178173071, -0.1373119846655697, -0.07119941044543882, 0.0598855239376691, 0.0365497555952217, 0.09940083973287311, 0.02170561702085787, 0.02523145542278863, 0.01398860677045751, -0.02099249665794002, -0.08042834487614063, -0.04514933257707622, 0.0210691994836113, -0.01304565123088667, 0.003317809080060446, 0.01880126864882835, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.363427418619814, -17.41903576009931, 9.186568349711468, 0.1111029283919205, 0.08777631782411636, -0.0106122045071789, 0.1144225997334068, -0.02466841586746403, 0.02750112055321526, -0.05524437334870362, 0.04541263818821106, 0.04741842472464215, 0.03068743352629459, -0.03255656589538247, -0.03729968912772544, 0.01062121564506963, -0.008575892547858845, 0.02301960098527405, 0.01221098646015711, -0.007828736372639752, -0.02174734678713348, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.23220561660408, -31.51893707701785, 0.629104414809966, -0.002885901152494686, -0.04654352249775812, 0.05655136143073162, 0.04644981489440897, 0.04886269814398012, 0.01421146833364892, -0.02220699538623673, 0.05311321315234985, -0.001358424574760307, 0.00136891734406154, -0.01810167863750104, 0.05846985549778336, 0.02464847599577873, 5.045357884432963e-05, 0.02313650001543124, -0.01897592900555872, -0.01000566869781843, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6213531321316156, -24.30034243436851, -1.105212323117883, 0.1225585085553164, -0.2970472162797997, -0.1131121492749726, 0.005524192917051245, -0.005016083344128715, -0.05408343623542385, -0.02819561803866161, 0.009006334912992457, -0.02024545484485562, 0.03816393987230592, -0.0007047877611201743, 0.04901678014439114, -0.05163410574806857, -0.03130055103817821, 0.03533492988517593, 0.01195601678346641, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.097158496205909, -16.73710946124244, -9.426989245602673, -0.06261182983602319, -0.1059035148370443, 0.05076346286898199, 0.003678172466163399, -0.0454660155043527, 0.02462054291284395, -0.02110890517636086, 0.008241203910568698, 0.02390589384329424, 0.01198364473687612, -0.02957542631061049, 0.002236629456648171, -0.02809381563903465, 0.001689229093064753, -0.007600764285513168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.412003466484951, -31.65984264675678, -0.1254812244514544, -0.09114636575550933, -0.0366463804259801, -0.03322040198025862, -0.01209970867041294, -0.01021849930537397, 0.02256075215944923, 0.01825223707293363, 0.003993042619294536, -0.008507286595193135, -0.02427249385479496, 0.03381794787948238, -0.02914842372731508, 0.007082873675038417, -0.006655560097220788, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.27548187849782, -16.01246939790233, 5.644600469890476, -0.04244915968443123, -0.0371436610514518, 0.0530212677895391, 0.008626194479801664, -0.02358451461610269, 0.007412437106157236, -0.04628615223361372, 0.0826909370927158, -0.01312239177378535, 0.05019812567992653, 0.05643602731883488, -0.03169977188973144, -0.02409525389114796, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.831745814038495, -20.41725582289098, -1.583013759260222, -0.02098081085371714, -0.03289988933600374, -0.006011309758863401, 0.03459650459981792, 0.01348477813223562, -0.02336540423557105, -0.003969872715414671, -0.05998169351462899, 0.05263821645435009, -0.0144354245014559, -0.005674777729486418, -0.03142277004383006, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.562800616132969, -36.13433050173559, 0.2585654510438173, -0.02913169721040965, 0.002592481347938085, 0.004329834978588065, 0.06325089767860387, 0.01951445115945309, -0.03070674283592272, -0.02183384192678349, 0.009849968434859515, -0.02891816499635688, 0.002667591177598971, -0.02361460878909238, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2286035973327459, -15.02261004686781, 5.184122379409034, -0.0264079721355016, -0.007786216137000334, -0.008663526410932022, -0.005309693290799501, -0.006680538291880966, 0.001397532516833339, -0.01528554327177548, -0.01182046150296639, 0.005955666147884051, 0.003523919303238692, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.214570242697843, -21.4621144179193, -1.555874989179182, -0.001447535808513384, 0.03124103143611023, 0.01560612912433155, 0.01254222023040845, -0.0006565581414721336, -0.005837445535672976, 0.003328905310192099, -0.003109407401498421, -0.001359993487917328, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.575215080762542, -36.12196181704586, -0.009581763987488548, 0.02181190823948241, 0.004249343259232833, 0.008866640947567769, -0.008827428692463307, 0.0111903702615688, -0.008259743446844802, 0.005994103918828306, 0.02884522108807095, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.02332478841374811, -20.31760288431249, 5.902175782312199, 0.01411291075117598, -0.0401626029282366, -0.04333034577745157, 0.006563645334078613, -0.02686027801335236, 1.82653938945055e-05, -0.009451944888619017, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.843446424852287, -17.22694391469142, 4.615021811975704, 0.03880112444568462, 0.01156878860697344, -0.02011735633875036, 0.007254465185871957, 0.006976302646061595, 0.01061407563995378, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.636349195088934, -35.03142250661902, 0.03540637402307944, 0.006380325215592348, -0.01715112535803765, -0.005381045082520479, -0.02796704437114206, -0.01837431744975316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03325953074641371, -17.29072432858197, 5.995094557622266, -0.004356649575832386, 0.01324648360020382, -0.002576747161993423, -0.0164552533090047, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.976772821535572, -18.99788030681546, 0.01396461545715264, -0.007601183590626498, 0.005853929901760483, 0.0201199907208218, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.002983340164191267, -20.0342372815637, -5.741448414658583, -0.01215113512395332, -0.00662723431795657, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.752040939724589, -16.25515722920224, -0.00713497387655803, -0.004958024634924642, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0004916632598946193, -12.09805746213948, 0.000198676020167099, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0001765653829615133, -12.09823117436413, + }, + evWant: []complex128{ + -0.2513649571095319 + 26.5196181977274i, + -0.2513649571095319 - 26.5196181977274i, + -0.3323427794627154 + 14.12147023570828i, + -0.3323427794627154 - 14.12147023570828i, + -0.3885760957072044 + 34.01549575140551i, + -0.3885760957072044 - 34.01549575140551i, + -0.4938394681672298 + 19.28755724237434i, + -0.4938394681672298 - 19.28755724237434i, + -0.5354723308245726 + 44.07811563049843i, + -0.5354723308245726 - 44.07811563049843i, + -0.8831210193505878 + 40.64617136580856i, + -0.8831210193505878 - 40.64617136580856i, + -1.063691744877652 + 54.90113796777709i, + -1.063691744877652 - 54.90113796777709i, + -1.270999250073418 + 55.92169849615225i, + -1.270999250073418 - 55.92169849615225i, + -1.641962795944021 + 124.0727533257146i, + -1.641962795944021 - 124.0727533257146i, + -1.866212165366329 + 67.51198073484791i, + -1.866212165366329 - 67.51198073484791i, + -2.66562659457705 + 102.4818444744388i, + -2.66562659457705 - 102.4818444744388i, + -2.677285588970379 + 109.3976583973073i, + -2.677285588970379 - 109.3976583973073i, + -3.592328373007462 + 116.2450441105874i, + -3.592328373007462 - 116.2450441105874i, + -3.658587455178502 + 105.6223525143237i, + -3.658587455178502 - 105.6223525143237i, + -3.738335632746128 + 95.41374995650723i, + -3.738335632746128 - 95.41374995650723i, + -4.05659124602542 + 85.08673687146815i, + -4.05659124602542 - 85.08673687146815i, + -11.7967401639067 + 0.03421683561959875i, + -11.7967401639067 - 0.03421683561959875i, + -12.06591356324058 + 0.03010079020722811i, + -12.06591356324058 - 0.03010079020722811i, + -12.08354870692898, + -12.09435136773809 + 0.0007639916648241464i, + -12.09435136773809 - 0.0007639916648241464i, + -12.09785209014901 + 0.02991559300476182i, + -12.09785209014901 - 0.02991559300476182i, + -12.09806212746318, + -12.09850417485291, + -12.09864274565634, + -12.10160612637007 + 0.004700099158908263i, + -12.10160612637007 - 0.004700099158908263i, + -12.16873692768957 + 0.02446545858852495i, + -12.16873692768957 - 0.02446545858852495i, + -12.23495190373921 + 0.1453184367031505i, + -12.23495190373921 - 0.1453184367031505i, + -13.54778407074696 + 141.1839768257274i, + -13.54778407074696 - 141.1839768257274i, + -15.38790969472481 + 114.0584849752244i, + -15.38790969472481 - 114.0584849752244i, + -23.60369882806601 + 0.2464158068361128i, + -23.60369882806601 - 0.2464158068361128i, + -24.04314341198735 + 0.3315626206724418i, + -24.04314341198735 - 0.3315626206724418i, + -24.12753399862331 + 0.1634093642552133i, + -24.12753399862331 - 0.1634093642552133i, + -24.18103712080912, + -24.18908889661277, + -24.19357072143492, + -24.19567681157636, + -24.20660003986661, + -24.228086198612 + 0.0220672004906673i, + -24.228086198612 - 0.0220672004906673i, + -24.30677145425284 + 0.1813999700804981i, + -24.30677145425284 - 0.1813999700804981i, + -25.23862373866253 + 0.8733279005402655i, + -25.23862373866253 - 0.8733279005402655i, + -29.42427841595277 + 1.666886570068163i, + -29.42427841595277 - 1.666886570068163i, + -33.94959271558832, + -35.51958918286584, + -36.20666045708104 + 0.1660921702962803i, + -36.20666045708104 - 0.1660921702962803i, + -36.25710351845593 + 0.01052251476620707i, + -36.25710351845593 - 0.01052251476620707i, + -36.28714605125749, + -36.29431583135849, + -36.29711199023137, + -36.31304183793699, + -36.32232768169418, + -36.37871120972082 + 0.1557647672076243i, + -36.37871120972082 - 0.1557647672076243i, + -36.47694233727385 + 0.3738707259908102i, + -36.47694233727385 - 0.3738707259908102i, + -36.66483183150206, + -37.75937189360096, + }, + }, + { + // TUB100 matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave, and embedded into a 104×104 + // diagonal matrix to test with ilo != 0 and ihi != n-1. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix big (n > 75). + n: 104, + ilo: 2, + ihi: 101, + tol: 1e-10, + h: []float64{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -1063.761, -960.3970563202379, -0.0006079108185996773, -0.009201940691316367, 0.002442836240270196, 0.01550988534551903, -0.005482455008401117, -0.02216870959395947, 0.009747347615349792, 0.02941831540681939, -0.01530136178573213, -0.03750794345694437, 0.02225359194453896, 0.046705617938318, -0.0307619752542162, -0.05730825585675074, 0.04103856105936231, 0.06965250072575992, -0.05335624663776811, -0.08412633500439758, 0.06805680196063389, 0.1011811513254484, -0.08555957035531082, -0.1213434441393789, 0.106369291926541, 0.1452243676184516, -0.1310809449650698, 0.1735240650736495, 0.1603769717276725, 0.2070245946752049, -0.195009056622052, 0.2465616197175694, 0.2357520481176992, 0.2929587463757468, -0.2833105069304027, 0.3469005841220431, 0.3381503031304328, 0.4087132445918312, -0.4002236126054999, 0.4780213717840138, 0.4685650013761221, 0.5532750093152425, -0.5407842250274101, 0.6312148133425258, 0.6125866029330725, 0.7064838330293224, -0.6776224584955323, 0.7717672671130079, 0.728093737707456, 0.4477228711606641, -1.832801684441419, 1.950252997191289, 0.804390452586547, 0.4832557718849113, 0.3060066166102118, 0.2756451553030591, 0.1719798268352208, 0.1844690914416081, 0.1028522851629666, 0.1338501876768783, 0.05922545829023376, 0.1041210893998114, 0.0294781768570502, 0.08738772703908808, 0.008665658061761334, 0.07957418017688388, -0.005841802748350547, 0.07832978350913038, -0.01561691241238414, 0.08229737118429636, -0.02164114160477788, 0.09076446627208183, -0.02452178964005379, -0.1034535010713481, 0.02461324557496748, 0.1203839900069163, -0.02209524508102444, 0.1417838483570761, -0.01702626635186736, 0.1680394493064578, 0.009377435518891378, -0.1996795871970759, -0.0009558646643977288, 0.2373933824702814, -0.01416583764558031, 0.2820880046959302, 0.03057782300299389, -0.3349961435755344, 0.05073634798692103, -0.3978562481735693, -0.0755607412701291, -0.4732063781751494, 0.1066126139010085, -0.5648764073871733, 0.1465759215609417, 0.67885880956596, 0.2001993093624898, -0.8249735752515708, 0.2762967421832379, -7.383366696690373, 0, 0, + 0, 0, -504.7000323579025, -960.7839130908893, 455.6939154064305, -0.0005890239049151091, 0.01222453307167895, 0.002380254112046573, -0.0183767018575125, -0.005347164384529943, 0.02487432959226112, 0.009507444863507727, -0.03195485414878263, -0.0149219770912947, 0.03986517031337426, 0.02169664773526838, -0.04887103316029169, -0.02998576954964119, 0.05926702273427436, 0.03999696952048423, -0.07138712464416012, -0.05199744338214077, 0.08561585141999975, 0.06632116378894419, -0.1023995009673016, -0.08337613594660015, 0.1222563158317329, 0.1036500341236005, -0.145783656379474, 0.1277114126111218, 0.173658096672846, 0.1562008437363875, -0.2066214365478053, 0.1898032066448404, 0.2454413266872829, 0.2291867817273585, -0.290828708487696, 0.2748879884412016, 0.343286767980235, 0.327114242278849, -0.4028620578438859, 0.3854382883926989, 0.4687761898935385, 0.4483798648521518, -0.5389586517254393, 0.5129393074648648, 0.6095951621601606, 0.5742741750224843, -0.6749584326212456, 0.6258664262549096, 0.7279030750048989, 0.361160520701244, -1.817820120247178, 1.493677993805868, 0.9093218408940651, 0.3437577565805193, 0.362630116371123, 0.182491216989941, 0.221714417427429, 0.1064242506044702, 0.1554403491948274, 0.05893517713417926, 0.1191987572531298, 0.02593630450949156, 0.09940153443435777, 0.001987949044964486, 0.0900967012871452, -0.01567758628187121, 0.08812023104053984, -0.02871634215129631, 0.09168600701701864, -0.03819855166921124, 0.09983277639781361, -0.04483241285443643, 0.112135778661831, 0.04908165568011769, -0.1285288605462619, -0.05123906116349945, 0.1491912175066926, -0.05147890107583802, 0.1744806002258908, -0.04989507359069757, -0.2049040909139878, 0.04652399206028981, -0.2411228487302952, -0.04134974220480257, -0.2839940475275046, -0.03428683940013912, 0.3346573639346669, 0.02513376678028306, 0.3946840836316033, 0.01348469011538719, -0.466320753537143, -0.00142779450121434, 0.5528931223683594, -0.0210105793668851, 0.6595061978534259, 0.04783831497380739, 0.7943401758885881, -0.08674091416897045, 7.282263793289921, 1.964402124200457, 0, 0, + 0, 0, 0, 504.7001065567226, -960.8071533894852, -455.6899665187256, -0.0006381542544069418, -0.01696123848664222, 0.002571421839873352, 0.02356372357492877, -0.005765057328779014, -0.03054576659236009, 0.01023675166561691, 0.03816637411322649, -0.01605159633648196, -0.04669530536153424, 0.02332395960802052, 0.05642332124514469, -0.03222102273610906, -0.06767293164234266, 0.04296780496196387, 0.08080966049331523, -0.05585344634069236, -0.09625362412257953, 0.07123822293842015, 0.1144906642960898, -0.08955981060276022, -0.1360815254382584, 0.1113369911164654, -0.1616662801387938, -0.1371665625346616, -0.1919585350680096, 0.1677064944291291, -0.2277205865868329, -0.2036342514104135, -0.2697050947227386, 0.2455629056115962, -0.3185418058062836, -0.2938904117765113, -0.3745411973588626, 0.3485540671441012, -0.4373871729832214, -0.4086704182323145, -0.5057124011628437, 0.4720841567744535, -0.5766169045256523, -0.5349437472430429, -0.6453152755169759, 0.5915742979267851, -0.705252589538002, -0.6350313138183948, -0.4095510871717013, 1.601644767644169, -1.801430257336091, -0.6783540858316911, -0.4521876448242478, -0.254377814677483, -0.2609137525907964, -0.1390187634586346, -0.1780644458672355, -0.07811098364662258, -0.1332228921784263, -0.03844450844393983, -0.1080065082071247, -0.01031758532230231, -0.09498853030853376, 0.01036100507490249, -0.09032395086444481, 0.02576859065961766, -0.09180684083159034, 0.03723131440198095, -0.09818648544931335, 0.04561209756712017, -0.1088355401035232, 0.05148345180798951, 0.1235465165704314, -0.05522144380747635, -0.1423972092039827, 0.05706613305793608, -0.1656652164809836, 0.0571654881872712, -0.1937812736972878, -0.05560491141385822, 0.2273160612316538, -0.05242306351060358, -0.2670005088314752, -0.04760687919206397, -0.3137829156332985, 0.04106438412981419, 0.3689347453356511, 0.03256097086263596, 0.4342239659065471, -0.02160937448771497, 0.5121963228132351, 0.007270440886606282, 0.6066421962514198, -0.01221319300610655, -0.7234154012137514, -0.04013586770219741, 7.505393492740379, 2.207569919375577, -2.286495948142137, 0, 0, + 0, 0, 0, 0, -504.7004946877645, -960.8313859426444, 455.6868630884425, -0.0004564668894400728, 0.01953047220881932, 0.002110185308335535, -0.02552492771185354, -0.004910008054476974, 0.03185603230051105, 0.008867203935794236, -0.03876493903116766, -0.0140372793617222, 0.04650258449956125, 0.02052143233325077, -0.05533916645715601, -0.02846939294478852, 0.06557394899483331, 0.03808355296447862, -0.07754536439486578, -0.04962400720722794, 0.09164110934556451, 0.06341371783532462, -0.1083072609262454, -0.07984241792495486, 0.1280548395158984, -0.09936692302911229, -0.1514604665622404, -0.1225031219103813, 0.1791553196119899, -0.1498024404391789, -0.2117929820588376, -0.181800940883612, 0.2499814001970585, -0.2189235487704594, -0.2941578702525302, -0.2613208334101781, 0.3443825148816139, -0.3086165449914435, -0.4000320253108334, -0.3595628891688978, 0.4594100673703709, -0.4116578643958037, -0.519368340488319, -0.4608838085460648, 0.5751583010135386, -0.5018561564823436, -0.6208288964715706, -0.2890646136834312, 1.547039886853192, -1.173755403489903, -0.7985207315322997, -0.2625825083083085, -0.321674668942854, -0.1352159819750655, -0.1999732725283456, -0.07366734029347159, -0.1440615953055945, -0.0338692953389332, -0.1147504606082463, -0.005029712242208511, -0.1000175433858401, 0.01695421717090311, -0.09456233266164106, 0.03415869939464086, -0.09556433616678824, 0.04784697925863496, -0.101446550453596, 0.05887259823103022, -0.1113844111571908, 0.06784319765312669, -0.1250437127185277, -0.07520036620749675, 0.1424161499432856, 0.08126890147440424, -0.1637146453439622, 0.08629375258215478, -0.189312804562382, 0.09046906112313131, 0.2197194565251569, -0.09395994411067805, 0.2555854707181692, 0.09691288686658349, 0.2977431307518454, 0.09945154948260918, -0.3472856237053809, -0.1016514559138057, -0.4057014604005721, -0.1034872918659082, 0.475092530300298, -0.1047384672449806, -0.5585328441816623, -0.1048045105961936, -0.6606855376279177, 0.1023541847811403, -7.645111917964669, -2.444190547643892, 3.259474730743878, -1.113400990501543, 0, 0, + 0, 0, 0, 0, 0, 504.7005483880675, -960.8563426765877, -455.6810385506663, -0.0006211890719464708, -0.02717449361052982, 0.002624545711740859, 0.03409357098285602, -0.005942159106883158, -0.04143715413018739, 0.01059135423887447, 0.04948858776950704, -0.0166413313054562, -0.05854418379382578, 0.0242148610679564, 0.06892421088657538, -0.03349146754772453, -0.0809841818387797, 0.04471193925388908, 0.09512623948475284, -0.05818359115254906, -0.1118100512572915, 0.07428496523273895, 0.1315618312735884, -0.09346828354041023, 0.1549790152282817, 0.1162558426750438, 0.1827256545244234, -0.1432240256832661, 0.2155105496963288, 0.1749650364632709, 0.254035038834301, -0.212010638405861, 0.2988909563929731, 0.2546958843850197, 0.3503831721602568, -0.3029377534844611, 0.4082512041088586, 0.3559113648605111, 0.471283605276577, -0.411645725224325, 0.5368790186329719, 0.4666463388955495, 0.6007202940611962, -0.5157903324539884, 0.6568675698020393, 0.5528415071271306, 0.3819646735423662, -1.398313345247025, 1.702130138980118, 0.5594893184855516, 0.4345731607149444, 0.2047273101100171, 0.2544540474780775, 0.1063741954770327, 0.1778805766776483, 0.05255231548952451, 0.137900569051342, 0.01589144268877343, 0.1168704015342846, -0.01147530402843068, 0.1075993573348887, -0.03281602394973369, 0.1063490908368691, -0.04987312975903418, 0.1109852985003045, -0.06374396058252166, 0.1203212709282059, -0.07519208505179932, 0.1337915946504525, -0.08477768059074928, -0.1512472309045833, 0.09292245189830053, 0.1728188948893017, -0.09995295179709891, 0.1988310587279109, -0.1061338258071349, 0.2297560668874317, 0.1116956612897333, -0.2662028365209533, 0.1168534044651449, 0.3089378582466848, 0.1218148638037771, 0.3589424141807773, -0.1267685950073432, -0.417514018459675, -0.1318530493084198, -0.4864325194506035, 0.1370935903164596, -0.5682256141066142, -0.1422822434012505, -0.666604844323565, -0.1467513256218947, 7.839832839255147, -2.591992660256728, 3.08252939024389, -1.472235565518307, 1.200611269528463, 0, 0, + 0, 0, 0, 0, 0, 0, -504.7015918274936, -960.8824172487933, 455.6786628322481, -0.0001386040108547678, 0.02825899575001721, 0.00148000990419925, -0.03396816329492456, -0.003913391729580158, 0.03999719012865367, 0.007442680878789934, -0.04659090322133554, -0.0121162968680667, 0.05400401596298283, 0.01802786748313866, -0.06251037884950617, -0.02531818062112227, 0.07241227284910066, 0.03417801432480141, -0.0840495440103118, -0.04485119411434383, 0.09780784101480898, 0.05763670862206309, -0.1141246897988619, 0.07288798740446953, 0.1334907230535002, 0.09100549877450563, -0.1564413552584702, 0.1124168465460749, 0.1835312438634551, 0.1375347555217266, -0.2152794341013849, 0.1666789233629258, 0.2520679325404323, 0.1999435400148238, -0.2939734797154126, 0.2369931492869313, 0.3405172515888476, 0.2767850762901711, -0.390345045347925, 0.3172634202969561, 0.4409132592457857, 0.3551552329611432, -0.4883580204443008, 0.3861049626417496, 0.5278024954606876, 0.221653617736939, -1.310709133012781, 0.8704550092422116, 0.7079030635461785, 0.1843303003648327, 0.289142189894577, 0.0890031466634482, 0.183755046796533, 0.04093279509465775, 0.1369845466667406, 0.008027106857080303, 0.1140671851302532, -0.01733485053642101, 0.104231064513174, -0.03796088669959809, 0.1026821086919593, -0.05525696194664861, 0.1068620954451136, -0.07011029660696497, 0.115354075966287, -0.08317464933480107, 0.1274397517866654, -0.09497453954477812, 0.1428557674294213, 0.1059485191998991, -0.1616373931580192, -0.116473125434708, 0.184018627644066, -0.1268840153469689, 0.2103748991036934, -0.1374978332735491, -0.2412002758106563, 0.1486321821340762, -0.2771135831612571, -0.1606234825346388, -0.318894700017657, -0.173836022567292, 0.3675540114045308, 0.1886613027997724, 0.4244484685316806, 0.2055082541208365, -0.4914687718702396, 0.224768184994539, 0.571342364466508, 0.246749172743278, 7.942734281408671, -2.790996821413193, -3.416416824440133, 1.502698673759963, -2.74025012280437, 0.4374074524376139, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 504.7014268866499, -960.9091609078547, -455.6702009059838, -0.0004715858695197065, -0.03982840046737102, 0.00242224023844466, 0.04693804869973257, -0.005712413463266942, -0.05453060690126599, 0.01036142963375495, 0.06291484964449161, -0.0164440331698878, -0.07241520054585564, 0.02409153161862073, 0.08338313108173702, -0.03349426180113407, -0.09620848027332857, 0.04490493324477595, 0.1113301550654768, -0.0586415214773373, -0.1292450786759426, 0.07508828443695986, -0.150513154673022, -0.09469143119899404, -0.1757538991751067, 0.1179438613939318, -0.2056275754842778, -0.1453500537954308, -0.2407890904812533, 0.1773573065390127, -0.2817971004678554, -0.2142337181273538, -0.3289552292807281, 0.255870859960439, -0.3820621733814443, -0.3014962025572454, -0.4400643963200938, 0.34931588173307, -0.5006585522123436, -0.3961850233060456, -0.5599910362173445, 0.4375268333475068, -0.612726531008857, -0.4678122672345172, -0.3569120201451431, 1.18831598199679, -1.617583791352987, -0.4321697836882517, -0.4219085060089673, -0.1510420456331972, -0.25146678538168, -0.07059891849129137, -0.1807609333405698, -0.0240329511553917, -0.1456531311906457, 0.009769195529775603, -0.1290384618111746, 0.03669700570302369, -0.1238682627899927, 0.05912761689067447, -0.1264561589974369, 0.07833483431516959, -0.1347055607275304, 0.0951733797931347, -0.1474724563406544, 0.1103088335611947, -0.1642393157936116, 0.1242996284536155, 0.1849045503710836, -0.1376315559768252, -0.2096404850603622, 0.150739321415534, -0.2388041370692126, 0.1640310219820809, -0.2728910081209138, -0.1779123181778702, 0.3125232856726328, -0.1928113592711771, -0.3584705110456833, -0.2091969136508766, -0.4117030466307595, 0.2275912605111247, 0.4734858653437208, 0.2485748286117511, 0.5455291692123926, -0.272779071272836, 0.6302263498990262, 0.3008643534306304, 8.20707478604357, 2.932590880343228, 3.566301858755951, 1.591737361864661, -2.080954844450352, 1.063336818518452, -0.312693340165919, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -504.7034311398602, -960.9369925632403, 455.6692107057009, 0.0004356100354586218, 0.03860199096161918, 0.0003618838493967148, -0.04386380370370079, -0.002169347414784144, 0.04942525667989209, 0.004982545942080307, -0.05553497828831112, -0.008840601544025953, 0.0624511939178053, 0.01382568492204521, -0.07045040500021758, -0.0200635944222586, 0.07983573655308961, 0.02772464186081651, -0.09094444742633617, -0.03702388344715066, 0.1041536259789221, -0.04821924316984402, -0.1198819820124656, -0.06160445551722481, 0.1385840425022496, -0.07749220106038934, -0.1607306169402915, -0.09617998733441638, 0.1867658703825194, -0.1178877608692904, -0.2170271396260865, -0.1426531229291118, 0.2516110942742074, -0.1701709400072701, -0.2901735669785757, -0.1995766655123539, 0.33167198231666, -0.2292104536632618, -0.3741087211620817, -0.2564669531327498, 0.4144141160994378, -0.2779196790709351, -0.4486695658607398, -0.1585148155348832, 1.108326036371431, -0.5816638331406274, -0.6376460733569355, -0.1083863705122823, -0.2651532591988918, -0.04346268036180279, -0.1731791135747381, -0.007919955521890586, -0.1343419559206488, 0.01884997316493552, -0.1172998435413015, 0.04139686964273688, -0.1122109969614702, 0.0612644512371045, -0.1146390321312077, 0.07920415164364861, -0.1222036115318655, 0.09574062739795554, -0.1335955000566879, 0.111342587990221, -0.1481684801491999, 0.1264688165440626, -0.1657058794392267, -0.1415730034357649, 0.1862665137934408, 0.1571022793772566, -0.2100850895889454, 0.1735027646062021, -0.2375159098214737, 0.1912338107828908, 0.2690093363603886, -0.2107891668533592, 0.305116325619871, 0.232719244011093, 0.3465174314368482, 0.2576565915212616, -0.3940792105482042, -0.2863453006006712, -0.4489464059320039, -0.3196699442525448, 0.5126872859904976, -0.3587010976918096, -8.28272768639917, -3.069060360130142, 3.927691039870548, 1.671176660764354, 2.407455234884137, -0.8625377998571393, 2.482297646744782, 0.1292734700574192, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7028824420881, -960.9653940857651, -455.6573959835257, -0.0001045342927213557, -0.05510952876884354, 0.001813256542621175, 0.06227481799574789, -0.004858797016936023, -0.07000242917077827, 0.009264808465575517, 0.07862878594870333, -0.01511232203008351, -0.08850890488940624, 0.02254001315406766, 0.1000277135969499, -0.03174536747972971, -0.1136106715000355, 0.04298556623718725, 0.1297326922178386, -0.05657684359155325, 0.1489234556474868, 0.07288927434017092, 0.1717652930940824, -0.09233189928394896, 0.198877283105147, 0.1153205669594968, 0.2308750852817715, -0.1422162239454809, 0.2682908269428334, 0.1732165788221063, 0.3114322670825245, -0.2081820549922315, 0.3601601689508011, 0.2463834229879688, 0.4135774742746823, -0.2861906631817055, 0.4696707079443848, 0.3247907144321164, 0.5250325498506966, -0.3581320852927125, 0.5749043514816392, 0.3813740651756898, 0.33559864255759, -0.975267052557106, 1.553286395488471, 0.2975654526534304, 0.4156488593431335, 0.09371170961137179, 0.2528219529681863, 0.0318602025876451, 0.1873286487076531, -0.007406320889202832, 0.1569749836318507, -0.03858434309919215, 0.144934740453739, -0.06545817090963257, 0.1441815831728718, -0.08945270328381889, 0.1510120365349771, -0.1113416651259841, 0.1633234601502849, -0.1317257394447766, 0.1799857228617523, -0.1511744615193794, 0.2005086220062386, -0.170257066128721, -0.2248204324462682, 0.1895400302751218, 0.2531160063974417, -0.2095887459424748, 0.2857621049048731, -0.2309786288335811, 0.3232475487327383, 0.2543197035673892, -0.3661698670568465, 0.2802839275652471, 0.4152519125737978, 0.3096388181156818, 0.4713879968706516, -0.3432857433502883, -0.5357238487236324, -0.3823039298241136, -0.6097820756813976, 0.4280142297040914, -8.593418202744859, -3.211955544343986, 4.01550610066904, -1.769542946482932, -2.385993943945727, -0.9351886806923488, 1.364050528322037, -0.9080040622263671, -0.4464199288967212, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7061722826078, -960.9950980825289, 455.6584934644936, 0.001353924213319257, 0.05069804235078336, -0.001403478172758728, -0.05531669887499667, 0.0005546746219488723, 0.0602176601279568, 0.001178736969878009, -0.06565366943648464, -0.003823298510146261, 0.07188614605884883, 0.007444087396122985, -0.07919288756514294, -0.0121433251462564, 0.08787498194637582, 0.01805863608944551, -0.09826218797222715, 0.02535989650826906, 0.1107152897665785, 0.0342421634090001, -0.1256225901932514, 0.04491137284146533, 0.1433858203414038, 0.05755711615621574, -0.1643879418622154, 0.07230425516591216, 0.1889319980546444, 0.08913300093328734, -0.2171379771443038, 0.107757891711349, 0.2487872536298442, 0.1274663214539597, -0.2831201330658301, 0.1469465463422727, 0.3186294299533511, 0.1641875797212851, -0.3529538909796769, 0.1765977012156841, 0.3830228392206152, 0.09923300750079445, -0.9387659102980379, 0.305398543764229, 0.5874526002501284, 0.03421711551743981, 0.2496160794636069, -0.00172104942964322, 0.1682097394146368, -0.02558725561576955, 0.1361268344344931, -0.04691707458719761, 0.1244564737090883, -0.06726669000070251, 0.1239690575086415, -0.08693811269512493, 0.1304369530627798, -0.1060389333362548, 0.141571663489697, -0.1247414524221453, 0.1561163886904096, -0.1433423840955047, 0.1734586694197238, -0.1622500485292275, 0.1933984716847243, 0.1819498382764446, -0.2159900192240643, -0.2029763815613684, 0.2414387822339389, -0.2259034630808185, 0.2700417931160715, -0.2513516107580024, -0.3021617326012637, 0.280007600114253, -0.3382255019637882, -0.3126552129313027, -0.3787429608129044, -0.3502182255490416, 0.4243439334152545, 0.3938138954989248, 0.4758372286628779, 0.4448387377462819, -8.646476556307604, 3.287657641880755, -4.395262558384979, 1.792030252359884, -2.73372973571881, -0.9241141660969929, -1.712422595404809, 0.4359874306747898, -2.432174107259886, -0.6397052114818167, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7050978056665, -961.0251353455429, -455.6426293119019, 0.0005789714464947707, -0.07319751886662666, 0.0006207879061930474, 0.0802799735867732, -0.003129094635399184, -0.08803596071851463, 0.006975460706357075, 0.09683290373786249, -0.01224653915288706, -0.1070596332625383, 0.01908491954449565, 0.1191369742779648, -0.02768776308106317, -0.1335267149602703, 0.03830435886062355, -0.1507372943186485, -0.05122967843956672, -0.1713229356970986, 0.06678971375544743, -0.1958705963395601, -0.08531182846472353, -0.2249654793739225, 0.107069570838405, -0.2591211079527574, -0.1321872027422623, -0.2986553751625171, 0.160487669363109, -0.3434934131000018, -0.191273923827569, -0.3928906485362413, 0.2230621626353611, -0.4451099722739455, -0.2533460049820092, -0.4971642549076689, 0.2785681040388742, -0.5448315365001141, -0.2945449187820606, -0.3188523354151554, 0.7617168830174238, -1.512960882421318, -0.1565418889317566, -0.416770638188017, -0.0330371554958069, -0.2590939561072727, 0.009692898702806391, -0.1979815715767451, 0.04169344337350171, -0.1721638220045798, 0.07052530713197516, -0.1647923498418741, 0.09775169543831891, -0.1687258056803347, 0.1237881291548195, -0.1801639057873346, 0.1488794308490554, -0.1969463086568264, 0.1733613896964222, -0.2179209500175104, 0.1977104526182695, -0.242597178003689, 0.2225166824607487, 0.2709069147142353, -0.2484447312925564, -0.303039084913382, 0.2762089619529779, -0.3393348213625563, 0.3065757332901756, -0.3802323858876161, -0.3403810643090954, 0.4262480705852916, -0.3785664996638002, -0.4779857272391611, -0.4222285054438267, -0.5361702328195965, 0.4726795168378314, 0.6017042384742251, 0.5315431534297506, 8.988404257252103, -3.434234591407497, -4.436704087040918, 1.904958600463788, -2.667252960757383, 1.019315404694702, 1.553413773220462, 0.5240360258904643, -0.8521059937283484, 0.9531203463970385, 1.133055091391562, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7100346863414, -961.0567364446957, 455.646613143601, 0.002722295284934282, 0.06461681973477371, -0.004007947943993217, -0.0683635324772939, 0.004536694220093283, 0.07238640000970466, -0.00433430930478059, -0.07694262150014541, 0.003392025878594218, 0.08229618144787393, -0.001670278858418917, -0.0887242115986121, -0.0008975016974408089, 0.09652212032887546, -0.004400201670914741, -0.1060064440564509, -0.008941741499294128, 0.1175134358385135, -0.01462879396175798, -0.1313898772830384, -0.02154950721841662, 0.1479705007616418, -0.02973757948750487, -0.1675338272440166, -0.03911447566452358, 0.1902263373250469, -0.0494038851796016, -0.2159464070642364, -0.06002011198536771, 0.24419037399957, -0.06995441855483667, -0.2738896861740276, -0.0777218007125729, 0.3033115380943844, -0.08147776924470845, -0.3301302888852998, -0.04342138832490353, 0.800108427299287, -0.04000732313755277, -0.5563775145367175, 0.03855669146460623, -0.2421457122014047, 0.04673467675853111, -0.1685947713495393, 0.05966925766215405, -0.1421356546813504, 0.07617060670611064, -0.1353431117620796, 0.09486340695112068, -0.1392947724748802, 0.1148236878882152, -0.1498272473624081, 0.1355229389653643, -0.1646584030588876, 0.1567892967260354, -0.1825265390991063, 0.1787580887629875, -0.2028097674378218, 0.2017993595211208, -0.2252868325806165, -0.2264439082886397, 0.2499694264649327, 0.2533278498840449, -0.2769901080244833, 0.2831665936584349, -0.3065367197788879, 0.31675352352134, 0.3388193022269569, -0.354979335807952, 0.3740594600432878, 0.3988728455325729, 0.412493048200239, 0.4496557166350698, -0.454379410749675, -0.5088325604398763, -9.020420590072227, -3.450565579378631, -4.828910565671182, -1.874110745373426, 3.031455262150587, -0.9554280057985601, 1.918824600147808, 0.4370410894016331, 1.245159522031377, -0.1566307455549422, 2.552719012229264, 1.137055157228564, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7083084832581, -961.088403701372, -455.6259949644748, 0.001693462288155773, -0.09425609907144253, -0.00135812958186467, 0.1011210298209119, -0.0002358251806337989, -0.1088168511442754, 0.003123702470935177, 0.117746189310862, -0.007394509226016558, -0.1283352037931964, 0.01318721808082886, 0.1410426164823464, -0.02068614552863905, 0.1563657899240353, 0.03011316521908753, 0.1748410515523016, -0.04171287552624901, 0.1970333700401475, 0.05572504926140202, 0.2235071819563995, -0.07233534673786346, 0.2547659637536581, 0.09159167502337025, 0.2911438853529135, -0.1132728046470395, 0.3326320892944551, 0.1367013692972142, 0.3786326012788764, -0.1605193483772494, 0.4276675386247564, 0.1824972953091496, 0.4771381978993297, -0.199534230207109, 0.5233118023773972, 0.2080647751939719, 0.3071312523515405, -0.549473955438997, 1.498520087318462, 0.00989782058163087, 0.4257392836989572, -0.03066419348029967, 0.27053141082994, -0.05385429393158369, 0.2128586455021746, -0.07865838364579553, 0.1912804624944068, -0.1054218514397032, 0.1886052588272439, -0.1333817841205637, 0.1974301330414755, -0.1618922650232225, 0.2137720478898956, -0.1906429188221663, 0.2353555123291881, -0.2196953036046989, 0.2609640871623732, -0.2494334138871651, 0.2900702342300163, -0.2804781709204113, -0.3225735541543351, 0.3136051709871521, 0.3586152379559984, -0.3496963324210602, 0.3984605855948943, -0.3897237334354889, 0.442433754373803, 0.4347674252373997, -0.4908899809534614, 0.48605633051341, 0.5442128827277137, 0.5450303291374311, 0.6028273664098085, -0.6134359722665157, -9.383238747186924, -3.600916739919184, 4.832694315608912, 2.003470413821713, 2.931212798765991, -1.076233974356122, 1.727556840630514, -0.5584158153153711, -0.9677000168663793, -0.2850220760337975, 0.4848137226350174, -1.162124180800043, -1.793676268616248, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7153141286621, -961.1217498954065, 455.6338248564796, 0.004666236513345801, 0.08033835876549655, -0.007676437270062325, -0.08295141844108442, 0.01009977011228604, 0.0858558666115623, -0.01197879976722524, -0.08931330796488612, 0.01333079539699938, 0.09358896098647876, -0.01415383176294858, -0.09895648285762505, -0.0144330727549111, 0.1057012528087135, -0.01414858625643324, -0.114120817737291, -0.01328610322696056, 0.1245201008433383, -0.01185312169985896, -0.1371974259500803, -0.009903932278386084, 0.1524155095853953, -0.007577483035196663, -0.170349858019879, -0.005151094173442019, 0.1910076219888127, -0.003106911843602696, -0.2141162385930753, -0.00219223603220216, 0.2389982098664602, -0.003428653267689329, -0.2644761408819428, -0.007993135284190185, 0.2888757583999775, -0.009238357725273051, -0.689494763421366, -0.2155878440195048, 0.5426652421405607, -0.1100760809768825, 0.2419872852187903, -0.0915757211308498, 0.1738068042043262, -0.09421490159299305, 0.1519131253021238, -0.1063902295366557, 0.1495062851706462, -0.1238496488930524, 0.1576921868225562, -0.144457445676418, 0.1722377145797942, -0.1670559652778887, 0.1907853469363053, -0.1911367180744256, 0.2120098595295308, -0.2166813899045869, 0.2352309624985876, -0.2440312262325445, 0.2601594028118362, 0.2737719046620724, -0.2867127897537385, -0.3066513544997664, 0.3148910096033804, -0.3435341329051073, 0.3446994182012239, -0.3853912741508331, -0.3761050372799959, 0.4333221867749439, -0.4090113357290798, -0.4885956544839816, -0.4432370036767068, -0.5527297958804152, 9.393725843325772, 3.559142669539414, -5.233438534663443, 1.922140772052916, 3.30916008332548, 0.9639922588619462, -2.108426983838054, 0.4210596150978028, -1.37488546401417, -0.126172291118237, -0.9417910946035264, -0.02489482226941209, -2.820413837240554, -1.65719959391188, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.712822627705, -961.1549732256356, -455.6077127096619, 0.003370363513768094, -0.1184233948149237, -0.004352589134933815, 0.1249488727742578, 0.004142598150015885, -0.1325266147065525, -0.002702309633903203, 0.1415989061506627, -5.193242257853952e-05, -0.1526322638582052, 0.004242516041704322, -0.1661238420831387, -0.01002108162905441, -0.1826028877145596, 0.01755321339895132, -0.2026229299653129, -0.02699257791731359, -0.2267375503327169, 0.03843678368101805, -0.2554486834745714, -0.05185463742576753, -0.2891125143344822, 0.06697380838544749, -0.3277869557881715, -0.08312340296797521, -0.3710132247776353, 0.09904931306822057, -0.4175532297672665, -0.1127668418736266, -0.4651618147564519, 0.121590215262521, -0.510544244533257, -0.1225288992181756, -0.3005345609258526, 0.3399230830669571, -1.510041866246306, 0.1414029629131923, -0.4424813889986434, 0.0969566625439009, -0.287030472441386, 0.1002877273344002, -0.2318097264729576, 0.1179696537132148, -0.2141130560573038, 0.1428989401173152, -0.216085496212976, 0.1718969363526398, -0.2299160646037506, 0.2032113426057577, -0.2513516264549205, 0.2359542056548815, -0.2779404049836417, 0.269903604489502, -0.3083522861668259, 0.3053525231567537, -0.3419775604673035, 0.3429586234253998, 0.3786342689363086, -0.3836208986559502, -0.4183589706424067, 0.4283986271914125, -0.4612706968478629, 0.4784824630112978, -0.5074923782141396, -0.5352066248608507, 0.5571092548388775, -0.6000923998546913, -0.6101471292691906, -0.6749305319888952, -9.770051112346868, 3.712532157622387, -5.204107151313059, 2.068330691047585, -3.18125125479366, -1.111446716858055, -1.892155190902516, 0.5769109527951105, -1.074175671579627, 0.2964457689798568, 0.5539281293589068, 0.1648327863802309, -0.2172096485697859, 1.512241614146546, 2.467635656276092, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7224116592663, -961.1902571610938, 455.6205915183505, 0.007332560323131098, 0.09772650675515225, -0.01266681647409895, -0.09890946144936448, 0.01761061930967164, 0.1004319663138764, -0.02223151529100917, -0.1025589734040736, 0.02658527800478494, 0.1055543905435332, 0.0307240137177325, -0.1096846360720932, 0.03470480005138991, 0.1152206928700177, 0.03859926962869588, -0.1224372229859417, 0.04250540794695284, 0.1316063042861069, 0.04656276217394649, -0.1429819416890049, 0.05097254854312608, 0.156770043109164, 0.05602256159687267, -0.1730781884191307, 0.06211263471333318, 0.1918417495221531, 0.06976604123079083, -0.212731221653107, 0.07959687794489242, 0.2350594264866488, 0.09218568189114314, -0.2577207095948243, 0.05895216380708893, 0.6030344606072978, 0.4616425346359402, -0.5436208097610066, 0.1801615878388285, -0.2479542818639472, 0.1359942495801694, -0.1829951211861444, 0.1288696776689487, -0.1647070482516714, 0.1370851711017615, -0.166186009742888, 0.1535729004651733, -0.1783286433187104, 0.175004017949945, -0.1967160001753221, 0.1996016370756137, -0.2188405755084354, 0.2265274150255044, -0.2432545072656078, 0.255616995167631, -0.2691644778819984, 0.287188623645841, -0.296154558573445, -0.3218894031796202, 0.3239813218519342, 0.3605820289961011, -0.3524309991867358, 0.404281451485633, -0.3812277505186181, 0.4541373257413515, 0.4099740685595717, -0.5114462459203447, 0.4381037210394499, 0.5777085075240355, 9.757187794715053, 3.613965379149533, 5.610766740550909, -1.938835199033022, 3.571436149045066, -0.9542168243229318, -2.288013661621963, -0.3938480967566447, 1.496351683252224, -0.08808345484880223, 1.023046330373567, -0.06957848752644458, 0.7559950874575174, 0.1446377341673701, 3.223159785518482, 2.231109599751307, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7190540960186, -961.2250192748934, -455.588180522695, 0.005760119451667827, -0.1458018459472323, -0.008617871967446157, 0.1518886251707371, 0.01036045836723483, -0.1593339434673855, -0.01095512117368798, 0.168623432319206, 0.01033715383235535, 0.1802652315855236, -0.008421308021689847, 0.194792393053006, 0.005117854913200912, 0.2127573865763628, -0.0003573018673901766, 0.2347123846839292, -0.005870115341541783, 0.2611655306170398, 0.0134514921104915, 0.2924997329898752, -0.02205646148738518, 0.3288391697120372, 0.03100724814840945, 0.3698554289066493, -0.0391314172858762, 0.4145293741812473, 0.04465629171074397, 0.4609333830920124, -0.04526915247447261, 0.5061591284697164, 0.03850943070266388, 0.2988211434046964, -0.1343140034874617, 1.545791848932921, -0.2960335360025335, 0.4663736910206594, -0.1651993031618597, 0.3081206807361616, -0.148466528783414, 0.2543776892222589, -0.1590822972569348, 0.2401547949000193, -0.1823264347853362, 0.2466363598796981, -0.2125374666877397, 0.2654664586167893, -0.2468230014420065, 0.2920378799634734, -0.28369945780944, 0.3236595023368128, -0.3226554917179421, 0.3588325700155615, -0.3638932634463122, 0.3968084947760234, -0.4081139430426112, -0.4372603761207967, 0.4563448325195634, 0.4800432615153861, -0.5098306130089106, 0.5250360251830816, -0.5699872792909377, 0.5720443097383854, 0.6384042472680606, -0.620739093955173, 0.7168958955657478, 10.1416026925784, 3.769624166608563, -5.550197612007544, -2.101714625470462, 3.418765229089471, -1.128530918815057, 2.05030202920546, 0.5843666730352316, 1.176141611311618, -0.2998770983489928, 0.6178281648963292, -0.1687738124565776, -0.2572515070648175, -0.1256951327451982, 0.01616907141314794, -1.992214070149926, -3.189662381847132, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7318794445075, -961.2622111936237, 455.6076615218215, 0.01089221138384335, 0.1164944818989575, -0.01927027124317406, -0.1159105114196266, 0.02747804138380453, 0.1157590237274542, -0.03562101111504409, -0.1163053571198556, -0.04381054622555893, 0.11780798689624, -0.05217348627038508, -0.1205218765117039, -0.06086108892227842, 0.1247010612781868, -0.07005691264492792, -0.1305992812196758, -0.07998336769309033, 0.1384666763445831, -0.09090568207321333, -0.148539099266325, -0.103130632313689, 0.1610155426830076, -0.1169945067947107, -0.1760175642549749, -0.1328292092990493, 0.1935251760227961, -0.1508900371219247, -0.2132847544560474, -0.1712230826203191, 0.2346889242553419, -0.1057755931109957, -0.5357642487146973, -0.6973878233988416, 0.5555297188556486, -0.2482482426823123, 0.2583893820691848, -0.1794481217099651, 0.1949556011152848, -0.1629964039187765, 0.1794404990383949, -0.167454966242039, 0.1842879058626768, -0.1830230404376604, 0.2000060175644817, -0.205209645685749, 0.2218995693363221, -0.2316338998877495, 0.2472470804664445, -0.2611383861136601, 0.2744206707423583, -0.2934188634283356, 0.3024520161486941, -0.3287766158418658, 0.330727168992488, 0.3679203274465594, -0.3587549762608285, -0.4118259797084023, 0.3860024176740223, -0.4616568968449378, 0.4117833750068759, -0.5187284681093876, -0.4351768010753159, 0.5845252467597436, -10.10272037837622, -3.615759296992346, 5.961002309639331, -1.925982279272278, -3.820398085376841, 0.9288290974303622, -2.461282861258473, 0.3588964134966156, 1.614524108256882, 0.04643312460190491, -1.101929869918408, -0.1156934037864506, -0.8069532966049089, 0.1939414294536783, -0.6549974120119686, -0.2285123742746999, -3.758505654153285, -2.887002774786242, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7275737129024, -961.2986900862034, -455.5680475291849, 0.00903586301318594, -0.1764481378529507, -0.01443633323006236, 0.1820293926317921, 0.01880447073763833, -0.1893830763324559, -0.02212739922183875, -0.1990394755651686, 0.02438113653662378, -0.2115459961113778, -0.02554785138683405, -0.2274636911241468, 0.02563963642219436, -0.2473516518290995, -0.02473404186599173, -0.271730510328668, 0.02302808689174882, -0.3010128812352733, -0.02091691897707183, -0.3353869095894007, 0.01909834439431709, -0.3746441757811209, -0.01868481784601551, -0.4179627386782013, 0.02126895992019769, -0.4636967305855159, -0.02883173464380446, -0.5092745443586736, 0.04334833925615389, -0.3014407655914791, -0.06601281923988526, -1.602324544766366, 0.4521688717502506, -0.4962602535568542, 0.2344899085974771, -0.3329721059649142, 0.1976354384687227, -0.2798012120081235, 0.201207847611257, -0.2686044483634154, 0.2227918565877333, -0.2793525517309335, 0.254208949035389, -0.3030265762539144, 0.2914075927648672, -0.3345889425740216, 0.3323002062548046, -0.3710472412454519, 0.376082825113517, -0.410672419727643, 0.4228703215020564, -0.4525090987053563, 0.4734101217025521, 0.4960038585709059, -0.5288630443220137, -0.5407310407243179, 0.5906642373893218, -0.5862073308755801, 0.6604544266659836, -0.631770882164199, -0.7400800113225439, 10.4912498465414, -3.773373232627433, 5.869292321428817, -2.105388476297262, 3.643747899009217, 1.129947070197685, -2.20333116034871, 0.5839586073720042, -1.276059903111896, -0.299240532723705, -0.6800685739125477, 0.1698588504724025, -0.2942327379600606, 0.1304150900865758, 0.03800351903695634, 0.1417197104665032, 0.1425294782604167, 2.600515797914067, 3.992077820801224, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7444899137037, -961.3378869284877, 455.5961766575729, 0.01554496586389417, 0.1361607262454429, -0.02781289414814694, -0.1334206115553933, 0.04015195437573545, 0.1312610252962056, 0.0527238328643537, -0.1299420806015547, 0.06571735393480846, 0.1297113267134137, 0.07935679284872428, -0.1308093221619015, 0.09390646392500906, 0.1334765342836597, 0.1096692934744826, -0.137961097981063, 0.1269759901739711, 0.1445257840878497, 0.1461596796124059, -0.1534505818065084, 0.1675090650339144, 0.1650223724407157, 0.1911922811662067, -0.1794965959880791, 0.2171469054347325, 0.1970054498924576, 0.2449372580636083, -0.2173831194355537, 0.1495893184212565, 0.4816785595258409, 0.9209202815588715, -0.5736517097497067, 0.313353604698171, -0.2711605588560934, 0.221082155663423, -0.2081281229339226, 0.195658000237407, -0.1947111978907778, 0.1963739070246782, -0.2023853087811128, 0.2108169700402979, -0.2211665513822386, 0.2333844452691181, -0.2460259436412557, 0.2611196517524419, -0.2739795084733933, 0.2925613936013013, -0.3031638285603235, 0.3272759615201772, -0.3323671520526524, 0.3655494198939995, -0.3606901700963588, -0.4081518881755232, 0.3872850919084128, 0.4561704112264385, -0.411165351471291, 0.5109046669029912, -0.4310695720851319, 0.5738286008172455, 10.42318783741847, -3.566018330179493, -6.283039963892671, 1.885086978417805, -4.056461148196111, 0.8896096623583637, 2.629879524658232, -0.3183134586090979, 1.732009409551348, -0.003597002249112677, -1.181752365540581, 0.1607426656367353, 0.8594318003331071, 0.2409887971627989, 0.6872601018528763, -0.2776927275225095, 0.6162945944580821, 0.2949229569475111, 4.432330830999809, 3.652258417704127, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7391854477888, -961.3761134831929, -455.5483160115629, 0.01339975427289111, -0.2103617083669475, -0.02212129334677451, 0.2154107935057459, 0.02989586468758025, 0.2227762054914026, -0.03675410570225757, 0.233029559420389, 0.04274488714190522, 0.2467489261215965, -0.04795860482498126, 0.2645069025107166, 0.05255917574259697, 0.2868406962417143, -0.05682989248602897, 0.3141931378633969, 0.06123725611583161, 0.3468116005115335, -0.06651167350925496, 0.3845953195758418, 0.07372631291715646, 0.4268969633578305, -0.084324035113474, 0.472317693749994, 0.09999329127000312, 0.5185766012306021, -0.122267111761034, 0.3075794130567557, 0.2594922311530679, 1.674677840688869, -0.6074411217165189, 0.530504621157434, -0.3036489093269464, 0.3604292259290603, -0.2468040165898022, 0.3070437102038547, -0.2433124059830945, 0.2983965063767964, -0.2631034380950553, 0.3130548980457453, -0.2954872738506904, 0.3412458946213262, -0.3352576648480358, 0.3774381296472452, -0.3797257621045876, 0.4182777341843855, -0.4278008133993835, 0.4617385983648974, -0.4795135491180799, 0.5065767007844517, -0.5356633184142464, -0.5519108635118929, 0.5975519447496171, 0.5969093166328796, -0.6668064787959627, 0.6405721802139768, -0.7452989581305071, 10.81295073151522, 3.725997667527157, 6.159022350342218, 2.081113170768998, -3.855102702242159, 1.117501368797665, -2.351235823926313, -0.5777697467504209, 1.374856223267653, -0.29701181947491, 0.7424138377886643, 0.1710585953742098, 0.330797445008233, -0.1353650627227564, 0.0576408564358677, -0.1510793503432264, 0.1322861784530395, -0.1959399824468592, -0.2765948893642101, -3.344039432155814, -4.906745836243842, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7613365642291, -961.4178098908683, 455.5878220684487, 0.02152739456950745, 0.155990589845504, -0.03865954626620611, -0.1506307363154621, -0.05612307601046214, 0.1460612037459447, -0.07415968563775244, -0.1425284489543925, -0.09305949879988605, 0.1402637839647557, -0.1131625092824421, -0.1394959528064121, -0.1348497243264618, 0.1404692206213771, -0.1585184900258227, -0.1434668149614358, -0.1845343498098827, 0.1488370709744961, -0.2131515106483328, -0.1570114703269528, -0.2443967819326662, 0.168490761061717, -0.2779233867878602, -0.1837542375722553, -0.3128574421494117, 0.203035425587468, -0.1900946734061147, -0.433834219025143, -1.129221067589957, 0.5923000478378968, -0.3740906900280064, 0.2836979264745814, -0.2597387711190001, 0.22062681445908, -0.2256295048723918, 0.2088235792854549, -0.2224048277552317, 0.2187578425407568, -0.2352143633671168, 0.2399405360599269, -0.2574227677607072, 0.2669932721109848, -0.2855421185023375, 0.2966388173566911, -0.317835119944384, 0.3267272928345747, -0.3537499822930283, 0.35572663703428, -0.3935627878927179, 0.382347718395156, 0.4381069694359088, -0.4052516396076142, -0.4885743991703206, 0.4228306365409398, -0.546400243704626, 10.7123505563827, -3.467401368528632, 6.574905698665654, 1.817773117729432, 4.278777619641925, -0.8378218541754415, 2.793944829112401, -0.2733177456826802, -1.849759245051467, -0.03915110965119177, -1.264069361132026, -0.2034284048409766, 0.9153371450385213, -0.2846049852576992, -0.7235404151249138, -0.3227953515570327, -0.637237958096172, 0.342187055210012, -0.6250483028853673, -0.3568764257507016, -5.257937304882959, -4.55508554936837, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7550364030109, -961.4583496977284, -455.530480379083, 0.0190938476296795, -0.2474730170941161, -0.0320248394429458, -0.2520068723070391, 0.04409746139951185, -0.2595497997911581, -0.05542064500866747, -0.2707037328264438, 0.06615890175647458, -0.2860590669957729, -0.07656112549161879, -0.3061707763092542, 0.08699898599850459, -0.3315091701035143, -0.09801668999733169, -0.3623728933478695, 0.1103893488200521, -0.3987539286431652, -0.1251703436227577, -0.4401558607610471, 0.1436810276293193, -0.4853934971597049, -0.1673540627022936, -0.5324352881075169, 0.1973214093273239, -0.3162259135719306, -0.4443061610633235, -1.756700779373999, 0.7590020979393318, -0.5670900504193579, 0.3712553167121694, -0.3890806275027168, 0.2947777467691565, -0.3348571513627888, 0.2841510646953452, -0.3282692231155715, 0.3018275022954646, -0.3463689030326972, 0.3346649164831056, -0.3785725697111055, 0.3763313412808598, -0.418806990424517, 0.4235591970882376, -0.4633012783675338, 0.4749833840580253, -0.5096588677124098, 0.5305616262560031, -0.5562508167799632, 0.5911571677427112, 0.6017445089562359, -0.658220168495264, -0.6447469122637461, 0.7335866606257689, -11.10138605254825, 3.631034314442978, 6.416520283055733, -2.030929045438653, -4.050883210517207, -1.09263234274095, 2.492947931639272, -0.5671254785083639, 1.472262538497965, 0.294648565121288, -0.8053212026371659, 0.1740959578194711, -0.3680979667177443, -0.1426477808213935, -0.07701400313898601, 0.1623356308255878, 0.1242639559307309, 0.2112653724844634, -0.2740335801422096, 0.2779853011318764, 0.3991136330708569, 4.237178417243852, 5.966755879689668, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7839768955486, -961.5031356303735, 455.5850306639925, 0.02912480258648458, 0.1749203040042703, 0.05222060442792607, -0.1663669930730279, 0.07592414985531605, 0.1588763076469116, 0.1005831663097198, -0.1526711551376601, 0.1266078291343768, 0.1479660097637017, 0.1544547454180628, -0.1449948514511539, 0.1845887043750316, 0.1440505633533104, 0.2174126453759208, -0.1455339392818743, 0.253156701007274, 0.1499995768662069, 0.2917237939532877, -0.1581666783968385, 0.3325088566360749, 0.1708317017743966, 0.3742344872602825, -0.188600178511197, 0.2268316604370843, 0.3845480392234077, 1.318322244561246, -0.6050237732153305, 0.428731430577431, -0.2930800029727587, 0.2940064673796119, -0.2303095703759141, 0.2514426080702059, -0.2198597838188783, 0.2438453429385534, -0.2314722939759387, 0.2541700231595779, -0.2542443363261532, 0.2748630106477523, -0.2824784951384094, 0.3019732811307502, -0.3125960540799213, 0.3335263049897976, -0.342113632573852, 0.3688741680327827, -0.3690936466192343, 0.4082952782635644, -0.3917330876661867, -0.4526883946043698, 0.4080384200378837, 0.5033598302349126, -10.96490758246675, 3.324010782640217, 6.833995337770606, 1.726068427677496, -4.485538946284208, -0.7744900179888866, -2.952462441243869, 0.2245238076687357, -1.96746806450077, -0.08132430877219025, 1.349148411398959, 0.2433017034817874, 0.9753204169954288, 0.3244179414574758, -0.7646022741758332, 0.3636921476151955, 0.6637918690093022, 0.3848718174085247, 0.6393750651856561, -0.402120829041611, 0.672076261839223, 0.4236321878220717, 6.255464776858338, 5.625936364814542, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7767711685316, -961.5466022439307, -455.5167169920276, 0.02641646045759053, 0.2876293875521561, -0.04455269836068995, 0.2917046426611087, 0.06192864199017718, 0.2996413203859867, -0.07877768540105098, 0.3120491459019933, 0.09543210301352055, 0.3294985036302559, -0.1123540725858994, 0.3524803724007334, 0.1301721006693483, 0.3813326175940071, -0.1497179815896551, 0.4161216500474114, 0.1720439307471236, 0.456476553154757, -0.1983762992393827, 0.5013934945639351, 0.229926008851196, 0.5490538865200292, -0.2674630790920627, 0.3262584781762246, 0.6184594756429348, 1.841505465819113, -0.9036920907968744, 0.6037649288986811, -0.435730331781932, 0.4173633503092889, -0.3402273078184248, 0.3618792001829753, -0.3223329221765415, 0.3568694292734518, -0.3373610302359374, 0.3778471175268359, -0.3698307686701466, 0.4133989349283659, -0.4123481977579463, 0.4568802691238098, -0.4611046705689894, 0.5040519090114971, -0.5144902166835649, 0.5520670643889852, -0.5724133548481751, 0.5987991975851327, -0.6358180460131468, -0.6423152491290044, 0.7063313713285493, 11.35202456455329, -3.493500196224254, -6.638568150183083, -1.957344673859988, -4.228485425971068, 1.056606712337717, 2.626551471527081, 0.5527901502998748, -1.5670524346359, 0.2928237369304179, -0.8682190156229788, -0.1797627572714807, 0.4061836395463059, -0.1532886909026603, 0.09679996807476349, 0.1768465936273609, -0.1170417081935488, -0.2292432522445197, -0.2742907297354369, -0.2992562708270863, 0.40201700883393, -0.38229571927536, -0.5200048155415438, -5.301175868637563, -7.207800765406747, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.8146309446975, -961.5954948017205, 455.5912580995108, -0.03868887300459015, 0.1914593508419486, -0.06896288380706332, -0.1789757931782649, -0.1001298844401407, 0.1678836436039876, -0.1326643353856479, -0.1583758389218828, -0.1670959289351405, 0.1506643220501891, -0.2039577762706567, -0.1450354518997625, -0.2436945939407161, 0.1419222648546592, -0.286520727014479, -0.1419791043669855, -0.3322284769841388, 0.1461191154367376, -0.3799736358824325, -0.1554340998005074, -0.4281019938694952, 0.1708890736518134, -0.2592200631304444, -0.3256852567521202, -1.483625349429867, 0.6048929864489581, -0.4753236422915989, 0.2961694592646632, -0.3223046209916502, 0.2348874153138894, -0.2714626999105824, 0.2257895769533033, -0.2588066214268311, 0.2385080365992549, -0.2654198271110554, 0.2619285315116793, -0.2829866644015172, 0.2901165131905762, -0.3071846631133203, 0.3192058852536734, -0.3358595624892154, 0.3463380609514268, -0.3683054470711298, 0.3690746037927644, -0.4048218311662792, 0.3849522860948287, 0.4463965618803197, -11.17658830910763, -3.141599888182389, -7.057308180610275, -1.612632569840935, -4.674228358739717, -0.7006254562246356, 3.103524645986586, 0.1721449712789752, 2.083843108349515, 0.1230344465499392, 1.436244916006413, 0.2805779655633087, -1.039058835442039, -0.3606873771771562, -0.8103535254099236, -0.4007449405027154, 0.6957974817861713, -0.4236310613634878, -0.6603595623427048, -0.4431665472145394, -0.6828038414913131, 0.4676302900407178, -0.7523362731509651, -0.5019606323960604, -7.451487262070271, -6.898592890440204, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.8067442478319, -961.6430987511887, 455.5101352313706, 0.03574672013766993, -0.3305806211988256, -0.06018793703629798, -0.3342789822135747, 0.08398862072600807, -0.3428477394831397, -0.1075626639881692, -0.3568661462114826, 0.1314655734088672, -0.3768341259425303, -0.1564176785432246, -0.4031115942603709, 0.1833201534769062, -0.4358166092177098, -0.2132428552839921, -0.4746756170442514, 0.2473424911876484, -0.5188341233287944, -0.2866404669967078, -0.566654544358885, 0.3315822789153745, -0.3365523808315161, -0.7799477365989287, -1.92204447761313, 1.038304945171675, -0.6382333295246007, 0.4954672252621077, -0.4437009237950818, 0.3817879746615038, -0.3867630435618042, 0.3564182943353214, -0.3828941956014584, 0.3680304652111646, -0.4061335779417263, 0.3989834362533684, -0.4442583228007695, 0.4409123847406293, -0.4900404834181868, 0.4895313969246102, -0.5387255048657738, 0.5430334536942414, -0.5869290800627904, 0.6013145526212335, -0.6318954893637412, 0.6654442464724272, 11.56123863009346, -3.319983549512171, 6.821845065194244, 1.863466932603496, 4.38488470063812, 1.01067094368389, 2.749511386838089, -0.5351194258268466, -1.657256920227764, -0.2915679928571555, 0.9297221747564861, -0.1880812619045127, 0.4442416560586033, 0.167463535694055, -0.1167505114866327, 0.1950254755353985, 0.1102695455592749, -0.2505965089753026, 0.2762752306336164, 0.3233977751863117, 0.4086760961549661, 0.4088566255401637, -0.527180830087615, 0.5067736816255463, 0.6471037120006224, 6.563582277433596, 8.669169878915001, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.8564496879252, -961.6978071512939, -455.611344166528, -0.05065962634433919, -0.2035667717073716, -0.08941939694818055, 0.1861819141070234, -0.1293463728361657, -0.1705641231959824, -0.1710413062870665, 0.1568853187052691, -0.2151073082088822, -0.1454027021144876, -0.2620355483771115, 0.1365557074206818, -0.3120320827642339, -0.1310718629875927, -0.364788555337083, 0.1300347438234267, -0.4192352859893375, -0.1348167335882609, -0.473360750181653, 0.1467438213440089, -0.2866158909387535, -0.2490263897518478, -1.620329947670383, 0.5848677254506903, -0.5118461330390914, 0.2897889114975229, -0.3429946413052233, 0.2320656306481047, -0.2839885316813635, 0.2246136703445073, -0.2653143559437961, 0.2379182651793468, -0.2665902029177392, 0.2609701715451156, -0.2789374326510159, 0.2877297688810677, -0.2977825578364603, 0.3140810644157221, -0.3208740171767074, 0.3367519648803812, -0.347497849625001, 0.3526960178041265, -0.3780240749856291, 11.34415339639681, 2.9276728518795, 7.241716186208386, -1.480912627484681, -4.841851735919054, -0.6174008600345655, -3.244551359081532, -0.1161699839121046, 2.196810963053788, -0.1648403832407603, 1.52378878614412, 0.3160144776303719, 1.105419207445201, 0.3942117305648183, -0.8599720166997633, -0.4347652751226382, -0.7325429176455468, -0.4593657200668957, 0.6870715556985062, -0.4812114897627066, -0.7009216608316468, -0.5083517726327081, -0.7613887957889477, 0.5458417512230326, -0.8637959811793713, -0.5970603500508016, -8.878579618167663, -8.41079729749319, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.8483022209899, -961.7515375401339, -455.515103378266, 0.04757600714722041, 0.3759601994912693, -0.07952182508355922, 0.3793600134854735, 0.1109858526574028, 0.3887731574427825, -0.1426212566623932, 0.4046909058892191, 0.1752498328905884, 0.4274717745852317, -0.2098572245667174, 0.4572568690190124, 0.2475512176980405, 0.4938376701380627, -0.2894449308435921, 0.5364758189264845, 0.3364018036152697, 0.5836858088124017, -0.3885795342274033, 0.3460998677017337, 0.9269607883637689, 1.991751849844172, -1.159894903453939, 0.6683678480468542, -0.5489774865143997, 0.4666584984984303, -0.4181743697237709, 0.4083256137378595, -0.3850224904055522, 0.4052531090492756, -0.3922030940012985, 0.430154764416738, -0.4201452172640414, 0.4700533145873315, -0.4596423877934347, 0.5171413042952349, -0.5060190814650223, 0.5661040793608841, -0.5573376710742627, 0.6129220747774261, -0.6135503322915893, 11.72621780801965, -3.118567404640785, 6.963211382717763, 1.75302164155703, -4.516867569899999, -0.9561071819941682, -2.858888666291709, -0.5141429755265274, -1.740364185208108, 0.2903667692240343, 0.9878145752430977, 0.1983973188452912, -0.4807765726797618, 0.1846015909228558, -0.1358948953187996, -0.2164957212324468, -0.1043808041537456, -0.2751935128773355, -0.279826746444909, 0.3505627343904102, -0.4181686778299342, -0.4382062477600169, -0.5392140048606524, -0.5377014109662097, 0.6579315820212267, -0.6517663504946155, -0.7869275609113959, -8.05753646041288, -10.39414405360874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.9138637696153, -961.8143515653112, 455.6519677186474, -0.065587947208334, 0.2085029215343718, -0.1141904493380159, -0.1849281174071089, -0.16417292084848, 0.1635422401442634, -0.2162120711863979, -0.1445429665498645, -0.2708523356285875, 0.128343198787713, -0.3282995933633563, -0.115712162032152, -0.3881537124649574, 0.1078796554266659, -0.4491292094201663, -0.1064891874455163, -0.5088711427777188, 0.113241647884544, -0.3083741181691479, -0.1467011040433109, -1.723923205907633, 0.5382296108587682, -0.5363846735303583, 0.27092624926658, -0.3545066321432684, 0.2197099884192319, -0.287363686337111, 0.2145312764451768, -0.2614204612340402, 0.2280211406842278, -0.2553142195422838, 0.2496987336771662, -0.2598467419074491, 0.2735997743104482, -0.2703495132715409, 0.2954157424967072, -0.2845730952075546, 0.311423814533789, -0.3018822827637243, 11.46523893315575, -2.691413015229958, -7.384362245400597, 1.335236216275609, 4.985185235965488, -0.5262745591804759, -3.372485074148798, -0.05648924165287231, -2.303682267268397, 0.2076207204669117, 1.609522758219237, -0.3508002202525652, 1.172561778202216, 0.4262482117585027, 0.9119656734777154, 0.4669796982018008, -0.7727539450790861, -0.4932706593868525, -0.7182401966339386, -0.5175074770463448, 0.7247978830712355, -0.5473237053574408, -0.7783621609313609, -0.5876369322550071, -0.8723083916636201, 0.6419574139158084, -1.00657473616704, -0.7131802559475791, -10.57449072135191, -10.20410649815866, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.9061412862011, -961.8770732639229, 455.5376417683805, 0.06254419195417743, -0.4232684972590032, -0.1032882224080658, -0.4264012907068119, 0.1437641786514711, -0.4367775016311054, -0.1849091479680357, -0.4547230616343913, 0.2278125351396496, -0.4803659165556683, -0.2736445954407336, -0.5135240332136976, 0.3235038064582032, -0.5535385281539781, -0.3781288842484928, -0.5990476261198098, 0.4374274060989551, -0.3541391351405594, -1.058073342162964, -2.045216966325468, 1.266080794797456, -0.6924316493113732, 0.5950376234995193, -0.4851062828675501, 0.4482900280297341, -0.4257039247593362, 0.4069187711414488, -0.4232424419027072, 0.4083834788979941, -0.4493250721690615, 0.4314669583481853, -0.4903032612085907, 0.4662810430706394, -0.5378049265577316, 0.5078722409403839, -0.5859084246214689, 0.5542724904405595, -11.84485447706039, 2.898542856056091, 7.060252299552289, 1.630303727224056, -4.621383723680353, -0.8942453459292238, 2.951610305967167, 0.4895834794482448, 1.813545938433091, 0.2881843187274703, 1.040043542488245, -0.2094177206260044, -0.5137794499925029, -0.2034268577435624, 0.1527024933413826, -0.2401406725930453, -0.1004080668438968, 0.3021385233083859, 0.2854472563703663, 0.3800924576032388, 0.4303872415260588, -0.4699267499381296, 0.5551933085574434, 0.5711417670203969, 0.6747267714850889, 0.6859780125203653, -0.8010046828883495, 0.8192592301466893, 0.94515561658495, 9.820426173212363, 12.42939017103546, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.9930103786541, -961.9513356663066, -455.7221717257553, -0.08414743711096713, -0.2026736860667679, -0.1439128065966526, 0.1712281387505495, -0.2050964145610792, -0.1424763186319537, -0.2683067024845924, 0.1167626582609214, -0.333761142126125, -0.0948595784588155, -0.4009780128477423, 0.07811577117355756, -0.4684645116803408, -0.06843920146675211, -0.5335327087101004, 0.0679294038621997, -0.3239054824125787, -0.0116792012931699, -1.790663616927004, 0.4590524896071508, -0.5473106572190689, 0.2369585734237551, -0.3554648484778318, 0.1960271233909658, -0.2800877958506142, 0.1941244183782809, -0.2453078173802557, 0.2076091627418861, -0.2293383987055, 0.227046232106705, -0.2229498501452899, 0.2467672230652324, -0.2215577701206991, 0.2623437054600908, -0.2230571348710727, 11.53795815371153, -2.443315951606555, -7.483391968859528, -1.180817659033836, -5.101147725873458, 0.4291177015601163, 3.484008053855922, 0.006968221311336701, -2.401299468052032, 0.2524588129698827, -1.690603619495555, 0.3864574901609267, 1.238005582549325, -0.4584326101560443, 0.9641940337828574, 0.49897471755453, 0.8145568272198119, 0.5268294835097378, -0.7521215969515586, -0.5534552278380493, -0.7525858951277018, -0.5859592679598992, 0.8009010588386255, -0.6289928712031305, -0.8890676867080832, -0.6859830214698649, -1.014965640327654, 0.7599429084175442, -1.182234401254345, -0.8539617213615083, -12.58037930190747, -12.3224597531326, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.9867232586682, -962.0267397173889, -455.5858482841886, 0.08146568040030745, 0.4718570639702241, -0.1323792393628501, 0.4746520270081164, 0.1832926548394762, 0.4859370727590149, -0.2354260094769804, 0.5057808128620681, 0.2900438647951354, 0.5339800783871049, -0.3482656295242084, 0.5699120289626995, 0.410743635210365, 0.612307221970398, -0.4771765920828036, 0.3602759907915838, 1.17231410234708, 2.078779437679099, -1.355247085704674, 0.7092702971335834, -0.6327846462311433, 0.4983600087248974, -0.4713003995691609, 0.4384934063277775, -0.4210960673642488, 0.4367016135277066, -0.4152685840028347, 0.4637359288734594, -0.431277660159945, 0.5053758360548571, -0.4587373301787441, 0.5527030534382514, -0.4925622070803836, 11.91525071372664, -2.669737940207489, -7.112070179658535, -1.499950988056173, -4.695989395278955, -0.8264068408364236, 3.024764719308382, 0.4608488246132006, -1.873884959550882, -0.2834560461830024, -1.083707901266197, -0.2191901436954789, -0.5408889135616145, 0.2219393955259065, 0.1652261958197461, 0.2640887562841959, 0.09983770284304504, 0.3297673240943492, 0.2941272369903571, -0.4105473985768032, -0.4457746369230076, -0.5027821554303129, -0.5749124856717664, 0.6060241185316116, -0.6964125744179374, -0.7222036226954593, -0.8219917097087917, -0.8553991180861862, 0.961952339859114, -1.012160660965054, -1.126829376377705, -11.89125844216821, -14.82268386167739, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.1021960848271, -962.1169026393795, 455.8338729921806, -0.1071062110747086, 0.1815070603285521, -0.179150267652292, -0.1400998028560625, -0.2522503910014173, 0.1021004970621845, -0.3266542012589974, -0.06823635379950285, -0.4018139642522497, 0.03994126095184518, -0.4760406224002068, -0.01938011015157691, -0.5463234758642321, 0.009080595156260448, -0.332710657886771, 0.1616900475175027, -1.817966811669035, 0.3426834356104604, -0.5434318586351045, 0.1858789109600244, -0.3447965208108256, 0.1597482455188877, -0.260904925528362, 0.1625453870579868, -0.2153733000095499, 0.1761648327255745, -0.1866055914925562, 0.1928056464078325, -0.1656576200451232, 0.2073444379444271, -0.1482507898985436, 11.55984343995971, -2.194330913236887, -7.539191327935495, -1.023568455741856, -5.187360036320147, -0.328277306992068, -3.575805403221234, -0.07408649072083257, 2.486163835875462, 0.3004875937099439, -1.763663794387484, 0.4247125801810033, -1.298641369289637, 0.4926794598061576, 1.013844940412112, -0.5326247822284832, 0.855408835835386, 0.5617664880260144, 0.7863621255143287, 0.5906033658897508, -0.7819719026602904, -0.625663908357995, -0.8264736550053368, -0.6712690869377209, 0.9108668466439265, -0.7306688749077851, -1.031594825877172, -0.8068049947691155, -1.19005694174046, 0.9028377648786338, -1.393080617256989, -1.022486576162642, -14.93725702842511, -14.80858779518792, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.0986792310538, -962.2097661716811, 455.6702293933568, 0.1053158391624666, -0.5209308336066629, -0.167801730661908, -0.5231587860538264, 0.2305615961092414, -0.5350545218265784, -0.2949981297092716, -0.5563330952365698, 0.3622987997093375, -0.5863529471226727, -0.4330778853603579, -0.6238972077621375, 0.5068738237225937, -0.3645929382416744, -1.269034197433159, -2.091002309996033, 1.426568270000934, -0.7184531759372009, 0.6617359656374076, -0.5062857257808602, 0.4866398522234159, -0.4468522920838534, 0.426758635928322, -0.4461365544464869, 0.4117361542474164, -0.4743095042403939, 0.4180529165899515, -0.5166800360497492, 0.4350417285374433, -11.93487401223153, 2.441424296363036, 7.120614763298893, 1.366543100975028, 4.739536856455961, 0.7537631620120923, 3.07601221737414, 0.4269745581475306, -1.918657953164775, -0.2740524529274999, 1.116076917175963, 0.22506572849195, 0.5595705076145522, 0.2373597796023182, 0.1712561169743348, -0.2856470413363019, 0.1044690985263356, -0.3555730312438909, -0.3071946247653678, -0.4396379038796807, -0.4651362087062904, 0.5346799860173224, 0.5985834061049665, 0.640392538677784, 0.7224826043854548, -0.7585342198697523, 0.8484129027006324, 0.8926513574029241, 0.9861836715435827, 1.048258602424987, -1.145257873605194, 1.233529400113939, 1.336236455566228, 14.30571745164884, 17.61787905052259, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.2522684045481, -962.3209091459635, -456.0021243571045, -0.135204950106543, -0.1394617235875679, -0.220127550372105, 0.08571928452292403, -0.3049409043236431, -0.03659504642708369, -0.3890574180257759, -0.006436425325169574, -0.4706108350838175, 0.04096694825184889, -0.5462820434899358, -0.06401136348259447, -0.3343815237245166, 0.3770481192076843, -1.804641348780662, 0.1862488607745145, -0.5241026690461806, 0.1165329851236274, -0.3218108422408898, 0.1103182214298427, -0.2288701150093211, 0.1197089351929335, -0.1702872232337064, 0.1340809261902273, -0.1252999394856697, 0.1478955058540885, -0.08560365295523495, 11.52576378974406, -1.954372039977865, -7.556599118670414, -0.8696416229998727, -5.243139426145771, -0.2265893727803473, -3.645001180400495, 0.1444022525350471, -2.554614576511419, -0.3526936465053139, 1.824862320705907, 0.4673053399212604, -1.35071736012791, 0.531014596069754, -1.057368223650742, 0.5699553062659776, 0.8919929683549828, -0.5999463785086376, 0.8178418137071368, 0.630579143988404, 0.809941527510296, 0.6678139095408332, -0.8520024722473533, -0.7156241704641815, -0.934272389637509, -0.7770482361065687, 1.05215121053177, -0.8548848555187463, -1.205491122946197, -0.9521918975626668, -1.398620727934507, 1.072675726622418, -1.64131363116556, -1.220973810147752, -17.67939399433237, -17.69696009914344, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.253017754159, -962.4364747394324, -455.8036682152643, 0.1351126787098899, 0.5695864039965876, -0.2104884546621504, 0.5708245939994814, 0.2862709367223656, 0.5827540820095056, -0.3637808074554126, 0.6046421105793508, 0.4436589944498553, 0.6352690932451194, -0.5253459950861361, 0.3677303232551267, 1.347453344746686, 2.082926012424898, -1.479753805386014, 0.7203282114221324, -0.6816721371214693, 0.5093388325091368, -0.4939242839721554, 0.4515458590346876, -0.4232358982106663, 0.4527789299653081, -0.396731197291685, 0.482881928016134, -0.3902827551017815, 11.89894466315718, -2.22090063369331, -7.092747734361658, -1.234026593177227, -4.753181046423188, -0.6771950822291326, -3.104140201531702, -0.3866040328596608, -1.945692839472312, -0.2572635974024494, 1.134652874596721, 0.2236606491303219, -0.5673297987656002, -0.2460750486326881, -0.1685020505679479, -0.3012253263999956, 0.116250006339078, 0.3761133268443195, -0.3261558958623166, 0.4641080126177665, 0.4894613648488647, 0.5625417455833565, 0.6266107088037656, -0.6712930493524196, -0.7526658702381472, -0.7920386924545679, -0.8791718349910133, 0.9279565248449416, -1.015643135720146, -1.083803569712843, -1.170845050805069, -1.266390093671474, 1.354037366376675, -1.485576073474351, -1.576400237129784, -17.08748638019799, -20.84557350276546, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.4566106321672, -962.5733809140785, 456.2446669456525, -0.1688459112995087, 0.07034403444173644, -0.2661925457838576, -0.00201291370003544, -0.360842606721788, -0.05949303565750251, -0.4507864673737421, 0.1115494205452214, -0.5324222730975748, -0.150692878879795, -0.3285617939930261, 0.6352611728442655, -1.750928292301286, -0.01079073303553477, -0.4892798325673497, 0.02887167931331536, -0.2862455254245249, 0.04809364620457122, -0.1833951993284249, 0.06648914871000661, -0.1090258324830243, 0.08288235905924721, -0.04388087225057338, 11.42397334205316, -1.730411869135157, -7.54872126209005, -0.7246099232898299, -5.271259193087543, -0.1273016997487224, -3.689949677751227, 0.2168582799717596, -2.60315967042078, 0.4095966898831329, -1.869993120606597, -0.5156814339442469, 1.38982674111601, 0.5753023219269168, -1.090398441258875, 0.6129015965698307, -0.9200861758805992, 0.6431623698555172, 0.842501341267445, -0.6749156741454959, 0.8325483404989181, 0.713623361375966, 0.8735437835352988, 0.7629401789412279, -0.9551462767593792, -0.8256933589190248, -1.071962632591364, -0.9045223083409126, 1.222727743028186, -1.002327294123344, -1.410056693758905, -1.122638822704943, -1.640877341853048, 1.26995573475215, -1.927844246417485, -1.45003227706329, -20.82307411706698, -21.00155992122358, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.4627685739322, -962.7160457792522, 456.0005200775191, 0.171584773148045, -0.6169168507138828, -0.2608304899009982, -0.6165570206329561, 0.3501697797170152, -0.627679892134454, -0.4403605479968019, -0.6489829640847168, 0.5308300518602039, -0.3709301239614179, -1.405815328723569, -2.058062413586543, 1.514443425105629, -0.7159719725315271, 0.692368587676033, -0.5085223559524636, 0.4927483234228063, -0.4539119844509412, 0.409786918662957, -0.4585601641836641, 0.369060795992091, -11.79766504079141, 2.012479939028762, 7.043555197226082, 1.105137043752469, 4.741914128289426, 0.5972094437860065, 3.109868363286502, 0.3381216846268515, 1.953867566077465, 0.2299457233923843, 1.137533669668121, 0.2109462622238532, -0.5620043637972509, -0.2436579564637029, 0.1548443572169821, 0.306307345836395, -0.1370525568840376, 0.3869435542219369, -0.3524856590577575, -0.4796460558277326, 0.5197151476832278, -0.5821783731153887, -0.6593590868915518, -0.6946136487705999, -0.7866414714126642, 0.8185951248778229, 0.913148489829942, 0.9570365064732725, 1.048232753669613, -1.114138187570384, 1.200190769798651, 1.295704602378807, 1.377356049197987, 1.509847257194258, -1.589258765649288, 1.768262183131415, 1.848069109594906, 20.23420853365266, 24.50766781694805, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.7302235739897, -962.8808897579297, -456.5799751938149, -0.2074665694865197, 0.03179270034629982, -0.314911648796822, -0.1160409354435016, -0.414899941317193, 0.1896042423128672, -0.5035929949910716, -0.2485406654930217, -0.3148720318285624, 0.9334281744469859, -1.658358518134329, -0.2459729705045449, -0.4395368675508144, -0.07575020637815727, -0.238298110932487, -0.02543448920587639, -0.1242798269864487, 0.00493022955061947, -0.03092176867721523, 11.22885110571361, -1.52501965073773, -7.543615992492188, -0.592424165410839, -5.281049101322963, -0.03384112642572992, -3.711740461545836, 0.2895170179898658, -2.629192995613142, 0.4707504030082303, -1.894805671641967, 0.5704662427677495, -1.411023004415436, -0.6267630427501154, 1.107747137626518, 0.662893542409588, -0.934479879776553, 0.692778028843108, -0.8551991883552512, 0.7247338818733859, 0.8447234697913153, -0.763869215310247, 0.8860283550216375, 0.8135940022344247, 0.9682811777983255, 0.8765586475933742, -1.085448060890765, -0.9552512796328857, -1.235412367552187, -1.052408869707694, 1.419557246828857, -1.171343028943237, -1.642863640112578, -1.316259793628108, -1.914688728881414, 1.492601140725079, -2.250602542324417, -1.707371208414184, -24.34911222913227, -24.69682337532403, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.741435494995, -963.0504155847199, -456.2741036613125, 0.214479472715505, 0.6621861981953745, -0.3177872890555592, 0.659477202360043, 0.4199363883935496, 0.6686966992655288, -0.5204604440629446, 0.3760250100904552, 1.440136329901755, 2.022077415101587, -1.529242860821105, 0.7070177320978236, -0.6931608182158253, 0.5052503305200324, -0.4823639976910435, 0.4557292865512613, -0.385316970783089, 11.61106437256959, -1.818394061749481, -7.001963622764721, -0.9813357744591734, -4.716881178048456, -0.5141556100260524, -3.0969906159148, -0.280097039848389, -1.943793145915662, -0.1889996708430733, -1.123912478997343, -0.18264542910118, -0.5421787669130134, -0.2251582877779384, 0.1286970772462299, 0.2956319802801666, 0.1683473607021652, -0.3827115546150297, 0.3873303842983701, -0.4809087334725033, 0.5565590506576561, 0.5882754140327704, -0.6968797879222629, 0.7050226515021639, 0.8237435880499643, 0.8327756810598531, 0.9488550233241532, -0.9742434109257527, -1.081502395328126, -1.133196471873608, -1.229668358197086, 1.3146823158554, -1.401016876114531, -1.525516610156299, -1.603885466468684, -1.775180446964151, 1.848426978531237, -2.07736997486411, -2.148126517552196, -23.69694322453203, -28.55450387022301, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506.0870994444517, -963.2380980143934, 457.0227998243373, -0.2485169973393713, -0.1708755956446555, -0.3608775819654662, 0.2702463148020641, -0.4583288971296218, -0.3528976210982101, -0.2928214663649001, 1.263652831351624, -1.529505325655311, -0.5130238387785291, -0.3760704452139064, -0.1942204111583247, -0.1786533015765691, -0.1073884668217014, -0.05177939288958904, 10.88603291358535, -1.337180308687955, -7.596957579622598, -0.4747035515000937, -5.293796730009392, 0.05043538802520772, -3.716922670417109, 0.3592165384067125, -2.632466505734362, 0.5340539274802235, -1.895818658518178, 0.6306645190841967, -1.409275395512805, 0.685196075280273, -1.103655066088433, -0.7201507688034566, 0.929097908006366, 0.7491204140241028, -0.8497455883339168, 0.7802302755862421, -0.8402329799755162, 0.8184522926487809, 0.8831625818888247, -0.8670840673667023, 0.9672225533587266, 0.928669763681313, 1.085819612885373, 1.005581967725039, -1.236140490171399, -1.100404676155905, -1.418629151651308, -1.216231218475, 1.63686735128274, -1.356940773255257, -1.897950583839266, -1.527515842606489, -2.213574416593122, 1.73441741027332, -2.602284267564217, -1.985971407789865, -28.17877747730259, -28.69146328143491, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 506.0995030305882, -963.4251163002542, 456.6319082336776, 0.2614208946746435, -0.7049929537479934, -0.3775469776448249, -0.6990129299253891, 0.4897228036148983, -0.3853539179729928, -1.442770760684808, -1.98216326068838, 1.520548699194699, -0.6953740263821517, 0.6824190354472228, -0.5011233283967811, 0.4613118931865929, -11.29796537330876, 1.64449147211759, 7.022169169615215, 0.8641805347117423, 4.699276336140136, 0.4291404936096105, 3.07407334406547, 0.2123539984677152, 1.918769023964996, 0.1324679335590006, 1.09476296754075, 0.1352170432778689, 0.5077652860572863, 0.185910694584077, 0.08952722613195557, 0.2638426913931702, 0.2107393703819989, -0.3576622830692115, -0.4310960937466334, 0.4619085175014147, -0.5999884739982514, 0.5746756856778464, -0.7385868745992383, -0.6961886963160135, 0.8626657356149082, -0.8280065670824533, -0.9841390899478625, -0.9726569738046391, -1.112325598821782, 1.133551592359431, 1.25500535004336, 1.315134855586846, 1.419345051714987, -1.523232765666847, 1.612773491431782, 1.765677755404849, 1.843930722061922, 2.053380737994717, -2.123837663941296, 2.402145835888836, 2.467526732917271, 27.35441123139784, 32.85590905559759, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 506.535108831963, -963.6167931351213, -457.5765788302061, -0.2861761743318959, 0.3461105740480527, -0.3947395339422998, -0.4564377447058072, -0.2617296324114806, 1.611734008281398, -1.367678013419382, -0.8010059019283635, -0.3006880659872381, -0.3213053025395997, -0.1085392364738896, 10.2725543041519, -1.168526626564622, -7.82064895354263, -0.3713337568773262, -5.352508738636831, 0.1222893217356636, -3.722102280656161, 0.4211608377876347, -2.617734196748431, 0.594901972075254, -1.871992486237874, 0.6925901148668441, -1.38058734154616, 0.74787922336183, -1.072581160949938, 0.7826644587414839, -0.8975809094419182, -0.8105767210582541, 0.8193405723194567, 0.8399098661914142, -0.8120222073214457, 0.875770220099946, -0.8576881155650289, 0.9215289264833487, 0.9444708197958593, -0.9797395325755353, 1.065205863140835, 1.052722623302901, 1.216460299462672, 1.142943964195683, -1.397905992342116, -1.253291158068077, -1.612055771894061, -1.387322544088788, 1.864373007497077, -1.549535917211965, -2.163879565979816, -1.745709327273886, -2.524523036401785, 1.983325027495365, -2.967830167452788, -2.272019538910634, -32.14658674016512, -32.79917505195669, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506.5385766328296, -963.7950492893284, -457.0688147458119, 0.3064737493454045, 0.7451295489392065, -0.4320824231461616, 0.4015780387117531, 1.401276142639599, 1.946107688605819, -1.48150526542528, 0.6828643239680722, -0.6570927744752225, 10.7638914509755, -1.517523554864524, -7.212410025151229, -0.7594650802490791, -4.727779988834981, -0.3459479511652795, -3.056982946412603, -0.137792378203823, -1.885965897429857, -0.06147034578463532, -1.053619513536147, -0.06771520575915954, -0.4606626658479292, -0.1231959710791077, -0.03846712123960974, -0.2069083481076168, 0.2634078610725342, -0.3068550531907182, -0.4829610805074276, 0.4170585080045313, 0.6489288141016536, -0.5352933146117154, 0.7829424333419256, -0.6615771584317809, 0.9012282823913962, 0.797293809624204, -1.016026767128407, 0.9447489034757597, 1.136789528309099, 1.107026430413602, 1.271196791521118, -1.288051047513149, -1.426037977791292, -1.492842932266066, -1.60802186802236, 1.727960361905206, -1.824590624194746, -2.002232368690374, -2.084863210703189, -2.327985171787624, 2.400861196107053, -2.723108602478969, -2.789278491542184, -30.98867169157857, -37.17333705763805, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507.0685285381397, -963.9513225378075, 458.2239814297878, -0.3105094100833926, -0.5489621604214274, -0.2207001619135986, 1.956288574692065, -1.176681603230856, -1.09375598392015, -0.2158081274278867, 9.039432404200522, -1.044683628994101, -8.468785467802409, -0.2840135792540254, -5.542745543449104, 0.1779572946344857, -3.761606785421675, 0.4684797722662275, -2.598930526573113, 0.6453592933930452, -1.827562760363265, 0.7487181877066253, -1.324101584715386, 0.808286952945908, -1.010847733279209, 0.8449471423636297, -0.8346332998503472, 0.8724833572892089, -0.7577244949265606, -0.8996473668870159, 0.7532210193109008, 0.9319700291879087, -0.8023001449790493, 0.9731169256921198, -0.8923272475697563, 1.025808942383718, 1.015464062032189, -1.092414194595597, 1.167634916611444, 1.175336052505714, 1.34782203022553, 1.277290630873182, -1.557658237162463, -1.401532229855291, -1.801354910586623, -1.552090405661354, 2.085991956058786, -1.734049468830996, -2.422322212155974, -1.953922901839827, -2.826392120689291, 2.220125678702697, -3.322576673428888, -2.543480350687961, -35.98052650947123, -36.71809122641062, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 507.044358239568, -964.0731038498507, 457.5609921269437, 0.339186245230021, -0.4273969477024003, -1.29863116329144, -1.9212155175519, 1.401898391182813, -9.726271535257508, 1.553331598619713, 7.831565439526993, 0.6875158984530817, 4.876888986260434, 0.2743174969664351, 3.073278715408381, 0.06481527948414105, 1.857848936458911, -0.0172058553164797, 1.007270300003323, -0.015493908041739, 0.4052734656641692, 0.03886914827152865, -0.02120544418256508, 0.1245454447689218, -0.3236527085621929, 0.2283392770229724, -0.5404903245807748, 0.3431422365149781, 0.7009598725924222, -0.4659137295498349, -0.8273152365264473, 0.5961381254254794, -0.9363871554481444, 0.7348226673958823, -1.040881025210011, -0.8839501590062537, 1.150503496114657, -1.046240633846492, -1.272940104510185, -1.2251386270737, -1.414709746711867, 1.424957765640063, 1.581930391736834, 1.651204358082938, 1.781057179003545, -1.911084747398959, 2.01966517958886, 2.214321569792053, 2.307406860022854, 2.574510651133963, -2.657307283406697, 3.01140106208788, 3.087681881697911, 34.27753948458455, 41.14981894020637, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 507.6607402118162, -964.1324178062038, -458.9202293050566, -0.1686378441806772, 2.26918481619089, -0.9605814475857066, 5.330862093858574, -1.138949076550252, -10.32445599072876, -0.2278821376240088, -6.053185271755386, 0.2111992660067487, -3.90195016026017, 0.4916948027703619, -2.604992480633718, 0.6736549508248011, -1.775821097551055, 0.7869195888388132, -1.245117363143849, 0.85511197805049, -0.9191931180792211, 0.8969679044521599, -0.7382433689234038, 0.9261198029941115, -0.6611696707630135, 0.9518531231496314, -0.6589875072665196, -0.9803308643977939, 0.7113879440961655, 1.015736615269503, -0.8045956932013681, 1.061136120387407, -0.9298638326235749, 1.119078818816151, 1.082360654284157, -1.191995373104534, 1.260356303986052, 1.282483463463084, 1.46470232087969, 1.393532235248562, -1.698581785001543, -1.528731717952134, -1.967581344572053, -1.69251044093007, 2.280123193492441, -1.890433165088037, -2.648431439034473, -2.129603108392172, -3.090370039310071, 2.419171909638182, -3.632813078727661, -2.770878258545604, -39.30905440906147, -40.04060379184506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507.5823569101401, -964.1327952153448, -453.1525519625071, 24.40574541777206, -56.14514099816383, -2.422186406437542, -25.22429964965732, 1.444867813899084, -12.70852566601807, 2.547941134817951, -6.850174344806808, 2.975175307411678, -3.480196946314358, 2.990960801627664, -1.417378358439735, 2.740289627402432, -0.1451237393712128, 2.339923467563752, 0.6224326970934283, 1.877490924183014, 1.064055147754233, 1.410245383546048, 1.298670025286794, 0.9699280356465935, 1.407692033072784, 0.570056365428795, -1.447206482446987, -0.2126606347621276, 1.45549590027687, -0.106700427367443, 1.458217449192367, -0.3956662520866513, 1.472227262174601, 0.6631737994890589, -1.508479947856337, 0.9184906204287088, 1.574231058518403, 1.170872531544465, 1.674716872315271, -1.429622942231864, -1.814460422530907, -1.704464741494625, -1.998356318905909, 2.006172401087063, -2.232676942948992, -2.347554579943283, -2.526186304333157, -2.745015993852846, 2.891570896342571, -3.221095840304374, -3.347521504585615, -36.81977934526557, -44.35189490614219, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -929.5916205582998, -941.0365306526329, -83.0205570677121, 28.17439325219577, 75.87533570257695, -1.696520866989221, 26.60699159785555, -5.409361115615388, 12.56934180801319, -6.877261269176024, 5.687519948140556, -7.195311665250237, 1.882753730836734, -6.793257487426405, -0.243954230030588, -5.985952308839798, -1.376766663139118, -5.007212173644259, -1.909776318300887, -4.012480308119807, -2.086793153052898, -3.09156896456971, -2.063263714473415, -2.286718302219568, -1.938915871123262, 1.609507069182077, 1.776860515294737, -1.053845022404726, -1.615732919376842, -0.6048003006133782, -1.477928334454509, -0.2440699657679927, 1.375377784059099, -0.0469141625735761, 1.313620215666728, 0.2854287861559656, 1.294663638447388, 0.4868539710419071, -1.318984666977386, -0.6646185691294326, -1.386978049510149, -0.8304585614062736, 1.500098994703478, -0.9948396546158864, -1.661963350617514, -1.167481907502111, -1.879718152404978, 1.357937431688009, -2.166151621008019, -1.576149522040385, -22.8426934593021, -23.12611835160169, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39.74325951288207, -1186.431523127095, 891.9981651399358, -63.78630277783328, -227.1996575944138, -21.36263524515902, -134.9940747033731, -11.91053467248452, -92.38872197451053, -7.137773558531492, -66.40883312595787, -4.159839971417969, -48.55372147263157, -2.266393752869894, -35.63597637393651, -1.094787188040574, -26.12268218585725, -0.3740073215893996, -19.11470230422248, 0.09756406262595478, -14.00177931344374, 0.4539441356094622, -10.33193495392373, 0.7738574705683541, 7.757284995888257, -1.098280483037155, -6.008113485615493, 1.446238834722165, -4.877217783576145, 1.8260185749213, -4.208135864627979, -2.242051708641171, 3.885327967594733, -2.698727377102662, -3.825903864288941, -3.202420566106344, -3.972879079281471, 3.762630114298621, 4.289949398982492, 4.392965687767301, 4.757754982238793, -5.112366708632306, 5.371588692477695, 5.947098472803463, 6.140643591545218, 6.934244894234055, -7.089006463457302, 8.127774292215216, 8.258953377781268, 92.70654077487185, 110.8916502269361, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 786.2689336767368, -815.9863464302587, -502.0050839453779, -90.73950140949509, -56.87432228337573, -51.99165992440596, -33.34091308622924, -34.04113075780467, -21.43377478029886, -23.06225529920733, -14.14681954842458, -15.59204793972567, -9.417386184375989, -10.29776713475104, -6.330831000664216, -6.493371297236832, -4.358412747427537, -3.752309549753657, -3.152344856102681, -1.780646844936822, -2.474087100314609, -0.3652993582829661, -2.159473586844666, -0.6519861739832791, 2.096803744336349, 1.389930130712824, -2.211583888600316, 1.937926207260219, -2.455755504596307, 2.363440987643714, 2.800164407662094, -2.717650504667941, 3.229401718516578, 3.039864785640401, 3.738480085017688, 3.361030069362782, -4.33092205126337, -3.706511692235448, -5.018136256707792, -4.098399590204935, 5.820036523452692, -4.557455346103694, -6.767262056924007, -5.104890578388991, -7.905837082177761, 5.763931574597367, -9.306048512065884, -6.560810197006163, -99.50178779115197, -96.99432423638203, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -321.507651312602, -910.0072663299117, -591.4192374647588, 2.348605212951472, -124.3655421160505, 2.519037737123322, -84.26548427045947, 2.573811571186274, -59.67166318149743, 2.542520312756454, -42.7047736707389, 2.300331152371294, -30.40208946365, 1.868906337655643, -21.33294075666419, 1.342284397278395, -14.64893633535513, 0.8120400288034471, -9.763872639971726, 0.3354516359221829, -6.235124240181859, -0.06553144651026029, 3.716540641341441, 0.3931256138944335, -1.936614843167815, -0.6618294981785842, -0.6848912674945181, -0.8900811776756501, 0.199127185761292, 1.095738020332698, -0.8359393889447138, 1.294255063198197, 1.31492328463649, 1.498467646770268, 1.702006092723583, -1.719202962560454, -2.046109758511857, -1.966270920929146, -2.384503193805934, 2.249628522569334, -2.747318106025392, -2.580712635786556, -3.161596749861384, -2.974131519986319, 3.655356432931151, -3.449999148965924, -4.262437651783252, -40.50763259878801, -54.03571513338518, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -344.0713331149046, -952.725510121053, -416.8443995257026, -1.06754986885831, 45.84646413547254, -1.058403868892041, 31.77101137436911, -1.019954379151325, 22.80926291367322, -0.9071659718312616, 16.5022307529763, -0.7068440514134203, 11.86549955113823, -0.4524387095841191, 8.40538251216984, -0.1887047159960708, 5.82217952814256, 0.05065134824649881, 3.9055606710333, 0.2489662036219396, 2.495002070050333, -0.4034520268008114, -1.463934384255092, 0.5196357992327747, 0.7123003579271661, 0.6066099511692123, 0.1617857928516114, 0.6740824416340541, 0.2481361170724213, -0.7308946494537877, 0.5637692276795909, 0.7845255109986143, 0.8204101808272708, 0.8411152733767217, -1.045170820232432, -0.9057592610820282, -1.259454345228306, -0.9828579943559127, 1.481169292533973, -1.076498380875339, -1.726879905570609, -1.190773320672958, -2.014212738164722, 1.33001392092199, -2.365085594225679, -1.498734072363048, -24.7211856905308, -22.78270797180551, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442.6907539702701, -958.4534825933663, -525.0790057885872, 0.4830776577375593, -34.3647256467903, 0.6314006455905202, -24.3348172625214, 0.7058287395586245, -17.41434346405917, 0.6762376591103615, -12.39697921157262, 0.5581637364705839, -8.69979036834804, 0.3923850266317464, -5.976507461418807, 0.2173455777493897, -3.987524183530083, 0.05722832788370733, -2.551827878146577, -0.07817291001085155, 1.527904886231801, 0.1888356566437113, -0.8048407679343973, -0.2797226979198223, -0.2967379564291665, -0.3574286627927332, 0.06184616772257682, 0.4283754863248733, -0.3199942490552064, 0.4980819539573895, 0.5140709901171847, 0.5710827814267276, 0.6708672126762525, -0.6511525664070008, -0.8102397807569323, -0.741692223923563, -0.9473054632669835, 0.8461535960354408, -1.094295489000015, -0.9685246843169275, -1.262227087133157, -1.113917136472349, 1.462601455450445, -1.289351439294402, -1.709469206945622, -15.37887836207466, -21.35497052390839, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -428.3101323308657, -960.7693411578422, -474.342891355963, 0.04496720051684034, 19.40931799070891, -0.1673280524757375, 13.92731470257143, -0.2557102683826377, 10.07353665325728, -0.242060653548165, 7.24394212742543, -0.1622596506986207, 5.13483244576956, -0.05331961081104578, 3.56174021542921, 0.05739982125560644, 2.395487323148687, 0.1547037661558607, 1.537813226473135, -0.2331433212654467, -0.911475734135779, 0.2933066494077648, 0.4555476781368759, 0.338711646959178, 0.1224074525370889, 0.3738275323799262, 0.1247194820414306, -0.4030263556972666, 0.313950693100759, 0.4301452572858044, 0.4667062381065167, 0.4584109424144206, -0.5994212319450118, -0.4905216003205117, -0.7250428404204554, -0.5287981906358582, 0.8543669982497838, -0.5753440721198483, -0.9973355647586041, -0.6321710321880218, -1.164486942694627, 0.701242039243045, -1.368908791826208, -0.7842864184450526, -14.12684531258338, -12.34623872489789, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.5947291948034, -961.2035052944622, -514.6492553039509, 0.4825672633043259, -14.63884772835812, 0.4728625789819674, -10.46609788926318, 0.4223503876316634, -7.442448460093368, 0.3329214300137407, -5.216277203642393, 0.2244794898769337, -3.578425180158726, 0.1168914409785088, -2.383907106504585, 0.02230924598695424, -1.523064408492582, -0.05507450668021285, 0.9101446618023145, 0.1163992499184654, -0.4779690543716839, -0.1653691281434937, -0.1745659182869991, -0.2063444223336585, 0.039602682285727, 0.2433424061835201, -0.1941384821064465, 0.2796828695057331, 0.3109312828739628, 0.3179775825463946, 0.4060797546311572, -0.3603111282843304, -0.4915070533384577, -0.4084758403447379, -0.5763074319912898, 0.464226600596208, -0.6678922566067029, -0.5295368917237421, -0.7730382893753434, -0.6068884203575737, 0.89897954742318, -0.699610046209151, -1.054787068983536, -8.609652087354156, -12.8579032884007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -446.0038881412778, -961.3008847776382, -491.7175432274707, 0.1943007163358473, 9.906958572878336, 0.02345340704111558, 7.173866633051514, -0.04242250621999444, 5.166677008312024, -0.03855525151603313, 3.669944479628774, 0.002466257542828118, 2.552845379807538, 0.05656495909653988, 1.723914622877545, 0.109389231273188, 1.113704343754537, -0.154326556966241, -0.6676835332672917, 0.1897295486417266, 0.3428450695372164, 0.2165827955413441, 0.1055512320135479, 0.2369862849228626, 0.07020719515760521, -0.2532876029564753, 0.2043491608705294, 0.2676915043075377, 0.3120764248151033, 0.2821088161452195, -0.4050727622745833, -0.2981576244336274, -0.4925541862044852, -0.3172019895469589, 0.5822117700075157, -0.3404097672817541, -0.6811329794436601, -0.3687673652742239, -0.7968425416319206, 0.4030092522096378, -0.9387219855322787, -0.4433201240139981, -9.48396669353969, -7.512457904532764, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.4328410845339, -961.0071327788293, -510.5524809166798, 0.4111184351918524, -6.829176411984103, 0.3361386406116716, -4.837760995294381, 0.2502764457319974, -3.37603312459292, 0.1626067927924462, -2.304361871960009, 0.08316396128852019, -1.525802347503765, 0.01755632843579077, -0.9670336043134922, -0.03330222974734559, 0.5708045845795261, 0.07150324591409365, -0.2923816210281723, -0.1003945101884875, -0.09727229178655826, -0.1234001397404901, 0.04066183518259721, 0.1434628037600845, -0.1409083950734027, 0.1628660783751044, 0.2178168134361163, 0.1832999676758237, 0.2819041405558238, -0.2060026677157682, -0.3409546634835108, -0.2319393727963857, -0.4009411424908401, 0.2619589247865226, -0.4668200628062795, -0.296933951573955, -0.5432787484033776, -0.3378788989574256, 0.6355506795869581, -0.3860209451465164, -0.7505093709414847, -5.105954891950948, -8.781352077679234, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452.3304115985688, -960.7608316563131, -498.9493530569109, 0.2350526026148503, 5.452765778836735, 0.1144413317324554, 3.942743416705443, 0.06575193956155491, 2.813198060193881, 0.05979656827468521, 1.967247253532042, 0.07476481999950792, 1.33716927453409, 0.09679248669884244, 0.8715028539151225, -0.1184142632347635, -0.5297539525430655, 0.1364376500843866, 0.279883315023392, 0.1501362016677295, 0.0967277743463185, 0.1600101117691853, 0.0392623455333137, -0.1670646460060667, 0.1431394010753874, 0.1724122128993197, 0.2264583241675105, 0.1770984549392259, -0.2981564198474064, -0.1820260600993679, -0.3653319148757525, -0.1879277629602221, 0.433953340411416, -0.1953399947167113, -0.509568285645821, -0.2045344918635905, -0.5981230469754966, 0.2153519198444021, -0.7071121725209079, -0.2267809863092065, -6.916134867991262, -4.577761093605716, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.2821812366932, -960.4249791586459, -508.406803593705, 0.3314600419524246, -3.131681676256192, 0.2387019139078725, -2.160834219382301, 0.1558482495866747, -1.455216313053963, 0.0871664614814559, -0.9473663287775979, 0.03419837662062589, -0.5864332248384088, -0.00432458333663224, 0.3329441537673535, 0.03128353627523617, -0.1562804280922136, -0.04999176058110387, -0.03302664185232766, -0.06346986930062509, 0.05440406541970694, 0.07411879158850035, -0.1190014687949248, 0.08368929303132233, 0.170242902230307, 0.09336390814052453, 0.2150244781654537, -0.1038994057814532, -0.2584450235024301, -0.1157578492126067, -0.3044688209695106, 0.1292115445076401, -0.3565100159947209, -0.144401977523982, -0.4180074998279228, -0.1613341173509704, 0.4930955968984639, -0.1797468301316631, -0.5875758018381303, -2.883918681365754, -6.475332235697652, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.0155128763931, -960.1981319999863, -502.3405067762259, 0.2542491852062611, 3.131489617552865, 0.1670909868692584, 2.252853211778165, 0.1252928337711295, 1.589512082778476, 0.1095856577497441, 1.091340808355062, 0.1069182126000217, 0.7200044935476559, -0.1094190566032491, -0.4450831238377702, 0.1128668647285452, 0.242278665253527, 0.1152987829103931, 0.09231415427747117, 0.1160486567327278, 0.0199468566918988, -0.1151073353429353, 0.1062892592500759, 0.1127688588569004, 0.1758680910212436, 0.1094184084764459, -0.2358574126255636, -0.1054171918706391, -0.2920380304032841, -0.1010121781961295, 0.3493514987155218, -0.09624584560739964, -0.4124750394872714, -0.09081842264154093, -0.4865154108104184, 0.08383114316573474, -0.5780232680965639, -0.07323520324207744, -5.417494102776475, -2.610329978177295, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.4493352528837, -959.989698663586, -507.1401709474283, 0.286121368416555, -1.277585644216466, 0.1965314549725704, -0.8296361757391397, 0.126150204699882, -0.5143609771621193, 0.07411570076725935, -0.2955753603877085, 0.03772510850741548, 0.1456031206933647, -0.01346154359781873, -0.04333286374184881, -0.002152095041771392, 0.02709212845432325, -0.01203934086886425, 0.07735364223423614, 0.0184196895883106, -0.1159068759281938, 0.02282300685654621, 0.1487971666617892, 0.0262064128753012, 0.1803514533516238, -0.02907864514102102, -0.2137591327763108, -0.03161342078618522, -0.2515671959433391, 0.03371538499219204, -0.296132352891611, -0.0350175049709756, -0.3500936488703787, -0.03478013453039555, 0.4169709529674968, -0.03159734770668429, -0.5021045752952693, -1.359189375072352, -5.137658691990629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.1816434524407, -959.8717700049582, -503.9632365405722, 0.2710790852321758, 1.868103062408168, 0.201731258488131, 1.336518241630041, 0.1607751340471668, 0.9312150774562233, 0.136744864573931, 0.6245135082334604, -0.1220039814863793, -0.3939736948288325, 0.1118064051450731, 0.2212852465254199, 0.1033807000084225, 0.09161715516324435, 0.09519253715708004, 0.006912715432142194, -0.08645745594199336, 0.08374228844933723, 0.07681239647201249, 0.1463556032104103, 0.06610891321647951, -0.2007459498469933, -0.05425819168043056, -0.2518586281471307, -0.0410971094331229, 0.3040320723461977, -0.02624784596427822, -0.3614859250552229, -0.00891781755958999, -0.4289462964027577, -0.01244251094956762, -0.5126072586924517, 0.0408259308513107, -4.58392784156386, -1.246428269166816, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.3475780693374, -959.8013715842148, -506.3396543584333, 0.2767928687754797, -0.3507679094211566, 0.1964561308894208, -0.175454380884666, 0.1369018349817932, -0.06171313754209207, 0.0948996407982716, -0.01057868944381583, -0.06660941623334156, 0.05625273023108911, 0.04841249702381548, 0.08604193382443961, 0.03731356346471822, 0.1075373379529352, -0.03107613794426697, -0.1259926823207867, -0.02817283438261568, 0.1449896389440946, -0.02768249041446454, 0.1669869201040142, 0.0291682437735234, -0.1937749805283248, 0.03258348528255475, -0.2268682319663226, -0.03823766887670215, -0.2678770945127273, 0.0468458004168191, -0.318925108122332, 0.05970717770473746, 0.3832225686061499, 0.07913811719945757, -0.4660307877839935, -0.283439945606522, -4.418862273762176, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6253594082521, -959.785934980976, -504.6940382140627, 0.2905146476860859, 1.164315682401765, 0.2287874192618208, 0.8278901909084367, 0.1855742595690876, 0.5670794972681463, -0.1543255466444327, -0.3664024755348232, 0.1304088025212251, 0.2126108080946933, 0.1106574375165147, 0.09451778970188139, 0.09297359092819958, -0.00282311457116445, -0.07598524984762452, 0.07011698901922347, 0.05880426133990931, 0.1305654348080172, 0.04082738142446098, -0.1837050518882388, -0.02156733869032677, -0.2339588783576583, -0.0004920786516655548, 0.2853442102851388, 0.02315710617373445, -0.3419026525153549, 0.05062046787596538, -0.4082936953470016, -0.08404423049499717, -0.4907590591221084, 0.1273101919619071, -4.206720311439787, -0.3002127507778516, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.1342767647928, -959.8106159477925, -505.8018624707027, 0.2900898798822178, 0.09138444482380856, 0.2187118527593231, 0.1292492004000186, 0.1662045097025605, -0.1438635095448789, -0.1291313858324679, 0.146482412369866, 0.104009216338187, 0.1447220224795449, 0.08785328495101051, 0.1435558243554511, -0.07835861397425346, -0.1461036208296098, -0.07391291396692715, 0.1542496939603918, -0.07351683292489485, 0.1691302490659806, 0.07668777947971103, -0.191528688062261, 0.08339243901741469, -0.2222158695109802, -0.09404049750512089, -0.262283667277891, 0.1095744988108133, -0.3135425638449527, 0.1317142932715506, 0.3791044132771236, 0.1635054212875869, -0.4644162154949849, 0.4754117380195617, -4.133127727067452, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.7075938580194, -959.859187561279, -504.9641545879152, 0.3112115826946246, 0.7603819900412184, 0.2515787922254607, 0.5346525976842389, -0.2046698188884306, -0.3549498970832715, 0.1667993851467113, 0.2128194443512869, 0.1349829906843502, 0.1004097453865731, 0.1069128978938258, -0.01069617548430252, -0.08086180012056307, 0.06245121559445837, 0.05554789383536447, 0.1243240851970876, 0.02998652907082099, -0.1795147550946357, -0.003335227685768387, -0.232122564808795, 0.02527939571162375, 0.2860328739068638, 0.05697314553891727, -0.3453056616278151, 0.09340770900657025, -0.4147626826939698, -0.1373004236343103, -0.5009888584183517, 0.1933830034629809, -4.165639675833453, 0.3383554269676927, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.8782696374187, -959.9297648403151, -505.4159286188464, 0.3121561806109645, 0.2822056061123752, 0.247980497057797, -0.2569956304425891, -0.1998295916895239, 0.2284297348242049, 0.1650722678022543, 0.2029125660834568, 0.1410884792635043, 0.1841746600175908, -0.1256771230171495, -0.174184152010238, -0.1171886991653117, 0.1738211936975961, -0.1145301840222644, 0.1833868779235939, 0.1171275690499658, -0.2030007615539205, 0.1248977602701297, -0.2329370726129333, -0.1382764499321328, -0.27395747110102, 0.1583471608991634, -0.3277192476797476, 0.1871380238475298, 0.3974011701543539, 0.2282921486952801, -0.4888358484669846, 0.9965699211078363, -4.174355176167373, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6116649438044, -960.0038871245156, -505.0023454177997, 0.3295930205438109, 0.5143442094150634, -0.2695356906932027, -0.3518849459077303, 0.2184195529530754, 0.2177473194353936, 0.1742696183299925, 0.107588929061941, 0.1351123343048535, -0.01670816731731302, -0.09919323231873232, 0.05953720029339046, 0.06503073496805913, 0.125532380449224, 0.03137214041729913, -0.1853658264427238, 0.002916428236328955, -0.2429142837357705, 0.03901258336924512, 0.3020465696948311, 0.07836548079886681, -0.3669787240345666, 0.1230474258479728, -0.4428645014247397, -0.1763255542849716, -0.5368662993446999, 0.2437700678950443, -4.391525855268358, 0.7382567408086977, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6126089063781, -960.0836158047517, -505.1187555600291, 0.3334848577914001, -0.348428051728459, -0.2752367222186492, 0.3006944638633078, 0.2302721093152811, 0.2591967524250096, 0.1970876226025629, 0.2278690906060197, -0.1740115500094767, -0.2085463212280925, -0.1595867622233282, 0.2018162461301135, -0.1527406251408078, 0.2076385119268662, 0.1528504282670753, -0.2258110308909343, 0.1597827219954589, -0.2563523040186093, -0.173969694548823, -0.2998702186943654, 0.1965747840879211, -0.3580175279469813, 0.229863604568186, 0.4341837938265395, 0.277970170008693, -0.5347627558106645, 1.329764914690779, -4.483596648143033, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.4349056684294, -960.156647229524, -504.9319775147893, -0.3423523620698637, -0.3475550534848461, 0.2809466994778753, 0.2215706829932298, 0.2255846777578883, 0.1128246391312395, 0.1754514594654858, -0.01937340515435665, -0.1292864557086762, 0.06168462942056975, 0.08573413224271821, 0.1336954218460845, 0.04347198911094055, -0.2001906469386318, -0.00119376064663685, -0.2648271503726893, 0.04251266830607562, 0.3315045719474604, 0.0893994185444924, -0.4046778456006963, 0.1419228134888831, -0.4899638274253278, -0.2038944668407005, -0.5952966220065167, 0.2817106712351145, -4.848415701454543, 0.9427020574859393, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.3526903101317, -960.2239683681914, 504.8729234307502, -0.3489451907029376, 0.3589886699197148, 0.2961466969614354, 0.310480710370148, 0.2543129428137268, 0.2722939468109425, -0.2230677496498586, -0.2472988907469534, -0.2016181817997352, 0.2366019906197148, -0.1891922917107881, 0.2403800750135453, 0.1852769979754018, -0.2584933857871972, 0.1897672879791922, -0.2909693456884552, -0.2031063479701883, -0.3384573551697876, 0.226529417912314, -0.4027594406465836, 0.2624902798236902, 0.4876253939462449, 0.3155583157701459, -0.6001811424846641, 1.506088170407175, -5.032413448243027, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 456.2281437872571, -960.2817251702837, -504.8181052368888, -0.3473974178704272, -0.2160721566413612, -0.2844115901002985, -0.1109673640897398, -0.2249663433659822, 0.01558619777087037, 0.1691160884458819, -0.07065303999293307, -0.1161602619016208, -0.1496942207346384, -0.06504337994709028, 0.2242986455097327, 0.01449731249119731, 0.2977971368954605, -0.03700838008878649, -0.3740870837044805, -0.09144942901497075, 0.457896128782557, -0.1516347645680779, 0.5553971193015861, 0.221891957236842, 0.6754711755316094, -0.3094582971264419, 5.522765460179463, -0.97751110694022, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.1038688686278, -960.3270004185782, 504.6545436979824, -0.356402682870272, -0.351340066980498, -0.309181275719597, -0.3137167192606073, 0.2710350810973345, 0.2878350893000941, 0.2426229671933997, -0.2763168527076123, 0.2239747467509561, -0.280241947819618, -0.214997170417235, 0.3000011000597085, -0.2157829211419849, 0.3359590943512027, 0.2268880461285561, 0.3890394964897786, -0.2496482263626514, 0.4613794461017247, -0.2867172754999331, -0.5572551598551461, -0.3430608494894536, 0.6847182926632671, -1.544015999089003, 5.81277117568367, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 456.0159328177219, -960.3639010644911, -504.6932803542561, 0.3438026307622749, 0.09449263891861819, 0.2791924853298788, -0.0003950261355616105, -0.2158018381788221, 0.08970415379288814, 0.1544060725265021, 0.1757031383879306, 0.09475353685250953, -0.2591866322084164, -0.03594501565049272, -0.3429135694153541, 0.02344530556719954, 0.4306584188832464, 0.08549582247561358, -0.5273917016008263, 0.1532791130988579, -0.6399042657976388, -0.2316168130063649, -0.778179175299526, 0.3285885099115871, -6.416369594901841, 0.8564491667855068, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.8653704619311, -960.3842612497629, -504.4466252991523, 0.3553710744569122, 0.3464161627180581, -0.3141480426464132, -0.3263434732993854, -0.2805185077726005, 0.318452179605292, -0.2561088381842067, 0.3256076632881188, 0.2417423068618511, -0.3493440004841665, 0.2380375239176739, -0.3907849327216811, -0.2458444207499498, -0.4514338824492233, 0.2667224509879774, -0.5339931109453619, 0.3035639225688179, 0.6434745768399498, 0.3617520533213044, -0.7890836608012997, 1.453287590263238, -6.830587030361006, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.8082369972718, -960.3994442233231, -504.5727798070742, 0.3313951499504466, 0.03334672491870352, -0.2650323687322864, 0.1237756771616079, 0.1977229200322088, 0.2152372282453819, 0.1308144824330917, -0.3074811043383469, -0.06431874746251602, -0.4022833530695494, 0.002753039484875582, 0.5030555348702184, 0.07234641380894129, -0.6149136653510678, 0.147681447081999, -0.7452813394287314, -0.2340032399414377, -0.9053839955214958, 0.3402398000888476, -7.541821253164034, 0.5849103543979055, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.6329040043291, -960.3950114540172, -504.2353754001218, -0.3460929449122671, -0.3573008762499605, -0.3114301376926339, 0.3594512386076111, -0.2833177549503088, 0.3742883157355104, 0.2642891667618492, -0.4053000240462633, 0.2559854273447855, -0.4549386843075994, -0.2598956392005766, -0.5256874172585198, 0.2779895068618159, -0.6211224810880993, 0.313525507512514, 0.7472565377041231, 0.3723660978852033, -0.9147314187079836, 1.237565421662729, -8.101822161846965, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.6073466604758, -960.3894853751993, 504.4633572926642, -0.3103733552874035, 0.1798092000949148, 0.2419934417708158, 0.2733274466086066, 0.170608369891661, -0.3730126262676927, -0.09792141422899953, -0.4790220884834106, -0.02392951925676049, 0.5940246336099106, 0.05285511329060938, -0.72308359247846, 0.1355803277369181, -0.8742174899740623, -0.2298115577107615, -1.060011360233898, 0.3453065574734215, -8.919981193604276, 0.1624134764758667, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.4000921853053, -960.361309464515, -504.007882194183, 0.3290914395050692, -0.3942786634383071, 0.3016661987186222, -0.4232028367455296, -0.2802278665379578, 0.4661762517445954, -0.2682364496083171, 0.5277412575464714, 0.2683110547053154, 0.6119088573807965, -0.2831724063939194, 0.7235386787769833, -0.3166483539775581, -0.8699916087218257, -0.3752194315750562, 1.063702555577482, -0.8961354452926642, 9.650619636505867, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.411737801223, -960.33634002581, -504.3683031089997, -0.2810675792469359, -0.3568683235024433, -0.2101973773067176, 0.4610263218581945, 0.1342569173742763, 0.5773846640444537, 0.0549895002126496, -0.7072872888655298, -0.02810812468448988, 0.8554232500908963, -0.1177949641523385, 1.030291473272884, 0.2197751447614384, 1.245920882288997, -0.3445848993688538, 10.57920381944338, 0.4160829872124499, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.1591691278096, -960.2853155130464, 503.7506267530316, 0.3049590480459953, -0.4680278418562256, -0.2856076919532088, 0.5295716933187377, -0.2723080782051216, 0.6081924100973243, 0.2695854300651085, 0.7101704945576234, -0.2814097861384926, 0.8422035444139073, -0.3125162969328145, -1.013460137059419, -0.3702351580276053, 1.238618787929362, -0.4245068253530189, 11.50934860393606, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.2183025514214, -960.2418420556575, 504.2904567527979, 0.2437489235262463, -0.5785902355402166, -0.1696099295696916, -0.7030543018352547, -0.08807726217552897, 0.8477643119258153, -0.0003803922022015914, -1.016538148397893, 0.09536127235557913, -1.218135087789733, -0.2047067633976007, -1.468068679276456, 0.3388478362779086, -12.55632491341529, -1.160129556695031, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.9011576326581, -960.1679733535419, 503.4480310997173, -0.2743159215154021, 0.59210690664036, -0.2642341403577922, 0.6948327035340854, 0.2611611633095301, 0.820468994814445, -0.2710734389097403, 0.9783065442168752, -0.3001250829922114, -1.179929020129721, -0.3568752809307986, 1.442834925435452, 0.1861860221886378, 13.72072654131889, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.0234951961737, -960.1065185460631, -504.2341761382918, -0.1985155387376615, -0.8636702893987938, -0.1197570863030018, 1.022005815169442, -0.03046148161363051, -1.212498738675283, 0.06965185900521845, -1.44380567993779, -0.1855411271964486, -1.732900209415532, 0.3288765751169174, -14.89970702904785, -2.085331319125681, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454.6155022554338, -960.0090394364709, 503.080419120223, 0.2378578162407876, -0.7855779404374899, -0.2389268322384859, -0.9427265300586574, 0.2493889345428649, -1.133389617235434, 0.2776001160195384, 1.372380149780934, 0.3338733668864364, -1.680779007748177, -0.9514699644735849, -16.34248127983827, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.8236752088293, -959.9291937205099, 504.2068595622975, 0.1450192700206833, -1.238921588152978, 0.05908037491561525, 1.451502248422423, -0.04247506464443443, 1.715440182112174, 0.1633637326099601, 2.049030098342237, -0.3153926679720489, 17.67488245777389, 3.216886963304409, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.2888780517075, -959.8060141768642, 502.6209139189659, -0.1963783784418207, -1.07681015710693, 0.2118129088940946, -1.30957289263114, 0.2416506844030767, 1.594926385284288, 0.2987764905571196, -1.958528602633205, -1.89790052548914, -19.45550897611078, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.6150435510897, -959.7057073918052, -504.2207918385922, 0.08191276561459389, 1.744978959223401, -0.01623102385292412, 2.044325279439126, 0.139362395300141, 2.428380353063932, -0.2989187527977135, 20.97397716279267, 4.596081079911148, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.9030102952942, -959.5514771839804, -502.0302313735755, -0.1509069873047727, 1.509921737993699, -0.1866506960156188, -1.853460072170985, -0.2470701568585754, 2.284756111156089, 3.070922511010462, 23.1773864785971, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454.393273204417, -959.4263564611852, 504.2962075579032, 0.005942404933789297, 2.446660862635643, 0.1147302269971472, 2.888007099445928, -0.2794135351323237, 24.93107187619451, 6.291448555715359, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 453.4308183834945, -959.2306762470356, 501.2467662460859, 0.1030197566665109, 2.15672544959436, 0.1707450834055513, -2.672257869508826, -4.548465509453017, -27.68489865384783, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.1521964870133, -959.071043583621, 504.4663679395445, 0.09038098396525029, 3.453184686592636, -0.2556696326547585, 29.74790742438, 8.418178566025752, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 452.828604749646, -958.8118098643598, -500.1677840008083, 0.05562336274628601, -3.140588015388957, -6.465358070370396, -33.25328104675387, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.8814454933349, -958.5973523296369, -504.7879798529249, 0.2240186812962395, -35.739305932474, -11.17424401632893, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452.0207842240151, -958.2280932680816, 498.6099988306628, -9.061273073482408, -40.32955903922403, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 453.5608878051024, -957.9144120234951, 542.7656821084641, 14.91304502929086, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 450.8656330991661, -969.8578951037719, 452.1887612775597, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 787.8967774818433, -898.9789215779133, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + }, + evWant: []complex128{ + 1, + 2, + -0.8238783640171078 + 1.579766228862017i, + -0.8238783640171078 - 1.579766228862017i, + -3.922907917607387 + 1.654540870297146i, + -3.922907917607387 - 1.654540870297146i, + -10.04176861796659 + 1.651471031280953i, + -10.04176861796659 - 1.651471031280953i, + -19.90533512613429 + 1.64196864045227i, + -19.90533512613429 - 1.64196864045227i, + -33.60610872827028 + 1.635560741682501i, + -33.60610872827028 - 1.635560741682501i, + -51.10943733404228 + 1.631805014774364i, + -51.10943733404228 - 1.631805014774364i, + -72.34919707090897 + 1.629522740505929i, + -72.34919707090897 - 1.629522740505929i, + -97.24021794530901 + 1.628064860261413i, + -97.24021794530901 - 1.628064860261413i, + -125.6811625494976 + 1.627074041605065i, + -125.6811625494976 - 1.627074041605065i, + -157.5556174346503 + 1.626392967840776i, + -157.5556174346503 - 1.626392967840776i, + -192.732837945876 + 1.625893674037654i, + -192.732837945876 - 1.625893674037654i, + -231.0684238575969 + 1.625523897559938i, + -231.0684238575969 - 1.625523897559938i, + -272.404932676379 + 1.625248463045784i, + -272.404932676379 - 1.625248463045784i, + -316.5725618120467 + 1.625029322230836i, + -316.5725618120467 - 1.625029322230836i, + -363.3898435346347 + 1.624863705104029i, + -363.3898435346347 - 1.624863705104029i, + -412.6644183160402 + 1.624734783685709i, + -412.6644183160402 - 1.624734783685709i, + -464.1938275598905 + 1.624629407600858i, + -464.1938275598905 - 1.624629407600858i, + -517.7663337295413 + 1.624555040627727i, + -517.7663337295413 - 1.624555040627727i, + -573.1617958392867 + 1.62448889134649i, + -573.1617958392867 - 1.62448889134649i, + -630.1525854166166 + 1.624445355378192i, + -630.1525854166166 - 1.624445355378192i, + -688.5045249303587 + 1.624414401302088i, + -688.5045249303587 - 1.624414401302088i, + -747.9778126976437 + 1.624396390555459i, + -747.9778126976437 - 1.624396390555459i, + -808.3280706224909 + 1.62438480760184i, + -808.3280706224909 - 1.62438480760184i, + -869.3072903249724 + 1.624387678902335i, + -869.3072903249724 - 1.624387678902335i, + -930.6648831979091 + 1.624396130880259i, + -930.6648831979091 - 1.624396130880259i, + -992.1487134378474 + 1.624417808682915i, + -992.1487134378474 - 1.624417808682915i, + -1053.506114553354 + 1.624453056189826i, + -1053.506114553354 - 1.624453056189826i, + -1114.484928198698 + 1.62449544649428i, + -1114.484928198698 - 1.62449544649428i, + -1174.834554234014 + 1.624553207269019i, + -1174.834554234014 - 1.624553207269019i, + -1234.306981514973 + 1.624623553438826i, + -1234.306981514973 - 1.624623553438826i, + -1292.657768972259 + 1.624709216827242i, + -1292.657768972259 - 1.624709216827242i, + -1349.647106741638 + 1.624814444572517i, + -1349.647106741638 - 1.624814444572517i, + -1405.040739357668 + 1.624951632752096i, + -1405.040739357668 - 1.624951632752096i, + -1458.610953350783 + 1.625104547041682i, + -1458.610953350783 - 1.625104547041682i, + -1510.137508646807 + 1.625304666073007i, + -1510.137508646807 - 1.625304666073007i, + -1559.408520122221 + 1.625548293255404i, + -1559.408520122221 - 1.625548293255404i, + -1606.221305250554 + 1.625851986073836i, + -1606.221305250554 - 1.625851986073836i, + -1650.383201531125 + 1.62624202844641i, + -1650.383201531125 - 1.62624202844641i, + -1691.712315735984 + 1.6267345498979i, + -1691.712315735984 - 1.6267345498979i, + -1730.038177420971 + 1.627388968656263i, + -1730.038177420971 - 1.627388968656263i, + -1765.20230058066 + 1.628268412022146i, + -1765.20230058066 - 1.628268412022146i, + -1797.05860162894 + 1.629473972633416i, + -1797.05860162894 - 1.629473972633416i, + -1825.473493639258 + 1.631220665229006i, + -1825.473493639258 - 1.631220665229006i, + -1850.32542664842 + 1.633834593918563i, + -1850.32542664842 - 1.633834593918563i, + -1871.503056018116 + 1.637993570641514i, + -1871.503056018116 - 1.637993570641514i, + -1888.90026514681 + 1.64508855982818i, + -1888.90026514681 - 1.64508855982818i, + -1902.402515327158 + 1.658179541614067i, + -1902.402515327158 - 1.658179541614067i, + -1911.858940404498 + 1.682209391409579i, + -1911.858940404498 - 1.682209391409579i, + -1916.92602113601 + 1.761877988650816i, + -1916.92602113601 - 1.761877988650816i, + -1930.484166851586 + 1.202676762393897i, + -1930.484166851586 - 1.202676762393897i, + 3, + 4, + }, + }, +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlabrd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlabrd.go new file mode 100644 index 00000000..460cefe7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlabrd.go @@ -0,0 +1,107 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" +) + +type Dlabrder interface { + Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauq, taup, x []float64, ldx int, y []float64, ldy int) +} + +func DlabrdTest(t *testing.T, impl Dlabrder) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, nb, lda, ldx, ldy int + }{ + {4, 5, 2, 0, 0, 0}, + {4, 5, 4, 0, 0, 0}, + {5, 5, 2, 0, 0, 0}, + {5, 5, 5, 0, 0, 0}, + {5, 4, 4, 0, 0, 0}, + {5, 4, 4, 0, 0, 0}, + + {4, 5, 2, 10, 11, 12}, + {4, 5, 4, 10, 11, 12}, + {5, 5, 2, 10, 11, 12}, + {5, 5, 5, 10, 11, 12}, + {5, 4, 2, 10, 11, 12}, + {5, 4, 4, 10, 11, 12}, + + {4, 5, 2, 11, 12, 10}, + {4, 5, 4, 11, 12, 10}, + {5, 5, 2, 11, 12, 10}, + {5, 5, 5, 11, 12, 10}, + {5, 4, 2, 11, 12, 10}, + {5, 4, 4, 11, 12, 10}, + + {4, 5, 2, 12, 11, 10}, + {4, 5, 4, 12, 11, 10}, + {5, 5, 2, 12, 11, 10}, + {5, 5, 5, 12, 11, 10}, + {5, 4, 2, 12, 11, 10}, + {5, 4, 4, 12, 11, 10}, + } { + m := test.m + n := test.n + nb := test.nb + lda := test.lda + if lda == 0 { + lda = n + } + ldy := test.ldy + if ldy == 0 { + ldy = nb + } + ldx := test.ldx + if ldx == 0 { + ldx = nb + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + d := make([]float64, nb) + for i := range d { + d[i] = math.NaN() + } + e := make([]float64, nb) + for i := range e { + e[i] = math.NaN() + } + tauP := make([]float64, nb) + for i := range tauP { + tauP[i] = math.NaN() + } + tauQ := make([]float64, nb) + for i := range tauP { + tauQ[i] = math.NaN() + } + x := make([]float64, m*ldx) + for i := range x { + x[i] = rnd.NormFloat64() + } + y := make([]float64, n*ldy) + for i := range y { + y[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Compute the reduction. + impl.Dlabrd(m, n, nb, a, lda, d, e, tauQ, tauP, x, ldx, y, ldy) + + if m >= n && nb == n { + tauP[n-1] = 0 + } + if m < n && nb == m { + tauQ[m-1] = 0 + } + checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacn2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacn2.go new file mode 100644 index 00000000..9e76c0b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacn2.go @@ -0,0 +1,72 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlacn2er interface { + Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) +} + +func Dlacn2Test(t *testing.T, impl Dlacn2er) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 15, 20, 100} { + for cas := 0; cas < 10; cas++ { + a := randomGeneral(n, n, n, rnd) + + // Compute the 1-norm of A explicitly. + var norm1 float64 + for j := 0; j < n; j++ { + var sum float64 + for i := 0; i < n; i++ { + sum += math.Abs(a.Data[i*a.Stride+j]) + } + if sum > norm1 { + norm1 = sum + } + } + + // Compute the estimate of 1-norm using Dlanc2. + x := make([]float64, n) + work := make([]float64, n) + v := make([]float64, n) + isgn := make([]int, n) + var ( + kase int + isave [3]int + got float64 + ) + loop: + for { + got, kase = impl.Dlacn2(n, v, x, isgn, got, kase, &isave) + switch kase { + default: + panic("Dlacn2 returned invalid value of kase") + case 0: + break loop + case 1: + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) + copy(x, work) + case 2: + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) + copy(x, work) + } + } + + // Check that got is either accurate enough or a + // lower estimate of the 1-norm of A. + if math.Abs(got-norm1) > 1e-8 && got > norm1 { + t.Errorf("Case n=%v: not lower estimate. 1-norm %v, estimate %v", n, norm1, got) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacpy.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacpy.go new file mode 100644 index 00000000..aa3e5e0f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlacpy.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dlacpyer interface { + Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) +} + +func DlacpyTest(t *testing.T, impl Dlacpyer) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, test := range []struct { + m, n, lda, ldb int + }{ + {3, 5, 0, 0}, + {5, 5, 0, 0}, + {7, 5, 0, 0}, + + {3, 5, 10, 12}, + {5, 5, 10, 12}, + {7, 5, 10, 12}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + b := make([]float64, m*ldb) + for i := range b { + b[i] = rnd.Float64() + } + impl.Dlacpy(uplo, m, n, a, lda, b, ldb) + equal := true + switch uplo { + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + } + DoneCheck: + if !equal { + fmt.Println(blas.Lower) + t.Errorf("Matrices not equal after copy. Uplo = %d, m = %d, n = %d", uplo, m, n) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlae2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlae2.go new file mode 100644 index 00000000..236b3f2b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlae2.go @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "testing" +) + +type Dlae2er interface { + Dlae2(a, b, c float64) (rt1, rt2 float64) +} + +func Dlae2Test(t *testing.T, impl Dlae2er) { + for _, test := range []struct { + a, b, c float64 + }{ + {-10, 5, 3}, + {3, 5, -10}, + {0, 3, 0}, + {1, 3, 1}, + {1, -3, 1}, + {5, 0, 3}, + {3, 0, -5}, + {1, 3, 1.02}, + {1.02, 3, 1}, + {1, -3, -9}, + } { + a := test.a + b := test.b + c := test.c + rt1, rt2 := impl.Dlae2(a, b, c) + + errStr := fmt.Sprintf("a = %v, b = %v, c = %v", a, b, c) + // Check if rt1 and rt2 are eigenvalues by checking if det(a - λI) = 0 + a1 := a - rt1 + c1 := c - rt1 + det := a1*c1 - b*b + if math.Abs(det) > 1e-10 { + t.Errorf("First eigenvalue mismatch. %s. Det = %v", errStr, det) + } + + a2 := a - rt2 + c2 := c - rt2 + det = a2*c2 - b*b + if math.Abs(det) > 1e-10 { + t.Errorf("Second eigenvalue mismatch. %s. Det = %v", errStr, det) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaev2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaev2.go new file mode 100644 index 00000000..3aea2d74 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaev2.go @@ -0,0 +1,46 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" +) + +type Dlaev2er interface { + Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) +} + +func Dlaev2Test(t *testing.T, impl Dlaev2er) { + rnd := rand.New(rand.NewSource(1)) + for trial := 0; trial < 100; trial++ { + a := rnd.NormFloat64() + b := rnd.NormFloat64() + c := rnd.NormFloat64() + + rt1, rt2, cs1, sn1 := impl.Dlaev2(a, b, c) + tmp := mul2by2([2][2]float64{{cs1, sn1}, {-sn1, cs1}}, [2][2]float64{{a, b}, {b, c}}) + ans := mul2by2(tmp, [2][2]float64{{cs1, -sn1}, {sn1, cs1}}) + if math.Abs(ans[0][0]-rt1) > 1e-14 { + t.Errorf("Largest eigenvalue mismatch. Returned %v, mul %v", rt1, ans[0][0]) + } + if math.Abs(ans[1][0]) > 1e-14 || math.Abs(ans[0][1]) > 1e-14 { + t.Errorf("Non-zero off diagonal. ans[1][0] = %v, ans[0][1] = %v", ans[1][0], ans[0][1]) + } + if math.Abs(ans[1][1]-rt2) > 1e-14 { + t.Errorf("Smallest eigenvalue mismatch. Returned %v, mul %v", rt2, ans[1][1]) + } + } +} + +func mul2by2(a, b [2][2]float64) [2][2]float64 { + var c [2][2]float64 + c[0][0] = a[0][0]*b[0][0] + a[0][1]*b[1][0] + c[0][1] = a[0][0]*b[0][1] + a[0][1]*b[1][1] + c[1][0] = a[1][0]*b[0][0] + a[1][1]*b[1][0] + c[1][1] = a[1][0]*b[0][1] + a[1][1]*b[1][1] + return c +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaexc.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaexc.go new file mode 100644 index 00000000..e69f41d8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaexc.go @@ -0,0 +1,227 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaexcer interface { + Dlaexc(wantq bool, n int, t []float64, ldt int, q []float64, ldq int, j1, n1, n2 int, work []float64) bool +} + +func DlaexcTest(t *testing.T, impl Dlaexcer) { + rnd := rand.New(rand.NewSource(1)) + + for _, wantq := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + j1 := rnd.Intn(n) + n1 := min(rnd.Intn(3), n-j1) + n2 := min(rnd.Intn(3), n-j1-n1) + testDlaexc(t, impl, wantq, n, j1, n1, n2, extra, rnd) + } + } + } + } +} + +func testDlaexc(t *testing.T, impl Dlaexcer, wantq bool, n, j1, n1, n2, extra int, rnd *rand.Rand) { + const tol = 1e-14 + + tmat := randomGeneral(n, n, n+extra, rnd) + // Zero out the lower triangle. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + tmat.Data[i*tmat.Stride+j] = 0 + } + } + // Make any 2x2 diagonal block to be in Schur canonical form. + if n1 == 2 { + // Diagonal elements equal. + tmat.Data[(j1+1)*tmat.Stride+j1+1] = tmat.Data[j1*tmat.Stride+j1] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(tmat.Data[j1*tmat.Stride+j1+1]) { + c *= -1 + } + tmat.Data[(j1+1)*tmat.Stride+j1] = c + } + if n2 == 2 { + // Diagonal elements equal. + tmat.Data[(j1+n1+1)*tmat.Stride+j1+n1+1] = tmat.Data[(j1+n1)*tmat.Stride+j1+n1] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(tmat.Data[(j1+n1)*tmat.Stride+j1+n1+1]) { + c *= -1 + } + tmat.Data[(j1+n1+1)*tmat.Stride+j1+n1] = c + } + tmatCopy := cloneGeneral(tmat) + var q, qCopy blas64.General + if wantq { + q = eye(n, n+extra) + qCopy = cloneGeneral(q) + } + work := nanSlice(n) + + ok := impl.Dlaexc(wantq, n, tmat.Data, tmat.Stride, q.Data, q.Stride, j1, n1, n2, work) + + prefix := fmt.Sprintf("Case n=%v, j1=%v, n1=%v, n2=%v, wantq=%v, extra=%v", n, j1, n1, n2, wantq, extra) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if wantq && !generalOutsideAllNaN(q) { + t.Errorf("%v: out-of-range write to Q", prefix) + } + + if !ok { + if n1 == 1 && n2 == 1 { + t.Errorf("%v: unexpected failure", prefix) + } else { + t.Logf("%v: Dlaexc returned false", prefix) + } + } + + if !ok || n1 == 0 || n2 == 0 || j1+n1 >= n { + // Check that T is not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if tmat.Data[i*tmat.Stride+j] != tmatCopy.Data[i*tmatCopy.Stride+j] { + t.Errorf("%v: ok == false but T[%v,%v] modified", prefix, i, j) + } + } + } + if !wantq { + return + } + // Check that Q is not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if q.Data[i*q.Stride+j] != qCopy.Data[i*qCopy.Stride+j] { + t.Errorf("%v: ok == false but Q[%v,%v] modified", prefix, i, j) + } + } + } + return + } + + // Check that T is not modified outside of rows and columns [j1:j1+n1+n2]. + for i := 0; i < n; i++ { + if j1 <= i && i < j1+n1+n2 { + continue + } + for j := 0; j < n; j++ { + if j1 <= j && j < j1+n1+n2 { + continue + } + diff := tmat.Data[i*tmat.Stride+j] - tmatCopy.Data[i*tmatCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification of T[%v,%v]", prefix, i, j) + } + } + } + + if n1 == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[(j1+n2)*tmat.Stride+j1+n2] + want := tmatCopy.Data[j1*tmatCopy.Stride+j1] + if want != got { + t.Errorf("%v: unexpected value of T[%v,%v]. Want %v, got %v", prefix, j1+n2, j1+n2, want, got) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + // The n1×n1 block is now located at T[j1+n2,j1+n2]. + a, b, c, d := extract2x2Block(tmat.Data[(j1+n2)*tmat.Stride+j1+n2:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, j1+n2, j1+n2) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The n1×n1 block was originally located at T[j1,j1]. + a, b, c, d = extract2x2Block(tmatCopy.Data[j1*tmatCopy.Stride+j1:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1+n2, j1+n2, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1+n2, j1+n2, ev2Want, ev2Got) + } + } + if n2 == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[j1*tmat.Stride+j1] + want := tmatCopy.Data[(j1+n1)*tmatCopy.Stride+j1+n1] + if want != got { + t.Errorf("%v: unexpected value of T[%v,%v]. Want %v, got %v", prefix, j1, j1, want, got) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + // The n2×n2 block is now located at T[j1,j1]. + a, b, c, d := extract2x2Block(tmat.Data[j1*tmat.Stride+j1:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, j1, j1) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The n2×n2 block was originally located at T[j1+n1,j1+n1]. + a, b, c, d = extract2x2Block(tmatCopy.Data[(j1+n1)*tmatCopy.Stride+j1+n1:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1, j1, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1, j1, ev2Want, ev2Got) + } + } + + if !wantq { + return + } + + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Check that Q is unchanged outside of columns [j1:j1+n1+n2]. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if j1 <= j && j < j1+n1+n2 { + continue + } + diff := q.Data[i*q.Stride+j] - qCopy.Data[i*qCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification of Q[%v,%v]", prefix, i, j) + } + } + } + // Check that Q^T TOrig Q == T. + tq := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmatCopy, q, 0, tq) + qtq := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tq, 0, qtq) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + diff := qtq.Data[i*qtq.Stride+j] - tmat.Data[i*tmat.Stride+j] + if math.Abs(diff) > tol { + t.Errorf("%v: unexpected value of T[%v,%v]", prefix, i, j) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlags2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlags2.go new file mode 100644 index 00000000..2a3da46d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlags2.go @@ -0,0 +1,100 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlags2er interface { + Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) +} + +func Dlags2Test(t *testing.T, impl Dlags2er) { + rnd := rand.New(rand.NewSource(1)) + for _, upper := range []bool{true, false} { + for i := 0; i < 100; i++ { + a1 := rnd.Float64() + a2 := rnd.Float64() + a3 := rnd.Float64() + b1 := rnd.Float64() + b2 := rnd.Float64() + b3 := rnd.Float64() + + csu, snu, csv, snv, csq, snq := impl.Dlags2(upper, a1, a2, a3, b1, b2, b3) + + detU := det2x2(csu, snu, -snu, csu) + if !floats.EqualWithinAbsOrRel(math.Abs(detU), 1, 1e-14, 1e-14) { + t.Errorf("U not orthogonal: det(U)=%v", detU) + } + detV := det2x2(csv, snv, -snv, csv) + if !floats.EqualWithinAbsOrRel(math.Abs(detV), 1, 1e-14, 1e-14) { + t.Errorf("V not orthogonal: det(V)=%v", detV) + } + detQ := det2x2(csq, snq, -snq, csq) + if !floats.EqualWithinAbsOrRel(math.Abs(detQ), 1, 1e-14, 1e-14) { + t.Errorf("Q not orthogonal: det(Q)=%v", detQ) + } + + u := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csu, snu, -snu, csu}, + } + v := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csv, snv, -snv, csv}, + } + q := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csq, snq, -snq, csq}, + } + + a := blas64.General{Rows: 2, Cols: 2, Stride: 2} + b := blas64.General{Rows: 2, Cols: 2, Stride: 2} + if upper { + a.Data = []float64{a1, a2, 0, a3} + b.Data = []float64{b1, b2, 0, b3} + } else { + a.Data = []float64{a1, 0, a2, a3} + b.Data = []float64{b1, 0, b2, b3} + } + + tmp := blas64.General{Rows: 2, Cols: 2, Stride: 2, Data: make([]float64, 4)} + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, a, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, a) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, b, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, b) + + var gotA, gotB float64 + if upper { + gotA = a.Data[1] + gotB = b.Data[1] + } else { + gotA = a.Data[2] + gotB = b.Data[2] + } + if !floats.EqualWithinAbsOrRel(gotA, 0, 1e-14, 1e-14) { + t.Errorf("unexpected non-zero value for zero triangle of U^T*A*Q: %v", gotA) + } + if !floats.EqualWithinAbsOrRel(gotB, 0, 1e-14, 1e-14) { + t.Errorf("unexpected non-zero value for zero triangle of V^T*B*Q: %v", gotB) + } + } + } +} + +func det2x2(a, b, c, d float64) float64 { return a*d - b*c } diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahqr.go new file mode 100644 index 00000000..c68680a7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahqr.go @@ -0,0 +1,441 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlahqrer interface { + Dlahqr(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int) int +} + +type dlahqrTest struct { + h blas64.General + ilo, ihi int + iloz, ihiz int + wantt, wantz bool + + evWant []complex128 // Optional slice holding known eigenvalues. +} + +func DlahqrTest(t *testing.T, impl Dlahqrer) { + rnd := rand.New(rand.NewSource(1)) + + // Tests that choose the [ilo:ihi+1,ilo:ihi+1] and + // [iloz:ihiz+1,ilo:ihi+1] blocks randomly. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + iloz := rnd.Intn(ilo + 1) + ihiz := ihi + rnd.Intn(n-ihi) + h := randomHessenberg(n, n+extra, rnd) + if ilo-1 >= 0 { + h.Data[ilo*h.Stride+ilo-1] = 0 + } + if ihi+1 < n { + h.Data[(ihi+1)*h.Stride+ihi] = 0 + } + test := dlahqrTest{ + h: h, + ilo: ilo, + ihi: ihi, + iloz: iloz, + ihiz: ihiz, + wantt: wantt, + wantz: wantz, + } + testDlahqr(t, impl, test) + } + } + } + } + } + // Tests that make sure that some potentially problematic corner cases, + // like zero-sized matrix, are covered. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + for _, test := range []dlahqrTest{ + { + h: randomHessenberg(0, extra, rnd), + ilo: 0, + ihi: -1, + iloz: 0, + ihiz: -1, + }, + { + h: randomHessenberg(1, 1+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 1, + ihi: 1, + iloz: 1, + ihiz: 1, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 9, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + } { + if test.ilo-1 >= 0 { + test.h.Data[test.ilo*test.h.Stride+test.ilo-1] = 0 + } + if test.ihi+1 < test.h.Rows { + test.h.Data[(test.ihi+1)*test.h.Stride+test.ihi] = 0 + } + test.wantt = wantt + test.wantz = wantz + testDlahqr(t, impl, test) + } + } + } + } + + // Tests with explicit eigenvalues computed by Octave. + for _, test := range []dlahqrTest{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ilo: 1, + ihi: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ilo: 0, + ihi: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + testDlahqr(t, impl, test) + } +} + +func testDlahqr(t *testing.T, impl Dlahqrer, test dlahqrTest) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ilo := test.ilo + ihi := test.ihi + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + wr := nanSlice(ihi + 1) + wi := nanSlice(ihi + 1) + + unconverged := impl.Dlahqr(wantt, wantz, n, ilo, ihi, h.Data, h.Stride, wr, wi, iloz, ihiz, z.Data, z.Stride) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ilo=%v, ihi=%v, iloz=%v, ihiz=%v, extra=%v", + wantt, wantz, n, ilo, ihi, iloz, ihiz, extra) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + + if !isUpperHessenberg(h) { + t.Logf("%v: H is not Hessenberg", prefix) + } + + start := ilo // Index of the first computed eigenvalue. + if unconverged != 0 { + start = unconverged + if start == ihi+1 { + t.Logf("%v: no eigenvalue has converged", prefix) + } + } + + // Check that wr and wi have not been modified in [:start]. + if !isAllNaN(wr[:start]) { + t.Errorf("%v: unexpected modification of wr", prefix) + } + if !isAllNaN(wi[:start]) { + t.Errorf("%v: unexpected modification of wi", prefix) + } + + var hasReal bool + for i := start; i <= ihi; { + if wi[i] == 0 { // Real eigenvalue. + hasReal = true + // Check that the eigenvalue corresponds to a 1×1 block + // on the diagonal of H. + if wantt { + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + for _, index := range []struct{ r, c int }{ + {i, i - 1}, // h h h + {i + 1, i - 1}, // 0 wr[i] h + {i + 1, i}, // 0 0 h + } { + if index.r >= n || index.c < 0 { + continue + } + if h.Data[index.r*h.Stride+index.c] != 0 { + t.Errorf("%v: H[%v,%v] != 0", prefix, index.r, index.c) + } + } + } + i++ + continue + } + + // Complex eigenvalue. + + // In the conjugate pair the real parts must be equal. + if wr[i] != wr[i+1] { + t.Errorf("%v: real part of conjugate pair not equal, i=%v", prefix, i) + } + // The first imaginary part must be positive. + if wi[i] < 0 { + t.Errorf("%v: wi[%v] not positive", prefix, i) + } + // The second imaginary part must be negative with the same + // magnitude. + if wi[i] != -wi[i+1] { + t.Errorf("%v: wi[%v] != -wi[%v]", prefix, i, i+1) + } + if wantt { + // Check that wi[i] has the correct value. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + if wr[i] != h.Data[(i+1)*h.Stride+i+1] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i+1, i+1) + } + prod := math.Abs(h.Data[(i+1)*h.Stride+i] * h.Data[i*h.Stride+i+1]) + if math.Abs(math.Sqrt(prod)-wi[i]) > tol { + t.Errorf("%v: unexpected value of wi[%v]: want %v, got %v", prefix, i, math.Sqrt(prod), wi[i]) + } + + // Check that the corresponding diagonal block is 2×2. + for _, index := range []struct{ r, c int }{ + {i, i - 1}, // i + {i + 1, i - 1}, // h h h h + {i + 2, i - 1}, // 0 wr[i] b h i + {i + 2, i}, // 0 c wr[i+1] h + {i + 2, i + 1}, // 0 0 0 h + } { + if index.r >= n || index.c < 0 { + continue + } + if h.Data[index.r*h.Stride+index.c] != 0 { + t.Errorf("%v: H[%v,%v] != 0", prefix, index.r, index.c) + } + } + } + i += 2 + } + // If the number of found eigenvalues is odd, at least one must be real. + if (ihi+1-start)%2 != 0 && !hasReal { + t.Errorf("%v: expected at least one real eigenvalue", prefix) + } + + // Compare found eigenvalues to the reference, if known. + if test.evWant != nil { + for i := start; i <= ihi; i++ { + ev := complex(wr[i], wi[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + // Z should contain the orthogonal matrix U. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Z should have been modified only in the + // [iloz:ihiz+1,ilo:ihi+1] block. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if iloz <= i && i <= ihiz && ilo <= j && j <= ihi { + continue + } + if z.Data[i*z.Stride+j] != zCopy.Data[i*zCopy.Stride+j] { + t.Errorf("%v: Z modified outside of [iloz:ihiz+1,ilo:ihi+1] block", prefix) + } + } + } + if wantt { + hu := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu) + uhu := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu) + if !equalApproxGeneral(uhu, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahr2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahr2.go new file mode 100644 index 00000000..28aee344 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlahr2.go @@ -0,0 +1,240 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "compress/gzip" + "encoding/json" + "fmt" + "log" + "math" + "math/rand" + "os" + "path/filepath" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlahr2er interface { + Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) +} + +type Dlahr2test struct { + N, K, NB int + A []float64 + + AWant []float64 + TWant []float64 + YWant []float64 + TauWant []float64 +} + +func Dlahr2Test(t *testing.T, impl Dlahr2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + n, k, nb int + }{ + {3, 0, 3}, + {3, 1, 2}, + {3, 1, 1}, + + {5, 0, 5}, + {5, 1, 4}, + {5, 1, 3}, + {5, 1, 2}, + {5, 1, 1}, + {5, 2, 3}, + {5, 2, 2}, + {5, 2, 1}, + {5, 3, 2}, + {5, 3, 1}, + + {7, 3, 4}, + {7, 3, 3}, + {7, 3, 2}, + {7, 3, 1}, + + {10, 0, 10}, + {10, 1, 9}, + {10, 1, 5}, + {10, 1, 1}, + {10, 5, 5}, + {10, 5, 3}, + {10, 5, 1}, + } { + for cas := 0; cas < 100; cas++ { + for _, extraStride := range []int{0, 1, 10} { + n := test.n + k := test.k + nb := test.nb + + a := randomGeneral(n, n-k+1, n-k+1+extraStride, rnd) + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + tmat := nanTriangular(blas.Upper, nb, nb+extraStride) + y := nanGeneral(n, nb, nb+extraStride) + tau := nanSlice(nb) + + impl.Dlahr2(n, k, nb, a.Data, a.Stride, tau, tmat.Data, tmat.Stride, y.Data, y.Stride) + + prefix := fmt.Sprintf("Case n=%v, k=%v, nb=%v, ldex=%v", n, k, nb, extraStride) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !triangularOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data) + } + if !generalOutsideAllNaN(y) { + t.Errorf("%v: out-of-range write to Y\n%v", prefix, y.Data) + } + + // Check that A[:k,:] and A[:,nb:] blocks were not modified. + for i := 0; i < n; i++ { + for j := 0; j < n-k+1; j++ { + if i >= k && j < nb { + continue + } + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected write to A[%v,%v]", prefix, i, j) + } + } + } + + // Check that all elements of tau were assigned. + for i, v := range tau { + if math.IsNaN(v) { + t.Errorf("%v: tau[%v] not assigned", prefix, i) + } + } + + // Extract V from a. + v := blas64.General{ + Rows: n - k + 1, + Cols: nb, + Stride: nb, + Data: make([]float64, (n-k+1)*nb), + } + for j := 0; j < v.Cols; j++ { + v.Data[(j+1)*v.Stride+j] = 1 + for i := j + 2; i < v.Rows; i++ { + v.Data[i*v.Stride+j] = a.Data[(i+k-1)*a.Stride+j] + } + } + + // VT = V. + vt := v + vt.Data = make([]float64, len(v.Data)) + copy(vt.Data, v.Data) + // VT = V * T. + blas64.Trmm(blas.Right, blas.NoTrans, 1, tmat, vt) + // YWant = A * V * T. + ywant := blas64.General{ + Rows: n, + Cols: nb, + Stride: nb, + Data: make([]float64, n*nb), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, vt, 0, ywant) + + // Compare Y and YWant. + for i := 0; i < n; i++ { + for j := 0; j < nb; j++ { + diff := math.Abs(ywant.Data[i*ywant.Stride+j] - y.Data[i*y.Stride+j]) + if diff > 1e-14 { + t.Errorf("%v: unexpected Y[%v,%v], diff=%v", prefix, i, j, diff) + } + } + } + + // Construct Q directly from the first nb columns of a. + q := constructQ("QR", n-k, nb, a.Data[k*a.Stride:], a.Stride, tau) + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Construct Q as the product Q = I - V*T*V^T. + qwant := blas64.General{ + Rows: n - k + 1, + Cols: n - k + 1, + Stride: n - k + 1, + Data: make([]float64, (n-k+1)*(n-k+1)), + } + for i := 0; i < qwant.Rows; i++ { + qwant.Data[i*qwant.Stride+i] = 1 + } + blas64.Gemm(blas.NoTrans, blas.Trans, -1, vt, v, 1, qwant) + if !isOrthonormal(qwant) { + t.Errorf("%v: Q = I - V*T*V^T is not orthogonal", prefix) + } + + // Compare Q and QWant. Note that since Q is + // (n-k)×(n-k) and QWant is (n-k+1)×(n-k+1), we + // ignore the first row and column of QWant. + for i := 0; i < n-k; i++ { + for j := 0; j < n-k; j++ { + diff := math.Abs(q.Data[i*q.Stride+j] - qwant.Data[(i+1)*qwant.Stride+j+1]) + if diff > 1e-14 { + t.Errorf("%v: unexpected Q[%v,%v], diff=%v", prefix, i, j, diff) + } + } + } + } + } + } + + // Go runs tests from the source directory, so unfortunately we need to + // include the "../testlapack" part. + file, err := os.Open(filepath.FromSlash("../testlapack/testdata/dlahr2data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + r, err := gzip.NewReader(file) + if err != nil { + log.Fatal(err) + } + defer r.Close() + + var tests []Dlahr2test + json.NewDecoder(r).Decode(&tests) + for _, test := range tests { + tau := make([]float64, len(test.TauWant)) + for _, ldex := range []int{0, 1, 20} { + n := test.N + k := test.K + nb := test.NB + + lda := n - k + 1 + ldex + a := make([]float64, (n-1)*lda+n-k+1) + copyMatrix(n, n-k+1, a, lda, test.A) + + ldt := nb + ldex + tmat := make([]float64, (nb-1)*ldt+nb) + + ldy := nb + ldex + y := make([]float64, (n-1)*ldy+nb) + + impl.Dlahr2(n, k, nb, a, lda, tau, tmat, ldt, y, ldy) + + prefix := fmt.Sprintf("Case n=%v, k=%v, nb=%v, ldex=%v", n, k, nb, ldex) + if !equalApprox(n, n-k+1, a, lda, test.AWant, 1e-14) { + t.Errorf("%v: unexpected matrix A\n got=%v\nwant=%v", prefix, a, test.AWant) + } + if !equalApproxTriangular(true, nb, tmat, ldt, test.TWant, 1e-14) { + t.Errorf("%v: unexpected matrix T\n got=%v\nwant=%v", prefix, tmat, test.TWant) + } + if !equalApprox(n, nb, y, ldy, test.YWant, 1e-14) { + t.Errorf("%v: unexpected matrix Y\n got=%v\nwant=%v", prefix, y, test.YWant) + } + if !floats.EqualApprox(tau, test.TauWant, 1e-14) { + t.Errorf("%v: unexpected slice tau\n got=%v\nwant=%v", prefix, tau, test.TauWant) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaln2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaln2.go new file mode 100644 index 00000000..07a322b8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaln2.go @@ -0,0 +1,139 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" +) + +type Dlaln2er interface { + Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool) +} + +func Dlaln2Test(t *testing.T, impl Dlaln2er) { + rnd := rand.New(rand.NewSource(1)) + for _, trans := range []bool{true, false} { + for _, na := range []int{1, 2} { + for _, nw := range []int{1, 2} { + for _, extra := range []int{0, 1, 2, 13} { + for cas := 0; cas < 1000; cas++ { + testDlaln2(t, impl, trans, na, nw, extra, rnd) + } + } + } + } + } +} + +func testDlaln2(t *testing.T, impl Dlaln2er, trans bool, na, nw, extra int, rnd *rand.Rand) { + const tol = 1e-12 + const dlamchE = 1.0 / (1 << 53) + const dlamchP = 2 * dlamchE + + ca := rnd.NormFloat64() + d1 := rnd.NormFloat64() + d2 := rnd.NormFloat64() + + var w complex128 + if nw == 1 { + w = complex(rand.NormFloat64(), 0) + } else { + w = complex(rand.NormFloat64(), rand.NormFloat64()) + } + smin := dlamchP * (math.Abs(real(w)) + math.Abs(imag(w))) + + a := randomGeneral(na, na, na+extra, rnd) + b := randomGeneral(na, nw, nw+extra, rnd) + x := randomGeneral(na, nw, nw+extra, rnd) + + scale, xnormGot, ok := impl.Dlaln2(trans, na, nw, smin, ca, a.Data, a.Stride, d1, d2, b.Data, b.Stride, real(w), imag(w), x.Data, x.Stride) + + prefix := fmt.Sprintf("Case trans=%v, na=%v, nw=%v, extra=%v", trans, na, nw, extra) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !generalOutsideAllNaN(b) { + t.Errorf("%v: out-of-range write to B\n%v", prefix, b.Data) + } + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to X\n%v", prefix, x.Data) + } + + if scale <= 0 || 1 < scale { + t.Errorf("%v: invalid value of scale=%v", prefix, scale) + } + + var xnormWant float64 + for i := 0; i < na; i++ { + var rowsum float64 + for j := 0; j < nw; j++ { + rowsum += math.Abs(x.Data[i*x.Stride+j]) + } + if rowsum > xnormWant { + xnormWant = rowsum + } + } + if xnormWant != xnormGot { + t.Errorf("Case %v: unexpected xnorm with scale=%v. Want %v, got %v", prefix, scale, xnormWant, xnormGot) + } + + if !ok { + // If ok is false, the matrix has been perturbed but we don't + // know how. Return without comparing both sides of the + // equation. + return + } + + m := make([]complex128, na*na) + if trans { + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + m[i*na+j] = complex(ca*a.Data[j*a.Stride+i], 0) + } + } + } else { + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + m[i*na+j] = complex(ca*a.Data[i*a.Stride+j], 0) + } + } + } + m[0] -= w * complex(d1, 0) + if na == 2 { + m[3] -= w * complex(d2, 0) + } + + cx := make([]complex128, na) + cb := make([]complex128, na) + switch nw { + case 1: + for i := 0; i < na; i++ { + cx[i] = complex(x.Data[i*x.Stride], 0) + cb[i] = complex(scale*b.Data[i*x.Stride], 0) + } + case 2: + for i := 0; i < na; i++ { + cx[i] = complex(x.Data[i*x.Stride], x.Data[i*x.Stride+1]) + cb[i] = complex(scale*b.Data[i*b.Stride], scale*b.Data[i*b.Stride+1]) + } + } + + mx := make([]complex128, na) + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + mx[i] += m[i*na+j] * cx[j] + } + } + for i := 0; i < na; i++ { + if cmplx.Abs(mx[i]-cb[i]) > tol { + t.Errorf("Case %v: unexpected value of left-hand side at row %v with scale=%v. Want %v, got %v", prefix, i, scale, cb[i], mx[i]) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlange.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlange.go new file mode 100644 index 00000000..33f7efe1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlange.go @@ -0,0 +1,93 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dlanger interface { + Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 +} + +func DlangeTest(t *testing.T, impl Dlanger) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {4, 3, 0}, + {3, 4, 0}, + {4, 3, 100}, + {3, 4, 100}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() - 0.5 + } + work := make([]float64, n) + for i := range work { + work[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Test MaxAbs norm. + norm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, work) + var ans float64 + for i := 0; i < m; i++ { + idx := blas64.Iamax(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans = math.Max(ans, math.Abs(a[i*lda+idx])) + } + // Should be strictly equal because there is no floating point summation error. + if ans != norm { + t.Errorf("MaxAbs mismatch. Want %v, got %v.", ans, norm) + } + + // Test MaxColumnSum norm. + norm = impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) + ans = 0 + for i := 0; i < n; i++ { + sum := blas64.Asum(m, blas64.Vector{Inc: lda, Data: aCopy[i:]}) + ans = math.Max(ans, sum) + } + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("MaxColumnSum mismatch. Want %v, got %v.", ans, norm) + } + + // Test MaxRowSum norm. + norm = impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) + ans = 0 + for i := 0; i < m; i++ { + sum := blas64.Asum(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans = math.Max(ans, sum) + } + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("MaxRowSum mismatch. Want %v, got %v.", ans, norm) + } + + // Test Frobenius norm + norm = impl.Dlange(lapack.NormFrob, m, n, a, lda, work) + ans = 0 + for i := 0; i < m; i++ { + sum := blas64.Nrm2(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans += sum * sum + } + ans = math.Sqrt(ans) + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("NormFrob mismatch. Want %v, got %v.", ans, norm) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanst.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanst.go new file mode 100644 index 00000000..224f1d07 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanst.go @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/lapack" +) + +type Dlanster interface { + Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 + Dlanger +} + +func DlanstTest(t *testing.T, impl Dlanster) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, n := range []int{1, 3, 10, 100} { + for cas := 0; cas < 100; cas++ { + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + + m := n + lda := n + a := make([]float64, m*lda) + for i := 0; i < n; i++ { + a[i*lda+i] = d[i] + } + for i := 0; i < n-1; i++ { + a[i*lda+i+1] = e[i] + a[(i+1)*lda+i] = e[i] + } + work := make([]float64, n) + syNorm := impl.Dlanst(norm, n, d, e) + geNorm := impl.Dlange(norm, m, n, a, lda, work) + if math.Abs(syNorm-geNorm) > 1e-12 { + t.Errorf("Norm mismatch: norm = %v, cas = %v, n = %v. Want %v, got %v.", string(norm), cas, n, geNorm, syNorm) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlansy.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlansy.go new file mode 100644 index 00000000..b38f6bb0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlansy.go @@ -0,0 +1,80 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +type Dlansyer interface { + Dlanger + Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 +} + +func DlansyTest(t *testing.T, impl Dlansyer) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {3, 0}, + + {1, 10}, + {3, 10}, + } { + for trial := 0; trial < 100; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, lda*n) + if trial == 0 { + for i := range a { + a[i] = float64(i) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + + aDense := make([]float64, n*n) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a[i*lda+j] + aDense[i*n+j] = v + aDense[j*n+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := a[i*lda+j] + aDense[i*n+j] = v + aDense[j*n+i] = v + } + } + } + work := make([]float64, n) + got := impl.Dlansy(norm, uplo, n, a, lda, work) + want := impl.Dlange(norm, n, n, aDense, n, work) + if math.Abs(want-got) > 1e-14 { + t.Errorf("Norm mismatch. norm = %c, upper = %v, n = %v, lda = %v, want %v, got %v.", + norm, uplo == blas.Upper, n, lda, got, want) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlantr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlantr.go new file mode 100644 index 00000000..74f3c656 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlantr.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +type Dlantrer interface { + Dlanger + Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 +} + +func DlantrTest(t *testing.T, impl Dlantrer) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + m, n, lda int + }{ + {3, 3, 0}, + {3, 5, 0}, + {10, 5, 0}, + + {5, 5, 11}, + {5, 10, 11}, + {10, 5, 11}, + } { + // Do a couple of random trials since the values change. + for trial := 0; trial < 100; trial++ { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + if trial == 0 { + for i := range a { + a[i] = float64(i) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + aDense := make([]float64, len(a)) + if uplo == blas.Lower { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } + if diag == blas.Unit { + for i := 0; i < min(m, n); i++ { + aDense[i*lda+i] = 1 + } + } + work := make([]float64, n+6) + for i := range work { + work[i] = rnd.Float64() + } + got := impl.Dlantr(norm, uplo, diag, m, n, a, lda, work) + want := impl.Dlange(norm, m, n, aDense, lda, work) + if math.Abs(got-want) > 1e-13 { + t.Errorf("Norm mismatch. norm = %c, unitdiag = %v, upper = %v, m = %v, n = %v, lda = %v, Want %v, got %v.", + norm, diag == blas.Unit, uplo == blas.Upper, m, n, lda, got, want) + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanv2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanv2.go new file mode 100644 index 00000000..07cf2c51 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlanv2.go @@ -0,0 +1,69 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" +) + +type Dlanv2er interface { + Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) +} + +func Dlanv2Test(t *testing.T, impl Dlanv2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 1000; i++ { + a := rnd.NormFloat64() + b := rnd.NormFloat64() + c := rnd.NormFloat64() + d := rnd.NormFloat64() + aa, bb, cc, dd, rt1r, rt1i, rt2r, rt2i, cs, sn := impl.Dlanv2(a, b, c, d) + + mat := fmt.Sprintf("[%v %v; %v %v]", a, b, c, d) + if cc == 0 { + if rt1i != 0 || rt2i != 0 { + t.Errorf("Unexpected complex eigenvalues for %v", mat) + } + } else { + if aa != dd { + t.Errorf("Diagonal elements not equal for %v: got [%v %v]", mat, aa, dd) + } + if bb*cc >= 0 { + t.Errorf("Non-diagonal elements have the same sign for %v: got [%v %v]", mat, bb, cc) + } else { + im := math.Sqrt(-bb * cc) + if math.Abs(rt1i-im) > 1e-14 && math.Abs(rt1i+im) > 1e-14 { + t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt1i, im, -im) + } + if math.Abs(rt2i-im) > 1e-14 && math.Abs(rt2i+im) > 1e-14 { + t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt2i, im, -im) + } + } + } + if rt1r != aa && rt1r != dd { + t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt1r, aa, dd) + } + if rt2r != aa && rt2r != dd { + t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt2r, aa, dd) + } + if math.Abs(math.Hypot(cs, sn)-1) > 1e-14 { + t.Errorf("Unexpected unitary matrix for %v: got cs %v, sn %v", mat, cs, sn) + } + + gota := cs*(aa*cs-bb*sn) - sn*(cc*cs-dd*sn) + gotb := cs*(aa*sn+bb*cs) - sn*(cc*sn+dd*cs) + gotc := sn*(aa*cs-bb*sn) + cs*(cc*cs-dd*sn) + gotd := sn*(aa*sn+bb*cs) + cs*(cc*sn+dd*cs) + if math.Abs(gota-a) > 1e-14 || + math.Abs(gotb-b) > 1e-14 || + math.Abs(gotc-c) > 1e-14 || + math.Abs(gotd-d) > 1e-14 { + t.Errorf("Unexpected factorization: got [%v %v; %v %v], want [%v %v; %v %v]", gota, gotb, gotc, gotd, a, b, c, d) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapll.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapll.go new file mode 100644 index 00000000..1c35f039 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapll.go @@ -0,0 +1,46 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlapller interface { + Dgesvder + Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 +} + +func DlapllTest(t *testing.T, impl Dlapller) { + rnd := rand.New(rand.NewSource(1)) + for i, m := range []int{5, 6, 9, 300, 400, 600} { + n := 2 + lda := n + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + got := impl.Dlapll(m, a[0:], 2, a[1:], 2) + + s := make([]float64, min(m, n)) + work := make([]float64, 1) + impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, -1) + work = make([]float64, int(work[0])) + impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, len(work)) + want := s[len(s)-1] + + if !floats.EqualWithinAbsOrRel(got, want, 1e-14, 1e-14) { + t.Errorf("unexpected ssmin for test %d: got:%f want:%f", i, got, want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapmt.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapmt.go new file mode 100644 index 00000000..b2fd1f8d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapmt.go @@ -0,0 +1,113 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlapmter interface { + Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) +} + +func DlapmtTest(t *testing.T, impl Dlapmter) { + for ti, test := range []struct { + forward bool + k []int + + want blas64.General + }{ + { + forward: true, k: []int{0, 1, 2}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + forward: false, k: []int{0, 1, 2}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + forward: true, k: []int{1, 2, 0}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 2, 3, 1, + 5, 6, 4, + 8, 9, 7, + 11, 12, 10, + }, + }, + }, + { + forward: false, k: []int{1, 2, 0}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 3, 1, 2, + 6, 4, 5, + 9, 7, 8, + 12, 10, 11, + }, + }, + }, + } { + m := test.want.Rows + n := test.want.Cols + if len(test.k) != n { + panic("bad length of k") + } + + for _, extra := range []int{0, 11} { + x := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + x.Data[i*x.Stride+j] = float64(c) + c++ + } + } + + k := make([]int, len(test.k)) + copy(k, test.k) + + impl.Dlapmt(test.forward, m, n, x.Data, x.Stride, k) + + prefix := fmt.Sprintf("Case %v (forward=%t,m=%v,n=%v,extra=%v)", ti, test.forward, m, n, extra) + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to X", prefix) + } + + if !equalApproxGeneral(x, test.want, 0) { + t.Errorf("%v: unexpected X\n%v\n%v", prefix, x, test.want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapy2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapy2.go new file mode 100644 index 00000000..6efb81d9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlapy2.go @@ -0,0 +1,30 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlapy2er interface { + Dlapy2(float64, float64) float64 +} + +func Dlapy2Test(t *testing.T, impl Dlapy2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 10; i++ { + x := math.Abs(1e200 * rnd.NormFloat64()) + y := math.Abs(1e200 * rnd.NormFloat64()) + got := impl.Dlapy2(x, y) + want := math.Hypot(x, y) + if !floats.EqualWithinRel(got, want, 1e-16) { + t.Errorf("Dlapy2(%g, %g) = %g, want %g", x, y, got, want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqp2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqp2.go new file mode 100644 index 00000000..230b2ecc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqp2.go @@ -0,0 +1,115 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqp2er interface { + Dlapmter + Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) +} + +func Dlaqp2Test(t *testing.T, impl Dlaqp2er) { + for ti, test := range []struct { + m, n, offset int + }{ + {m: 4, n: 3, offset: 0}, + {m: 4, n: 3, offset: 2}, + {m: 4, n: 3, offset: 4}, + {m: 3, n: 4, offset: 0}, + {m: 3, n: 4, offset: 1}, + {m: 3, n: 4, offset: 2}, + {m: 8, n: 3, offset: 0}, + {m: 8, n: 3, offset: 4}, + {m: 8, n: 3, offset: 8}, + {m: 3, n: 8, offset: 0}, + {m: 3, n: 8, offset: 1}, + {m: 3, n: 8, offset: 2}, + {m: 10, n: 10, offset: 0}, + {m: 10, n: 10, offset: 5}, + {m: 10, n: 10, offset: 10}, + } { + m := test.m + n := test.n + jpiv := make([]int, n) + + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + aCopy := cloneGeneral(a) + for j := range jpiv { + jpiv[j] = j + } + + tau := make([]float64, n) + vn1 := columnNorms(m, n, a.Data, a.Stride) + vn2 := columnNorms(m, n, a.Data, a.Stride) + work := make([]float64, n) + + impl.Dlaqp2(m, n, test.offset, a.Data, a.Stride, jpiv, tau, vn1, vn2, work) + + prefix := fmt.Sprintf("Case %v (offset=%d,m=%v,n=%v,extra=%v)", ti, test.offset, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if test.offset == m { + continue + } + + mo := m - test.offset + q := constructQ("QR", mo, n, a.Data[test.offset*a.Stride:], a.Stride, tau) + // Check that q is orthonormal + for i := 0; i < mo; i++ { + nrm := blas64.Nrm2(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", ti) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}, blas64.Vector{Inc: 1, Data: q.Data[j*mo:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", ti) + } + } + } + + // Check that A * P = Q * R + r := blas64.General{ + Rows: mo, + Cols: n, + Stride: n, + Data: make([]float64, mo*n), + } + for i := 0; i < mo; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a.Data[(test.offset+i)*a.Stride+j] + } + } + got := nanGeneral(mo, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := aCopy + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpiv) + want.Rows = mo + want.Data = want.Data[test.offset*want.Stride:] + if !equalApproxGeneral(got, want, 1e-12) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", ti, got, want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqps.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqps.go new file mode 100644 index 00000000..7bb4800b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqps.go @@ -0,0 +1,112 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqpser interface { + Dlapmter + Dlaqps(m, n, offset, nb int, a []float64, lda int, jpvt []int, tau, vn1, vn2, auxv, f []float64, ldf int) (kb int) +} + +func DlaqpsTest(t *testing.T, impl Dlaqpser) { + for ti, test := range []struct { + m, n, nb, offset int + }{ + {m: 4, n: 3, nb: 2, offset: 0}, + {m: 4, n: 3, nb: 1, offset: 2}, + {m: 3, n: 4, nb: 2, offset: 0}, + {m: 3, n: 4, nb: 1, offset: 2}, + {m: 8, n: 3, nb: 2, offset: 0}, + {m: 8, n: 3, nb: 1, offset: 4}, + {m: 3, n: 8, nb: 2, offset: 0}, + {m: 3, n: 8, nb: 1, offset: 1}, + {m: 10, n: 10, nb: 3, offset: 0}, + {m: 10, n: 10, nb: 2, offset: 5}, + } { + m := test.m + n := test.n + jpiv := make([]int, n) + + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + aCopy := cloneGeneral(a) + for j := range jpiv { + jpiv[j] = j + } + + tau := make([]float64, n) + vn1 := columnNorms(m, n, a.Data, a.Stride) + vn2 := columnNorms(m, n, a.Data, a.Stride) + auxv := make([]float64, test.nb) + f := zeros(test.n, test.nb, n) + + kb := impl.Dlaqps(m, n, test.offset, test.nb, a.Data, a.Stride, jpiv, tau, vn1, vn2, auxv, f.Data, f.Stride) + + prefix := fmt.Sprintf("Case %v (offset=%d,m=%v,n=%v,extra=%v)", ti, test.offset, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if test.offset == m { + continue + } + + mo := m - test.offset + q := constructQ("QR", mo, kb, a.Data[test.offset*a.Stride:], a.Stride, tau) + // Check that q is orthonormal + for i := 0; i < mo; i++ { + nrm := blas64.Nrm2(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", ti) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}, blas64.Vector{Inc: 1, Data: q.Data[j*mo:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", ti) + } + } + } + + // Check that A * P = Q * R + r := blas64.General{ + Rows: mo, + Cols: kb, + Stride: kb, + Data: make([]float64, mo*kb), + } + for i := 0; i < mo; i++ { + for j := i; j < kb; j++ { + r.Data[i*kb+j] = a.Data[(test.offset+i)*a.Stride+j] + } + } + got := nanGeneral(mo, kb, kb) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := aCopy + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpiv) + want.Rows = mo + want.Cols = kb + want.Data = want.Data[test.offset*want.Stride:] + if !equalApproxGeneral(got, want, 1e-12) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", ti, got, want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr04.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr04.go new file mode 100644 index 00000000..c92104e7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr04.go @@ -0,0 +1,449 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr04er interface { + Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int, work []float64, lwork int, recur int) int + + Dlahqrer +} + +type dlaqr04Test struct { + h blas64.General + ilo, ihi int + iloz, ihiz int + wantt, wantz bool + + evWant []complex128 // Optional slice holding known eigenvalues. +} + +func Dlaqr04Test(t *testing.T, impl Dlaqr04er) { + rnd := rand.New(rand.NewSource(1)) + + // Tests for small matrices that choose the ilo,ihi and iloz,ihiz pairs + // randomly. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 11, 12, 18, 29} { + for _, extra := range []int{0, 11} { + for recur := 0; recur <= 2; recur++ { + for cas := 0; cas < n; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + iloz := rnd.Intn(ilo + 1) + ihiz := ihi + rnd.Intn(n-ihi) + h := randomHessenberg(n, n+extra, rnd) + if ilo-1 >= 0 { + h.Data[ilo*h.Stride+ilo-1] = 0 + } + if ihi+1 < n { + h.Data[(ihi+1)*h.Stride+ihi] = 0 + } + test := dlaqr04Test{ + h: h, + ilo: ilo, + ihi: ihi, + iloz: iloz, + ihiz: ihiz, + wantt: wantt, + wantz: wantz, + } + testDlaqr04(t, impl, test, false, recur) + testDlaqr04(t, impl, test, true, recur) + } + } + } + } + } + } + + // Tests for matrices large enough to possibly use the recursion (but it + // doesn't seem to be the case). + for _, n := range []int{100, 500} { + for cas := 0; cas < 5; cas++ { + h := randomHessenberg(n, n, rnd) + test := dlaqr04Test{ + h: h, + ilo: 0, + ihi: n - 1, + iloz: 0, + ihiz: n - 1, + wantt: true, + wantz: true, + } + testDlaqr04(t, impl, test, true, 1) + } + } + + // Tests that make sure that some potentially problematic corner cases, + // like zero-sized matrix, are covered. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + for _, test := range []dlaqr04Test{ + { + h: randomHessenberg(0, extra, rnd), + ilo: 0, + ihi: -1, + iloz: 0, + ihiz: -1, + }, + { + h: randomHessenberg(1, 1+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 1, + ihi: 1, + iloz: 1, + ihiz: 1, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 9, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + } { + if test.ilo-1 >= 0 { + test.h.Data[test.ilo*test.h.Stride+test.ilo-1] = 0 + } + if test.ihi+1 < test.h.Rows { + test.h.Data[(test.ihi+1)*test.h.Stride+test.ihi] = 0 + } + test.wantt = wantt + test.wantz = wantz + testDlaqr04(t, impl, test, false, 1) + testDlaqr04(t, impl, test, true, 1) + } + } + } + } + + // Tests with known eigenvalues computed by Octave. + for _, test := range []dlaqr04Test{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ilo: 1, + ihi: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ilo: 0, + ihi: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + testDlaqr04(t, impl, test, false, 1) + testDlaqr04(t, impl, test, true, 1) + } +} + +func testDlaqr04(t *testing.T, impl Dlaqr04er, test dlaqr04Test, optwork bool, recur int) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ilo := test.ilo + ihi := test.ihi + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + wr := nanSlice(ihi + 1) + wi := nanSlice(ihi + 1) + + var work []float64 + if optwork { + work = nanSlice(1) + impl.Dlaqr04(wantt, wantz, n, ilo, ihi, nil, 0, nil, nil, iloz, ihiz, nil, 0, work, -1, recur) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, n)) + } + + unconverged := impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h.Data, h.Stride, wr, wi, iloz, ihiz, z.Data, z.Stride, work, len(work), recur) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ilo=%v, ihi=%v, iloz=%v, ihiz=%v, extra=%v, opt=%v", + wantt, wantz, n, ilo, ihi, iloz, ihiz, extra, optwork) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + + start := ilo // Index of the first computed eigenvalue. + if unconverged != 0 { + start = unconverged + if start == ihi+1 { + t.Logf("%v: no eigenvalue has converged", prefix) + } + } + + // Check that wr and wi have not been modified within [:start]. + if !isAllNaN(wr[:start]) { + t.Errorf("%v: unexpected modification of wr", prefix) + } + if !isAllNaN(wi[:start]) { + t.Errorf("%v: unexpected modification of wi", prefix) + } + + var hasReal bool + for i := start; i <= ihi; { + if wi[i] == 0 { // Real eigenvalue. + hasReal = true + // Check that the eigenvalue corresponds to a 1×1 block + // on the diagonal of H. + if wantt && wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + i++ + continue + } + + // Complex eigenvalue. + + // In the conjugate pair the real parts must be equal. + if wr[i] != wr[i+1] { + t.Errorf("%v: real part of conjugate pair not equal, i=%v", prefix, i) + } + // The first imaginary part must be positive. + if wi[i] < 0 { + t.Errorf("%v: wi[%v] not positive", prefix, i) + } + // The second imaginary part must be negative with the same + // magnitude. + if wi[i] != -wi[i+1] { + t.Errorf("%v: wi[%v] != wi[%v]", prefix, i, i+1) + } + if wantt { + // Check that wi[i] has the correct value. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + if wr[i] != h.Data[(i+1)*h.Stride+i+1] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i+1, i+1) + } + im := math.Sqrt(math.Abs(h.Data[(i+1)*h.Stride+i])) * math.Sqrt(math.Abs(h.Data[i*h.Stride+i+1])) + if math.Abs(im-wi[i]) > tol { + t.Errorf("%v: unexpected value of wi[%v]: want %v, got %v", prefix, i, im, wi[i]) + } + } + i += 2 + } + // If the number of found eigenvalues is odd, at least one must be real. + if (ihi+1-start)%2 != 0 && !hasReal { + t.Errorf("%v: expected at least one real eigenvalue", prefix) + } + + // Compare found eigenvalues to the reference, if known. + if test.evWant != nil { + for i := start; i <= ihi; i++ { + ev := complex(wr[i], wi[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + // Z should contain the orthogonal matrix U. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Z should have been modified only in the + // [iloz:ihiz+1,ilo:ihi+1] block. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if iloz <= i && i <= ihiz && ilo <= j && j <= ihi { + continue + } + if z.Data[i*z.Stride+j] != zCopy.Data[i*zCopy.Stride+j] { + t.Errorf("%v: Z modified outside of [iloz:ihiz+1,ilo:ihi+1] block", prefix) + } + } + } + if wantt { + // Zero out h under the subdiagonal because Dlaqr04 uses it as + // workspace. + for i := 2; i < n; i++ { + for j := 0; j < i-1; j++ { + h.Data[i*h.Stride+j] = 0 + } + } + hz := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hz) + zhz := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hz, 0, zhz) + if !equalApproxGeneral(zhz, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr1.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr1.go new file mode 100644 index 00000000..9276bfd5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr1.go @@ -0,0 +1,91 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlaqr1er interface { + Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) +} + +func Dlaqr1Test(t *testing.T, impl Dlaqr1er) { + rnd := rand.New(rand.NewSource(1)) + + for _, n := range []int{2, 3} { + for _, ldh := range []int{n, n + 1, n + 10} { + for _, cas := range []int{1, 2} { + for k := 0; k < 100; k++ { + v := make([]float64, n) + for i := range v { + v[i] = math.NaN() + } + h := make([]float64, n*(n-1)*ldh) + for i := range h { + h[i] = math.NaN() + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + h[i*ldh+j] = rnd.NormFloat64() + } + } + var sr1, sr2, si1, si2 float64 + if cas == 1 { + sr1 = rnd.NormFloat64() + sr2 = sr1 + si1 = rnd.NormFloat64() + si2 = -si1 + } else { + sr1 = rnd.NormFloat64() + sr2 = rnd.NormFloat64() + si1 = 0 + si2 = 0 + } + impl.Dlaqr1(n, h, ldh, sr1, si1, sr2, si2, v) + + // Matrix H - s1*I. + h1 := make([]complex128, n*n) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + h1[i*n+j] = complex(h[i*ldh+j], 0) + if i == j { + h1[i*n+j] -= complex(sr1, si1) + } + } + } + // First column of H - s2*I. + h2 := make([]complex128, n) + for i := 0; i < n; i++ { + h2[i] = complex(h[i*ldh], 0) + } + h2[0] -= complex(sr2, si2) + + wantv := make([]float64, n) + // Multiply (H-s1*I)*(H-s2*I) to get a tentative + // wantv. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + wantv[i] += real(h1[i*n+j] * h2[j]) + } + } + // Get the unknown scale. + scale := v[0] / wantv[0] + // Compute the actual wantv. + floats.Scale(scale, wantv) + + // The scale must be the same for all elements. + if floats.Distance(wantv, v, math.Inf(1)) > 1e-13 { + t.Errorf("n = %v, ldh = %v, case = %v: Unexpected value of v: got %v, want %v", n, ldh, cas, v, wantv) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr23.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr23.go new file mode 100644 index 00000000..e55d2bc0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr23.go @@ -0,0 +1,335 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr23er interface { + Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int) +} + +type dlaqr23Test struct { + wantt, wantz bool + ktop, kbot int + nw int + h blas64.General + iloz, ihiz int + + evWant []complex128 // Optional slice with known eigenvalues. +} + +func Dlaqr23Test(t *testing.T, impl Dlaqr23er) { + rnd := rand.New(rand.NewSource(1)) + + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 100} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 30; cas++ { + var nw int + if nw <= 75 { + nw = rnd.Intn(n) + 1 + } else { + nw = 76 + rnd.Intn(n-75) + } + ktop := rnd.Intn(n - nw + 1) + kbot := ktop + nw - 1 + kbot += rnd.Intn(n - kbot) + h := randomHessenberg(n, n+extra, rnd) + if ktop-1 >= 0 { + h.Data[ktop*h.Stride+ktop-1] = 0 + } + if kbot+1 < n { + h.Data[(kbot+1)*h.Stride+kbot] = 0 + } + iloz := rnd.Intn(ktop + 1) + ihiz := kbot + rnd.Intn(n-kbot) + test := dlaqr23Test{ + wantt: wantt, + wantz: wantz, + ktop: ktop, + kbot: kbot, + nw: nw, + h: h, + iloz: iloz, + ihiz: ihiz, + } + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + } + } + } + } + } + + // Tests with n=0. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + test := dlaqr23Test{ + wantt: wantt, + wantz: wantz, + h: randomHessenberg(0, extra, rnd), + ktop: 0, + kbot: -1, + iloz: 0, + ihiz: -1, + nw: 0, + } + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + } + } + } + + // Tests with explicit eigenvalues computed by Octave. + for _, test := range []dlaqr23Test{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ktop: 0, + kbot: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ktop: 1, + kbot: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ktop: 0, + kbot: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + test.nw = test.kbot - test.ktop + 1 + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + } +} + +func testDlaqr23(t *testing.T, impl Dlaqr23er, test dlaqr23Test, opt bool, recur int, rnd *rand.Rand) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ktop := test.ktop + kbot := test.kbot + nw := test.nw + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + sr := nanSlice(kbot + 1) + si := nanSlice(kbot + 1) + + v := randomGeneral(nw, nw, nw+extra, rnd) + var nh int + if nw > 0 { + nh = nw + rnd.Intn(nw) // nh must be at least nw. + } + tmat := randomGeneral(nw, nh, nh+extra, rnd) + var nv int + if nw > 0 { + nv = rnd.Intn(nw) + 1 + } + wv := randomGeneral(nv, nw, nw+extra, rnd) + + var work []float64 + if opt { + work = nanSlice(1) + impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, nil, h.Stride, iloz, ihiz, nil, z.Stride, + nil, nil, nil, v.Stride, tmat.Cols, nil, tmat.Stride, wv.Rows, nil, wv.Stride, work, -1, recur) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, 2*nw)) + } + + ns, nd := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, h.Data, h.Stride, iloz, ihiz, z.Data, z.Stride, + sr, si, v.Data, v.Stride, tmat.Cols, tmat.Data, tmat.Stride, wv.Rows, wv.Data, wv.Stride, work, len(work), recur) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ktop=%v, kbot=%v, nw=%v, iloz=%v, ihiz=%v, extra=%v", + wantt, wantz, n, ktop, kbot, nw, iloz, ihiz, extra) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + if !generalOutsideAllNaN(v) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data) + } + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data) + } + if !generalOutsideAllNaN(wv) { + t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data) + } + if !isAllNaN(sr[:kbot-nd-ns+1]) || !isAllNaN(sr[kbot+1:]) { + t.Errorf("%v: out-of-range write to sr", prefix) + } + if !isAllNaN(si[:kbot-nd-ns+1]) || !isAllNaN(si[kbot+1:]) { + t.Errorf("%v: out-of-range write to si", prefix) + } + + if !isUpperHessenberg(h) { + t.Errorf("%v: H is not upper Hessenberg", prefix) + } + + if test.evWant != nil { + for i := kbot - nd + 1; i <= kbot; i++ { + ev := complex(sr[i], si[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + var zmod bool + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if z.Data[i*z.Stride+j] == zCopy.Data[i*zCopy.Stride+j] { + continue + } + if i < iloz || i > ihiz || j < kbot-nw+1 || j > kbot { + zmod = true + } + } + } + if zmod { + t.Errorf("%v: unexpected modification of Z", prefix) + } + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + if wantt { + hu := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu) + uhu := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu) + if !equalApproxGeneral(uhu, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr5.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr5.go new file mode 100644 index 00000000..a93181dc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaqr5.go @@ -0,0 +1,214 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "compress/gzip" + "encoding/json" + "fmt" + "log" + "math" + "math/rand" + "os" + "path/filepath" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr5er interface { + Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, nshfts int, sr, si []float64, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, u []float64, ldu int, nh int, wh []float64, ldwh int, nv int, wv []float64, ldwv int) +} + +type Dlaqr5test struct { + WantT bool + N int + NShifts int + KTop, KBot int + ShiftR, ShiftI []float64 + H []float64 + + HWant []float64 + ZWant []float64 +} + +func Dlaqr5Test(t *testing.T, impl Dlaqr5er) { + // Test without using reference data. + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 30} { + for _, extra := range []int{0, 1, 20} { + for _, kacc22 := range []int{0, 1, 2} { + for cas := 0; cas < 100; cas++ { + testDlaqr5(t, impl, n, extra, kacc22, rnd) + } + } + } + } + + // Test using reference data computed by the reference netlib + // implementation. + file, err := os.Open(filepath.FromSlash("../testlapack/testdata/dlaqr5data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + r, err := gzip.NewReader(file) + if err != nil { + log.Fatal(err) + } + defer r.Close() + + var tests []Dlaqr5test + json.NewDecoder(r).Decode(&tests) + for _, test := range tests { + wantt := test.WantT + n := test.N + nshfts := test.NShifts + ktop := test.KTop + kbot := test.KBot + sr := test.ShiftR + si := test.ShiftI + + for _, extra := range []int{0, 1, 10} { + v := randomGeneral(nshfts/2, 3, 3+extra, rnd) + u := randomGeneral(3*nshfts-3, 3*nshfts-3, 3*nshfts-3+extra, rnd) + nh := n + wh := randomGeneral(3*nshfts-3, n, n+extra, rnd) + nv := n + wv := randomGeneral(n, 3*nshfts-3, 3*nshfts-3+extra, rnd) + + h := nanGeneral(n, n, n+extra) + + for _, kacc22 := range []int{0, 1, 2} { + copyMatrix(n, n, h.Data, h.Stride, test.H) + z := eye(n, n+extra) + + impl.Dlaqr5(wantt, true, kacc22, + n, ktop, kbot, + nshfts, sr, si, + h.Data, h.Stride, + 0, n-1, z.Data, z.Stride, + v.Data, v.Stride, + u.Data, u.Stride, + nv, wv.Data, wv.Stride, + nh, wh.Data, wh.Stride) + + prefix := fmt.Sprintf("wantt=%v, n=%v, nshfts=%v, ktop=%v, kbot=%v, extra=%v, kacc22=%v", + wantt, n, nshfts, ktop, kbot, extra, kacc22) + if !equalApprox(n, n, h.Data, h.Stride, test.HWant, 1e-13) { + t.Errorf("Case %v: unexpected matrix H\nh =%v\nhwant=%v", prefix, h.Data, test.HWant) + } + if !equalApprox(n, n, z.Data, z.Stride, test.ZWant, 1e-13) { + t.Errorf("Case %v: unexpected matrix Z\nz =%v\nzwant=%v", prefix, z.Data, test.ZWant) + } + } + } + } +} + +func testDlaqr5(t *testing.T, impl Dlaqr5er, n, extra, kacc22 int, rnd *rand.Rand) { + wantt := true + wantz := true + nshfts := 2 * n + sr := make([]float64, nshfts) + si := make([]float64, nshfts) + for i := 0; i < n; i++ { + re := rnd.NormFloat64() + im := rnd.NormFloat64() + sr[2*i], sr[2*i+1] = re, re + si[2*i], si[2*i+1] = im, -im + } + ktop := rnd.Intn(n) + kbot := rnd.Intn(n) + if kbot < ktop { + ktop, kbot = kbot, ktop + } + + v := randomGeneral(nshfts/2, 3, 3+extra, rnd) + u := randomGeneral(3*nshfts-3, 3*nshfts-3, 3*nshfts-3+extra, rnd) + nh := n + wh := randomGeneral(3*nshfts-3, n, n+extra, rnd) + nv := n + wv := randomGeneral(n, 3*nshfts-3, 3*nshfts-3+extra, rnd) + + h := randomHessenberg(n, n+extra, rnd) + if ktop > 0 { + h.Data[ktop*h.Stride+ktop-1] = 0 + } + if kbot < n-1 { + h.Data[(kbot+1)*h.Stride+kbot] = 0 + } + hCopy := h + hCopy.Data = make([]float64, len(h.Data)) + copy(hCopy.Data, h.Data) + + z := eye(n, n+extra) + + impl.Dlaqr5(wantt, wantz, kacc22, + n, ktop, kbot, + nshfts, sr, si, + h.Data, h.Stride, + 0, n-1, z.Data, z.Stride, + v.Data, v.Stride, + u.Data, u.Stride, + nv, wv.Data, wv.Stride, + nh, wh.Data, wh.Stride) + + prefix := fmt.Sprintf("Case n=%v, extra=%v, kacc22=%v", n, extra, kacc22) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + if !generalOutsideAllNaN(u) { + t.Errorf("%v: out-of-range write to U\n%v", prefix, u.Data) + } + if !generalOutsideAllNaN(v) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data) + } + if !generalOutsideAllNaN(wh) { + t.Errorf("%v: out-of-range write to WH\n%v", prefix, wh.Data) + } + if !generalOutsideAllNaN(wv) { + t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data) + } + + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + if h.Data[i*h.Stride+j] != 0 { + t.Errorf("%v: H is not Hessenberg, H[%v,%v]!=0", prefix, i, j) + } + } + } + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Construct Z^T * HOrig * Z and check that it is equal to H from Dlaqr5. + hz := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hCopy, z, 0, hz) + zhz := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hz, 0, zhz) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + diff := zhz.Data[i*zhz.Stride+j] - h.Data[i*h.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Z^T*HOrig*Z and H are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarf.go new file mode 100644 index 00000000..82b2756a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarf.go @@ -0,0 +1,173 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlarfer interface { + Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) +} + +func DlarfTest(t *testing.T, impl Dlarfer) { + rnd := rand.New(rand.NewSource(1)) + for i, test := range []struct { + m, n, ldc int + incv, lastv int + lastr, lastc int + tau float64 + }{ + { + m: 3, + n: 2, + ldc: 2, + + incv: 4, + lastv: 1, + + lastr: 2, + lastc: 1, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 1, + + lastr: 1, + lastc: 2, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 1, + + lastr: 0, + lastc: 1, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 0, + + lastr: 0, + lastc: 1, + + tau: 2, + }, + { + m: 10, + n: 10, + ldc: 10, + + incv: 4, + lastv: 6, + + lastr: 9, + lastc: 8, + + tau: 2, + }, + } { + // Construct a random matrix. + c := make([]float64, test.ldc*test.m) + for i := 0; i <= test.lastr; i++ { + for j := 0; j <= test.lastc; j++ { + c[i*test.ldc+j] = rnd.Float64() + } + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + cCopy2 := make([]float64, len(c)) + copy(cCopy2, c) + + // Test with side right. + sz := max(test.m, test.n) // so v works for both right and left side. + v := make([]float64, test.incv*sz+1) + // Fill with nonzero entries up until lastv. + for i := 0; i <= test.lastv; i++ { + v[i*test.incv] = rnd.Float64() + } + // Construct h explicitly to compare. + h := make([]float64, test.n*test.n) + for i := 0; i < test.n; i++ { + h[i*test.n+i] = 1 + } + hMat := blas64.General{ + Rows: test.n, + Cols: test.n, + Stride: test.n, + Data: h, + } + vVec := blas64.Vector{ + Inc: test.incv, + Data: v, + } + blas64.Ger(-test.tau, vVec, vVec, hMat) + + // Apply multiplication (2nd copy is to avoid aliasing). + cMat := blas64.General{ + Rows: test.m, + Cols: test.n, + Stride: test.ldc, + Data: cCopy, + } + cMat2 := blas64.General{ + Rows: test.m, + Cols: test.n, + Stride: test.ldc, + Data: cCopy2, + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMat2, hMat, 0, cMat) + + // cMat now stores the true answer. Compare with the function call. + work := make([]float64, sz) + impl.Dlarf(blas.Right, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) + if !floats.EqualApprox(c, cMat.Data, 1e-14) { + t.Errorf("Dlarf mismatch right, case %v. Want %v, got %v", i, cMat.Data, c) + } + + // Test on the left side. + copy(c, cCopy2) + copy(cCopy, c) + // Construct h. + h = make([]float64, test.m*test.m) + for i := 0; i < test.m; i++ { + h[i*test.m+i] = 1 + } + hMat = blas64.General{ + Rows: test.m, + Cols: test.m, + Stride: test.m, + Data: h, + } + blas64.Ger(-test.tau, vVec, vVec, hMat) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hMat, cMat2, 0, cMat) + impl.Dlarf(blas.Left, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) + if !floats.EqualApprox(c, cMat.Data, 1e-14) { + t.Errorf("Dlarf mismatch left, case %v. Want %v, got %v", i, cMat.Data, c) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfb.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfb.go new file mode 100644 index 00000000..89e65e64 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfb.go @@ -0,0 +1,161 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlarfber interface { + Dlarfter + Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, + store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, + c []float64, ldc int, work []float64, ldwork int) +} + +func DlarfbTest(t *testing.T, impl Dlarfber) { + rnd := rand.New(rand.NewSource(1)) + for _, store := range []lapack.StoreV{lapack.ColumnWise, lapack.RowWise} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.Trans, blas.NoTrans} { + for cas, test := range []struct { + ma, na, cdim, lda, ldt, ldc int + }{ + {6, 6, 6, 0, 0, 0}, + {6, 8, 10, 0, 0, 0}, + {6, 10, 8, 0, 0, 0}, + {8, 6, 10, 0, 0, 0}, + {8, 10, 6, 0, 0, 0}, + {10, 6, 8, 0, 0, 0}, + {10, 8, 6, 0, 0, 0}, + {6, 6, 6, 12, 15, 30}, + {6, 8, 10, 12, 15, 30}, + {6, 10, 8, 12, 15, 30}, + {8, 6, 10, 12, 15, 30}, + {8, 10, 6, 12, 15, 30}, + {10, 6, 8, 12, 15, 30}, + {10, 8, 6, 12, 15, 30}, + {6, 6, 6, 15, 12, 30}, + {6, 8, 10, 15, 12, 30}, + {6, 10, 8, 15, 12, 30}, + {8, 6, 10, 15, 12, 30}, + {8, 10, 6, 15, 12, 30}, + {10, 6, 8, 15, 12, 30}, + {10, 8, 6, 15, 12, 30}, + } { + // Generate a matrix for QR + ma := test.ma + na := test.na + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := 0; i < ma; i++ { + for j := 0; j < lda; j++ { + a[i*lda+j] = rnd.Float64() + } + } + k := min(ma, na) + + // H is always ma x ma + var m, n, rowsWork int + switch { + default: + panic("not implemented") + case side == blas.Left: + m = test.ma + n = test.cdim + rowsWork = n + case side == blas.Right: + m = test.cdim + n = test.ma + rowsWork = m + } + + // Use dgeqr2 to find the v vectors + tau := make([]float64, na) + work := make([]float64, na) + impl.Dgeqr2(ma, k, a, lda, tau, work) + + // Correct the v vectors based on the direct and store + vMatTmp := extractVMat(ma, na, a, lda, lapack.Forward, lapack.ColumnWise) + vMat := constructVMat(vMatTmp, store, direct) + v := vMat.Data + ldv := vMat.Stride + + // Use dlarft to find the t vector + ldt := test.ldt + if ldt == 0 { + ldt = k + } + tm := make([]float64, k*ldt) + + impl.Dlarft(direct, store, ma, k, v, ldv, tau, tm, ldt) + + // Generate c matrix + ldc := test.ldc + if ldc == 0 { + ldc = n + } + c := make([]float64, m*ldc) + for i := 0; i < m; i++ { + for j := 0; j < ldc; j++ { + c[i*ldc+j] = rnd.Float64() + } + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + ldwork := k + work = make([]float64, rowsWork*k) + + // Call Dlarfb with this information + impl.Dlarfb(side, trans, direct, store, m, n, k, v, ldv, tm, ldt, c, ldc, work, ldwork) + + h := constructH(tau, vMat, store, direct) + + cMat := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, m*ldc), + } + copy(cMat.Data, cCopy) + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, m*ldc), + } + copy(ans.Data, cMat.Data) + switch { + default: + panic("not implemented") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, cMat, 0, ans) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, h, cMat, 0, ans) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMat, h, 0, ans) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMat, h, 0, ans) + } + if !floats.EqualApprox(ans.Data, c, 1e-14) { + t.Errorf("Cas %v mismatch. Want %v, got %v.", cas, ans.Data, c) + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfg.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfg.go new file mode 100644 index 00000000..aa463235 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfg.go @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlarfger interface { + Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) +} + +func DlarfgTest(t *testing.T, impl Dlarfger) { + rnd := rand.New(rand.NewSource(1)) + for i, test := range []struct { + alpha float64 + n int + x []float64 + }{ + { + alpha: 4, + n: 3, + }, + { + alpha: -2, + n: 3, + }, + { + alpha: 0, + n: 3, + }, + { + alpha: 1, + n: 1, + }, + { + alpha: 1, + n: 2, + x: []float64{4, 5, 6}, + }, + } { + n := test.n + incX := 1 + var x []float64 + if test.x == nil { + x = make([]float64, n-1) + for i := range x { + x[i] = rnd.Float64() + } + } else { + x = make([]float64, n-1) + copy(x, test.x) + } + xcopy := make([]float64, n-1) + copy(xcopy, x) + alpha := test.alpha + beta, tau := impl.Dlarfg(n, alpha, x, incX) + + // Verify the returns and the values in v. Construct h and perform + // the explicit multiplication. + h := make([]float64, n*n) + for i := 0; i < n; i++ { + h[i*n+i] = 1 + } + hmat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: h, + } + v := make([]float64, n) + copy(v[1:], x) + v[0] = 1 + vVec := blas64.Vector{ + Inc: 1, + Data: v, + } + blas64.Ger(-tau, vVec, vVec, hmat) + eye := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, hmat, hmat, 0, eye) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(eye.Data[i*n+j]-1) > 1e-14 { + iseye = false + } + } else { + if math.Abs(eye.Data[i*n+j]) > 1e-14 { + iseye = false + } + } + } + } + if !iseye { + t.Errorf("H^T * H is not I %v", eye) + } + + xVec := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + xVec.Data[0] = test.alpha + copy(xVec.Data[1:], xcopy) + + ans := make([]float64, n) + ansVec := blas64.Vector{ + Inc: 1, + Data: ans, + } + blas64.Gemv(blas.NoTrans, 1, hmat, xVec, 0, ansVec) + if math.Abs(ans[0]-beta) > 1e-14 { + t.Errorf("Case %v, beta mismatch. Want %v, got %v", i, ans[0], beta) + } + for i := 1; i < n; i++ { + if math.Abs(ans[i]) > 1e-14 { + t.Errorf("Case %v, nonzero answer %v", i, ans) + break + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarft.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarft.go new file mode 100644 index 00000000..e63abb9e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarft.go @@ -0,0 +1,168 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlarfter interface { + Dgeqr2er + Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, v []float64, ldv int, tau []float64, t []float64, ldt int) +} + +func DlarftTest(t *testing.T, impl Dlarfter) { + rnd := rand.New(rand.NewSource(1)) + for _, store := range []lapack.StoreV{lapack.ColumnWise, lapack.RowWise} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, test := range []struct { + m, n, ldv, ldt int + }{ + {6, 6, 0, 0}, + {8, 6, 0, 0}, + {6, 8, 0, 0}, + {6, 6, 10, 15}, + {8, 6, 10, 15}, + {6, 8, 10, 15}, + {6, 6, 15, 10}, + {8, 6, 15, 10}, + {6, 8, 15, 10}, + } { + // Generate a matrix + m := test.m + n := test.n + lda := n + if lda == 0 { + lda = n + } + + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < lda; j++ { + a[i*lda+j] = rnd.Float64() + } + } + // Use dgeqr2 to find the v vectors + tau := make([]float64, n) + work := make([]float64, n) + impl.Dgeqr2(m, n, a, lda, tau, work) + + // Construct H using these answers + vMatTmp := extractVMat(m, n, a, lda, lapack.Forward, lapack.ColumnWise) + vMat := constructVMat(vMatTmp, store, direct) + v := vMat.Data + ldv := vMat.Stride + + h := constructH(tau, vMat, store, direct) + + k := min(m, n) + ldt := test.ldt + if ldt == 0 { + ldt = k + } + // Find T from the actual function + tm := make([]float64, k*ldt) + for i := range tm { + tm[i] = 100 + rnd.Float64() + } + // The v data has been put into a. + impl.Dlarft(direct, store, m, k, v, ldv, tau, tm, ldt) + + tData := make([]float64, len(tm)) + copy(tData, tm) + if direct == lapack.Forward { + // Zero out the lower traingular portion. + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + tData[i*ldt+j] = 0 + } + } + } else { + // Zero out the upper traingular portion. + for i := 0; i < k; i++ { + for j := i + 1; j < k; j++ { + tData[i*ldt+j] = 0 + } + } + } + + T := blas64.General{ + Rows: k, + Cols: k, + Stride: ldt, + Data: tData, + } + + vMatT := blas64.General{ + Rows: vMat.Cols, + Cols: vMat.Rows, + Stride: vMat.Rows, + Data: make([]float64, vMat.Cols*vMat.Rows), + } + for i := 0; i < vMat.Rows; i++ { + for j := 0; j < vMat.Cols; j++ { + vMatT.Data[j*vMatT.Stride+i] = vMat.Data[i*vMat.Stride+j] + } + } + var comp blas64.General + if store == lapack.ColumnWise { + // H = I - V * T * V^T + tmp := blas64.General{ + Rows: T.Rows, + Cols: vMatT.Cols, + Stride: vMatT.Cols, + Data: make([]float64, T.Rows*vMatT.Cols), + } + // T * V^T + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, T, vMatT, 0, tmp) + comp = blas64.General{ + Rows: vMat.Rows, + Cols: tmp.Cols, + Stride: tmp.Cols, + Data: make([]float64, vMat.Rows*tmp.Cols), + } + // V * (T * V^T) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vMat, tmp, 0, comp) + } else { + // H = I - V^T * T * V + tmp := blas64.General{ + Rows: T.Rows, + Cols: vMat.Cols, + Stride: vMat.Cols, + Data: make([]float64, T.Rows*vMat.Cols), + } + // T * V + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, T, vMat, 0, tmp) + comp = blas64.General{ + Rows: vMatT.Rows, + Cols: tmp.Cols, + Stride: tmp.Cols, + Data: make([]float64, vMatT.Rows*tmp.Cols), + } + // V^T * (T * V) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vMatT, tmp, 0, comp) + } + // I - V^T * T * V + for i := 0; i < comp.Rows; i++ { + for j := 0; j < comp.Cols; j++ { + comp.Data[i*m+j] *= -1 + if i == j { + comp.Data[i*m+j] += 1 + } + } + } + if !floats.EqualApprox(comp.Data, h.Data, 1e-14) { + t.Errorf("T does not construct proper H. Store = %v, Direct = %v.\nWant %v\ngot %v.", string(store), string(direct), h.Data, comp.Data) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfx.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfx.go new file mode 100644 index 00000000..a73e4f44 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlarfx.go @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlarfxer interface { + Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) +} + +func DlarfxTest(t *testing.T, impl Dlarfxer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Right, blas.Left} { + for m := 1; m < 12; m++ { + for n := 1; n < 12; n++ { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 10; cas++ { + testDlarfx(t, impl, side, m, n, extra, rnd) + } + } + } + } + } +} + +func testDlarfx(t *testing.T, impl Dlarfxer, side blas.Side, m, n, extra int, rnd *rand.Rand) { + const tol = 1e-13 + + c := randomGeneral(m, n, n+extra, rnd) + cWant := randomGeneral(m, n, n+extra, rnd) + tau := rnd.NormFloat64() + + var ( + v []float64 + h blas64.General + ) + if side == blas.Left { + v = randomSlice(m, rnd) + h = eye(m, m+extra) + } else { + v = randomSlice(n, rnd) + h = eye(n, n+extra) + } + blas64.Ger(-tau, blas64.Vector{Inc: 1, Data: v}, blas64.Vector{Inc: 1, Data: v}, h) + if side == blas.Left { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, c, 0, cWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, c, h, 0, cWant) + } + + var work []float64 + if h.Rows > 10 { + // Allocate work only if H has order > 10. + if side == blas.Left { + work = make([]float64, n) + } else { + work = make([]float64, m) + } + } + + impl.Dlarfx(side, m, n, v, tau, c.Data, c.Stride, work) + + prefix := fmt.Sprintf("Case side=%v, m=%v, n=%v, extra=%v", side, m, n, extra) + + // Check any invalid modifications of c. + if !generalOutsideAllNaN(c) { + t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) + } + + if !equalApproxGeneral(c, cWant, tol) { + t.Errorf("%v: unexpected C\n%v", prefix, c.Data) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlartg.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlartg.go new file mode 100644 index 00000000..c7cade84 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlartg.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlartger interface { + Dlartg(f, g float64) (cs, sn, r float64) +} + +func DlartgTest(t *testing.T, impl Dlartger) { + const tol = 1e-14 + // safmn2 and safmx2 are copied from native.Dlartg. + safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) + safmx2 := 1 / safmn2 + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 1000; i++ { + var f float64 + var fHuge bool + switch rnd.Intn(3) { + case 0: + // Huge f. + fHuge = true + f = math.Pow(10, 10-20*rnd.Float64()) * safmx2 + case 1: + // Tiny f. + f = math.Pow(10, 10-20*rnd.Float64()) * safmn2 + default: + f = rnd.NormFloat64() + } + if rnd.Intn(2) == 0 { + f *= -1 + } + + var g float64 + var gHuge bool + switch rnd.Intn(3) { + case 0: + // Huge g. + gHuge = true + g = math.Pow(10, 10-20*rnd.Float64()) * safmx2 + case 1: + // Tiny g. + g = math.Pow(10, 10-20*rnd.Float64()) * safmn2 + default: + g = rnd.NormFloat64() + } + if rnd.Intn(2) == 0 { + g *= -1 + } + + cs, sn, r := impl.Dlartg(f, g) + + rWant := cs*f + sn*g + if !floats.EqualWithinAbsOrRel(math.Abs(rWant), math.Abs(r), tol, tol) { + t.Errorf("Case f=%v,g=%v: unexpected r. Want %v, got %v", f, g, rWant, r) + } + oneTest := cs*cs + sn*sn + if math.Abs(oneTest-1) > tol { + t.Errorf("Case f=%v,g=%v: expected cs^2+sn^2==1, got %v", f, g, oneTest) + } + if !fHuge && !gHuge { + zeroTest := -sn*f + cs*g + if math.Abs(zeroTest) > tol { + t.Errorf("Case f=%v,g=%v: expected zero, got %v", f, g, zeroTest) + } + } + if math.Abs(f) > math.Abs(g) && cs < 0 { + t.Errorf("Case f=%v,g=%v: unexpected negative cs %v", f, g, cs) + } + } + for i := 0; i < 100; i++ { + cs, sn, _ := impl.Dlartg(rnd.NormFloat64(), 0) + if cs != 1 { + t.Errorf("Unexpected cs for g=0. Want 1, got %v", cs) + } + if sn != 0 { + t.Errorf("Unexpected sn for g=0. Want 0, got %v", sn) + } + } + for i := 0; i < 100; i++ { + cs, sn, _ := impl.Dlartg(0, rnd.NormFloat64()) + if cs != 0 { + t.Errorf("Unexpected cs for f=0. Want 0, got %v", cs) + } + if sn != 1 { + t.Errorf("Unexpected sn for f=0. Want 1, got %v", sn) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlas2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlas2.go new file mode 100644 index 00000000..a76e2742 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlas2.go @@ -0,0 +1,34 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "testing" +) + +type Dlas2er interface { + Dlas2(f, g, h float64) (min, max float64) +} + +func Dlas2Test(t *testing.T, impl Dlas2er) { + for i, test := range []struct { + f, g, h, ssmin, ssmax float64 + }{ + // Singular values computed from Octave. + {10, 30, 12, 3.567778859365365, 33.634371616111189}, + {10, 30, -12, 3.567778859365365, 33.634371616111189}, + {2, 30, -12, 0.741557056404952, 32.364333658088754}, + {-2, 5, 12, 1.842864429909778, 13.023204317408728}, + } { + ssmin, ssmax := impl.Dlas2(test.f, test.g, test.h) + if math.Abs(ssmin-test.ssmin) > 1e-12 { + t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) + } + if math.Abs(ssmax-test.ssmax) > 1e-12 { + t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlascl.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlascl.go new file mode 100644 index 00000000..db792a4d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlascl.go @@ -0,0 +1,106 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/lapack" +) + +type Dlascler interface { + Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) +} + +func DlasclTest(t *testing.T, impl Dlascler) { + const tol = 1e-16 + + rnd := rand.New(rand.NewSource(1)) + for ti, test := range []struct { + m, n int + }{ + {0, 0}, + {1, 1}, + {1, 10}, + {10, 1}, + {2, 2}, + {2, 11}, + {11, 2}, + {3, 3}, + {3, 11}, + {11, 3}, + {11, 11}, + {11, 100}, + {100, 11}, + } { + m := test.m + n := test.n + for _, extra := range []int{0, 11} { + for _, kind := range []lapack.MatrixType{lapack.General, lapack.UpperTri, lapack.LowerTri} { + a := randomGeneral(m, n, n+extra, rnd) + aCopy := cloneGeneral(a) + cfrom := rnd.NormFloat64() + cto := rnd.NormFloat64() + scale := cto / cfrom + + impl.Dlascl(kind, -1, -1, cfrom, cto, m, n, a.Data, a.Stride) + + prefix := fmt.Sprintf("Case #%v: kind=%v,m=%v,n=%v,extra=%v", ti, kind, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + switch kind { + case lapack.General: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + case lapack.UpperTri: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification in lower triangle of A", prefix) + } + } + } + case lapack.LowerTri: + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification in upper triangle of A", prefix) + } + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaset.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaset.go new file mode 100644 index 00000000..f0af77f5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaset.go @@ -0,0 +1,76 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dlaseter interface { + Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) +} + +func DlasetTest(t *testing.T, impl Dlaseter) { + rnd := rand.New(rand.NewSource(1)) + for ti, test := range []struct { + m, n int + }{ + {0, 0}, + {1, 1}, + {1, 10}, + {10, 1}, + {2, 2}, + {2, 10}, + {10, 2}, + {11, 11}, + {11, 100}, + {100, 11}, + } { + m := test.m + n := test.n + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, extra := range []int{0, 10} { + a := randomGeneral(m, n, n+extra, rnd) + alpha := 1.0 + beta := 2.0 + + impl.Dlaset(uplo, m, n, alpha, beta, a.Data, a.Stride) + + prefix := fmt.Sprintf("Case #%v: m=%v,n=%v,uplo=%v,extra=%v", + ti, m, n, uplo, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + for i := 0; i < min(m, n); i++ { + if a.Data[i*a.Stride+i] != beta { + t.Errorf("%v: unexpected diagonal of A", prefix) + } + } + if uplo == blas.Upper || uplo == blas.All { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != alpha { + t.Errorf("%v: unexpected upper triangle of A", prefix) + } + } + } + } + if uplo == blas.Lower || uplo == blas.All { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if a.Data[i*a.Stride+j] != alpha { + t.Errorf("%v: unexpected lower triangle of A", prefix) + } + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq1.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq1.go new file mode 100644 index 00000000..064eaea0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq1.go @@ -0,0 +1,87 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlasq1er interface { + Dlasq1(n int, d, e, work []float64) int + Dgetrfer +} + +func Dlasq1Test(t *testing.T, impl Dlasq1er) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + // TODO(btracey): Increase the size of this test when we have a more numerically + // stable way to test the singular values. + for _, n := range []int{1, 2, 5, 8} { + work := make([]float64, 4*n) + d := make([]float64, n) + e := make([]float64, n-1) + for cas := 0; cas < 1; cas++ { + for i := range work { + work[i] = rnd.Float64() + } + for i := range d { + d[i] = rnd.NormFloat64() + 10 + } + for i := range e { + e[i] = rnd.NormFloat64() + } + ldm := n + m := make([]float64, n*ldm) + // Set up the matrix + for i := 0; i < n; i++ { + m[i*ldm+i] = d[i] + if i != n-1 { + m[(i+1)*ldm+i] = e[i] + } + } + + ldmm := n + mm := make([]float64, n*ldmm) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, m, ldm, m, ldm, 0, mm, ldmm) + + impl.Dlasq1(n, d, e, work) + + // Check that they are singular values. The + // singular values are the square roots of the + // eigenvalues of X^T * X + mmCopy := make([]float64, len(mm)) + copy(mmCopy, mm) + ipiv := make([]int, n) + for elem, sv := range d[0:n] { + copy(mm, mmCopy) + lambda := sv * sv + for i := 0; i < n; i++ { + mm[i*ldm+i] -= lambda + } + + // Compute LU. + ok := impl.Dgetrf(n, n, mm, ldmm, ipiv) + if !ok { + // Definitely singular. + continue + } + // Compute determinant + var logdet float64 + for i := 0; i < n; i++ { + v := mm[i*ldm+i] + logdet += math.Log(math.Abs(v)) + } + if math.Exp(logdet) > 2 { + t.Errorf("Incorrect singular value. n = %d, cas = %d, elem = %d, det = %v", n, cas, elem, math.Exp(logdet)) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq2.go new file mode 100644 index 00000000..80b41b86 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq2.go @@ -0,0 +1,714 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasq2er interface { + Dgetrfer + Dlasq2(n int, z []float64) (info int) +} + +func Dlasq2Test(t *testing.T, impl Dlasq2er) { + dTol := 1e-6 + // Answers from calling the netlib Dlasq2 function directly. + for c, test := range []struct { + n int + z []float64 + info int + zOut []float64 + }{ + { + z: []float64{0.9975595900926172E+00, 0.5668247076112733E+00, 0.9659153754961249E+00, 0.7479276854714322E+00, 0.3673908973747557E+00, 0.4806368987547315E+00, 0.7375426363398452E-01, 0.5355229277727247E-02, 0.3470812885180155E+00, 0.3422438160728350E+00, 0.2179517263384726E+00, 0.1331604100136593E+00, 0.9005245144218924E+00, 0.3867660104574036E+00, 0.4454822893878481E+00, 0.6619321808958428E+00, 0.1610830043055933E-01, 0.6508548361039168E+00, 0.6464088254838254E+00, 0.3229872909405558E+00, 0.8556924028853313E+00, 0.4012869193638139E+00, 0.2068743292187569E+00, 0.9685394642165999E+00, 0.5983995343181346E+00, 0.6729807327762632E+00, 0.4568823106729620E+00, 0.3300151235733747E+00, 0.1003829265021773E+00, 0.7554533047597268E+00, 0.6056932669802318E+00, 0.7190479134084530E+00, 0.8973346038865299E+00, 0.6582291204811077E+00, 0.1507168371301046E+00, 0.6123149049967000E+00, 0.9786602381321465E+00, 0.9991422694268032E+00, 0.2567979861831603E+00, 0.5508654031552206E+00, 0.6590475178936379E+00, 0.5540051353968156E+00, 0.9777600986094505E+00, 0.9019233044604550E+00, 0.6579246844202109E+00, 0.7288585083995637E+00, 0.4024552650632751E+00, 0.9286276631540373E+00, 0.1478351900438915E+00, 0.6745292990637881E+00, 0.7696143092758962E+00, 0.3393225521457851E+00, 0.1158188549489931E+00, 0.6143691843615144E+00, 0.8206171394658319E+00, 0.9470946559240657E+00, 0.7311286518535550E+00, 0.4976039064630389E+00, 0.3748017407872005E+00, 0.4215058560045335E+00, 0.5529030382557849E+00, 0.9979192791781042E+00, 0.9903947480415133E+00, 0.7463096553073095E+00, 0.9537590617479789E+00, 0.9327469033343772E-01, 0.7340236871158429E+00, 0.7517616159256260E+00, 0.9468485056759987E+00, 0.7061763632511533E+00, 0.8138096664824992E+00, 0.5585945195965548E+00, 0.6170557687507783E-01, 0.4803807801853603E+00, 0.5976897721963292E+00, 0.1375319188363359E+00, 0.5873952004066820E+00, 0.5199682629163997E+00, 0.8858783448129579E+00, 0.3038101719904888E+00, 0.6696573039722583E+00, 0.6649400915297697E+00, 0.5036768993979404E+00, 0.2615751204119269E+00}, + n: 21, + zOut: []float64{0.2550031738262204E+01, 0.2480977513501848E+01, 0.2366602269912148E+01, 0.2169993432366266E+01, 0.1810817848712033E+01, 0.1681677309759878E+01, 0.1303743375476047E+01, 0.1202161769544433E+01, 0.1183377192742860E+01, 0.1094206688544886E+01, 0.9154376259418607E+00, 0.8241395430971566E+00, 0.7318275341991307E+00, 0.5186198053161721E+00, 0.4143051093784424E+00, 0.2112065329503869E+00, 0.1093987140067686E+00, 0.9751785856405315E-01, 0.2818174710670554E-01, 0.1697846193036144E-01, 0.2117542506861687E-04, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.2171122324673871E+02, 0.2171122324673871E+02, 0.1020000000000000E+03, 0.3081632653061225E+01, 0.2941176470588236E+01, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + info: 0, + }, + { + z: []float64{0.7655950151081736E-01, 0.1012496627944287E+00, 0.5492657397218519E+00, 0.3755849474908193E+00, 0.1514950257902281E-01, 0.7929154460744389E+00, 0.6208775449015512E+00, 0.7736035774285512E+00, 0.9535807609862423E+00, 0.1142443721338974E+00, 0.3184626428755636E+00, 0.5968198462235605E+00, 0.4815290260558158E-01, 0.1142057780273510E+00, 0.2159649191761220E+00, 0.1005733924928321E+00, 0.7334180249993905E-01, 0.2468617397276878E+00, 0.4433842667962828E+00, 0.2083675732544600E+00, 0.5669983427348256E+00, 0.2431239969651688E-01, 0.4202905770712168E+00, 0.3978530241169832E+00, 0.9765854254920880E+00, 0.6926050329928320E+00, 0.4943367486777372E-02, 0.1299210324451839E+00, 0.4677725963527957E-01, 0.8397777412847708E+00, 0.6784888222113696E+00, 0.5819508167748705E+00, 0.7335259194567719E+00, 0.1160427446694747E+00, 0.8402996546275487E+00, 0.8349959735427709E+00, 0.7465363962886192E+00, 0.8432008930683078E+00, 0.5288390014350658E+00, 0.6654846664813405E+00, 0.7307365692392301E+00, 0.4106042636492306E+00, 0.3557215961646439E+00, 0.7353770423280176E+00, 0.4713176648251016E+00, 0.4626254343486430E+00, 0.7596917071958065E+00, 0.7024594192654096E+00, 0.2579658084846748E+00, 0.9377050325544740E+00, 0.4561035840049426E+00, 0.8084892970067921E+00, 0.9088480529888660E+00, 0.6948766633235142E+00, 0.2194885062923195E+00, 0.8549545559228027E+00, 0.7443966896835119E+00, 0.3011130612705175E+00, 0.6719685452983997E+00, 0.6187140363783860E+00, 0.9675736114028010E+00, 0.9902393027740470E+00, 0.3380065169449795E+00, 0.9207672475882130E+00, 0.3390733399571427E+00, 0.9309435300662920E+00, 0.5465285509796513E+00, 0.4655125893217942E+00, 0.1769140958718970E+00, 0.3779940975005719E+00, 0.1752206228227682E+00, 0.3568582675012224E+00, 0.6656764250906758E+00, 0.6185492680730227E+00, 0.4689472437795331E+00, 0.3162518610221317E+00, 0.2688799086902824E+00, 0.1999212438248075E+00, 0.4154279763213168E+00, 0.9793029133347251E+00, 0.5432115888768534E+00, 0.1295182752745038E+00, 0.8047416637896615E+00, 0.8458210244967665E+00}, + n: 21, + zOut: []float64{0.2649710614371106E+01, 0.2321564474027070E+01, 0.2090779203479937E+01, 0.2001510674733695E+01, 0.1702794694134603E+01, 0.1077066053646038E+01, 0.1060140274732043E+01, 0.9894235909971354E+00, 0.9539342071687115E+00, 0.8046649468928653E+00, 0.7009142227469247E+00, 0.5502651835254770E+00, 0.4423863025187732E+00, 0.3697086796938907E+00, 0.1446051340026323E+00, 0.1110032523123295E+00, 0.7513603923341917E-01, 0.6860214953971246E-01, 0.2434478048112329E-01, 0.6989818532012803E-03, 0.7811996215926567E-04, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.1813933158005285E+02, 0.1813933158005285E+02, 0.1090000000000000E+03, 0.3231292517006803E+01, 0.5504587155963303E+01, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + info: 0, + }, + { + z: []float64{0.7090328374865308E+00, 0.5289732604915972E+00, 0.6638408676820399E+00, 0.9007392577685345E+00, 0.9411642674278379E+00, 0.1144202631330921E+00, 0.8666675899972089E+00, 0.6323680737151134E+00, 0.2427877245566508E+00, 0.1603957810123527E+00, 0.2123565414665629E-01, 0.1902539934369850E+00, 0.3123401294447815E+00, 0.8096475663099788E+00, 0.5737184899962203E+00, 0.8262606712006769E+00, 0.2864548736211023E+00, 0.1605147759074373E+00, 0.3309241142010387E+00, 0.2658533720189140E+00, 0.5447811280109880E+00, 0.5535203163154195E+00, 0.2161483615344606E-01, 0.1487480590324270E+00, 0.1049033762317957E+00, 0.6142137665037214E+00, 0.4062909815669834E+00, 0.9015282863354186E+00, 0.9428381000165521E+00, 0.1566198551488233E+00, 0.9369593797444957E+00, 0.1354729715149707E+00, 0.3712821832808397E+00, 0.3215112250898227E+00, 0.7149642455474942E+00, 0.7297077774959745E+00, 0.3785927874981971E+00, 0.8289344072747380E+00, 0.9536643756705742E+00, 0.3084192540817629E+00, 0.5797406195506623E+00, 0.2334488720392539E+00, 0.8444034680728870E+00, 0.2581324672603945E+00, 0.8397436353763532E+00, 0.5376562757207516E+00, 0.6215703771401371E+00, 0.4908247191212207E+00, 0.2848423854658637E+00, 0.2355591822832676E+00, 0.6513799258897619E+00, 0.6071703403704332E+00, 0.3981458512505542E+00, 0.8487946917355450E+00, 0.6376169839751418E+00, 0.2588233361358196E+00, 0.3588309885453386E+00, 0.5618301121344036E+00, 0.1214685095104872E+00, 0.9784693864155333E+00, 0.3832063578469370E+00, 0.7206987579838013E+00, 0.3582640246022534E+00, 0.9098815720988161E+00, 0.5436872318254895E+00, 0.9596753969896468E+00, 0.9294728975416107E+00, 0.6333208483475120E+00, 0.2956089747729942E+00, 0.1747395639573214E+00, 0.8425785962238860E+00, 0.6185896542974498E+00, 0.7058928872472775E+00, 0.2424399357290958E+00, 0.7979610473510427E+00, 0.3910140128664733E+00, 0.1099592891010870E+00, 0.7536879342329168E+00, 0.2979717756246736E-01, 0.7006607890734408E+00, 0.5252033671714352E+00, 0.7525598235593517E+00, 0.6476778890126167E+00, 0.8710847630132640E+00}, + n: 21, + zOut: []float64{0.2486733497028020E+01, 0.2359071020584524E+01, 0.2276435093308226E+01, 0.2061969496713965E+01, 0.1674052496256098E+01, 0.1634406821090099E+01, 0.1324515540477209E+01, 0.1213036064691536E+01, 0.1142092570196908E+01, 0.8479728747156923E+00, 0.7723287409164926E+00, 0.6845846156476076E+00, 0.4690003902541462E+00, 0.3969394481970619E+00, 0.3209839311891622E+00, 0.1762493640751034E+00, 0.1552318325824889E+00, 0.1299582823757977E+00, 0.4568511390642456E-01, 0.2058742849236605E-01, 0.6687292092604351E-04, 0.0000000000000000E+00, 0.9075510178548721E-16, 0.1809089799756099E-15, 0.1324515540477209E+01, 0.1972152263052530E-28, 0.7207148989396829E-15, 0.1135837106477965E-14, 0.1213036064691536E+01, 0.6865185493883853E-20, 0.3862483738583121E-14, 0.5795548067006594E-14, 0.1142092570196908E+01, 0.1237761291638161E-15, 0.1761387669893985E-13, 0.1204467761940304E-13, 0.8479728747156923E+00, 0.5980780785048348E-20, 0.5961915529495600E-12, 0.8546407799162654E-12, 0.7723287409164926E+00, 0.9983823616477125E-26, 0.2019190149561986E+02, 0.2019190149561985E+02, 0.1120000000000000E+03, 0.3267573696145125E+01, 0.7142857142857143E+01, 0.2981196239393922E-10, 0.4690003902541462E+00, 0.1411215361455214E-23, 0.1291839253366726E-09, 0.2114581039065388E-09, 0.3969394481970619E+00, 0.3215018396446338E-24, 0.8992249144513522E-09, 0.1460279739604385E-08, 0.3209839311891622E+00, 0.5301710738582062E-20, 0.5956459688113839E-08, 0.9509260151006140E-08, 0.1762493640751034E+00, 0.3305918938014538E-18, 0.2145126200057182E-06, 0.1391189925457742E-06, 0.1552318325824889E+00, 0.0000000000000000E+00, 0.8222867095540534E-06, 0.8520250895881005E-06, 0.1299582823757977E+00, 0.1946507846527860E-19, 0.4299487364203470E-05, 0.2670451838837521E-05, 0.4568511390642456E-01, 0.1783600337601646E-17, 0.1688330183620908E-03, 0.2840434656464124E-03, 0.2058742849236605E-01, 0.2127174768075152E-17, 0.5266290662212281E-04, 0.3082204001196310E-04, 0.6687292092604351E-04, 0.4725269249209171E-22, 0.3479992598793783E-02, 0.7157534417412210E-03}, + info: 0, + }, + { + z: []float64{0.8307212987388154E+00, 0.9571804405037874E+00, 0.2222674360399970E+00, 0.5794927951917870E+00, 0.9907605078898842E+00, 0.8399673535531696E+00, 0.1748054629244838E+00, 0.7095417514667766E+00, 0.3015507353664195E+00, 0.2504155371033889E-01, 0.9167396887269817E+00, 0.6888065712047682E+00, 0.7567577995550097E+00, 0.9327280452266753E+00, 0.5500991579404824E-01, 0.4989499454693689E+00, 0.5949898652751251E-01, 0.1718660951302574E+00, 0.6883620036166904E+00, 0.3066205390931208E+00, 0.7351901912310475E+00, 0.7521684164853142E+00, 0.3957210266430871E+00, 0.8778502662051324E-01, 0.4896297811280748E-01, 0.7793618951247419E+00, 0.6807766665219679E+00, 0.3115699624095645E+00, 0.5227646665950632E+00, 0.5057964692468060E+00, 0.4385260593432981E+00, 0.5876392780963172E+00, 0.2973252261444674E+00, 0.2948995727695043E+00, 0.7378444260331429E-01, 0.9749457382350615E+00, 0.7281626398300706E+00, 0.7580903878987629E+00, 0.3091762186458183E+00, 0.2464983240671905E+00, 0.2568872936019900E+00, 0.6180627613788815E+00, 0.9377882352337240E+00, 0.9921824152100049E+00, 0.2248192100106184E+00, 0.9472840045361628E+00, 0.8477853668436538E+00, 0.7001263233958666E+00, 0.5544440083201581E+00, 0.4415839019184687E+00, 0.2491818172148126E+00, 0.8976627554942691E+00, 0.1457298176556392E+00, 0.4345936198183369E+00, 0.4573762249453559E+00, 0.3093805347522776E+00, 0.4809246108862507E+00, 0.6897426752489948E+00, 0.8107988692352123E+00, 0.3921644162683642E+00, 0.2931487419364392E+00, 0.5759780604710760E+00, 0.7253418085569345E+00, 0.1427733376597652E+00, 0.3335555091947459E+00, 0.1603897948564823E+00, 0.5345943097231743E+00, 0.7233253065718669E+00, 0.2281802915301432E+00, 0.1990064435881517E+00, 0.9726196083044836E+00, 0.9935713768557323E+00, 0.8195201715007894E-01, 0.2508806553004002E+00, 0.2158489797899930E+00, 0.1957771185505375E+00, 0.8502651710165565E+00, 0.4468235108377239E-01, 0.8639211642125266E+00, 0.6713373034638015E-01, 0.4273173462824215E+00, 0.1373188375801981E+00, 0.1190874985301729E+00, 0.3059495456429208E+00}, + n: 21, + zOut: []float64{0.2399198387954965E+01, 0.2388283868878418E+01, 0.2234728187505421E+01, 0.1947641030296732E+01, 0.1845273105794422E+01, 0.1837097911259683E+01, 0.1471118007292610E+01, 0.1105651020532553E+01, 0.9883044021137968E+00, 0.9478841363642468E+00, 0.8550293065516678E+00, 0.7566674361156733E+00, 0.5310790726859680E+00, 0.3571217714437427E+00, 0.2893653184719416E+00, 0.2534414197270934E+00, 0.2173582726294167E+00, 0.4908458037260943E-01, 0.1246498683649276E-01, 0.5862142085722914E-02, 0.4704104342516643E-04, 0.1939986690620616E-19, 0.1034652479755287E-16, 0.1536368559490732E-16, 0.1471118007292610E+01, 0.5364686198585281E-13, 0.6088846084221820E-07, 0.1529604999486430E-06, 0.1105651020532553E+01, 0.2903008131213323E-27, 0.1160127138141562E-06, 0.1335479603764263E-06, 0.9883044021137968E+00, 0.2125606020077514E-18, 0.5906967539735199E-07, 0.6675815740532400E-07, 0.9478841363642468E+00, 0.1331202777560457E-29, 0.4438231138534822E-07, 0.3948328125271971E-07, 0.8550293065516678E+00, 0.5860341995390921E-20, 0.2049270140595660E+02, 0.2049270140595660E+02, 0.9800000000000000E+02, 0.2893424036281179E+01, 0.4081632653061225E+01, 0.1377712740565197E-07, 0.5310790726859680E+00, 0.1537961403283359E-19, 0.8011211497963711E-08, 0.8400248580143560E-08, 0.3571217714437427E+00, 0.5389497704469953E-25, 0.6965765014245226E-08, 0.7336584331089061E-08, 0.2893653184719416E+00, 0.6081961202185573E-17, 0.9973730165755502E-08, 0.8562226724273748E-08, 0.2534414197270934E+00, 0.3644137891043716E-17, 0.1552441635408352E-06, 0.1605842922922618E-07, 0.2173582726294167E+00, 0.1710250442519154E-26, 0.2805940935843235E-04, 0.1153299285109565E-04, 0.4908458037260943E-01, 0.1140499340513312E-15, 0.3458275194991493E-03, 0.2689727098393103E-03, 0.1246498683649276E-01, 0.4437342591868191E-30, 0.1429141842628293E-03, 0.1683368406483595E-03, 0.5862142085722914E-02, 0.2515327803596613E-22, 0.2394538487567536E-03, 0.1603201011413965E-03, 0.4704104342516643E-04, 0.0000000000000000E+00, 0.2149753858259932E-02, 0.4092589741085703E-02}, + info: 0, + }, + { + z: []float64{0.6132370003914160E+00, 0.6636632940312478E+00, 0.8959100063178993E+00, 0.7536793777540497E+00, 0.6298705159481864E+00, 0.2209880035966978E+00, 0.4838373503885766E+00, 0.6150203746616348E+00, 0.9876587724998732E+00, 0.5591876171910803E+00, 0.3708840600033242E+00, 0.3375947236522073E+00, 0.7454250822233153E+00, 0.5697349010621601E+00, 0.4561367007431339E+00, 0.6481896738286699E+00, 0.6835960923418801E+00, 0.1703905177923075E+00, 0.2730661115049011E+00, 0.4407624886449348E+00, 0.4577220273293221E+00, 0.3952566732937318E+00, 0.6883342106097436E+00, 0.2988887099704991E+00, 0.2052274263883085E+00, 0.1922842703083140E+00, 0.4189999528960880E+00, 0.6906452535299822E+00, 0.1405554539793709E+00, 0.1437412601859918E+00, 0.6624635742176765E+00, 0.5756752017566100E+00, 0.7749505183416766E+00, 0.7752965769666669E+00, 0.7653541054136069E+00, 0.8765107194498384E+00, 0.9921378985956986E-01, 0.3345156485504346E+00, 0.6450936562634260E+00, 0.1316181443467312E+00, 0.8075436662342752E+00, 0.5418723210737144E+00, 0.2657525890099199E+00, 0.4588749915888913E+00, 0.5109250246010762E+00, 0.5048342930643721E+00, 0.9617739307304302E+00, 0.5502351700731637E+00, 0.1896288106400514E+00, 0.2011189112848212E+00, 0.2487376305081674E+00, 0.9700914054633822E+00, 0.7763920500140777E+00, 0.2727004477756484E+00, 0.4969507403482072E+00, 0.3987515903118115E+00, 0.6132963384905279E+00, 0.8526865910258985E-01, 0.7370021348269777E+00, 0.8628692345603857E+00, 0.3410351221174988E+00, 0.6944408188735030E+00, 0.6418832405583447E+00, 0.8549561267667016E-01, 0.7079842121947655E+00, 0.5924596383322266E+00, 0.2327865765542259E+00, 0.7519783901092147E-01, 0.3243359400926964E+00, 0.9130914950306788E+00, 0.2042866226175709E+00, 0.4527677275849958E+00, 0.7271733772634871E+00, 0.2835797318864963E-01, 0.5170298378180002E+00, 0.7676612860726464E+00, 0.8943646165240225E+00, 0.9444900692816881E+00, 0.2898061819682256E+00, 0.5314658042534958E+00, 0.2328255902743269E+00, 0.3127766212762262E+00, 0.1415213232426512E+00, 0.3425808715425687E+00}, + n: 21, + zOut: []float64{0.2568497247033635E+01, 0.2474290441512907E+01, 0.2254355189310800E+01, 0.1987099258783412E+01, 0.1595738223681455E+01, 0.1520583769371047E+01, 0.1349481184037943E+01, 0.1286943522977408E+01, 0.1233633359467258E+01, 0.1105388350935419E+01, 0.8741663391031235E+00, 0.7042784684853729E+00, 0.6809050564171195E+00, 0.5312535309083547E+00, 0.3765999563195902E+00, 0.2982885955048700E+00, 0.1761408438030470E+00, 0.1021950592815966E+00, 0.5149411253987173E-01, 0.2409819364774552E-01, 0.3292801347387554E-02, 0.7649046082865931E-16, 0.2073367755475779E-07, 0.1625592945762753E-07, 0.1349481184037943E+01, 0.1183291357831518E-29, 0.4660703060512034E-13, 0.1807862490656452E-12, 0.1286943522977408E+01, 0.1649665924998180E-25, 0.1294990598064480E-10, 0.5231829186377068E-10, 0.1233633359467258E+01, 0.8526291632353489E-16, 0.3101844497115867E-08, 0.1140775990076438E-07, 0.1105388350935419E+01, 0.9624103043696344E-28, 0.5663389137423196E-06, 0.4346359020206590E-06, 0.8741663391031235E+00, 0.3067428736041242E-19, 0.2119872350446936E+02, 0.2119872350446936E+02, 0.1030000000000000E+03, 0.3056689342403628E+01, 0.2912621359223301E+01, 0.2039882393707806E-06, 0.6809050564171195E+00, 0.0000000000000000E+00, 0.3469744030301619E-06, 0.2644131172050035E-06, 0.5312535309083547E+00, 0.3043881270837009E-21, 0.5541811479797519E-05, 0.3827690844980446E-05, 0.3765999563195902E+00, 0.1909043390634849E-27, 0.3412067971678679E-04, 0.3418356678006945E-04, 0.2982885955048700E+00, 0.1167175485134229E-15, 0.1390598737761422E-03, 0.1685020271483295E-03, 0.1761408438030470E+00, 0.3311298373357662E-16, 0.2687183242739271E-03, 0.2970561145148615E-03, 0.1021950592815966E+00, 0.3861046454850253E-20, 0.3877059717439437E-03, 0.4274183271611622E-03, 0.5149411253987173E-01, 0.3171094621243632E-24, 0.5614281929126997E-03, 0.6201503766753644E-03, 0.2409819364774552E-01, 0.5854827030937197E-31, 0.8580439238194122E-03, 0.9937175751003719E-03, 0.3292801347387554E-02, 0.1687712113428427E-19, 0.6404816195044538E-02, 0.3574263865391779E-02}, + info: 0, + }, + { + z: []float64{0.1535280608392028E+00, 0.8492164242958209E+00, 0.9720508422713467E+00, 0.4409240313091006E+00, 0.7744413453832578E+00, 0.4562143200311385E+00, 0.8645004927526174E+00, 0.7279750979364787E+00, 0.6373358699411871E+00, 0.7240388495630282E+00, 0.6042124182518795E+00, 0.2629417492305242E-01, 0.2927658696806527E+00, 0.1971917075100318E+00, 0.9486620805007744E+00, 0.5318461733579811E+00, 0.1035922758398233E-01, 0.4521355876782263E+00, 0.9635828765019094E+00, 0.9861179636072996E+00, 0.3409131837267612E+00, 0.9592913933135179E+00, 0.3267081303471464E+00, 0.7042329006712417E+00, 0.7904477014671945E+00, 0.7235636505410947E+00, 0.7289557043239185E+00, 0.4453819137782510E+00, 0.3817792285714174E+00, 0.9222246883547156E+00, 0.7484233302016036E+00, 0.4267300781414476E+00, 0.2174272124496083E+00, 0.7294135193889231E+00, 0.7969150359898325E+00, 0.5584233158827989E+00, 0.8854167010119880E+00, 0.3831257236275667E+00, 0.2407966333760054E+00, 0.3150832526072347E+00, 0.4329046703236793E+00, 0.4798261053116015E-01, 0.4240797212710790E+00, 0.7373271503520912E+00, 0.8727856342792233E+00, 0.3079871491200393E+00, 0.8433176604823556E+00, 0.8160920845908722E+00, 0.4068006968345205E+00, 0.8649881745683563E+00, 0.8522504948442566E+00, 0.5120820890311298E+00, 0.7764141319706099E+00, 0.4928600452500731E+00, 0.2048536231221674E+00, 0.4451308747598662E+00, 0.4335546033385644E+00, 0.5471256397417612E-01, 0.7004960984988220E+00, 0.9192372420579460E+00, 0.3890133989146303E+00, 0.2488782917619309E+00, 0.3663470187625480E+00, 0.9986636866778884E+00, 0.6620792031393874E+00, 0.1797345205931197E+00, 0.8723761011602340E+00, 0.2439575243714007E+00, 0.1163919437436586E+00, 0.8182195270597429E+00, 0.5356403226658167E+00, 0.9880537276300997E+00, 0.4163057033602857E+00, 0.8081980088045720E+00, 0.2399383760782623E+00, 0.9702581513812658E+00, 0.3763181880939181E+00, 0.6334004896983517E+00, 0.1368995930243956E+00, 0.7684724492197631E+00, 0.1011989548860721E+00, 0.5519462180485674E+00, 0.8316516728108886E+00, 0.3772586994144635E+00}, + n: 21, + zOut: []float64{0.2579297838383781E+01, 0.2566242251743589E+01, 0.2402206059499122E+01, 0.2314572748831938E+01, 0.2210246243389976E+01, 0.2073991263591532E+01, 0.1647852770173070E+01, 0.1458062583915517E+01, 0.1424747680105817E+01, 0.1229594627898745E+01, 0.8682818248784862E+00, 0.7800126440184885E+00, 0.7769870810337002E+00, 0.4018986220147585E+00, 0.3451236345722463E+00, 0.2059421010707241E+00, 0.1665395041671736E+00, 0.1384541468623413E+00, 0.4569625338134105E-01, 0.3572364569397507E-01, 0.7785678858960618E-04, 0.1325624140040768E-19, 0.1464254707155794E-03, 0.9424803187834284E-04, 0.1647852770173070E+01, 0.1564186274351218E-15, 0.3473328524848360E-05, 0.4592867365821283E-05, 0.1458062583915517E+01, 0.3231174267785264E-26, 0.1403657959312935E-04, 0.9634257574341414E-05, 0.1424747680105817E+01, 0.1020140793606197E-15, 0.1723203566561169E-05, 0.6067379842882497E-05, 0.1229594627898745E+01, 0.2663149152121406E-17, 0.1061013981937667E-04, 0.1674993264096194E-04, 0.8682818248784862E+00, 0.8099755562101574E-24, 0.2367155138201492E+02, 0.2367155138201491E+02, 0.1110000000000000E+03, 0.3174603174603174E+01, 0.5405405405405405E+01, 0.8398559432747079E-06, 0.7769870810337002E+00, 0.0000000000000000E+00, 0.6532651675838807E-05, 0.1393736055608104E-04, 0.4018986220147585E+00, 0.1488702756444268E-16, 0.4786924897797409E-03, 0.2484818164296786E-03, 0.3451236345722463E+00, 0.1393994753571567E-18, 0.7967956438667165E-06, 0.1566848631115136E-05, 0.2059421010707241E+00, 0.1872521839860791E-17, 0.1674828806776016E-04, 0.3829209207735075E-04, 0.1665395041671736E+00, 0.5127595883936577E-29, 0.1145979873394449E-04, 0.6763541499702777E-05, 0.1384541468623413E+00, 0.6162975822039155E-31, 0.1509781169748205E-03, 0.4934238518442497E-04, 0.4569625338134105E-01, 0.3815207438965640E-25, 0.3298388086972868E-02, 0.1367005987525658E-02, 0.3572364569397507E-01, 0.2773930797150972E-21, 0.3955985102398275E-03, 0.3433403686203228E-03, 0.7785678858960618E-04, 0.7790054198074833E-21, 0.1914938157793930E-01, 0.1330976133014081E-01}, + info: 0, + }, + { + z: []float64{0.8677677383100214E+00, 0.6246622741727026E+00, 0.5523136647126087E+00, 0.2116103484147348E+00, 0.8227197076777661E+00, 0.3636019443697256E+00, 0.2305222034118074E+00, 0.3291143648196290E+00, 0.6800926583943011E+00, 0.4290450477605455E+00, 0.4523048516285796E+00, 0.9276084588261152E+00, 0.4462311938877914E+00, 0.6672491542978151E+00, 0.7808537049355564E+00, 0.7908271145868994E+00, 0.1977402045683964E+00, 0.2563794060302639E+00, 0.6768044668199432E+00, 0.8985309013607360E+00, 0.3750140409512910E+00, 0.2003663066929584E-01, 0.4020022629723622E+00, 0.9909625073113403E+00, 0.9747495116121061E+00, 0.9702779584867087E+00, 0.9688371740876045E+00, 0.3747269639045615E+00, 0.9728403214040160E-01, 0.7507234588709335E+00, 0.8245099981459856E+00, 0.7244448753186800E+00, 0.3670523289486082E+00, 0.6220520718362722E+00, 0.3063226611493952E+00, 0.3012769332894331E+00, 0.6763821017483275E+00, 0.8300640433662996E+00, 0.5563237542291373E+00, 0.5594449054752113E+00, 0.3278038518373678E+00, 0.7307041435680680E+00, 0.1582529760475658E+00, 0.5328751876026443E+00, 0.7841944053171677E+00, 0.2157818394558657E+00, 0.3253134136288985E+00, 0.5014502641306768E+00, 0.2229178930043155E+00, 0.4664985859426845E+00, 0.1867987929192785E+00, 0.1951091673564507E+00, 0.2069185156156168E+00, 0.9058058542218750E+00, 0.7999188612304056E+00, 0.7349484002829904E+00, 0.4153480749961962E+00, 0.8109879258422723E+00, 0.9883741464101338E+00, 0.4911202582082937E+00, 0.2193166361224579E+00, 0.7618820222564749E+00, 0.9073087210515056E+00, 0.5896383620860655E+00, 0.8706198942119541E+00, 0.3860710050052940E-01, 0.9380336544251486E+00, 0.4690283060543987E-01, 0.8970820572284144E+00, 0.1974579201509297E-01, 0.9992442335759629E+00, 0.9801967887432729E+00, 0.6116617864086051E+00, 0.5875675950916066E+00, 0.9622537584002233E+00, 0.8934200351761762E+00, 0.2022182729782195E+00, 0.1273316669652236E-01, 0.2549904925850485E+00, 0.8904280763656908E+00, 0.2695748922419082E+00, 0.8890196843116763E+00, 0.5191439214393291E+00, 0.3672061831861048E+00}, + n: 21, + zOut: []float64{0.3071910136434907E+01, 0.2366684893081943E+01, 0.2247985022656176E+01, 0.2134160618983571E+01, 0.1929380862422316E+01, 0.1895668448583188E+01, 0.1735809456784568E+01, 0.1390623822795548E+01, 0.1372853012616850E+01, 0.1197489438156041E+01, 0.1106600205023489E+01, 0.8564547950868329E+00, 0.4949238197552136E+00, 0.3889452841496929E+00, 0.3405947975938995E+00, 0.2516597920662951E+00, 0.2113890461921598E+00, 0.1169778386549868E+00, 0.1072268106836703E+00, 0.7646784687889400E-02, 0.1286588928027629E-02, 0.1194767075191949E-22, 0.1162094363453686E-09, 0.8691558890693288E-10, 0.1735809456784568E+01, 0.8134816760001801E-14, 0.1019665656815186E-08, 0.1906916241197346E-08, 0.1390623822795548E+01, 0.0000000000000000E+00, 0.1594323424098234E-05, 0.3312168640703357E-05, 0.1372853012616850E+01, 0.0000000000000000E+00, 0.3830524268846776E-04, 0.1577534719508939E-04, 0.1197489438156041E+01, 0.1592850300841939E-16, 0.1256296423282912E-03, 0.1149042579564614E-03, 0.1106600205023489E+01, 0.6530365529382261E-18, 0.2322627147533726E+02, 0.2322627147533726E+02, 0.1020000000000000E+03, 0.2963718820861678E+01, 0.3921568627450980E+01, 0.6483516393063832E-03, 0.4949238197552136E+00, 0.1972152263052530E-28, 0.5430985229870038E-04, 0.4447663749968261E-04, 0.3889452841496929E+00, 0.1329049288162406E-17, 0.2738942590248176E-04, 0.1582812372822289E-04, 0.3405947975938995E+00, 0.1187508759187252E-18, 0.7465410105999781E-04, 0.1255487400488340E-03, 0.2516597920662951E+00, 0.4141519752410312E-29, 0.2152266118694742E-04, 0.6710408995051273E-05, 0.2113890461921598E+00, 0.3333294884283764E-18, 0.6132111109262542E-03, 0.4277764486586744E-03, 0.1169778386549868E+00, 0.2711709361697228E-30, 0.3832079371139971E-03, 0.3904887652242632E-03, 0.1072268106836703E+00, 0.2176254805972020E-18, 0.4306247975784355E-03, 0.4948147025217374E-03, 0.7646784687889400E-02, 0.1110488679882733E-19, 0.1569670832436511E-02, 0.2092370053382882E-02, 0.1286588928027629E-02, 0.5442848430598922E-18, 0.4460307636637516E-02, 0.7046212350403941E-02}, + info: 0, + }, + { + z: []float64{0.9838241499564321E+00, 0.8769514477589457E+00, 0.6814467524843054E+00, 0.3624618995089947E+00, 0.1981908649829056E+00, 0.1872278407669582E+00, 0.9876554444003832E+00, 0.1826583579385833E+00, 0.1183269767614670E-01, 0.9437175277915953E+00, 0.4919320768587329E+00, 0.9805291749478650E+00, 0.6132842150855770E+00, 0.3626870797541525E+00, 0.5323780753704027E+00, 0.1457937981484730E+00, 0.1328300737138376E+00, 0.3811835111034733E+00, 0.7003413504474413E+00, 0.5497308136521228E+00, 0.8255713255718768E+00, 0.5373393799690840E+00, 0.6623327475759663E+00, 0.5316913920782962E-01, 0.1714649183335913E+00, 0.6186592957613974E+00, 0.7587327126921758E+00, 0.9100586255702885E+00, 0.7140000863381626E+00, 0.7400119974078728E+00, 0.3567025022071233E+00, 0.8218612151637966E+00, 0.5520556331010515E+00, 0.6508027169553372E+00, 0.1875664464519897E+00, 0.8183092398415237E+00, 0.2239662369231676E-01, 0.6571790154721793E+00, 0.1196415656369646E+00, 0.3853512775546503E+00, 0.2426450009067070E+00, 0.9653447575661293E+00, 0.4852906340727067E+00, 0.9923496603563310E+00, 0.2812811891225394E+00, 0.9784300144088514E+00, 0.9528689986126391E+00, 0.2431080020200448E+00, 0.4166208849723857E+00, 0.7357806826601304E+00, 0.1952831632199464E+00, 0.6393407699957093E+00, 0.6296804002658308E+00, 0.1028694374663701E+00, 0.1387452591062114E+00, 0.4549213107961220E+00, 0.9843671628976580E+00, 0.4249152858158138E+00, 0.7048043599695387E+00, 0.3653998904622074E+00, 0.2003765309007774E+00, 0.4095912484595889E+00, 0.2392233396621621E+00, 0.7050044605645847E+00, 0.7908086424110450E-01, 0.2038177493661538E+00, 0.1735168081909322E-01, 0.3343100300667304E+00, 0.2848572906345944E+00, 0.8454138442968477E+00, 0.4944340369822147E+00, 0.7101083458004501E+00, 0.2546477176633619E+00, 0.8227235336957786E+00, 0.2816146807741101E+00, 0.6247995550265835E+00, 0.7458069042729408E+00, 0.8739345864578790E+00, 0.1278937298671606E+00, 0.2791833532060612E+00, 0.9234762152279486E+00, 0.9863012584972185E+00, 0.7892913846591531E+00, 0.3479266835120939E+00}, + n: 21, + zOut: []float64{0.2623495482601064E+01, 0.2337512212773574E+01, 0.2310508039367694E+01, 0.2188663096012427E+01, 0.1954141717332891E+01, 0.1371476701077329E+01, 0.1267869950064541E+01, 0.1203016320141301E+01, 0.1132845050819559E+01, 0.9979737678355206E+00, 0.8633053234635751E+00, 0.6603430282082061E+00, 0.6064350433288983E+00, 0.4855760962077864E+00, 0.4280373135604714E+00, 0.3659370670152315E+00, 0.1453682093766173E+00, 0.9617861239701422E-01, 0.7192949634365248E-01, 0.1892143303127712E-02, 0.3946528731286962E-05, 0.0000000000000000E+00, 0.9258243476772570E-07, 0.9000418438492766E-07, 0.1267869950064541E+01, 0.0000000000000000E+00, 0.2500234135491857E-07, 0.1856395032302831E-07, 0.1203016320141301E+01, 0.2658426139847422E-18, 0.4168972835699797E-07, 0.5531467635213317E-07, 0.1132845050819559E+01, 0.2518044009465470E-24, 0.1194059466661935E-08, 0.2159625808467239E-08, 0.9979737678355206E+00, 0.1047506307937635E-23, 0.4478743649191460E-07, 0.9991281120631680E-07, 0.8633053234635751E+00, 0.5895762127714383E-22, 0.2111250861775921E+02, 0.2111250861775921E+02, 0.9900000000000000E+02, 0.2927437641723356E+01, 0.4040404040404041E+01, 0.9244672049175682E-07, 0.6064350433288983E+00, 0.1817535525629211E-26, 0.9398974933478891E-07, 0.9547946669183887E-07, 0.4855760962077864E+00, 0.3185418565406740E-17, 0.9937648506460343E-07, 0.9792626502078532E-07, 0.4280373135604714E+00, 0.2958228394578794E-30, 0.9921525775570031E-07, 0.1006425128472401E-06, 0.3659370670152315E+00, 0.4461863922899316E-21, 0.1047488573169732E-06, 0.1032270990738791E-06, 0.1453682093766173E+00, 0.6504493884088473E-15, 0.1102576940374778E-06, 0.1180293023862048E-06, 0.9617861239701422E-01, 0.6467797587852522E-18, 0.1844536574504796E-06, 0.1488485108626942E-06, 0.7192949634365248E-01, 0.2114103686638959E-13, 0.8531410278849863E-06, 0.1408572284551695E-05, 0.1892143303127712E-02, 0.0000000000000000E+00, 0.6242841403373791E-04, 0.3522115697192072E-04, 0.3946528731286962E-05, 0.6203854594147708E-24, 0.1209929086462260E-02, 0.4906802871097585E-03}, + info: 0, + }, + { + z: []float64{0.7643247442799757E+00, 0.1930914554442843E+00, 0.6441117687067544E-01, 0.4522061669974708E-01, 0.1465182320932497E+00, 0.8069033698425149E+00, 0.6560188128523874E+00, 0.2446749124420051E+00, 0.3243649544497533E+00, 0.9836733438970116E+00, 0.6137527621157332E+00, 0.2925225554635034E+00, 0.4955619768673408E+00, 0.7361289066349539E+00, 0.3953262269487445E-01, 0.1565854250658760E-01, 0.4785236355428808E+00, 0.7766165270899886E+00, 0.9069259340739989E+00, 0.9151936268801151E+00, 0.3338292872636017E+00, 0.2993135005490550E+00, 0.8287022194584887E+00, 0.4593628480546942E+00, 0.1484428934315618E-01, 0.3390977660295040E+00, 0.5819746692101802E-01, 0.9277352020779983E-01, 0.6517310862845033E+00, 0.3951866136249272E+00, 0.6199300068296295E+00, 0.8252199884043853E+00, 0.3390764160478065E+00, 0.3084679704183562E+00, 0.3609211283483548E+00, 0.4116857210304998E+00, 0.4609476939442378E+00, 0.3824129844545763E+00, 0.6431169626236315E+00, 0.2416519334621993E+00, 0.7156780768158061E+00, 0.8568018406565006E+00, 0.1639408452444666E+00, 0.7313040585903831E+00, 0.5099183572592548E+00, 0.2801641590611897E+00, 0.9930562568266591E+00, 0.7612468327164370E+00, 0.3271886985411110E-01, 0.7066605591101006E+00, 0.6720867845388043E+00, 0.9004209067318458E-01, 0.4611918168927077E+00, 0.2638384667560661E+00, 0.3554909044606102E+00, 0.7231384727137510E+00, 0.2729268177075039E-01, 0.5848397641916390E+00, 0.6942450598380807E+00, 0.1106927451590289E+00, 0.5262572286481777E+00, 0.9936768911750095E+00, 0.7262536107933111E+00, 0.7604873714570974E+00, 0.2036182130165832E+00, 0.8632527217998969E+00, 0.1924957421132846E+00, 0.8815968660524154E-01, 0.2412813036310424E+00, 0.9105232147744077E+00, 0.8298587923387578E+00, 0.7754575363227978E-01, 0.8714764594177653E+00, 0.5571901679066804E+00, 0.3971870017409277E+00, 0.9993097753535422E+00, 0.7700188328643205E+00, 0.7856615172810383E+00, 0.7533953600915489E+00, 0.5602208064288483E+00, 0.6944234372397261E+00, 0.8756090822068926E+00, 0.1433700749181099E-01, 0.2857413018245216E+00}, + n: 21, + zOut: []float64{0.2546753248931182E+01, 0.2051980365170268E+01, 0.1958366389726797E+01, 0.1631238683423845E+01, 0.1586034790683645E+01, 0.1538534425510682E+01, 0.1255412586747036E+01, 0.1121690972560896E+01, 0.9718147643766369E+00, 0.9049110982817965E+00, 0.7946671649858114E+00, 0.5884376759528481E+00, 0.4050217422474118E+00, 0.3189813042957475E+00, 0.2502079076659038E+00, 0.1378021633219403E+00, 0.1230588999356998E+00, 0.5024634530670342E-01, 0.4118371112977081E-01, 0.5279820157992808E-02, 0.1421284452028254E-03, 0.2680065184671810E-21, 0.2301930285321580E-14, 0.5132436462785431E-14, 0.1255412586747036E+01, 0.2424007516335156E-18, 0.1913029885324846E-10, 0.9021761757831104E-11, 0.1121690972560896E+01, 0.1977581519346623E-22, 0.4602280167506019E-08, 0.2460881124989248E-08, 0.9718147643766369E+00, 0.1104484640438811E-18, 0.4278245612761057E-07, 0.2387897413722468E-07, 0.9049110982817965E+00, 0.2768434971275651E-16, 0.3015076539683485E-07, 0.2961312447326530E-07, 0.7946671649858114E+00, 0.1262042385269225E-19, 0.1828176618885781E+02, 0.1828176618885782E+02, 0.1040000000000000E+03, 0.3122448979591837E+01, 0.3846153846153846E+01, 0.1851926648424158E-06, 0.4050217422474118E+00, 0.9293221980374701E-17, 0.1284245841610550E-05, 0.2164676294343609E-05, 0.3189813042957475E+00, 0.1378649105642637E-16, 0.4610281885819925E-06, 0.1003327305702036E-05, 0.2502079076659038E+00, 0.2177821011994986E-13, 0.3677246803752887E-04, 0.3095541926811936E-04, 0.1378021633219403E+00, 0.9210656120777790E-20, 0.9401458780737957E-05, 0.1039122642078444E-04, 0.1230588999356998E+00, 0.4930380657631324E-30, 0.6528493871226699E-06, 0.1524653341983116E-05, 0.5024634530670342E-01, 0.6838275466788171E-23, 0.2104276631320477E-03, 0.3160258883556432E-03, 0.4118371112977081E-01, 0.6162975822039155E-32, 0.9318133168194381E-04, 0.1261364640367337E-03, 0.5279820157992808E-02, 0.7005084838362585E-27, 0.1903158606362315E-02, 0.7288242235414376E-03, 0.1421284452028254E-03, 0.7703719777548943E-33, 0.7890744155827079E-03, 0.6129022301104231E-03}, + info: 0, + }, + { + z: []float64{0.1813251202119042E+00, 0.8077156210855166E+00, 0.5525396662071069E+00, 0.4858391136124270E+00, 0.5367389425969793E+00, 0.4534294101162717E-01, 0.1438386197304258E+00, 0.7801305810912117E+00, 0.7706244548712898E+00, 0.1595286891781422E+00, 0.4689597797472277E+00, 0.1630160981693277E+00, 0.5488525733069047E+00, 0.3050379405729475E+00, 0.1544160351990825E+00, 0.5750210099163514E+00, 0.1440876969429373E+00, 0.1932969959898051E+00, 0.6910796187912660E+00, 0.9501882645686455E+00, 0.1314109921701710E+00, 0.7099941843070685E+00, 0.3797313713209320E+00, 0.3979808845174081E+00, 0.1006018923100482E-02, 0.4131896358268045E+00, 0.8038132966802857E+00, 0.8778643630407806E+00, 0.1407889867849830E+00, 0.4305134083308382E-01, 0.5656496703997997E+00, 0.5820188952601091E-01, 0.8713537916178680E+00, 0.3443162753417257E+00, 0.4898335360866699E+00, 0.2822165738696382E+00, 0.2385629061714932E+00, 0.5496478420286478E+00, 0.7138724344268773E+00, 0.9028268569137332E+00, 0.7573748459251011E+00, 0.5392259606733280E+00, 0.6459213128573325E+00, 0.7769497211063184E+00, 0.8790154346127051E+00, 0.6027389165195913E+00, 0.6151696559086139E-01, 0.4391208291942791E+00, 0.8705350585502258E-02, 0.2995750933531418E+00, 0.9735013653226658E+00, 0.9551710085419519E+00, 0.2132875677034638E+00, 0.6739668529657764E+00, 0.5361543284664445E+00, 0.3596977928604983E+00, 0.1373006735837845E-02, 0.8494363479416891E+00, 0.4214720423022895E+00, 0.7478449906096684E+00, 0.1164429527473354E-01, 0.6143683285709396E+00, 0.4444360064738268E+00, 0.6626608299302873E+00, 0.6887459689591686E+00, 0.9391262494647765E+00, 0.7167310461528731E+00, 0.4516657019045726E+00, 0.6345059624902227E+00, 0.2241941493026407E+00, 0.3981621310014529E+00, 0.8300976429090324E+00, 0.1390103241004258E+00, 0.7559319384422415E+00, 0.7929892786129927E+00, 0.2279061631835571E+00, 0.5280867615120838E+00, 0.1374499172030500E+00, 0.1739503966093568E+00, 0.1475298919309330E+00, 0.8100098524713260E+00, 0.2514850916075489E+00, 0.4100580488172028E+00, 0.9565966467338131E+00}, + n: 21, + zOut: []float64{0.2319179815575576E+01, 0.1965907124623829E+01, 0.1887317422176422E+01, 0.1806195743608332E+01, 0.1738584542532610E+01, 0.1518839817892385E+01, 0.1233018482483247E+01, 0.1147944957333420E+01, 0.8847632334488245E+00, 0.7964611162721277E+00, 0.7478364459856081E+00, 0.6404526251941426E+00, 0.4533452491188792E+00, 0.4218888103472739E+00, 0.2727838365998446E+00, 0.2511907405802137E+00, 0.9874721307137806E-01, 0.7639943902083833E-01, 0.4105860224136690E-01, 0.2835039177122555E-01, 0.1849635761425839E-05, 0.5687744349931984E-17, 0.4733652108368680E-16, 0.8474188088642906E-16, 0.1233018482483247E+01, 0.2772075531849652E-16, 0.2588283290162890E-14, 0.3835910828290052E-14, 0.1147944957333420E+01, 0.1246926305809672E-21, 0.2331804915191085E-13, 0.1628473983494628E-13, 0.8847632334488245E+00, 0.1029638495848151E-18, 0.6869501877456999E-13, 0.5177641249986829E-13, 0.7964611162721277E+00, 0.2366582715663035E-28, 0.1931319748910825E-12, 0.1483226506162133E-12, 0.7478364459856081E+00, 0.0000000000000000E+00, 0.1833026745951331E+02, 0.1833026745951330E+02, 0.1060000000000000E+03, 0.3281179138321995E+01, 0.4716981132075472E+01, 0.1032982741787823E-11, 0.4533452491188792E+00, 0.1306947070833229E-13, 0.7648022419924529E-11, 0.9563864191611805E-11, 0.4218888103472739E+00, 0.2958228394578794E-30, 0.1901963755802408E-10, 0.2450915092704452E-10, 0.2727838365998446E+00, 0.2459678163240430E-25, 0.5533379126041796E-09, 0.3623624255644135E-09, 0.2511907405802137E+00, 0.1890110728909544E-26, 0.3358805149198491E-08, 0.5375184613165106E-08, 0.9874721307137806E-01, 0.5174927538249837E-27, 0.5300164302540724E-07, 0.8261446474891677E-07, 0.7639943902083833E-01, 0.5686866711287438E-23, 0.3075058441398368E-06, 0.1980286028193141E-06, 0.4105860224136690E-01, 0.3391723239215845E-21, 0.3233943307567427E-08, 0.7908141105983331E-09, 0.2835039177122555E-01, 0.0000000000000000E+00, 0.6263230510933575E-04, 0.3843833760247782E-04, 0.1849635761425839E-05, 0.1263270231490984E-18, 0.3749684628997549E-02, 0.9345197933294263E-02}, + info: 0, + }, + { + z: []float64{0.7197398584131909E+00, 0.8353840049537183E+00, 0.7768334206137515E+00, 0.5378835466874095E+00, 0.6112887154160760E+00, 0.6941229566444685E+00, 0.6006831303610110E+00, 0.9634869426512738E-01, 0.5491965547787625E+00, 0.2928965321959978E+00, 0.2058564636772363E+00, 0.8430652032339261E+00, 0.6514967955084195E+00, 0.9630832188959448E+00, 0.6099558369768557E+00, 0.4038812997556026E+00, 0.1286146012481256E+00, 0.1377932216741019E+00, 0.2151249629422850E+00, 0.5230096632076910E+00, 0.7097266420339532E+00, 0.5223889086485353E+00, 0.1844557902493219E+00, 0.8630886970819189E+00, 0.3143018526841452E+00, 0.3064747008129198E-02, 0.9995777893655772E+00, 0.8804003743833377E+00, 0.2437734590599224E+00, 0.5439224193002447E+00, 0.7609946860078259E+00, 0.6816222186177212E+00, 0.4213100187092527E+00, 0.5947299218072758E+00, 0.4464510683518146E+00, 0.9444991162538406E+00, 0.1663546170185037E+00, 0.9745722490509305E+00, 0.8691156687582791E-01, 0.1511122923287322E+00, 0.9099013034006386E+00, 0.2055280668016559E+00, 0.2215435147609097E+00, 0.1341458340087506E+00, 0.6974464577249216E+00, 0.9770585050570383E+00, 0.2836484389736937E-02, 0.4942205711890229E+00, 0.2476589071081227E+00, 0.9025674475802441E+00, 0.1043173067377164E+00, 0.7752297952628227E+00, 0.1045812556997563E+00, 0.6207135868564088E+00, 0.3343332589884191E+00, 0.9777410164371825E+00, 0.6919265640807399E+00, 0.8276791372331573E+00, 0.9681277631171376E+00, 0.2774385945770376E+00, 0.3660516291700039E+00, 0.1542243233614283E+00, 0.9809065840498956E+00, 0.9317468521553756E+00, 0.2342755587307467E+00, 0.1233924367977165E+00, 0.3662228319745224E+00, 0.8394462754756703E+00, 0.1257927855780998E+00, 0.9899742295380913E+00, 0.4800112259347978E+00, 0.9614338190585195E+00, 0.9605383026678687E+00, 0.7532278237974727E+00, 0.6455994058946259E+00, 0.6648840697262024E+00, 0.8792931963163917E+00, 0.7296338860815629E+00, 0.6962759488463338E+00, 0.5343477930729980E+00, 0.7488075021642351E+00, 0.8267598422017227E+00, 0.4128864062622362E-02, 0.2248794313377519E+00}, + n: 21, + zOut: []float64{0.2440396187223568E+01, 0.2429593845031884E+01, 0.2248977224883395E+01, 0.1983141106497864E+01, 0.1775047097539426E+01, 0.1685850120713433E+01, 0.1685238074648001E+01, 0.1228212776246503E+01, 0.1167582065653490E+01, 0.1163468828895948E+01, 0.9840288601088477E+00, 0.8446765744020336E+00, 0.5858419229944851E+00, 0.5828733061329966E+00, 0.4321746091262585E+00, 0.2506332278777725E+00, 0.1601952029039821E+00, 0.9519704710728188E-01, 0.5380488026634178E-01, 0.2070966044404248E-02, 0.4144953892415127E-03, 0.1577721810442024E-28, 0.2622007349295965E-13, 0.1959395597612919E-13, 0.1685238074648001E+01, 0.5298116057209151E-24, 0.4690429322435832E-13, 0.6275308499802102E-13, 0.1228212776246503E+01, 0.3786532345060857E-26, 0.6968636880972768E-12, 0.1483661956038748E-11, 0.1167582065653490E+01, 0.4135903062764930E-23, 0.1852086238235612E-10, 0.7750996975985970E-11, 0.1163468828895948E+01, 0.1171277614412583E-17, 0.1085363071939462E-09, 0.2643024434742409E-09, 0.9840288601088477E+00, 0.6878867093527223E-27, 0.2179941841968715E+02, 0.2179941841968716E+02, 0.1010000000000000E+03, 0.3140589569160998E+01, 0.4950495049504950E+01, 0.1077573597463830E-06, 0.5858419229944851E+00, 0.3627601229823987E-15, 0.8463992810044351E-06, 0.7647582718993818E-06, 0.5828733061329966E+00, 0.5798443197736525E-25, 0.5805124866712180E-06, 0.5336279095847515E-06, 0.4321746091262585E+00, 0.1164890830118439E-21, 0.3270430863981586E-06, 0.3120015969970153E-06, 0.2506332278777725E+00, 0.1344740577327136E-22, 0.6612009870063018E-06, 0.4716796838663449E-06, 0.1601952029039821E+00, 0.0000000000000000E+00, 0.1909143391170965E-04, 0.1029106625513428E-04, 0.9519704710728188E-01, 0.5127595883936577E-28, 0.3722911957200607E-04, 0.5334790194682025E-04, 0.5380488026634178E-01, 0.4916199468524512E-16, 0.8145434425645190E-04, 0.4879722252791062E-03, 0.2070966044404248E-02, 0.2051115390772406E-31, 0.1886522673573371E-02, 0.1146190938097804E-02, 0.4144953892415127E-03, 0.1134788402846185E-20, 0.5837570815253673E-02, 0.1435831510150291E-01}, + info: 0, + }, + { + z: []float64{0.4141124863190200E+00, 0.6286592513493726E+00, 0.4875442526190354E-01, 0.6631999174821102E+00, 0.1778328741285358E+00, 0.5820997881750413E+00, 0.9610329112936564E+00, 0.2860180457593013E+00, 0.2800413372286658E+00, 0.8782990052007664E+00, 0.6769848820880126E+00, 0.2361981145928655E+00, 0.1864129841856804E+00, 0.6207802268756868E-01, 0.1668832170172669E+00, 0.2136536864861034E+00, 0.4266698341219798E+00, 0.9672331991204097E-01, 0.2350195655513042E+00, 0.1297162551474343E+00, 0.9428942697229301E+00, 0.3355426683568981E+00, 0.6977568272344947E-01, 0.4926170514192555E+00, 0.6966571762613959E+00, 0.7422949877167778E+00, 0.1216493993328296E+00, 0.5414775352707472E+00, 0.4507250901570525E+00, 0.6851601412475350E+00, 0.8339584749808495E+00, 0.9321374665508209E+00, 0.7664819871766777E+00, 0.5935455015911359E+00, 0.4047285985374618E+00, 0.9996987445838635E+00, 0.1347158425141065E+00, 0.3601395592420920E+00, 0.1128763847009464E+00, 0.6316809196633902E+00, 0.1559195263655234E+00, 0.4041853050912981E+00, 0.1854167847278504E+00, 0.6852913644854558E+00, 0.6126092157077416E+00, 0.2444516268314137E+00, 0.1447238269517732E+00, 0.7179956614587130E+00, 0.8198652148251639E+00, 0.1186997025611126E+00, 0.1267596520196094E+00, 0.2863431547875360E+00, 0.9867539057590858E+00, 0.2454746550565152E+00, 0.4891318294681372E+00, 0.2969454310391295E-01, 0.2349636207332649E+00, 0.4537731552146703E+00, 0.2883801124165087E+00, 0.7150664117598651E+00, 0.4359050919721921E+00, 0.6116081525473241E+00, 0.5619840590438748E+00, 0.3431726287099235E+00, 0.7715898362788249E+00, 0.4981359837313185E+00, 0.4537925078699018E+00, 0.6956466175473529E+00, 0.1814680828887681E+00, 0.4413903687143481E+00, 0.4367593306147978E+00, 0.5875066776157845E-01, 0.3688522862246468E+00, 0.4308468783440871E+00, 0.1986553761412286E+00, 0.3949957841484223E+00, 0.2468986938324821E+00, 0.6216444107315144E-01, 0.9076510210089642E+00, 0.5197394332656491E+00, 0.8460559187475114E-01, 0.3959477165848089E+00, 0.1014864219123556E+00, 0.4789226780612066E-01}, + n: 21, + zOut: []float64{0.2746085040517442E+01, 0.2006646947029628E+01, 0.1843368381126182E+01, 0.1738309804669461E+01, 0.1678478075610122E+01, 0.1408432532104903E+01, 0.1219097982435216E+01, 0.1121569511965291E+01, 0.9315294884679637E+00, 0.7914377647612258E+00, 0.7334412101899261E+00, 0.6113376828240070E+00, 0.4134386595159317E+00, 0.3303980566325673E+00, 0.2866331058299493E+00, 0.2287206720574312E+00, 0.1408981800627584E+00, 0.6649497607659796E-01, 0.5733628497886722E-01, 0.1387598234001070E-02, 0.2497701489633820E-04, 0.3487740233155725E-22, 0.3361270559917294E-05, 0.1214091727263821E-05, 0.1219097982435216E+01, 0.2843433355651033E-23, 0.3877657623657789E-06, 0.2861458561047538E-06, 0.1121569511965291E+01, 0.1501849799666580E-22, 0.7980776610337536E-07, 0.1296132789777516E-06, 0.9315294884679637E+00, 0.1397279453391396E-14, 0.3797866386428551E-06, 0.5462183171930727E-06, 0.7914377647612258E+00, 0.1231982124821006E-21, 0.6463973892160826E-06, 0.4555968092429713E-06, 0.7334412101899261E+00, 0.9423416829408119E-25, 0.1835506693210437E+02, 0.1835506693210436E+02, 0.9800000000000000E+02, 0.2884353741496599E+01, 0.2040816326530612E+01, 0.6355562713716383E-07, 0.4134386595159317E+00, 0.4284860196510039E-21, 0.4931868922851139E-05, 0.2760082849901006E-05, 0.3303980566325673E+00, 0.1448288531514775E-16, 0.4631299886341806E-05, 0.9149811670123540E-05, 0.2866331058299493E+00, 0.1558000287811498E-28, 0.1337090019087612E-05, 0.8008074996380075E-06, 0.2287206720574312E+00, 0.2366582715663035E-29, 0.4303808308110317E-06, 0.3181248709867330E-06, 0.1408981800627584E+00, 0.2443697032165075E-19, 0.2973006759321362E-05, 0.5017304713868616E-05, 0.6649497607659796E-01, 0.1131941655598205E-16, 0.8328041136745409E-04, 0.8552508571764750E-04, 0.5733628497886722E-01, 0.9398173280441046E-25, 0.5097763200650848E-04, 0.5644224660768206E-04, 0.1387598234001070E-02, 0.8888394955180400E-22, 0.1868721561136477E-03, 0.1091351925463373E-03, 0.2497701489633820E-04, 0.0000000000000000E+00, 0.1020791029288490E-01, 0.2791888375404797E-02}, + info: 0, + }, + { + z: []float64{0.2396228092919251E+00, 0.6434601049058037E+00, 0.5488667726527494E+00, 0.1843504645657519E+00, 0.4269001369847240E+00, 0.6276093013166625E+00, 0.8724336393628729E-01, 0.5371039952903035E+00, 0.8447460457667564E+00, 0.4094766929502263E+00, 0.2031514124499976E+00, 0.8271428312997948E+00, 0.9658284302973903E+00, 0.3777353969048113E+00, 0.6471334022587341E+00, 0.6777435175679861E+00, 0.4456890557292859E+00, 0.1720826572683752E+00, 0.3520207432901141E+00, 0.3291396508341311E+00, 0.7468262262373744E+00, 0.2715104496960554E+00, 0.5612917863396235E+00, 0.1324429469286776E+00, 0.7983766064014711E+00, 0.2059599586019641E+00, 0.2655510256425775E-01, 0.1962390264484870E+00, 0.7845246896371560E-02, 0.8217737559711210E+00, 0.9444498218704492E+00, 0.4679957695831033E+00, 0.1135918053039552E+00, 0.1604948252571132E+00, 0.8452381101613837E+00, 0.8537070814716049E+00, 0.3013932596816266E+00, 0.2511715406702125E+00, 0.2008647638036438E+00, 0.2607897573444329E+00, 0.2571050910078490E+00, 0.6286174024463315E+00, 0.4739701849723611E+00, 0.8698947534844018E+00, 0.6486079589595961E+00, 0.8894321904301987E+00, 0.7952475840185558E+00, 0.8801661721215410E+00, 0.2147272194381030E+00, 0.9518356646476019E+00, 0.7191152289414877E+00, 0.1106524971173308E+00, 0.9574587230734148E+00, 0.6469474230679395E+00, 0.5818260757443584E+00, 0.1292202837075540E-01, 0.2761722913438078E+00, 0.8004535925585585E+00, 0.3278973855590038E+00, 0.5794037438664289E+00, 0.2396155443104175E-01, 0.6699048475753794E+00, 0.1814492937128086E+00, 0.2866184936222242E+00, 0.6584557212506269E+00, 0.5889651227775431E+00, 0.6369766519060738E-01, 0.1328193529598596E+00, 0.7416631417262871E+00, 0.5003318278706693E+00, 0.3144077296395376E-01, 0.9907393156403193E+00, 0.3423696594914594E-02, 0.6992922072850826E+00, 0.7590519617064543E+00, 0.2542182514116359E+00, 0.3314657184555089E+00, 0.5728659684019645E+00, 0.9915854796414423E+00, 0.4896749730105238E+00, 0.5611369720796141E+00, 0.6064142215043516E+00, 0.8567590164766914E-01, 0.2581731932678185E+00}, + n: 21, + zOut: []float64{0.2319327880258489E+01, 0.2079713994229665E+01, 0.1953873370330741E+01, 0.1755147049127663E+01, 0.1569664109844580E+01, 0.1497177879850755E+01, 0.1442939549198070E+01, 0.1142654640257259E+01, 0.1037259380018118E+01, 0.7336163063097807E+00, 0.6300572204242147E+00, 0.3966542874116493E+00, 0.3925821156107781E+00, 0.2721798695257625E+00, 0.2365431978248397E+00, 0.2044065204974935E+00, 0.1570073942488483E+00, 0.8918832674569614E-01, 0.5938710196407761E-01, 0.3241742658191688E-02, 0.4778146591607052E-04, 0.1325286320771300E-27, 0.1485620696270319E-14, 0.4653485276256090E-14, 0.1442939549198070E+01, 0.1846131417899111E-22, 0.1162592678154001E-11, 0.3263011919854044E-11, 0.1142654640257259E+01, 0.4412642697382792E-11, 0.1735169830505648E-08, 0.3333560963091213E-08, 0.1037259380018118E+01, 0.1055565179678919E-18, 0.1940309609380032E-07, 0.3465529731850831E-07, 0.7336163063097807E+00, 0.4440642298320086E-11, 0.3810071749579748E-06, 0.5916980508399715E-06, 0.6300572204242147E+00, 0.4658681208910640E-20, 0.1797266971780259E+02, 0.1797266971780259E+02, 0.1110000000000000E+03, 0.3253968253968254E+01, 0.3603603603603604E+01, 0.2492194730770069E-13, 0.3925821156107781E+00, 0.0000000000000000E+00, 0.7667233942003248E-12, 0.2416678934089916E-12, 0.2721798695257625E+00, 0.2051915459060795E-16, 0.1487877135020801E-08, 0.6143545671036994E-08, 0.2365431978248397E+00, 0.1972152263052530E-29, 0.1960096418178738E-05, 0.2274829676605902E-05, 0.2044065204974935E+00, 0.2021903259098794E-21, 0.8745843979356665E-06, 0.9251106153042376E-06, 0.1570073942488483E+00, 0.5482898835648120E-25, 0.7118492322907369E-04, 0.3316595178521346E-03, 0.8918832674569614E-01, 0.1022725463125710E-19, 0.2167108979032774E-02, 0.1228336641518804E-02, 0.5938710196407761E-01, 0.1994240368398718E-26, 0.2711464061500906E-02, 0.2561834534417173E-02, 0.3241742658191688E-02, 0.1814380082008327E-27, 0.4237092909216320E-02, 0.4420407214578293E-02, 0.4778146591607052E-04, 0.2596519942803954E-20, 0.1820843269063370E-02, 0.8929397931439835E-02}, + info: 0, + }, + { + z: []float64{0.4704013808869884E+00, 0.8133248937317098E+00, 0.7246209022332254E+00, 0.9930301346620946E+00, 0.6565279241713462E-01, 0.7480498761899035E-01, 0.8311943018468732E+00, 0.4127487814312358E+00, 0.6620288516904083E+00, 0.2540390589975015E+00, 0.4830377447593585E+00, 0.6124023244542695E+00, 0.6830062885714996E+00, 0.4006497306883100E+00, 0.2108017907398356E+00, 0.9099126499549155E+00, 0.4756780627224959E+00, 0.8563186613679700E+00, 0.9168447467108382E+00, 0.5153963449488133E+00, 0.7188966629304918E+00, 0.2875525393671987E+00, 0.6200986280097742E-01, 0.3765186242141257E+00, 0.2589923271177115E+00, 0.5404093081826918E+00, 0.5343437371907505E+00, 0.3104227497255196E-01, 0.4221838478889377E+00, 0.4233113354732956E+00, 0.6486058235731677E+00, 0.1590032665029245E+00, 0.3877113621801469E+00, 0.6038849620024899E+00, 0.5400341407425849E+00, 0.7060013907006117E+00, 0.1173345165878200E+00, 0.8548311704210352E+00, 0.5804532700087333E+00, 0.5231399784962363E+00, 0.4754841524148748E+00, 0.3395282932287647E-01, 0.7668594432348432E+00, 0.8184682560752043E+00, 0.5633264054575460E-01, 0.2127176392631261E+00, 0.7432372685121402E+00, 0.3098453278874418E+00, 0.1150335122169536E+00, 0.8681635561145716E+00, 0.3593935949259885E+00, 0.9085822737263088E+00, 0.2122810259380176E+00, 0.3589456483065394E+00, 0.9437026007300053E-01, 0.6518875210051764E+00, 0.9046367728621729E+00, 0.7638617707854546E+00, 0.8924521343092110E+00, 0.8353112965912926E+00, 0.5076189975461921E+00, 0.4955137299922637E+00, 0.5041148053921253E+00, 0.7686114107944846E+00, 0.3833696141187980E+00, 0.9181102072361824E-01, 0.9260679284685853E+00, 0.7081687340916837E+00, 0.8312629527805896E+00, 0.8010881636433624E+00, 0.5891143654107377E+00, 0.8149927954305255E+00, 0.7192672792238343E+00, 0.9981622901025261E+00, 0.9368513325443091E+00, 0.6909941993236977E+00, 0.7208744872845105E+00, 0.6334330703247726E+00, 0.8856108044732016E+00, 0.7612967011342276E+00, 0.6840498257884192E+00, 0.8627400929877541E+00, 0.2970500386847904E+00, 0.9828991929119790E+00}, + n: 21, + zOut: []float64{0.2548749189884266E+01, 0.2318283655447516E+01, 0.1949991272828373E+01, 0.1903113092077109E+01, 0.1681173723989745E+01, 0.1621144658162279E+01, 0.1435953736019784E+01, 0.1373215273744876E+01, 0.1276544145324249E+01, 0.8508650942792525E+00, 0.7433578075251207E+00, 0.7333566617981635E+00, 0.6327824956484905E+00, 0.5146506379994326E+00, 0.4497218333883862E+00, 0.2736876649003249E+00, 0.2262999758546705E+00, 0.6320618886076086E-01, 0.1413547856395308E-01, 0.6182735080657475E-02, 0.1223662826415605E-02, 0.9844984097158227E-26, 0.2664250906052687E-13, 0.8143635875649387E-14, 0.1435953736019784E+01, 0.7237830359838992E-24, 0.1147364015889613E-09, 0.4819137169184198E-10, 0.1373215273744876E+01, 0.5490471900338242E-27, 0.1654936529088367E-07, 0.7460880307437913E-08, 0.1276544145324249E+01, 0.2958228394578794E-30, 0.1455672577071588E-05, 0.7169454013791148E-06, 0.8508650942792525E+00, 0.4041314959719700E-19, 0.1917383253612269E-05, 0.1657209462004936E-05, 0.7433578075251207E+00, 0.2357464745776125E-22, 0.2061763898420382E+02, 0.2061763898420383E+02, 0.9600000000000000E+02, 0.2888888888888889E+01, 0.3125000000000000E+01, 0.6718966036888534E-06, 0.6327824956484905E+00, 0.1006441314168352E-20, 0.4252254757420258E-06, 0.3750418335727261E-06, 0.5146506379994326E+00, 0.1125208173090593E-20, 0.1634173128014842E-06, 0.1777130114194832E-06, 0.4497218333883862E+00, 0.1397861524051633E-26, 0.1373153840978587E-06, 0.1424351942740530E-06, 0.2736876649003249E+00, 0.3055476705078142E-15, 0.2530372171390620E-06, 0.3073674645773779E-06, 0.2262999758546705E+00, 0.3987473575125276E-15, 0.5814400581048744E-06, 0.7370753629310487E-06, 0.6320618886076086E-01, 0.9597492304117215E-21, 0.2453687283764395E-05, 0.3193610655869065E-05, 0.1413547856395308E-01, 0.8528167491936360E-20, 0.7231103044220720E-05, 0.9769896858142881E-05, 0.6182735080657475E-02, 0.0000000000000000E+00, 0.3039337033448658E-04, 0.5367078032707280E-04, 0.1223662826415605E-02, 0.6617444900424221E-23, 0.7353916438463039E-03, 0.2144171525794732E-02}, + info: 0, + }, + { + z: []float64{0.9714680453643365E-01, 0.6357804703219754E+00, 0.6664990519488578E-01, 0.1729636879767130E+00, 0.4638342338705743E+00, 0.4390808892462035E+00, 0.8041041328438946E+00, 0.4288731182982508E+00, 0.7624625505229141E+00, 0.7083386603826051E+00, 0.2464792096944004E+00, 0.9011775040224685E+00, 0.6339539510596026E-01, 0.1795036824346197E-01, 0.9473751738931280E+00, 0.4886196718733559E+00, 0.3845982510172906E+00, 0.8175566437299375E-01, 0.4796454941504319E+00, 0.1995303497008669E+00, 0.3542217290845850E+00, 0.4313075601907782E+00, 0.9062634832132850E+00, 0.9362490171108290E+00, 0.7454458344912314E+00, 0.9678028365928690E+00, 0.8785588729275070E+00, 0.2582842558253936E+00, 0.7937433110799214E+00, 0.7912406502001545E-01, 0.1813501620770241E-01, 0.3340784700607168E+00, 0.3348119644971841E+00, 0.5042866134297835E+00, 0.3808798817625770E+00, 0.8932448815066745E+00, 0.2612469692343123E+00, 0.4943911382967600E+00, 0.7396437014435053E+00, 0.6180267747680381E+00, 0.6768529193184074E+00, 0.7346572400466492E+00, 0.8658232798365260E+00, 0.6590888814314796E+00, 0.9020629495832085E+00, 0.2719526227756762E+00, 0.9337960905099231E+00, 0.1402012445044727E+00, 0.3363383773836534E+00, 0.4741712787560632E+00, 0.1270352327896518E-02, 0.2317652069389444E+00, 0.9583986396877475E+00, 0.8857657675309066E+00, 0.5564654172742324E+00, 0.3373121694331064E+00, 0.1866413892025005E+00, 0.3829716065530064E+00, 0.6660176769447556E+00, 0.9140619394089379E+00, 0.4126532961354976E+00, 0.9883322088463480E+00, 0.1678362296131076E+00, 0.1246866166129172E+00, 0.5083959276848560E+00, 0.4743484764552197E+00, 0.1561141239638767E+00, 0.4867628897662705E+00, 0.8068909470080686E+00, 0.9878597697456749E+00, 0.8535449450676436E-01, 0.9609706407601909E+00, 0.7015171470525342E+00, 0.4808513401395343E+00, 0.4421870922261545E+00, 0.2476919441028158E-01, 0.2417065613871903E+00, 0.1174043678151601E+00, 0.4259626380136439E-02, 0.2614829171642307E+00, 0.5973781466265196E+00, 0.3195524674053074E-01, 0.4778949570977242E+00, 0.2741401812748340E+00}, + n: 21, + zOut: []float64{0.2956562879292357E+01, 0.2160920112738185E+01, 0.2057048821491083E+01, 0.1826665062315388E+01, 0.1626476426276149E+01, 0.1617659828407750E+01, 0.1458559932420392E+01, 0.1037845007643388E+01, 0.9436387491729998E+00, 0.8889042931978449E+00, 0.8147110102488896E+00, 0.7938854029224469E+00, 0.5240642869032099E+00, 0.4281570616174346E+00, 0.4032231719469492E+00, 0.2134769254146812E+00, 0.1570954054223686E+00, 0.5771888278451791E-01, 0.2771650645038780E-01, 0.1168397530048623E-02, 0.8626671344136174E-03, 0.6837796509826355E-18, 0.5416843762303492E-12, 0.3045298824248355E-12, 0.1458559932420392E+01, 0.8473754517266856E-24, 0.4783112378014045E-11, 0.8163747631331082E-11, 0.1037845007643388E+01, 0.8077935669463161E-27, 0.2442833758035109E-10, 0.3576901446935589E-10, 0.9436387491729998E+00, 0.1292469707114106E-25, 0.1060154010453575E-09, 0.7148292157772074E-10, 0.8889042931978449E+00, 0.5995342879679690E-28, 0.2265830666026058E-09, 0.3413067902462323E-09, 0.8147110102488896E+00, 0.6874131484520357E-19, 0.1999636083133089E+02, 0.1999636083133089E+02, 0.1000000000000000E+03, 0.3002267573696145E+01, 0.2000000000000000E+01, 0.2441378744031031E-06, 0.5240642869032099E+00, 0.2169367489357782E-29, 0.9564347597274963E-06, 0.8629398155870994E-06, 0.4281570616174346E+00, 0.1533177238774536E-16, 0.2198723423439569E-05, 0.1852641299824983E-05, 0.4032231719469492E+00, 0.1742814620686677E-24, 0.6898774546312495E-05, 0.1242988026413374E-04, 0.2134769254146812E+00, 0.1303198215425112E-25, 0.3054946518379762E-04, 0.2458010895625246E-04, 0.1570954054223686E+00, 0.2480178686014861E-25, 0.5573684427056079E-04, 0.2879079609909993E-04, 0.5771888278451791E-01, 0.0000000000000000E+00, 0.4895501114079361E-04, 0.6615663653270374E-04, 0.2771650645038780E-01, 0.6559433690090112E-18, 0.2090848897194263E-03, 0.3843856621792604E-03, 0.1168397530048623E-02, 0.0000000000000000E+00, 0.2396113765895983E-02, 0.4353699886144585E-02, 0.8626671344136174E-03, 0.1420984816841217E-20, 0.3572874909786609E-04, 0.2591037812233495E-05}, + info: 0, + }, + { + z: []float64{0.7761482897976135E-01, 0.7690133527529974E-01, 0.8589697242168557E+00, 0.5718901484414876E+00, 0.8450349347421171E-01, 0.5688250545090190E+00, 0.6202247495663940E+00, 0.7388100008042665E+00, 0.9890328265375476E+00, 0.2969659976080158E+00, 0.5442392738534707E-01, 0.9562602329262000E+00, 0.8530135563879812E+00, 0.5471012261519459E-01, 0.9710076793297340E+00, 0.4869447961696205E+00, 0.4659851368281548E+00, 0.7647605444900396E-01, 0.7872766307526106E+00, 0.3237029299700311E+00, 0.7194522935712468E+00, 0.7270865543961295E+00, 0.5183429612108851E+00, 0.3145688411100903E+00, 0.9096514649777033E+00, 0.7816253592835525E+00, 0.4809049584349555E+00, 0.2052154618933422E-01, 0.1481963756328628E+00, 0.8742358520807045E+00, 0.4565878430880338E+00, 0.1977913919695908E+00, 0.6526813957349178E+00, 0.8032154703264597E+00, 0.2356108621359847E+00, 0.4857415898450358E+00, 0.2259727396620309E+00, 0.1176413330041139E+00, 0.8335507369731385E+00, 0.4539477133958770E+00, 0.8910876835374724E+00, 0.1559757847548392E+00, 0.1885199219441583E+00, 0.1520953639100613E+00, 0.6035948595957944E+00, 0.9286538294716984E+00, 0.9676298024186124E+00, 0.1209629819848071E+00, 0.1660874781174386E+00, 0.8622065054293394E+00, 0.7485077140876945E+00, 0.9420716698171637E+00, 0.2904751962009996E+00, 0.2180437045655230E+00, 0.6692025851955981E+00, 0.9258369042460884E+00, 0.6243742234586596E+00, 0.6760203577391158E+00, 0.2199572443863818E-02, 0.5981650670220221E+00, 0.8252506688545779E+00, 0.9433813762695346E+00, 0.5320093960532474E+00, 0.3846966829839934E+00, 0.6727780061271659E+00, 0.4937802596181958E+00, 0.1177802539787526E+00, 0.2963448754612064E-01, 0.2479547713122239E+00, 0.2694003173993550E+00, 0.8186090816580105E+00, 0.2886041049393229E-01, 0.7384561600560133E+00, 0.8345282295575730E+00, 0.1740871089016751E+00, 0.7946006936544379E+00, 0.5640836203667244E+00, 0.4951346622832815E+00, 0.4981407974176422E+00, 0.2513094341381288E+00, 0.4316077257561814E+00, 0.1685190107506288E+00, 0.3264570829830372E+00, 0.1676643753771256E-01}, + n: 21, + zOut: []float64{0.2309990065237698E+01, 0.2261037149894265E+01, 0.1946075797700671E+01, 0.1868880050926239E+01, 0.1838164096767709E+01, 0.1792848619787804E+01, 0.1601503570675395E+01, 0.1526383850720226E+01, 0.1395433670210245E+01, 0.1010109387319946E+01, 0.8644978203099237E+00, 0.7632668975571170E+00, 0.4552388959212355E+00, 0.4364144823342648E+00, 0.2696980874891977E+00, 0.1302983706884531E+00, 0.1278582769210706E+00, 0.7956979307866878E-01, 0.7389266586143965E-01, 0.8102308371415692E-02, 0.2690335013870282E-02, 0.5752609692135112E-13, 0.2842400234743069E-06, 0.1045980487121886E-05, 0.1601503570675395E+01, 0.1668093198756260E-18, 0.5190756964721459E-05, 0.2367180586416983E-05, 0.1526383850720226E+01, 0.1262177448353619E-27, 0.1974011051185169E-03, 0.4728862593194215E-03, 0.1395433670210245E+01, 0.2337388813815525E-19, 0.1632969150852556E-06, 0.4026698297028720E-06, 0.1010109387319946E+01, 0.3802651360818291E-21, 0.1380334146666910E-03, 0.1568641113059460E-03, 0.8644978203099237E+00, 0.2788260408793746E-19, 0.2076195419278686E+02, 0.2076195419278686E+02, 0.1070000000000000E+03, 0.3183673469387755E+01, 0.2803738317757009E+01, 0.1273578837393323E-04, 0.4552388959212355E+00, 0.1016579123433529E-20, 0.9426551662020599E-04, 0.5179870206653002E-04, 0.4364144823342648E+00, 0.7336406418555410E-28, 0.1112142557098828E-05, 0.1460057881679474E-05, 0.2696980874891977E+00, 0.8909623382378835E-18, 0.3232451044433717E-03, 0.3229988347563871E-03, 0.1302983706884531E+00, 0.0000000000000000E+00, 0.2867336104451064E-03, 0.2890982620847502E-03, 0.1278582769210706E+00, 0.6875938841518755E-23, 0.2127348925826359E-06, 0.9655734242129450E-07, 0.7956979307866878E-01, 0.3291208348307372E-17, 0.5717743824937758E-07, 0.2183606505996598E-06, 0.7389266586143965E-01, 0.7801771243763389E-24, 0.1012732311499954E-04, 0.2863554462185051E-05, 0.8102308371415692E-02, 0.5719241562852336E-29, 0.6292939995324734E-04, 0.3382281194073554E-04, 0.2690335013870282E-02, 0.4951522129891247E-25, 0.3008856418189283E-03, 0.2691027365699742E-03}, + info: 0, + }, + { + z: []float64{0.1834451937168287E+00, 0.4501020603239488E+00, 0.9673873583575473E+00, 0.2207688184907047E+00, 0.4205773270263516E+00, 0.6767264871143511E+00, 0.2493506785870784E+00, 0.7809638015955807E+00, 0.8297195492174936E+00, 0.1617611869044215E+00, 0.9206032300762146E+00, 0.1914715918877316E+00, 0.7976268296797403E+00, 0.9839522457816396E+00, 0.8841932579084628E+00, 0.6979540605797908E+00, 0.8049859576106227E+00, 0.8117504351099887E+00, 0.3842107296635322E+00, 0.6368881208030270E+00, 0.2369530469547876E+00, 0.8005533377467571E+00, 0.7105152962140180E+00, 0.5356376472112734E-02, 0.2192323464228777E+00, 0.8992715082939398E+00, 0.5988055508193698E+00, 0.4081645962203215E+00, 0.1002944447483383E+00, 0.1052431248059748E+00, 0.5730054733733171E+00, 0.2386396328544268E+00, 0.6503058109411604E+00, 0.9019164849722401E+00, 0.4702244241412763E+00, 0.5759947448793571E+00, 0.7588959717342861E+00, 0.4126392985506339E+00, 0.9987799941641187E+00, 0.5598172962702971E+00, 0.2151524348024290E+00, 0.7511708041336773E-01, 0.1539602741757972E+00, 0.4584191954304165E+00, 0.8937659116858414E+00, 0.6186897030318780E+00, 0.6386630452844105E+00, 0.9151803046984296E+00, 0.3614526997644965E+00, 0.9143967867261915E+00, 0.1523575506386343E+00, 0.9745493424336691E+00, 0.4149640117372425E+00, 0.7418302113477876E+00, 0.3041602774831942E-01, 0.4852660298208696E+00, 0.9115870107661288E+00, 0.9024516441581734E+00, 0.9201550825657324E+00, 0.5200815862126855E+00, 0.7353784634707106E+00, 0.8264932398040087E+00, 0.7035838297463828E+00, 0.6738634069153341E+00, 0.7657166064092835E-01, 0.4678396966074577E+00, 0.9927685693816569E+00, 0.5845157970225999E+00, 0.5638346985777254E+00, 0.5850492500516753E+00, 0.3856054034589584E+00, 0.8134648529141429E+00, 0.4174766661784889E+00, 0.3336151222017159E+00, 0.5355530597844248E+00, 0.9274106499154580E+00, 0.7442750408730826E+00, 0.2948331405701974E+00, 0.5696937454611060E+00, 0.3104181547964658E+00, 0.4694844160987418E+00, 0.1538578615150018E+00, 0.5969883537795497E+00, 0.3873507919637014E+00}, + n: 21, + zOut: []float64{0.2914952592069403E+01, 0.2353566179964282E+01, 0.2062119351173516E+01, 0.1965819938313762E+01, 0.1942714243081098E+01, 0.1812271492844174E+01, 0.1712144141310849E+01, 0.1666892005264074E+01, 0.1208030687686805E+01, 0.1159871012571561E+01, 0.9581193432281622E+00, 0.7738358894690665E+00, 0.7454032361827709E+00, 0.3901865930581417E+00, 0.3240765847275939E+00, 0.2173673669709887E+00, 0.1778074780703053E+00, 0.5660863840842725E-01, 0.3038731391621440E-01, 0.1466323002394464E-01, 0.7362797481955845E-02, 0.1496427221292385E-15, 0.2798385737764086E-17, 0.6348906733176861E-18, 0.1712144141310849E+01, 0.2625127144183791E-23, 0.5842516095868784E-15, 0.1699577922475928E-15, 0.1666892005264074E+01, 0.2934562567422164E-27, 0.7233314809955462E-13, 0.2286859678494404E-12, 0.1208030687686805E+01, 0.8467561517631538E-12, 0.2143114506868008E-08, 0.4305471816838367E-08, 0.1159871012571561E+01, 0.4930380657631324E-31, 0.3270528389239616E-07, 0.6410715811146478E-07, 0.9581193432281622E+00, 0.8911174733768286E-23, 0.2249420011581710E+02, 0.2249420011581710E+02, 0.1050000000000000E+03, 0.3197278911564626E+01, 0.2857142857142857E+01, 0.6896683202589802E-07, 0.7454032361827709E+00, 0.3255610023185390E-23, 0.5315428740895598E-04, 0.2875762635390457E-03, 0.3901865930581417E+00, 0.4610239445276015E-22, 0.9146669702187219E-04, 0.4183987855699404E-04, 0.3240765847275939E+00, 0.4688433862556419E-23, 0.8204008598914952E-05, 0.1523341313649621E-04, 0.2173673669709887E+00, 0.4570683409889788E-20, 0.9316307389873694E-05, 0.2741587710667867E-05, 0.1778074780703053E+00, 0.3706159570762342E-17, 0.9605798472890332E-04, 0.3099752510959849E-03, 0.5660863840842725E-01, 0.5638682600030866E-16, 0.1627758109301002E-02, 0.5977814903797443E-03, 0.3038731391621440E-01, 0.7161878634670464E-18, 0.4935537640644100E-05, 0.4281293465082162E-05, 0.1466323002394464E-01, 0.9343665470806783E-19, 0.1384059308707374E-05, 0.7139695062761456E-05, 0.7362797481955845E-02, 0.1252221392641006E-22, 0.1398979151771859E-02, 0.1830558814226920E-02}, + info: 0, + }, + { + z: []float64{0.1901253435444810E+00, 0.1005117877448146E+00, 0.7431497892893435E-02, 0.4180244733822649E+00, 0.5723993917742813E+00, 0.5092276894610764E+00, 0.6914570054828403E+00, 0.6343440208263138E+00, 0.9714240100252226E+00, 0.9708780190932921E+00, 0.7346948492781401E+00, 0.9261658900466149E+00, 0.6500321763704298E-01, 0.2101988980308164E+00, 0.2569765082490436E+00, 0.6872855071573251E+00, 0.7393915007490531E+00, 0.5293076476804583E+00, 0.5736721160165409E+00, 0.6249080544922647E+00, 0.1805969142240157E+00, 0.6235867578362418E+00, 0.3156395994838945E+00, 0.6768110107418109E+00, 0.5036038244498190E+00, 0.2096885591435443E+00, 0.2471056170621776E+00, 0.4420201221816504E+00, 0.5954916898507195E+00, 0.6849385183400085E+00, 0.6865376402638398E+00, 0.5015659601935997E+00, 0.9646916309223035E+00, 0.1976274617660123E+00, 0.6173831761654865E+00, 0.9161785290588952E+00, 0.8303766381148641E+00, 0.4163407208236638E+00, 0.2406183750735502E-01, 0.9033217043220854E+00, 0.3435327703530300E-01, 0.4851293431546745E+00, 0.1308952665690980E+00, 0.1639949900839996E+00, 0.6530528840204755E+00, 0.4007776795656349E+00, 0.6520732821596675E-01, 0.2482448577499247E+00, 0.6417548063561368E+00, 0.6287927677318972E+00, 0.2491821746122613E+00, 0.1309766085785375E+00, 0.1799023200797401E+00, 0.6166520678731939E+00, 0.4068347418426869E+00, 0.8022499378251485E+00, 0.2090643045880468E+00, 0.9552039287477454E-01, 0.3405285833145572E+00, 0.9010017729234689E+00, 0.8087026571264999E-01, 0.6784547103017031E+00, 0.5001579210546183E+00, 0.9044563563261202E+00, 0.6248337185292430E-01, 0.7231216956646513E+00, 0.3330924448715603E+00, 0.5906941805835393E+00, 0.6144619726434308E-01, 0.4494963607638514E-01, 0.5817524116985039E+00, 0.4323943825883398E+00, 0.9871518362913079E-01, 0.9577530955877981E+00, 0.7720928198042669E+00, 0.1473259710759589E+00, 0.7227644962870149E+00, 0.9964485210410867E+00, 0.3235582385765219E+00, 0.5984954533580267E-01, 0.1531719633524309E-01, 0.8969070444410814E+00, 0.8320043732823273E+00, 0.7541623800831910E+00}, + n: 21, + zOut: []float64{0.2943190889471759E+01, 0.2404733889291933E+01, 0.2164120218254414E+01, 0.2101040443717650E+01, 0.1828309865967689E+01, 0.1647179310188885E+01, 0.1393092850251358E+01, 0.1217421086377993E+01, 0.1157068329170861E+01, 0.9693609911235493E+00, 0.7556225164779018E+00, 0.6051010122910800E+00, 0.5244111548905432E+00, 0.4204021043595824E+00, 0.3294230503008973E+00, 0.2905705444026201E+00, 0.1318042053167392E+00, 0.6748792703931331E-01, 0.3115549452672914E-01, 0.3850968595106850E-02, 0.1766035472385010E-05, 0.2996366283941816E-12, 0.8018633237482923E-17, 0.2249911398990393E-16, 0.1393092850251358E+01, 0.8588781736260544E-19, 0.1768526861021460E-14, 0.8068659675231548E-15, 0.1217421086377993E+01, 0.2465190328815662E-30, 0.6841595655394777E-14, 0.1344694857995563E-13, 0.1157068329170861E+01, 0.2714422906896024E-19, 0.9771202940807984E-13, 0.1895423136689650E-12, 0.9693609911235493E+00, 0.1093011646009194E-15, 0.5148224565067754E-11, 0.9904113235317579E-11, 0.7556225164779018E+00, 0.6752649348691861E-27, 0.2098534861805207E+02, 0.2098534861805208E+02, 0.9600000000000000E+02, 0.2832199546485261E+01, 0.2083333333333333E+01, 0.3437245789676428E-09, 0.5244111548905432E+00, 0.2665011951551765E-23, 0.6566411319039389E-08, 0.3635282930812000E-08, 0.4204021043595824E+00, 0.1249353725478346E-22, 0.6690013285699780E-07, 0.1185995569029548E-06, 0.3294230503008973E+00, 0.3250106929510569E-26, 0.6264577969246473E-06, 0.1086745069147475E-05, 0.2905705444026201E+00, 0.1121066009627684E-24, 0.5553814969713904E-05, 0.9554866377781883E-05, 0.1318042053167392E+00, 0.1875595688253478E-25, 0.3215548179944659E-03, 0.4036498498040293E-03, 0.6748792703931331E-01, 0.4043956767801041E-20, 0.1191830515693705E-02, 0.1851908589351717E-02, 0.3115549452672914E-01, 0.1124126789939942E-28, 0.7898349055483677E-03, 0.3617649115749287E-02, 0.3850968595106850E-02, 0.4455486392688275E-26, 0.3971779475237804E-01, 0.1814591379891354E-01, 0.1766035472385010E-05, 0.2780981219403279E-20, 0.1014029004767683E-01, 0.8718057102094371E-02}, + info: 0, + }, + { + z: []float64{0.3437994630115073E+00, 0.2969584004763312E+00, 0.5428789456218400E+00, 0.3643219910857877E+00, 0.8842011736515154E-01, 0.4426793535323088E+00, 0.9851327949196382E+00, 0.9928836193844874E+00, 0.9294888334528270E+00, 0.5131906939013953E+00, 0.8372743749579292E-01, 0.3799113781856175E+00, 0.9980979619320958E+00, 0.1940068951405882E+00, 0.1265916571930514E+00, 0.7533120158726621E+00, 0.7604310151358937E+00, 0.9521608240404056E-01, 0.6048411980078113E+00, 0.8887307551694945E-01, 0.9109406880842844E+00, 0.9457532858494480E+00, 0.7192031611135805E+00, 0.5051759890546635E+00, 0.1927673350758418E+00, 0.6784576615085791E+00, 0.4582307655806892E+00, 0.4110913566635671E+00, 0.5843861752552199E+00, 0.1849014446101248E+00, 0.5286425989283670E+00, 0.9425316584065953E+00, 0.9757360470900053E+00, 0.4697986765545260E+00, 0.5423082602059015E-01, 0.4516134263086808E+00, 0.2022962345269688E+00, 0.4899666677522230E-01, 0.9657583521001409E+00, 0.7147044884479304E+00, 0.8698989147298346E+00, 0.1620630683580001E+00, 0.4917083507892124E+00, 0.6587971895356357E+00, 0.2830046270176211E+00, 0.8907428232631098E-01, 0.3385480253038764E-01, 0.3808208973559474E+00, 0.6301790073720519E+00, 0.7283330529106518E+00, 0.8754045015579843E+00, 0.5691786300850922E+00, 0.2221459247333947E+00, 0.3807253530058278E+00, 0.5099681617674874E+00, 0.8815981352292609E+00, 0.2670679959789202E-02, 0.3061419069919761E+00, 0.9088634553510815E+00, 0.3137439308670030E+00, 0.3256630871489109E+00, 0.7397175549546020E-01, 0.8600700672393357E+00, 0.2944165267259768E-01, 0.1962740610392520E+00, 0.7223088666910011E+00, 0.1555262415199788E+00, 0.7683934132272936E+00, 0.9837306979871404E+00, 0.4307236017454147E+00, 0.2763099157748476E+00, 0.5623054633156477E-01, 0.1414438705425911E+00, 0.3910643421231946E+00, 0.3414855836828583E+00, 0.4833767934540261E+00, 0.1874948602631823E+00, 0.6456680649630069E+00, 0.5377739930676261E+00, 0.4911199998049517E+00, 0.3925147326457343E+00, 0.1205990368593943E+00, 0.6208170182205421E+00, 0.4308681300066786E+00}, + n: 21, + zOut: []float64{0.2838978926644850E+01, 0.2478331275466363E+01, 0.2456585262660691E+01, 0.2180185738821122E+01, 0.1712066680562540E+01, 0.1602701074250422E+01, 0.1503969746560551E+01, 0.1233768461187729E+01, 0.9787455830966086E+00, 0.9668289373592873E+00, 0.7729605529095109E+00, 0.7035556930615693E+00, 0.5295938697567051E+00, 0.4165425267136870E+00, 0.3781386605204551E+00, 0.3701077812928417E+00, 0.1575477292510020E+00, 0.7328369731218511E-01, 0.3974472017556452E-01, 0.4256064253578745E-02, 0.1985700463370783E-02, 0.0000000000000000E+00, 0.2182718854229073E-04, 0.3091215918753839E-04, 0.1503969746560551E+01, 0.7889046064910921E-15, 0.8525655623819580E-10, 0.5987167574554257E-09, 0.1233768461187729E+01, 0.1850899338648654E-19, 0.6965867087478826E-06, 0.6532556049979120E-06, 0.9787455830966086E+00, 0.3101927297073854E-24, 0.3608646891594891E-06, 0.2907657476508735E-06, 0.9668289373592873E+00, 0.5936688180990121E-20, 0.1421522625242826E-07, 0.7063390122609291E-08, 0.7729605529095109E+00, 0.1231338578304599E-17, 0.2139987868232064E+02, 0.2139987868232063E+02, 0.9600000000000000E+02, 0.2854875283446712E+01, 0.2083333333333333E+01, 0.2575545978160743E-06, 0.5295938697567051E+00, 0.8537368260663878E-24, 0.6647760383095535E-05, 0.6726768703723720E-05, 0.4165425267136870E+00, 0.5898327163094257E-18, 0.6007815560144262E-05, 0.6070984870789135E-05, 0.3781386605204551E+00, 0.1932242212135588E-23, 0.5780348596252855E-05, 0.5727260717649887E-05, 0.3701077812928417E+00, 0.2291245128765917E-16, 0.5589406660782675E-05, 0.5617175435749363E-05, 0.1575477292510020E+00, 0.3855952104720306E-26, 0.8404567502440466E-05, 0.1060626986994499E-04, 0.7328369731218511E-01, 0.1176980470589750E-26, 0.3402042835087641E-05, 0.5518338211116594E-05, 0.3974472017556452E-01, 0.3697785493223493E-30, 0.6423930978115149E-05, 0.5690659965930955E-05, 0.4256064253578745E-02, 0.1813010266067178E-20, 0.3330330670135602E-05, 0.3509207052336586E-05, 0.1985700463370783E-02, 0.9911627066431288E-23, 0.2656536456367949E-04, 0.9644853918428974E-05}, + info: 0, + }, + { + z: []float64{0.6087347824331316E+00, 0.2344592930815549E+00, 0.1839180152431182E+00, 0.8946895357068063E-01, 0.3789275576065679E+00, 0.1028144130339237E-01, 0.8432962228323871E+00, 0.5720035990048252E+00, 0.9674750777949459E+00, 0.1387850858951470E+00, 0.1049983295079311E+00, 0.1869597635484084E+00, 0.2049847474830355E+00, 0.9353902309354832E+00, 0.7711597045807418E+00, 0.6677931698783810E+00, 0.5710020050743191E+00, 0.7559352115290241E+00, 0.8799700817290574E+00, 0.2989086447618220E+00, 0.7223221852829088E+00, 0.9172044263776469E-01, 0.8222766733565161E+00, 0.4357755436106698E+00, 0.3174399370719186E+00, 0.3716323007311311E+00, 0.5710261889832198E+00, 0.5875728000816982E-01, 0.1970825867540514E+00, 0.7514821290356389E+00, 0.4768968814440278E+00, 0.1414806690779697E+00, 0.5126469713172739E+00, 0.2618595999903317E-01, 0.3414455658478163E+00, 0.7845736413672471E+00, 0.3193997824316201E+00, 0.5244207174429636E+00, 0.7114985438553419E+00, 0.6380953409710879E+00, 0.5110544105167975E+00, 0.6987353947091863E+00, 0.2359552404464268E+00, 0.1389779414569779E+00, 0.4283565484470430E+00, 0.5978343235372734E+00, 0.8941068622870674E+00, 0.9993918591572127E+00, 0.9276104816334276E+00, 0.6840640077048410E+00, 0.1906252952212643E+00, 0.3896055694019390E+00, 0.8889540838698040E-01, 0.6972017776398595E+00, 0.7403854978121883E+00, 0.9624319129844994E-01, 0.7107468555423346E-01, 0.2167351328914763E+00, 0.5250363507339506E-01, 0.3012298012035964E+00, 0.7467053513110199E+00, 0.6311877906561809E+00, 0.6465457722939830E+00, 0.9462483307457270E-01, 0.1615629644808589E+00, 0.3714392567485900E+00, 0.5909086992570731E+00, 0.2147078824711308E+00, 0.8083150503324107E+00, 0.1136496291628873E+00, 0.3556622878263437E+00, 0.1687673308056986E+00, 0.2663369573375586E+00, 0.9992292880074174E+00, 0.4743706799728067E+00, 0.3784791276003248E+00, 0.9641428139214289E+00, 0.4526980047510465E-01, 0.5291384859598749E+00, 0.9114927597067145E+00, 0.2015740390806801E+00, 0.9111109510473957E+00, 0.4797378470164849E+00, 0.4344842342843944E+00}, + n: 21, + zOut: []float64{0.2535248843080872E+01, 0.2027297538476471E+01, 0.1999341423958793E+01, 0.1905819580237666E+01, 0.1558994176508815E+01, 0.1443542425236611E+01, 0.1321312714967014E+01, 0.1044341128979687E+01, 0.9175998827905956E+00, 0.8543653487373744E+00, 0.6128068085852322E+00, 0.5723484802692980E+00, 0.4865842293721045E+00, 0.4743009418296827E+00, 0.4424121716041568E+00, 0.2157744105271115E+00, 0.1401155020588904E+00, 0.9545054691199920E-01, 0.4846378139764250E-01, 0.2597131641839770E-01, 0.9574417588705024E-02, 0.7983827718913915E-23, 0.5897957913656464E-08, 0.4905965358471980E-08, 0.1321312714967014E+01, 0.1437620113674772E-24, 0.2330664696165742E-08, 0.2036082149427908E-08, 0.1044341128979687E+01, 0.7099748146989106E-29, 0.1191493821660667E-08, 0.1294122655697948E-08, 0.9175998827905956E+00, 0.7069460558567906E-16, 0.2320495180901029E-08, 0.3242686959161780E-08, 0.8543653487373744E+00, 0.3414430154917050E-13, 0.2143028595220802E-07, 0.3181347787023606E-07, 0.6128068085852322E+00, 0.0000000000000000E+00, 0.1873166566953712E+02, 0.1873166566953712E+02, 0.1040000000000000E+03, 0.3224489795918367E+01, 0.2884615384615385E+01, 0.3533200143891392E-06, 0.4865842293721045E+00, 0.4552522969733916E-17, 0.1776353409716398E-09, 0.6419018055060889E-09, 0.4743009418296827E+00, 0.4679164786798698E-18, 0.4782181507340309E-06, 0.1264406900548246E-06, 0.4424121716041568E+00, 0.1728289684559415E-20, 0.3046857378867568E-04, 0.2182730305393890E-04, 0.2157744105271115E+00, 0.1120182485413837E-27, 0.4003877877583194E-03, 0.2588513428463001E-03, 0.1401155020588904E+00, 0.0000000000000000E+00, 0.6916990427934659E-04, 0.5501406364660823E-04, 0.9545054691199920E-01, 0.6162975822039155E-32, 0.1059944134272042E-03, 0.1421052287262650E-03, 0.4846378139764250E-01, 0.1755514705909767E-17, 0.4499204819889415E-04, 0.2567010249779503E-03, 0.2597131641839770E-01, 0.1143848312570467E-28, 0.5289175880660015E-04, 0.5437725505075631E-04, 0.9574417588705024E-02, 0.3697785493223493E-31, 0.2606391166909807E-05, 0.6294847321319143E-06}, + info: 0, + }, + { + z: []float64{0.3257261020965838E+00, 0.9499222527145429E+00, 0.3597416524070001E+00, 0.7608369220069154E+00, 0.3348964244425234E-01, 0.9918240230913730E+00, 0.2435073049094116E-01, 0.2927090414647138E-01, 0.2724578324033788E+00, 0.7486167980650003E+00, 0.2854897136111678E+00, 0.2267361867398041E+00, 0.4294380831801550E+00, 0.7722184192395405E+00, 0.5889718788171796E+00, 0.5201154937785833E+00, 0.1341644467607439E-01, 0.3251983707424297E+00, 0.3712514383296180E+00, 0.8346822920283823E+00, 0.2613611110008908E+00, 0.7377020224374462E+00, 0.4290238209924468E-01, 0.8422463567888154E+00, 0.1390406385354674E+00, 0.8899155813346852E+00, 0.5366293959824918E+00, 0.1311808378334547E+00, 0.5127829646320820E+00, 0.3806825827063995E+00, 0.9008244723505014E+00, 0.8397173164045483E+00, 0.8005434668537068E+00, 0.4188784622408616E+00, 0.4815341947551696E+00, 0.2004130034689415E+00, 0.9620560381224039E+00, 0.9936712626034268E+00, 0.7996240982628953E+00, 0.9066259300527590E+00, 0.7119745510778175E+00, 0.4009593231138309E+00, 0.7503038869147766E+00, 0.2307657656692345E+00, 0.5796381959344894E+00, 0.4564585857276309E+00, 0.3087632483431468E-01, 0.4925813444884515E+00, 0.2548189626174928E+00, 0.7548007003619551E+00, 0.2595357873879023E+00, 0.2576161595637174E+00, 0.6530834734960895E+00, 0.9659056802808288E+00, 0.4073417244577716E+00, 0.7973054858347279E+00, 0.1098542135402614E-03, 0.5270152208809449E+00, 0.9503221531609122E+00, 0.3389760481404548E+00, 0.2936463197963648E+00, 0.1532837593240226E+00, 0.7039965742744211E+00, 0.1538522429841973E+00, 0.4565500206514618E+00, 0.4890306322657354E+00, 0.7406911389536464E+00, 0.4609110724077861E+00, 0.3010957214922741E+00, 0.4706875322819619E+00, 0.9245411658881026E+00, 0.1225486958523536E-02, 0.7513538867599376E+00, 0.7480092012350148E+00, 0.1668544624863488E+00, 0.6027497133760584E+00, 0.4060848284780354E+00, 0.7777661676033926E+00, 0.5476587806685121E+00, 0.3318235867866506E+00, 0.4865355710680780E+00, 0.9789804028805801E+00, 0.6449091593541079E-01, 0.3386899175207851E+00}, + n: 21, + zOut: []float64{0.2916446272919928E+01, 0.2518523111789073E+01, 0.1881620740030630E+01, 0.1802535552376618E+01, 0.1705712498790935E+01, 0.1630934300031556E+01, 0.1493206464268041E+01, 0.1289863129801601E+01, 0.1141879970494692E+01, 0.1064939765404915E+01, 0.9148995873510519E+00, 0.6667419164223021E+00, 0.5793746811807822E+00, 0.5763823737203533E+00, 0.5577209455074719E+00, 0.2258972104173268E+00, 0.1775772659782911E+00, 0.1224839196229167E+00, 0.7643325286481288E-01, 0.1088888144792382E-01, 0.1013218159024319E-07, 0.1529626957613473E-16, 0.4760904670371191E-26, 0.1685698503770275E-25, 0.1493206464268041E+01, 0.4740164255731978E-15, 0.6203207773025231E-22, 0.1697026618649852E-21, 0.1289863129801601E+01, 0.1555744028694447E-17, 0.2220966892754199E-18, 0.8352563633635413E-19, 0.1141879970494692E+01, 0.8283039504820624E-29, 0.9137114046044313E-17, 0.2186983724354431E-16, 0.1064939765404915E+01, 0.7560947786617519E-24, 0.1476623491156538E-14, 0.6521525514986541E-15, 0.9148995873510519E+00, 0.3956572890903056E-23, 0.2135406185055340E+02, 0.2135406185055340E+02, 0.1110000000000000E+03, 0.3462585034013606E+01, 0.7207207207207207E+01, 0.3107640874581820E-11, 0.5793746811807822E+00, 0.0000000000000000E+00, 0.5611258671513064E-10, 0.1000932867794445E-09, 0.5763823737203533E+00, 0.2935229715008717E-19, 0.5869279282596528E-09, 0.3232392517855140E-09, 0.5577209455074719E+00, 0.7161080495560552E-17, 0.6771347567635994E-08, 0.1273942735381484E-07, 0.2258972104173268E+00, 0.2531843062293473E-19, 0.3233128964696781E-05, 0.1839431244951091E-05, 0.1775772659782911E+00, 0.1025519176787315E-28, 0.1632093348006395E-04, 0.1394944946706296E-04, 0.1224839196229167E+00, 0.3147671031182890E-20, 0.4090539240175316E-04, 0.3499438731982919E-04, 0.7643325286481288E-01, 0.4418024966021139E-23, 0.7751221398283570E-04, 0.6522231732461535E-04, 0.1088888144792382E-01, 0.0000000000000000E+00, 0.1168516922729128E-02, 0.6798960389683572E-03, 0.1013218159024319E-07, 0.8311253061997563E-15, 0.2266806408535672E-02, 0.8228900118596701E-02}, + info: 0, + }, + { + z: []float64{0.9013837094783728E-01, 0.4093071371456288E+00, 0.7563443593246222E-01, 0.6047712831067179E+00, 0.3616734158068488E+00, 0.3179352368154293E+00, 0.4877726790168605E+00, 0.7283754332956183E+00, 0.6564126870433257E+00, 0.7426267273836333E+00, 0.9575970808689874E+00, 0.2328163542816707E+00, 0.9804488839127946E+00, 0.5880329556580101E+00, 0.6720101508999355E+00, 0.3029641470022006E+00, 0.9176198736416905E+00, 0.9273523415722473E-01, 0.7356501689695268E+00, 0.3516482504433937E+00, 0.5613309946663773E+00, 0.8064085547776983E+00, 0.2421909924481950E+00, 0.4321291285180304E+00, 0.7195726435630079E+00, 0.4201959590716675E-01, 0.6971840239025084E-03, 0.6931587576362976E+00, 0.4512374813335629E+00, 0.9105433528826555E+00, 0.8233348499205092E+00, 0.5270028711667427E+00, 0.5092902528068642E+00, 0.6527825111058926E+00, 0.8077059946216197E+00, 0.5037249441803524E+00, 0.7474524841642615E+00, 0.8361353459662745E+00, 0.6675800963161582E+00, 0.5004244151247563E+00, 0.7976263900002633E+00, 0.1983499023889042E+00, 0.7522366994446783E+00, 0.3654861843844912E+00, 0.8247542543249066E+00, 0.9124235995852386E+00, 0.1818459043196227E+00, 0.8196813052173683E+00, 0.5538880208895494E+00, 0.9080443570480472E+00, 0.2981632101337024E+00, 0.6044133722200155E+00, 0.1883025355842233E+00, 0.2434431972046255E+00, 0.3420561860884004E+00, 0.3312086041097358E+00, 0.8261796050670067E-01, 0.2597483126975232E+00, 0.9037350022806145E+00, 0.5691251256015616E+00, 0.5433137600205407E-01, 0.2948423088781353E+00, 0.7125818959241866E+00, 0.1168360183447441E+00, 0.2271931321361120E-01, 0.5832011197836875E+00, 0.4321285977614958E+00, 0.9214755199664483E+00, 0.2929460789941122E+00, 0.9911839954873096E+00, 0.9352897353900299E+00, 0.6549195608155846E+00, 0.7733376794047198E-01, 0.7345459966842849E+00, 0.2997108680399072E+00, 0.6923968300089707E+00, 0.9895794156524929E+00, 0.2694202749089550E+00, 0.2419924375765692E-01, 0.2728256718882756E+00, 0.7688978378093437E+00, 0.6794051971520565E-01, 0.8211384369868754E+00, 0.7581877817293103E-01}, + n: 21, + zOut: []float64{0.2587082763537058E+01, 0.2518438946693926E+01, 0.2381638511714923E+01, 0.2064758819607097E+01, 0.1861546331198453E+01, 0.1823771413694203E+01, 0.1462413605342042E+01, 0.1295483717305927E+01, 0.1204792654692795E+01, 0.1153126691944095E+01, 0.9646786889507554E+00, 0.8876075724637406E+00, 0.7328920239265601E+00, 0.5128961040525114E+00, 0.4187721082034697E+00, 0.3198505150609477E+00, 0.1661143074789019E+00, 0.1249876230738883E+00, 0.5554047196429147E-01, 0.2079344839078052E-02, 0.4713171572265143E-04, 0.1874281408120013E-19, 0.2104034717604745E-09, 0.2619972849686678E-09, 0.1462413605342042E+01, 0.9259545558536950E-18, 0.2890370685025388E-10, 0.3242632456342165E-10, 0.1295483717305927E+01, 0.1323488980084844E-22, 0.2279224462592833E-10, 0.2555931367214743E-10, 0.1204792654692795E+01, 0.2978738778114541E-26, 0.7485181957332586E-10, 0.4566030880095840E-10, 0.1153126691944095E+01, 0.6733803272339514E-21, 0.2633277318950464E-08, 0.1440235383519861E-08, 0.9646786889507554E+00, 0.7499216124683276E-17, 0.2253851934746039E+02, 0.2253851934746038E+02, 0.1040000000000000E+03, 0.3111111111111111E+01, 0.5769230769230769E+01, 0.2633869415622400E-06, 0.7328920239265601E+00, 0.6980417424693642E-13, 0.1603044445805627E-06, 0.1255532606981617E-06, 0.5128961040525114E+00, 0.6981404369947554E-21, 0.8484909168369356E-07, 0.7367232980661418E-07, 0.4187721082034697E+00, 0.2465190328815662E-30, 0.1470967366725541E-06, 0.2274394647752198E-06, 0.3198505150609477E+00, 0.9424343740971753E-25, 0.8932721831570202E-05, 0.5259727349591482E-05, 0.1661143074789019E+00, 0.1697763391846713E-18, 0.4712327641645974E-05, 0.7305995006514358E-05, 0.1249876230738883E+00, 0.9266645908481002E-19, 0.3596318120009657E-04, 0.2001742175196116E-04, 0.5554047196429147E-01, 0.5985976337495067E-16, 0.4811066675748340E-03, 0.3416912105856511E-03, 0.2079344839078052E-02, 0.8697917232094458E-24, 0.5710266423841766E-02, 0.2981491759065521E-02, 0.4713171572265143E-04, 0.0000000000000000E+00, 0.3288287603570621E-02, 0.1038987759212308E-02}, + info: 0, + }, + { + z: []float64{0.3453921918700114E+00, 0.8256584009865165E+00, 0.5027306146870630E+00, 0.5014619412470180E+00, 0.9910264683396075E+00, 0.7385152238869899E+00, 0.9936695869989243E+00, 0.6206355260490602E+00, 0.6835539321104728E+00, 0.3987727521414011E+00, 0.2155721742355131E+00, 0.8212295891891395E+00, 0.7021626430853991E+00, 0.3753314442932942E+00, 0.2575710525141791E+00, 0.6551328468445583E+00, 0.3738398426943970E+00, 0.8805730558289802E+00, 0.6848909798416613E+00, 0.5520069040756137E-01, 0.8817067703079440E+00, 0.3238117712584516E+00, 0.1001825089826291E+00, 0.7369585910327309E+00, 0.7601318359400422E+00, 0.4312449588193277E+00, 0.4932891154015395E+00, 0.1099211239093930E+00, 0.5764729343614433E+00, 0.1286539516629047E+00, 0.5170000684627285E+00, 0.4006756226519864E+00, 0.5897018197291505E+00, 0.3774659871747915E+00, 0.4211183018281148E+00, 0.6260997273722376E+00, 0.7810234892670644E+00, 0.9934154489086249E+00, 0.5116204079460294E+00, 0.7948452919719275E+00, 0.5998807734230309E+00, 0.4868691071952969E-01, 0.7977221292955683E+00, 0.4907992372099745E+00, 0.4337635562764541E-01, 0.4865658084478622E+00, 0.7887982210525304E+00, 0.6218441262679077E+00, 0.1807768964120138E-01, 0.7341707407508724E+00, 0.4738048273586776E+00, 0.9324751870816922E+00, 0.4643019354540665E+00, 0.2401905271601299E+00, 0.6072757133952530E+00, 0.6257046236339610E+00, 0.1662572295885112E-01, 0.3360107439465247E+00, 0.5925152832499899E+00, 0.4206234399601897E+00, 0.1828405120649758E+00, 0.8923354266778754E+00, 0.6211472795399554E+00, 0.3215240169291051E+00, 0.3967102459115966E+00, 0.4376502563326659E+00, 0.4571232280132043E-01, 0.2973405440159681E+00, 0.1737124961451384E+00, 0.1123665207380958E+00, 0.8069742345287393E+00, 0.5302931605046994E+00, 0.2541675285808478E+00, 0.9099997182043015E+00, 0.7562530283478575E-01, 0.2521110146593245E+00, 0.2525672524245413E+00, 0.8930826245328107E+00, 0.8545394186204489E+00, 0.1856025965008533E+00, 0.8541401621096930E+00, 0.7406868214039234E+00, 0.5851270108744718E+00, 0.7554853143122133E+00}, + n: 21, + zOut: []float64{0.2818806710434786E+01, 0.2596766072486540E+01, 0.2041400548479265E+01, 0.1919012388179902E+01, 0.1900863080415201E+01, 0.1778136512482050E+01, 0.1649297429111022E+01, 0.1375943901620400E+01, 0.1287933944237744E+01, 0.1246950647018126E+01, 0.9346701076388835E+00, 0.8619836761278706E+00, 0.6928534822715838E+00, 0.5816592049742084E+00, 0.4759893592204403E+00, 0.2537953742738920E+00, 0.2205935192530503E+00, 0.8350022078832350E-01, 0.3307087507037688E-01, 0.2105652896299196E-01, 0.3857874617179747E-02, 0.9177981866196648E-17, 0.6043035417783778E-14, 0.7682115486038763E-14, 0.1649297429111022E+01, 0.9047287949798740E-23, 0.2120842457393041E-14, 0.2617862539054627E-14, 0.1375943901620400E+01, 0.1499552906513639E-17, 0.3376573256769321E-15, 0.2886563968474245E-15, 0.1287933944237744E+01, 0.1966621906344823E-17, 0.2937881411718043E-15, 0.4577311861870994E-15, 0.1246950647018126E+01, 0.2742371736879744E-17, 0.2913637797754287E-14, 0.1483948533056680E-14, 0.9346701076388835E+00, 0.5800058106323822E-18, 0.2277814145766384E+02, 0.2277814145766384E+02, 0.9800000000000000E+02, 0.2997732426303855E+01, 0.1020408163265306E+01, 0.9030119244814722E-12, 0.6928534822715838E+00, 0.1471303281095442E-16, 0.2634125396797654E-10, 0.5071585384120369E-10, 0.5816592049742084E+00, 0.1365675999118616E-25, 0.3358753759221612E-09, 0.6258446588335648E-09, 0.4759893592204403E+00, 0.1479114197289397E-30, 0.3734630956704811E-08, 0.6716634735981551E-08, 0.2537953742738920E+00, 0.7467396771867359E-25, 0.3072344915986320E-06, 0.1829961043616119E-06, 0.2205935192530503E+00, 0.4437342591868191E-30, 0.2385309167517414E-05, 0.3978543929472447E-05, 0.8350022078832350E-01, 0.2436129622029919E-19, 0.4589207629691226E-04, 0.2836221395611648E-04, 0.3307087507037688E-01, 0.3081487911019577E-32, 0.1362072635971665E-04, 0.2978962617014088E-04, 0.2105652896299196E-01, 0.2711709361697228E-30, 0.2444625596237189E-05, 0.7827983423195974E-05, 0.3857874617179747E-02, 0.8925769947935872E-20, 0.9826965253502863E-02, 0.1259209175531780E-01}, + info: 0, + }, + { + z: []float64{0.9560856702670685E+00, 0.5885863857778361E+00, 0.8071258175651005E+00, 0.5175476341605639E+00, 0.1941426739297742E+00, 0.8451490614471896E+00, 0.9052305950784733E+00, 0.6791526261185319E+00, 0.6480230038264980E+00, 0.8438040949137990E+00, 0.3034844043967853E+00, 0.3090582723248356E+00, 0.3282769832503399E+00, 0.7489751201458807E+00, 0.6672021557248126E+00, 0.1697989591956236E+00, 0.5723860504781838E+00, 0.3660621222567975E+00, 0.1505291330148173E-01, 0.7436839329892437E+00, 0.3679212455376497E+00, 0.5305714072096270E+00, 0.5792221354999488E+00, 0.3031533452885045E+00, 0.9514596930492207E+00, 0.3278419583960311E+00, 0.5742176036064726E+00, 0.7216680447710266E+00, 0.6608941225668634E+00, 0.3887216422692293E+00, 0.6952172825541724E+00, 0.8072929471269218E+00, 0.8776672848787970E-01, 0.9363773133978057E+00, 0.3470717327786855E+00, 0.9438495003134180E+00, 0.5511880105145929E+00, 0.5826637033513504E+00, 0.3416802173197317E+00, 0.5650234571673005E+00, 0.2927187699119284E+00, 0.4936451925034285E+00, 0.7496439056333554E+00, 0.8462697295115110E+00, 0.4661250827466905E+00, 0.3912590593193351E+00, 0.9140228064649625E+00, 0.4016314378444454E+00, 0.7105479239000361E+00, 0.3751330850058705E+00, 0.7309804928539319E+00, 0.1378037023247644E+00, 0.7527056268407295E+00, 0.1640478774378548E+00, 0.6030857470066908E+00, 0.7427119073248016E+00, 0.9996405952923426E-01, 0.7406467144237725E+00, 0.3762498316380406E+00, 0.8295145255291534E+00, 0.8322845800948830E-01, 0.6101670185797291E+00, 0.9451596878306588E+00, 0.1176379504958335E+00, 0.7940514845464750E+00, 0.3068100097277620E+00, 0.2371282369406802E+00, 0.2163781309135768E+00, 0.4705542393165623E+00, 0.4003463805482307E+00, 0.2731285781388088E+00, 0.8862626881898287E+00, 0.5854390777280626E+00, 0.4661955367614972E+00, 0.1993415035442425E+00, 0.9213995968359628E+00, 0.1542739762296447E+00, 0.9419076789558214E+00, 0.9611493561784724E+00, 0.7596360150269755E+00, 0.6590873675145426E+00, 0.3894853423829039E+00, 0.8407621320868611E+00, 0.4517123559923821E+00}, + n: 21, + zOut: []float64{0.2583735261373388E+01, 0.2239759728480232E+01, 0.2157858012928955E+01, 0.2146305201359927E+01, 0.1853050031878152E+01, 0.1788497392649839E+01, 0.1558387970436693E+01, 0.1494017846927041E+01, 0.1323723239351723E+01, 0.1188003233397794E+01, 0.9827022795744828E+00, 0.8335582164080391E+00, 0.7854672559750093E+00, 0.6236176061997519E+00, 0.4677974993044671E+00, 0.2968385185647548E+00, 0.2304456569541352E+00, 0.1793008998018142E+00, 0.2471364396669566E-01, 0.7537422761275628E-02, 0.3241997301555496E-04, 0.1184063810429910E-21, 0.1281976731077423E-10, 0.2849227344309828E-10, 0.1558387970436693E+01, 0.3001369155282220E-19, 0.2940080271049715E-08, 0.1685793775386140E-08, 0.1494017846927041E+01, 0.1696366490587264E-24, 0.4557030850938984E-08, 0.5166797185591864E-08, 0.1323723239351723E+01, 0.1862197338326049E-12, 0.1908610209474282E-08, 0.1816527091730617E-08, 0.1188003233397794E+01, 0.1613415991578665E-17, 0.2801618631477443E-08, 0.2177314380835442E-08, 0.9827022795744828E+00, 0.1073695634537585E-17, 0.2276534933826718E+02, 0.2276534933826718E+02, 0.1060000000000000E+03, 0.3113378684807256E+01, 0.3773584905660377E+01, 0.2107018980320373E-07, 0.7854672559750093E+00, 0.7395570986446986E-31, 0.5134101120680572E-07, 0.6949862017183880E-07, 0.6236176061997519E+00, 0.1700003115737185E-12, 0.4917011909790346E-06, 0.6444201346122313E-06, 0.4677974993044671E+00, 0.1676329423594650E-29, 0.2178752696080751E-05, 0.1697685142168825E-05, 0.2968385185647548E+00, 0.2903323170704433E-20, 0.9062193610690628E-05, 0.7062135859641892E-05, 0.2304456569541352E+00, 0.9860761315262648E-30, 0.1460945060339096E-04, 0.1904220434906198E-04, 0.1793008998018142E+00, 0.4606947686490709E-27, 0.4451684144215141E-07, 0.1728984935219646E-06, 0.2471364396669566E-01, 0.1407327854914285E-26, 0.1942342839475662E-02, 0.3052712133602924E-02, 0.7537422761275628E-02, 0.9865964111678957E-20, 0.3214451590395407E-02, 0.5215635567340069E-02, 0.3241997301555496E-04, 0.0000000000000000E+00, 0.1184307710713820E-01, 0.9427403294935964E-02}, + info: 0, + }, + { + z: []float64{0.4101594051788160E+00, 0.1002974419660251E+00, 0.8434067081152193E+00, 0.7258916354493068E+00, 0.9256853341957688E+00, 0.8379265467529036E+00, 0.1564408324797836E+00, 0.8292039738515364E+00, 0.3771190822561328E+00, 0.8236097732630416E+00, 0.3320638300046872E+00, 0.6850750205938005E-01, 0.5616647045816037E+00, 0.8305938719521835E+00, 0.6006351465721590E+00, 0.8469146468608777E+00, 0.1179160781320751E+00, 0.6975716721259332E+00, 0.3237957597653003E+00, 0.1297318227605904E-01, 0.8416519209661123E+00, 0.2623987624579764E+00, 0.3323289069826861E+00, 0.9848995259497869E+00, 0.1295798367899781E-01, 0.4196318718239949E+00, 0.8791346827157692E+00, 0.9015205418757779E+00, 0.2557984197164971E+00, 0.7295221077613672E+00, 0.8796719157178668E+00, 0.6983240767110626E+00, 0.6461186804049626E+00, 0.5003600760145155E-01, 0.3411701822058120E+00, 0.6026846298507913E+00, 0.4649210011845201E+00, 0.4169632595817018E+00, 0.9745024564197420E+00, 0.9159749674174896E+00, 0.3798779762430529E+00, 0.6757581567027395E+00, 0.1501600637708167E+00, 0.8841295845033917E+00, 0.1700642059156726E+00, 0.5745602516925833E+00, 0.7146078194346678E+00, 0.7876321314233041E+00, 0.3623958693011297E+00, 0.1316504845867333E+00, 0.6150819295249010E+00, 0.9948396700221377E+00, 0.2186788175334711E+00, 0.3433450548510013E+00, 0.4434886569716980E+00, 0.6596978167473024E+00, 0.7067569387667516E+00, 0.2710992196058543E+00, 0.2531644393448058E+00, 0.6179743389634106E+00, 0.6395694224823617E+00, 0.6233992467844496E-01, 0.9270082862838847E-01, 0.6813409948026068E+00, 0.8489230752840353E+00, 0.4248777519526148E+00, 0.9258241367507150E+00, 0.7591306919901064E-01, 0.1337231221457533E+00, 0.6673452115706187E+00, 0.3161361894802919E+00, 0.9287930266484576E+00, 0.9211411715651807E+00, 0.7110889130885073E+00, 0.6783920645346327E+00, 0.5798290672446252E+00, 0.6003988035906362E+00, 0.8338909998640337E+00, 0.1150264810560550E+00, 0.8268177524919460E+00, 0.2868686997384918E+00, 0.7734675037869032E+00, 0.8495624932870276E+00, 0.7382167415731139E+00}, + n: 21, + zOut: []float64{0.2565771617602568E+01, 0.2464815559540473E+01, 0.2377249642737961E+01, 0.2182027799722737E+01, 0.1994511663794419E+01, 0.1777930797653110E+01, 0.1532836111328556E+01, 0.1298104160091711E+01, 0.1162548328490141E+01, 0.1031426069242260E+01, 0.9067767207978197E+00, 0.7702116437984168E+00, 0.7023507576840374E+00, 0.5846573732521254E+00, 0.3836750731694669E+00, 0.3732780616075560E+00, 0.2146097506115993E+00, 0.5462411591703480E-01, 0.3208967690429450E-01, 0.2788258306628742E-02, 0.1838228532938987E-03, 0.1703684557466520E-17, 0.8886730161731292E-14, 0.1725592004801531E-13, 0.1532836111328556E+01, 0.2310659810285515E-15, 0.8778995686431983E-12, 0.1396745951735637E-11, 0.1298104160091711E+01, 0.0000000000000000E+00, 0.8497749401208094E-11, 0.5925398902948847E-11, 0.1162548328490141E+01, 0.1292469707114106E-25, 0.1515360700076446E-10, 0.2085752134421418E-10, 0.1031426069242260E+01, 0.1195331315767287E-17, 0.8898419915788489E-10, 0.1186621585503233E-09, 0.9067767207978197E+00, 0.1888339631531495E-12, 0.2241246700510621E+02, 0.2241246700510621E+02, 0.1190000000000000E+03, 0.3539682539682540E+01, 0.7563025210084033E+01, 0.2596357213906324E-08, 0.7023507576840374E+00, 0.1416275483756143E-17, 0.5106480833143134E-08, 0.6438584684288567E-08, 0.5846573732521254E+00, 0.1317619996636992E-15, 0.1896058302301025E-07, 0.2367797858508706E-07, 0.3836750731694669E+00, 0.9199951564453634E-11, 0.8967796171107713E-07, 0.1296821709728121E-06, 0.3732780616075560E+00, 0.1615587133892578E-26, 0.3088999981101691E-06, 0.2343043411729366E-06, 0.2146097506115993E+00, 0.2055968734232262E-28, 0.9134179982896841E-05, 0.6280501592969192E-05, 0.5462411591703480E-01, 0.1901142159808155E-23, 0.3768301572228235E-05, 0.8777513601148953E-05, 0.3208967690429450E-01, 0.1479114197289397E-29, 0.1428515450408294E-03, 0.5208612044311805E-04, 0.2788258306628742E-02, 0.2057124874537592E-17, 0.2063479623178836E-02, 0.3566698154744510E-02, 0.1838228532938987E-03, 0.3273772756667199E-28, 0.8538542526496483E-03, 0.1571849612061994E-03}, + info: 0, + }, + { + z: []float64{0.1589037341524596E+00, 0.1455226073481288E+00, 0.1938395273812957E+00, 0.1962691615573132E+00, 0.1687822326883440E+00, 0.6650981615477494E+00, 0.8270615916362424E+00, 0.1710502783654970E+00, 0.2206713720159043E+00, 0.4369721197399372E+00, 0.9301314325299896E+00, 0.5722466234411457E+00, 0.1135089451836189E+00, 0.5846068541971138E+00, 0.9216025315561343E+00, 0.9066267701445474E+00, 0.5584279552920539E+00, 0.4343925455049338E+00, 0.9858452060735702E+00, 0.6563046209578444E+00, 0.7077011175365495E+00, 0.4947310926689127E+00, 0.7385820400647596E+00, 0.5937728681009750E+00, 0.9762402194896037E+00, 0.3450302019452143E+00, 0.3805099852593911E+00, 0.7529397554746390E+00, 0.7330092480109731E+00, 0.3330086450808912E+00, 0.9038518043983117E+00, 0.6574079221280790E+00, 0.2509077957372493E+00, 0.6249580721461656E+00, 0.2757992349681960E+00, 0.5001238277403597E+00, 0.9621194298806066E+00, 0.3061711826567661E+00, 0.1119838022409911E+00, 0.2976298035182879E+00, 0.6363137835930621E-01, 0.4930031667447814E+00, 0.1865676338649569E-01, 0.4250211458984191E+00, 0.1095501188334868E+00, 0.2763357459722963E+00, 0.7075737347301593E+00, 0.5363987747039417E+00, 0.3986581101260644E+00, 0.2692140175173962E+00, 0.5588052030209328E+00, 0.5539805437492590E+00, 0.6882419411200217E+00, 0.6525011142322502E+00, 0.2351213214810641E+00, 0.4862287407564582E+00, 0.9494457572755843E-01, 0.2775605674126462E+00, 0.6088686305117397E-01, 0.1602712446759722E+00, 0.6726078044316741E-01, 0.1771280849255007E+00, 0.9403546682132294E+00, 0.1182787468569617E+00, 0.6084837514797026E+00, 0.4725411123129805E+00, 0.2891346904124859E-01, 0.3056197468639377E-01, 0.3597281640784106E+00, 0.3047108802830497E+00, 0.9462624965987684E+00, 0.6795048656132132E+00, 0.3142878274718968E+00, 0.2255775176392846E+00, 0.5741746909618360E+00, 0.6125119194512041E+00, 0.8636232492271716E+00, 0.5595270150362563E-01, 0.4894380312911951E+00, 0.2945948126181174E+00, 0.4782956027971728E+00, 0.1100404727801326E+00, 0.2692801555328298E+00, 0.4567347029351195E+00}, + n: 21, + zOut: []float64{0.2662663085210597E+01, 0.2404979690430721E+01, 0.2214109781172517E+01, 0.2010332580463078E+01, 0.1879931283999763E+01, 0.1831239586461748E+01, 0.1664682288858752E+01, 0.1512516241203824E+01, 0.1081258277181201E+01, 0.8471473481460485E+00, 0.6221178288483303E+00, 0.5493156782308360E+00, 0.4496825320738197E+00, 0.3768653101376996E+00, 0.2833465507506064E+00, 0.2013980912694376E+00, 0.1418989984144841E+00, 0.7096946004385345E-01, 0.4542843847166723E-01, 0.6747056508451696E-02, 0.1343590842619022E-02, 0.4141519752410312E-28, 0.4845145585707669E-05, 0.3343357997526164E-05, 0.1664682288858752E+01, 0.8527270841077049E-25, 0.1655046287299363E-04, 0.2231546414257453E-04, 0.1512516241203824E+01, 0.5692210911982269E-19, 0.1383329297784762E-03, 0.1072264803352635E-03, 0.1081258277181201E+01, 0.1459392674658872E-28, 0.4158771817821724E-03, 0.3910579975830214E-03, 0.8471473481460485E+00, 0.2949199315750023E-16, 0.2216793811640345E-03, 0.2203201078239036E-03, 0.6221178288483303E+00, 0.2055113688275276E-18, 0.2085797369872005E+02, 0.2085797369872006E+02, 0.9000000000000000E+02, 0.2732426303854875E+01, 0.0000000000000000E+00, 0.1772659828830871E-05, 0.4496825320738197E+00, 0.4437342591868191E-30, 0.2138076899966292E-04, 0.1340116970023588E-04, 0.3768653101376996E+00, 0.2904017873172006E-24, 0.4668906275608195E-04, 0.7182837805013731E-04, 0.2833465507506064E+00, 0.4888968615550842E-22, 0.1290326696826671E-05, 0.6479808231987577E-06, 0.2013980912694376E+00, 0.4436553730962970E-26, 0.1673384055036320E-03, 0.7106703019344439E-04, 0.1418989984144841E+00, 0.3443985257364436E-16, 0.1415746442632383E-02, 0.1286112519803737E-02, 0.7096946004385345E-01, 0.1380506584136771E-29, 0.1898294559619081E-02, 0.3536485589649533E-02, 0.4542843847166723E-01, 0.9860761315262648E-31, 0.1085724134073318E-03, 0.2838967874935677E-03, 0.6747056508451696E-02, 0.2742900553697359E-16, 0.1307657950440773E-02, 0.4192938789348323E-02, 0.1343590842619022E-02, 0.2423380700838948E-25, 0.4340570868086748E-02, 0.9691995934364128E-02}, + info: 0, + }, + { + z: []float64{0.6603307676446488E+00, 0.5215490552441340E+00, 0.9279560414420993E+00, 0.3871591216009305E+00, 0.4489001158072897E+00, 0.2115798060938074E+00, 0.6013990647859857E-01, 0.6977506014884622E+00, 0.8981757899514635E+00, 0.6366966965554082E+00, 0.5447619366248987E+00, 0.2926906196279220E+00, 0.9538633412864880E+00, 0.4052441866103130E+00, 0.9970193775088028E+00, 0.1550480233350559E+00, 0.9697068099139655E+00, 0.3748402815554551E+00, 0.3906465669660910E+00, 0.4103562008634933E+00, 0.9514404866677418E+00, 0.5608812699221558E+00, 0.6226680723027547E+00, 0.8653188982275728E+00, 0.3999642050403411E+00, 0.8968004947108832E+00, 0.1007886665847859E+00, 0.2055140520989622E+00, 0.8479005785073866E+00, 0.4772281284198989E+00, 0.3664785333935638E+00, 0.9311163393120341E+00, 0.2051534177095988E+00, 0.5588930379235971E+00, 0.9385948972790567E+00, 0.1380523811906209E+00, 0.9076293986285472E+00, 0.9937542903014829E+00, 0.5330397746663563E+00, 0.5373590340921116E+00, 0.2667502750074380E-01, 0.9996497580467543E+00, 0.7460509377370035E+00, 0.5868152625248035E+00, 0.2352631583529476E+00, 0.2062979890255305E+00, 0.1864397664760209E-02, 0.1562262993494207E+00, 0.1880894213999632E+00, 0.5369024951393064E+00, 0.6560943776892021E+00, 0.9558063214302399E+00, 0.1463497248954505E+00, 0.6977928179134164E+00, 0.8204108917709737E+00, 0.9530026100161404E+00, 0.7191901603465490E+00, 0.4974721533134605E+00, 0.8445129869563219E+00, 0.9007488855711614E+00, 0.4164322161987429E+00, 0.5750362072910759E+00, 0.1935672755254650E+00, 0.2663393354536251E+00, 0.3913931132271733E+00, 0.7724103066167269E+00, 0.7871420607985310E+00, 0.3766724710952808E+00, 0.9224124235283799E+00, 0.1080194858843619E+00, 0.3512364719709385E+00, 0.9868075881536598E-02, 0.9893144531298202E+00, 0.5983612801716819E+00, 0.2882889058269555E-01, 0.2759662054778022E+00, 0.4865673169207868E+00, 0.4317793431152178E+00, 0.4039098350536063E-01, 0.7594353556100967E+00, 0.6702102151313558E+00, 0.5757953377080282E+00, 0.7036908158147406E+00, 0.3078985083785768E+00}, + n: 21, + zOut: []float64{0.2422149931211175E+01, 0.2394118175176597E+01, 0.2305882752563478E+01, 0.2031709011458775E+01, 0.2015634640599460E+01, 0.1933740155888154E+01, 0.1715509223328114E+01, 0.1559424733880939E+01, 0.1425500044444135E+01, 0.1021162532677627E+01, 0.8999999270989295E+00, 0.8371987758218183E+00, 0.7469639623683311E+00, 0.6494523294995699E+00, 0.4251816116188064E+00, 0.2881024603279346E+00, 0.2247792687845145E+00, 0.8318936570759092E-01, 0.1886599847837073E-01, 0.1029977709531541E-01, 0.8015530498900421E-03, 0.8380373580927862E-22, 0.1621276583815588E-04, 0.5889624784943332E-05, 0.1715509223328114E+01, 0.2616454581976124E-17, 0.2563506401168800E-03, 0.3048038004625151E-03, 0.1559424733880939E+01, 0.5629222562364776E-20, 0.1824080863602310E-03, 0.8021857862878124E-04, 0.1425500044444135E+01, 0.1078233452249475E-15, 0.2986624164553499E-03, 0.4306384056300427E-03, 0.1021162532677627E+01, 0.2425965640253176E-21, 0.3415477187080772E-04, 0.2730971166672021E-04, 0.8999999270989295E+00, 0.1110716154551185E-26, 0.2300966623107952E+02, 0.2300966623107953E+02, 0.9800000000000000E+02, 0.2877551020408163E+01, 0.3061224489795918E+01, 0.5341669529353412E-07, 0.7469639623683311E+00, 0.1147369787651374E-23, 0.3199917396615717E-04, 0.1114773640824220E-03, 0.6494523294995699E+00, 0.1324417262847731E-16, 0.4143040953885707E-03, 0.3815591968277185E-03, 0.4251816116188064E+00, 0.4294702353329713E-20, 0.5586157832836348E-03, 0.4985099391803953E-03, 0.2881024603279346E+00, 0.3449343154346125E-19, 0.3018840928486242E-04, 0.4804099248496092E-04, 0.2247792687845145E+00, 0.8223054085459871E-16, 0.6535536077614123E-03, 0.5704051254743707E-03, 0.8318936570759092E-01, 0.1269822990867506E-16, 0.2750660948852983E-03, 0.2439371709019565E-03, 0.1886599847837073E-01, 0.2261821987449685E-25, 0.1693307421164339E-03, 0.1879460762504110E-03, 0.1029977709531541E-01, 0.2207699818464282E-23, 0.8362752373159153E-06, 0.5564443135649789E-05, 0.8015530498900421E-03, 0.1142002837193949E-22, 0.2005722186927794E-03, 0.1790331282576109E-02}, + info: 0, + }, + { + z: []float64{0.7180522604364612E+00, 0.1926580568606098E+00, 0.9998274874952506E-01, 0.5945840846677781E+00, 0.6814004826706310E-01, 0.6532586662527488E+00, 0.6162535781196632E+00, 0.6323752897874746E+00, 0.6913197528064650E+00, 0.8218961980054600E+00, 0.2391583485552943E+00, 0.6893465701234240E+00, 0.8646254741258573E+00, 0.4399082441653793E+00, 0.7657207697437258E+00, 0.6442902814401660E+00, 0.2997828758931008E+00, 0.3311754429773528E+00, 0.4602753981904284E-01, 0.2937498413335546E+00, 0.9438033090912972E+00, 0.6689413829611792E+00, 0.3690605709328096E+00, 0.1297746871929878E+00, 0.5761771518385747E+00, 0.9470476076636891E+00, 0.6065387228873672E+00, 0.3279182193602236E+00, 0.7521029317260848E+00, 0.3448791591170053E-01, 0.8260379882894462E+00, 0.3381289908082724E+00, 0.6350192899014672E+00, 0.6181098759446546E+00, 0.7961594478307139E+00, 0.9929813242449080E+00, 0.4678192142649594E+00, 0.8317252674327552E+00, 0.1301328932823079E+00, 0.9710090231649569E+00, 0.1522128889234372E+00, 0.8594558260240532E+00, 0.6013715693159983E+00, 0.8742383713574672E+00, 0.7309721379377087E+00, 0.5021385621750218E+00, 0.9190365975533138E+00, 0.8027800227596282E-01, 0.1149439815205374E+00, 0.3491372322884074E+00, 0.3638810075690350E+00, 0.7397316797734275E+00, 0.6765505976038609E+00, 0.6412509132149137E+00, 0.6636796276324973E+00, 0.2769301898862327E+00, 0.6293983439129569E+00, 0.7661949976862148E+00, 0.1787796367414251E+00, 0.2134901744318570E+00, 0.8213730837735125E+00, 0.5732135541056227E+00, 0.8956530012694059E+00, 0.5095442527120628E+00, 0.8428538487299666E+00, 0.6837140150023939E+00, 0.1256023460764972E+00, 0.1828667371827231E-01, 0.3922785557614588E+00, 0.9906794824083128E+00, 0.6528984219237121E+00, 0.2175815548938115E+00, 0.5215238469901794E+00, 0.6874084104558049E+00, 0.4144717036123762E+00, 0.5901719497674505E+00, 0.3178975712304457E+00, 0.7061784208820305E+00, 0.6028763180221938E+00, 0.6012903376000152E+00, 0.6812913355997376E+00, 0.7728807542206401E+00, 0.4888911469874758E+00, 0.1012713084879602E+00}, + n: 21, + zOut: []float64{0.2588311953706596E+01, 0.2370344164465735E+01, 0.2152772432177807E+01, 0.2121020324458281E+01, 0.1935798000017230E+01, 0.1639966751245229E+01, 0.1447991497477954E+01, 0.1303796318075928E+01, 0.1122178474206467E+01, 0.1028684266176079E+01, 0.9663785372526962E+00, 0.8401839996503420E+00, 0.6468021461987292E+00, 0.5148128374433424E+00, 0.4081393344645305E+00, 0.3744044838513741E+00, 0.1951863401557736E+00, 0.1222936930600034E+00, 0.3610852087288927E-01, 0.2215175692702855E-02, 0.1055251342481684E-03, 0.5816113682013476E-24, 0.3490790538048844E-06, 0.5279190866861155E-06, 0.1447991497477954E+01, 0.6749793798367842E-21, 0.1187240552619153E-05, 0.8669686727541259E-06, 0.1303796318075928E+01, 0.2818270319791895E-16, 0.1425495821091504E-08, 0.4238958678865879E-08, 0.1122178474206467E+01, 0.1974523135472784E-17, 0.8140039386639262E-06, 0.3278912117172865E-06, 0.1028684266176079E+01, 0.3004196424688596E-17, 0.2459469608149132E-06, 0.1027360875624831E-06, 0.9663785372526962E+00, 0.8319175140295936E-21, 0.2181749477578394E+02, 0.2181749477578394E+02, 0.1040000000000000E+03, 0.3040816326530612E+01, 0.3846153846153846E+01, 0.3006532860022149E-05, 0.6468021461987292E+00, 0.2129924444096732E-28, 0.3097317061779137E-05, 0.3301766384461962E-05, 0.5148128374433424E+00, 0.5841522899747606E-17, 0.6589564866042633E-05, 0.8825655271690012E-05, 0.4081393344645305E+00, 0.5522026336547083E-29, 0.6929345622607317E-04, 0.1121666398022498E-03, 0.3744044838513741E+00, 0.4071868297361024E-19, 0.4964849153130707E-03, 0.6240579194345771E-03, 0.1951863401557736E+00, 0.3096999756315481E-22, 0.1538823843362176E-02, 0.5557701536471033E-03, 0.1222936930600034E+00, 0.9508642973366516E-17, 0.9344625728185554E-03, 0.1303932473154565E-02, 0.3610852087288927E-01, 0.2671050208464689E-19, 0.5349955893117279E-02, 0.9991286391872665E-02, 0.2215175692702855E-02, 0.2465190328815662E-30, 0.2737788875312504E-02, 0.2378589653250575E-02, 0.1055251342481684E-03, 0.0000000000000000E+00, 0.1487915832966980E-01, 0.9945584373260818E-02}, + info: 0, + }, + { + z: []float64{0.2443960928887767E+00, 0.5306690011327519E+00, 0.8844980893594125E+00, 0.8505050348613927E+00, 0.1179365025679910E+00, 0.6787232231004032E+00, 0.4781425309482933E+00, 0.8596658025119301E+00, 0.7267566040500681E+00, 0.7988986860541384E+00, 0.5066697395752245E+00, 0.9256193759419001E+00, 0.1614174453766865E+00, 0.7938782145253169E+00, 0.3207377639351938E+00, 0.5936236877473402E+00, 0.5294512496859689E+00, 0.3341300959064973E+00, 0.8739309914591177E+00, 0.1643518115289022E-01, 0.9695643985202173E+00, 0.9508789318813814E+00, 0.6599781146531454E+00, 0.8013437877388673E+00, 0.1929493765752847E+00, 0.7655052376601326E+00, 0.6319580998438735E+00, 0.6831519307583876E+00, 0.3834927697748418E+00, 0.7094548193343077E+00, 0.7020510393185050E+00, 0.6520146205437408E+00, 0.6562814689912274E+00, 0.5240471964184201E+00, 0.2362557689024753E+00, 0.4347621644220048E+00, 0.1660979681267404E+00, 0.2422730270980831E+00, 0.7891782502389337E+00, 0.5007812255281535E+00, 0.4444633531981611E+00, 0.3026778693869716E+00, 0.9990331636150707E-02, 0.4097233632314936E+00, 0.9940240633376396E+00, 0.1626467187830966E+00, 0.3461071508544706E+00, 0.6476433090511620E+00, 0.7204399230581238E-01, 0.6885344672911693E+00, 0.1941295874559149E+00, 0.5883115695765473E+00, 0.7359955011333836E+00, 0.4277388472789430E+00, 0.4017294206583021E+00, 0.7838762945853397E+00, 0.9128155969033611E+00, 0.4856080402782125E+00, 0.4763260467232836E+00, 0.5586410048770161E+00, 0.8031586091432461E+00, 0.6068401118620381E-01, 0.9247455618544214E+00, 0.5857147883918616E+00, 0.7467203590494284E+00, 0.1453563221196804E+00, 0.2297646010524917E+00, 0.8950965613541395E+00, 0.3335127494359967E+00, 0.9671078623732762E+00, 0.8023166958816280E+00, 0.1059134943829219E+00, 0.7122485680883537E+00, 0.3211310961264330E+00, 0.1626983074059779E+00, 0.4042697895935750E+00, 0.4799615975845870E+00, 0.3426607739026810E-02, 0.5147088911567483E+00, 0.7533023355653040E+00, 0.9693400349159813E+00, 0.7251923493536844E+00, 0.9132309180417886E-01, 0.4001770994110867E+00}, + n: 21, + zOut: []float64{0.2574587707602998E+01, 0.2548516143888565E+01, 0.2328646361106399E+01, 0.2152335028165169E+01, 0.1900054508136636E+01, 0.1821843561986577E+01, 0.1641395708303600E+01, 0.1593513640807486E+01, 0.1254245828754644E+01, 0.1184500984874290E+01, 0.9407518766665146E+00, 0.8321813659237318E+00, 0.6961683120499664E+00, 0.5315544763312857E+00, 0.4082285577131941E+00, 0.4022023658419822E+00, 0.2892256147411429E+00, 0.1412172326671640E+00, 0.7919841586115514E-01, 0.2055312514153672E-02, 0.1458583715266580E-03, 0.5995342879679690E-28, 0.2082901809770958E-07, 0.9383395476751434E-08, 0.1641395708303600E+01, 0.1321835131711384E-15, 0.1191741688360734E-04, 0.3695487724817346E-05, 0.1593513640807486E+01, 0.5607617048340495E-15, 0.5232768419257040E-05, 0.4082864434107817E-05, 0.1254245828754644E+01, 0.1850697850686327E-14, 0.2071860298001858E-05, 0.2753629328588578E-05, 0.1184500984874290E+01, 0.3549874073494553E-29, 0.9441520198112501E-05, 0.5871348343515868E-05, 0.9407518766665146E+00, 0.3656881477565973E-23, 0.2332256886230818E+02, 0.2332256886230818E+02, 0.1000000000000000E+03, 0.2984126984126984E+01, 0.3000000000000000E+01, 0.1218265160373847E-03, 0.6961683120499664E+00, 0.3847797347882626E-19, 0.2944801840696127E-03, 0.4565874591840146E-03, 0.5315544763312857E+00, 0.2366582715663035E-29, 0.5951942600827748E-04, 0.7082415940475930E-04, 0.4082285577131941E+00, 0.1744834104604043E-24, 0.4087064324555941E-04, 0.4051735857075661E-04, 0.4022023658419822E+00, 0.5055621275172978E-20, 0.1443306547898801E-05, 0.5013891517830428E-06, 0.2892256147411429E+00, 0.1446770900175336E-26, 0.7439355829951562E-04, 0.1741194257531676E-03, 0.1412172326671640E+00, 0.3448013628188340E-14, 0.2774107535050150E-02, 0.3338675080262731E-02, 0.7919841586115514E-01, 0.2413026984508734E-18, 0.7157138061395222E-03, 0.6803125903293225E-03, 0.2055312514153672E-02, 0.3994185778863994E-23, 0.5722078415717462E-03, 0.5910838594703896E-03, 0.1458583715266580E-03, 0.1183291357831518E-27, 0.8602246198024520E-03, 0.1402897408133881E-02}, + info: 0, + }, + { + z: []float64{0.6756942057876089E+00, 0.6579919202857232E+00, 0.8168130848194743E+00, 0.2483963371195050E+00, 0.2866280219451008E+00, 0.7172808579862799E-03, 0.2411898945446896E+00, 0.5534360794587689E-02, 0.3878248310175912E+00, 0.4256983490856848E+00, 0.7118512164413080E+00, 0.8762976594477806E+00, 0.6850772131038755E+00, 0.4603991232581716E+00, 0.6546622425118448E+00, 0.3103854094723100E+00, 0.7913005955185648E+00, 0.4864788053022765E+00, 0.6214717223070496E+00, 0.7079028836241165E+00, 0.2446362485461124E+00, 0.3062353821816216E+00, 0.8766788389923219E-01, 0.4381267847541642E+00, 0.4459912790878073E-01, 0.9432264671740954E+00, 0.3830574008366420E+00, 0.3381025391982955E+00, 0.6585260539196298E+00, 0.1004337858849739E+00, 0.9320890528134474E+00, 0.3322930037041504E+00, 0.7282334590214989E-02, 0.8367863647557111E+00, 0.9736104021592913E+00, 0.1613168640897539E+00, 0.6409545774446285E+00, 0.8441218931570360E-01, 0.9793937208019250E+00, 0.8303681522642254E+00, 0.1022316826967604E+00, 0.3021608972738009E+00, 0.1238379032543057E+00, 0.3839961366681232E+00, 0.8871553342676223E+00, 0.2909019998361990E+00, 0.7955411369197152E-01, 0.6476593477808288E+00, 0.1739219408315845E+00, 0.6498034164943688E+00, 0.3405210004266120E+00, 0.5459816771585898E+00, 0.2574285667818188E-01, 0.8691155035114945E+00, 0.4320450067500660E+00, 0.6967311316847606E+00, 0.9186339034853966E+00, 0.9491091410944081E+00, 0.2046793386144015E+00, 0.4114169869296881E+00, 0.9170199522695309E+00, 0.1514288291023066E+00, 0.2203325773257230E+00, 0.7891126546748299E+00, 0.4738113210301682E+00, 0.6729225031084131E+00, 0.2382373075875677E+00, 0.4180455054749687E+00, 0.9185761229203592E+00, 0.8030412579733187E+00, 0.4789612026295414E+00, 0.5038982716350845E+00, 0.9959829239394621E+00, 0.3087119711461705E-01, 0.6615773194242809E+00, 0.4461280013353816E+00, 0.1982838436639324E+00, 0.7583555141388076E+00, 0.7946309632008934E+00, 0.6749216068143323E+00, 0.9948312782688508E+00, 0.2854132428873886E+00, 0.8405396060835862E+00, 0.3412432527462372E-01}, + n: 21, + zOut: []float64{0.2393193272196224E+01, 0.2018136210599260E+01, 0.1995725670346335E+01, 0.1962470040389077E+01, 0.1880885332732760E+01, 0.1640866198530974E+01, 0.1381237309251015E+01, 0.1349378962361067E+01, 0.9454836406584929E+00, 0.7636867441308103E+00, 0.6820433637129892E+00, 0.6091604279437030E+00, 0.5856982990037397E+00, 0.4957297472312800E+00, 0.2553870576469542E+00, 0.2360257010865909E+00, 0.1371029529316844E+00, 0.8102847375475340E-01, 0.5521596879227348E-01, 0.9135542089709688E-02, 0.7426079491367038E-04, 0.1040308236944517E-14, 0.7301351780522185E-10, 0.7774740781328628E-10, 0.1381237309251015E+01, 0.2169367489357782E-29, 0.6020076428884570E-10, 0.5781767346304832E-10, 0.1349378962361067E+01, 0.1885108385497271E-16, 0.6878646083705261E-10, 0.6530919047819172E-10, 0.9454836406584929E+00, 0.5778430642028005E-17, 0.9207835097245334E-10, 0.7637719283517905E-10, 0.7636867441308103E+00, 0.1387778780781446E-16, 0.1259777267883337E-09, 0.1656656563258317E-09, 0.6820433637129892E+00, 0.0000000000000000E+00, 0.1947766517618461E+02, 0.1947766517618461E+02, 0.1070000000000000E+03, 0.3197278911564626E+01, 0.3738317757009346E+01, 0.5169611983503601E-09, 0.5856982990037397E+00, 0.2460562659624748E-15, 0.4628473083370263E-08, 0.9345989594028561E-08, 0.4957297472312800E+00, 0.2615714135774493E-18, 0.2264320058754590E-06, 0.2929148984854635E-06, 0.2553870576469542E+00, 0.1029104326196136E-18, 0.2640422579955958E-07, 0.2108896012270181E-07, 0.2360257010865909E+00, 0.3005450327091600E-17, 0.6822175517251369E-08, 0.8519370047734521E-08, 0.1371029529316844E+00, 0.3395257336071235E-24, 0.2687435952714477E-08, 0.2177398712709520E-08, 0.8102847375475340E-01, 0.0000000000000000E+00, 0.5343374415472690E-09, 0.5384901342094013E-09, 0.5521596879227348E-01, 0.2914620163738177E-24, 0.6457803167637477E-08, 0.2258738450739571E-07, 0.9135542089709688E-02, 0.5326388832052272E-25, 0.9576323906120589E-06, 0.3243967823107194E-05, 0.7426079491367038E-04, 0.3164925372525892E-18, 0.6752170208452239E-05, 0.3302115586194402E-04}, + info: 0, + }, + { + z: []float64{0.1859840927709887E+00, 0.1326482709507555E+00, 0.1830793816152183E+00, 0.4955347339015181E+00, 0.7174832323677909E+00, 0.1239131234434754E-01, 0.8960455455727024E+00, 0.1883195594308053E+00, 0.3701760109540279E+00, 0.5189832590024491E+00, 0.8746518205444311E+00, 0.5127960794741733E+00, 0.2715029219143491E+00, 0.3130984190329523E+00, 0.6427011945330067E+00, 0.2728531634457195E+00, 0.4849915812764480E+00, 0.4474855195890282E-01, 0.1232624016522375E+00, 0.4054507321320544E+00, 0.8168182420396084E+00, 0.5779650563825861E+00, 0.3336575737681243E+00, 0.4793345429794458E+00, 0.3323762775436829E+00, 0.4013874798394268E-01, 0.3250840079396182E+00, 0.3339528328323188E+00, 0.6534745789256358E+00, 0.1592419685588734E+00, 0.4882641395765897E-01, 0.3378473153079410E+00, 0.1498873352536064E+00, 0.9366519936638189E+00, 0.8628314489246045E+00, 0.9035188141748132E+00, 0.3376603415628452E+00, 0.8754867721780122E+00, 0.4314313357227496E+00, 0.6689080802643724E+00, 0.7427192946427073E+00, 0.8408966332922378E+00, 0.3923135283693152E+00, 0.9856346160535667E+00, 0.5253798946684216E+00, 0.4589666030610524E+00, 0.3627813920321372E+00, 0.6650592661455799E+00, 0.5488555419923284E+00, 0.8723519563008553E+00, 0.5759829964509324E+00, 0.8314551283704829E+00, 0.8033910216639006E-01, 0.5533270198466882E+00, 0.4579854660280547E-01, 0.8805162884999327E+00, 0.7798601625088321E+00, 0.3998529604552336E+00, 0.2290634020126769E-01, 0.4087780821380217E+00, 0.8084384129630373E-01, 0.1651045317338867E+00, 0.5138876592921692E+00, 0.1502237554834691E+00, 0.3139451210283801E+00, 0.4951417832103121E+00, 0.4305502836911147E+00, 0.4221379680427187E+00, 0.6629276271381638E+00, 0.6032939209531929E+00, 0.7486429236694788E+00, 0.4603187644190643E+00, 0.9910999698454684E+00, 0.9830579802970648E+00, 0.1327788029232968E+00, 0.7906300391462903E+00, 0.4870686063503010E+00, 0.9107501765395865E-01, 0.5847999740468798E+00, 0.5237055378474927E+00, 0.1949033413503392E+00, 0.6706570830152104E+00, 0.4839742423553839E+00, 0.6933746141255293E+00}, + n: 21, + zOut: []float64{0.2594702985921864E+01, 0.1963381202215380E+01, 0.1899121104965353E+01, 0.1852857657580134E+01, 0.1352179381057759E+01, 0.1316420368068040E+01, 0.1223907530772361E+01, 0.1104722051320913E+01, 0.1042814535040686E+01, 0.9392359492223399E+00, 0.5879944547218380E+00, 0.5343064059199153E+00, 0.3616892068472140E+00, 0.3474187565935542E+00, 0.3132932870269020E+00, 0.2394766491234008E+00, 0.1924620369224269E+00, 0.5796610832720670E-01, 0.4900919199482741E-01, 0.2087594658763894E-01, 0.6804292520862544E-03, 0.2186403793390500E-19, 0.2668268315891067E-16, 0.1216320938093713E-16, 0.1223907530772361E+01, 0.3077822220048293E-18, 0.9690290545884895E-18, 0.1677534925257981E-18, 0.1104722051320913E+01, 0.3294338264035954E-18, 0.1270509199570000E-13, 0.4678488073918506E-13, 0.1042814535040686E+01, 0.2740439675865377E-23, 0.1047809983111396E-11, 0.5781643460797313E-12, 0.9392359492223399E+00, 0.3379215452805658E-16, 0.8350045830190690E-10, 0.5730922211948388E-10, 0.5879944547218380E+00, 0.6938893903907228E-17, 0.1799451523948185E+02, 0.1799451523948184E+02, 0.1150000000000000E+03, 0.3578231292517007E+01, 0.6086956521739131E+01, 0.8630088713732289E-10, 0.3616892068472140E+00, 0.1664229231319872E-20, 0.9644621511794884E-10, 0.9354199679969641E-10, 0.3474187565935542E+00, 0.0000000000000000E+00, 0.1015403419286529E-09, 0.1046840761330470E-09, 0.3132932870269020E+00, 0.6366107505133565E-27, 0.3071873418074744E-11, 0.5342885575500614E-12, 0.2394766491234008E+00, 0.2599072586631376E-18, 0.1837414559126179E-09, 0.2303923049314304E-09, 0.1924620369224269E+00, 0.3400814535759169E-17, 0.9192916981159684E-08, 0.4803632388224207E-08, 0.5796610832720670E-01, 0.0000000000000000E+00, 0.1565526746702558E-05, 0.8408463868497472E-06, 0.4900919199482741E-01, 0.7888609052210118E-30, 0.1903794116022181E-04, 0.1014775117962413E-04, 0.2087594658763894E-01, 0.9734740470109229E-22, 0.4676468030348868E-06, 0.4248047233272650E-05, 0.6804292520862544E-03, 0.3161038140634776E-18, 0.1818811163938070E-02, 0.3653457173655013E-02}, + info: 0, + }, + { + z: []float64{0.2029039404458555E-01, 0.4529725864625287E+00, 0.6412066909421453E+00, 0.6139288440336396E+00, 0.3661028502807454E+00, 0.9178254749803582E+00, 0.4307551173824371E+00, 0.4985808870906128E+00, 0.8171615510934167E+00, 0.8279058065788196E+00, 0.3035261047197422E+00, 0.7877147223127390E+00, 0.7688130520483442E+00, 0.4834409462671818E-01, 0.3121145202501183E+00, 0.5269232357652766E+00, 0.7600633371694686E+00, 0.5251092877920901E+00, 0.8263235554592012E+00, 0.6894073332954654E+00, 0.3521429062439027E+00, 0.6447189811681343E+00, 0.1105592548668879E+00, 0.1049454508922576E+00, 0.7381247076050562E+00, 0.7320584094686099E+00, 0.7003114013559573E+00, 0.9638534557041758E+00, 0.5727311775052889E+00, 0.3930768970870516E+00, 0.7640649329763241E+00, 0.3221407324893386E+00, 0.9725443946255905E+00, 0.6922592425787558E+00, 0.3449642467056757E-01, 0.1384627086161467E+00, 0.4398391723165511E+00, 0.8406456486574913E+00, 0.4126144976348992E+00, 0.5351779876797247E-01, 0.6669497026260232E+00, 0.5746288223886410E+00, 0.4589594741804619E+00, 0.7484833637036891E+00, 0.3274476209575072E-01, 0.7067960763848782E+00, 0.8759136475280368E+00, 0.3284828537280239E+00, 0.2536109230678856E+00, 0.8799264273691800E+00, 0.8159607815416694E+00, 0.5729670098854700E-01, 0.8884200881604851E+00, 0.5249116128877267E+00, 0.6498061599007876E-01, 0.6075292761444269E+00, 0.2428201413403417E+00, 0.2668460043818345E+00, 0.1429723702275580E+00, 0.6942338078813951E+00, 0.9271225003121289E+00, 0.8931957344289477E+00, 0.6420336733834545E+00, 0.3786225606645894E+00, 0.9421368123010410E-01, 0.9476439119845459E+00, 0.6497389318978118E+00, 0.3841806572586668E+00, 0.1329188317035728E+00, 0.6545507077812880E+00, 0.4430247695845350E+00, 0.1753161904868739E+00, 0.2413409779703910E+00, 0.1476409499735053E+00, 0.1179852848482287E+00, 0.3704631210033814E+00, 0.1967445635592234E+00, 0.2100970549835486E+00, 0.5744473538919733E+00, 0.1093206314301038E+00, 0.5132572818416121E+00, 0.4964557538937117E+00, 0.7518888363275744E-02, 0.9720615373003737E+00}, + n: 21, + zOut: []float64{0.2563191374817756E+01, 0.2359364796169898E+01, 0.2296884847589588E+01, 0.2056943321577226E+01, 0.1949112826206492E+01, 0.1629835138023691E+01, 0.1562766390641567E+01, 0.1422208590143927E+01, 0.1368481726990307E+01, 0.1150114414099739E+01, 0.8482773777570239E+00, 0.7665061168435710E+00, 0.7135198036652551E+00, 0.3486547062556205E+00, 0.2456691453437445E+00, 0.2203009969871996E+00, 0.1404417091680581E+00, 0.1160909181211330E+00, 0.2112854362928769E-01, 0.5069559443178203E-02, 0.5650407111696261E-03, 0.3717112585401408E-26, 0.2316306425767847E-08, 0.1632477182259275E-08, 0.1562766390641567E+01, 0.6446192664231602E-24, 0.9634960729667980E-08, 0.6524712961691138E-08, 0.1422208590143927E+01, 0.1932709217791479E-28, 0.4932058767625490E-07, 0.7860293908453283E-07, 0.1368481726990307E+01, 0.1238511621196989E-27, 0.2778987342481399E-06, 0.5558918854266694E-06, 0.1150114414099739E+01, 0.2156683454185074E-19, 0.1662595987219070E-04, 0.2580299679298412E-04, 0.8482773777570239E+00, 0.7914569980025776E-17, 0.2178512734418544E+02, 0.2178512734418543E+02, 0.1000000000000000E+03, 0.2934240362811791E+01, 0.1000000000000000E+01, 0.1715129124192563E-05, 0.7135198036652551E+00, 0.1613909508212798E-19, 0.2836076293001813E-04, 0.1595224464977716E-04, 0.3486547062556205E+00, 0.3352658847189300E-29, 0.8812160938383347E-04, 0.1178320764067675E-03, 0.2456691453437445E+00, 0.0000000000000000E+00, 0.5251568647637462E-04, 0.4480459044047029E-04, 0.2203009969871996E+00, 0.6471183777709004E-25, 0.1114279427921990E-09, 0.2270576453660371E-10, 0.1404417091680581E+00, 0.2855676476900063E-27, 0.2886261726979772E-05, 0.5470704056451658E-06, 0.1160909181211330E+00, 0.3526208246337923E-27, 0.3588687949078309E-02, 0.5383294574404876E-02, 0.2112854362928769E-01, 0.2896602354076833E-17, 0.1732996915625309E-02, 0.1499310228751921E-02, 0.5069559443178203E-02, 0.1003594455767978E-17, 0.5081816639203317E-03, 0.1080637708244138E-02, 0.5650407111696261E-03, 0.0000000000000000E+00, 0.5066428376081889E-02, 0.3247326449492487E-02}, + info: 0, + }, + { + z: []float64{0.7177806115181969E+00, 0.9619042524298227E+00, 0.9756290650460009E-01, 0.2695657197860104E+00, 0.5092382615580680E+00, 0.2216490915715645E+00, 0.7713962041593733E+00, 0.9019626308054164E+00, 0.1009043823109016E+00, 0.7164892891763703E+00, 0.6972336574704985E+00, 0.5604456603447616E-01, 0.4658944020177349E+00, 0.4677429402719713E+00, 0.9395972368396054E+00, 0.6567060928508761E-01, 0.6711470087762763E+00, 0.3572615865847095E-01, 0.7841795004355456E-01, 0.2100489732227784E+00, 0.1528790147771258E+00, 0.2944728557463859E+00, 0.6929796239262105E+00, 0.5593689694083593E+00, 0.5600220347177359E+00, 0.6885800745012647E+00, 0.1441376161827218E+00, 0.2468678391528564E+00, 0.2219056216366488E+00, 0.7828887069679423E+00, 0.1781536622262658E-01, 0.9712383516530864E+00, 0.1031071887927941E+00, 0.5428204596104211E+00, 0.9920375605622551E+00, 0.2231614148449633E+00, 0.1774197365731667E+00, 0.1667803739895276E+00, 0.2293956181863850E+00, 0.8453959149417756E+00, 0.2211895679989639E+00, 0.5610288802043042E+00, 0.3749535737701304E-01, 0.7418144847444434E+00, 0.2593245755300763E+00, 0.5358881543370908E-01, 0.9118629582226685E+00, 0.6483736004795430E+00, 0.7595140552166778E+00, 0.2981894989055883E+00, 0.6091779707233183E+00, 0.7798268953767704E+00, 0.1682114110436058E+00, 0.3801835867597201E+00, 0.6380508025759659E+00, 0.7892946000460455E-01, 0.7607559424299619E+00, 0.3271484239841950E+00, 0.7700240256278714E+00, 0.5894107219393652E+00, 0.6207117138108632E+00, 0.4725019923733027E+00, 0.3616574024313524E+00, 0.6744122205664662E+00, 0.5489632027065386E+00, 0.1532930834122788E+00, 0.1692473010839316E+00, 0.7515070367293223E+00, 0.1186783750638719E+00, 0.1028479850139022E+00, 0.3468642488228025E+00, 0.5278752643808988E+00, 0.3849250707234438E+00, 0.7889573536656195E+00, 0.4738712276132427E+00, 0.7058571493185843E+00, 0.8948240863202030E+00, 0.3494029097065446E+00, 0.4916843795342892E+00, 0.1993321046695898E+00, 0.3650043431665774E+00, 0.2403686388300026E+00, 0.5474155466298688E+00, 0.6157434374908201E+00}, + n: 21, + zOut: []float64{0.1955717973339200E+01, 0.1915826728710446E+01, 0.1780143898982495E+01, 0.1751081083154649E+01, 0.1679171531306522E+01, 0.1398798787154148E+01, 0.1289579288306139E+01, 0.1171599632002814E+01, 0.9950381700653156E+00, 0.9008548767119643E+00, 0.7944341357698450E+00, 0.7347990252582277E+00, 0.4053391427425183E+00, 0.3415476013970046E+00, 0.2769292856200630E+00, 0.2086988709391624E+00, 0.7594980741000955E-01, 0.5721582845751132E-01, 0.5152297043277422E-01, 0.6186350115045150E-02, 0.5774958135565486E-05, 0.6722096271457334E-14, 0.6635533119216432E-06, 0.1048982691930868E-05, 0.1289579288306139E+01, 0.0000000000000000E+00, 0.9172850657907766E-08, 0.6527900227304331E-08, 0.1171599632002814E+01, 0.0000000000000000E+00, 0.3386861611239913E-06, 0.1115072165646295E-06, 0.9950381700653156E+00, 0.1044578056257455E-24, 0.5793689136913799E-11, 0.1625904890507595E-10, 0.9008548767119643E+00, 0.8883435102679349E-21, 0.3220671712964998E-09, 0.8453946299986560E-09, 0.7944341357698450E+00, 0.1653452457343241E-26, 0.1779044076283400E+02, 0.1779044076283399E+02, 0.1120000000000000E+03, 0.3267573696145125E+01, 0.3571428571428572E+01, 0.1211740269624600E-06, 0.4053391427425183E+00, 0.5298753945086544E-14, 0.1515410194583574E-06, 0.2069357347527298E-06, 0.3415476013970046E+00, 0.0000000000000000E+00, 0.2579333883676927E-05, 0.8435987645777294E-05, 0.2769292856200630E+00, 0.2465190328815662E-30, 0.1658852164453815E-08, 0.3207072615633299E-09, 0.2086988709391624E+00, 0.2017246551328580E-19, 0.6091457019925236E-05, 0.6297972233022177E-05, 0.7594980741000955E-01, 0.2553131970482608E-15, 0.2736366650719638E-04, 0.2348362771705736E-04, 0.5721582845751132E-01, 0.1141311335899276E-23, 0.6030351005218485E-04, 0.3385365250818500E-04, 0.5152297043277422E-01, 0.0000000000000000E+00, 0.4442856906399686E-04, 0.3980460155412817E-04, 0.6186350115045150E-02, 0.2711709361697228E-30, 0.1322896557202734E-03, 0.3209571887096705E-03, 0.5774958135565486E-05, 0.0000000000000000E+00, 0.9248295446812529E-03, 0.1317994001905306E-02}, + info: 0, + }, + { + z: []float64{0.7669589114699304E-01, 0.2959120838012549E+00, 0.8617075527885690E+00, 0.3774472194278293E+00, 0.7430204868341380E+00, 0.3337487204025202E-01, 0.2115072947611989E+00, 0.8195300149220009E+00, 0.4610153087687133E+00, 0.1049580467270205E+00, 0.6553761031646719E+00, 0.2044425657813468E+00, 0.1419536829746254E+00, 0.8338399989758465E+00, 0.9917105482281005E+00, 0.3698082853107363E+00, 0.5656210986926330E+00, 0.5849265049217818E+00, 0.9018145207330325E+00, 0.7089264704350354E+00, 0.2562038341655152E+00, 0.1524378342317656E-01, 0.9206210351037002E+00, 0.1877259832276945E+00, 0.3637451600309541E+00, 0.9979742594017312E+00, 0.8919698496914060E+00, 0.3716780472994426E+00, 0.3142548907151147E+00, 0.4170439734847903E+00, 0.3197415298896636E+00, 0.7285365914169133E+00, 0.5784968714882697E+00, 0.6831919512327895E+00, 0.6057174197537164E+00, 0.6413693987683566E-01, 0.8827799219498907E+00, 0.4192891003797022E+00, 0.6040167945472836E+00, 0.6469271762278970E+00, 0.7359461974470041E+00, 0.5539488596393002E+00, 0.4023966166720030E+00, 0.9915288950117843E+00, 0.3043860170301459E+00, 0.4917889743094436E+00, 0.1179472550216760E+00, 0.9125202427370891E+00, 0.8786441005384636E+00, 0.4634730997209351E+00, 0.1080276946115265E+00, 0.6187727001119313E+00, 0.6709766557170562E+00, 0.3818949179452977E+00, 0.8906457783485427E+00, 0.8010289089804480E+00, 0.6931910498827129E+00, 0.8914072225833563E+00, 0.3822463769530011E+00, 0.5898102885291842E+00, 0.1092049166271940E+00, 0.8496011938807149E+00, 0.2304394290731624E+00, 0.5949006075515944E+00, 0.3290638194228065E+00, 0.1971699984758039E+00, 0.7443144303888384E+00, 0.4653555333092598E+00, 0.8207632269304853E+00, 0.4152482306441556E+00, 0.1689785233215235E+00, 0.1721084345877374E+00, 0.3931596107353640E+00, 0.5403345228237123E+00, 0.6387555392172577E+00, 0.1804790096977364E+00, 0.5783025205396422E+00, 0.7395837791384520E+00, 0.5701597209798811E+00, 0.1952734055752668E+00, 0.9661114908130567E+00, 0.4893113195434146E+00, 0.6562980654604210E+00, 0.1879394621701417E+00}, + n: 21, + zOut: []float64{0.2390558120678448E+01, 0.2326196956724044E+01, 0.2071676597874671E+01, 0.1995424877356871E+01, 0.1973795189776371E+01, 0.1728273264358535E+01, 0.1492322130169846E+01, 0.1216694895544233E+01, 0.1149617898796123E+01, 0.1007011094632661E+01, 0.9207056739913982E+00, 0.7404938152461292E+00, 0.6082352700464410E+00, 0.5965144149455339E+00, 0.2276577044879657E+00, 0.1776272681811473E+00, 0.1662286875439616E+00, 0.8310804130734020E-01, 0.4604735683437314E-01, 0.1806926893972028E-01, 0.1257133375345320E-01, 0.3600386373101646E-15, 0.6280777483216298E-03, 0.1060573000233681E-02, 0.1492322130169846E+01, 0.1292469707114105E-25, 0.5799349861429450E-06, 0.5584709508928944E-06, 0.1216694895544233E+01, 0.2047280287874868E-18, 0.1299955932331242E-09, 0.8534229075832313E-10, 0.1149617898796123E+01, 0.5088714046955349E-16, 0.6001732451841635E-09, 0.4081989685050919E-09, 0.1007011094632661E+01, 0.5578719308559292E-21, 0.1498995168909837E-07, 0.5625367692005608E-08, 0.9207056739913982E+00, 0.2728742825015995E-21, 0.2094882986118927E+02, 0.2094882986118927E+02, 0.9800000000000000E+02, 0.3004535147392290E+01, 0.4081632653061225E+01, 0.6223967900246754E-04, 0.6082352700464410E+00, 0.4038967834731580E-26, 0.1122996207538654E-05, 0.1754126012223728E-05, 0.5965144149455339E+00, 0.4386207914826929E-19, 0.1334483593164094E-04, 0.6982705884252015E-05, 0.2276577044879657E+00, 0.3148538924591216E-18, 0.9085150621800872E-04, 0.4628114404518947E-04, 0.1776272681811473E+00, 0.1149284743081177E-19, 0.3934684725502468E-05, 0.5044161242313764E-05, 0.1662286875439616E+00, 0.3944304526105059E-30, 0.1149340461723492E-04, 0.8510588625472410E-05, 0.8310804130734020E-01, 0.1540743955509789E-32, 0.1285467894756909E-02, 0.9239857033877289E-03, 0.4604735683437314E-01, 0.2169367489357782E-29, 0.2808730938050547E-03, 0.3455059327639833E-03, 0.1806926893972028E-01, 0.4614836295542919E-28, 0.7683442768713957E-06, 0.1846813906304985E-05, 0.1257133375345320E-01, 0.2538554393001216E-26, 0.4028502005942143E-04, 0.8466712427867894E-04}, + info: 0, + }, + { + z: []float64{0.5568197491282034E+00, 0.7338530212513171E+00, 0.1711270247791036E+00, 0.6696990680288049E+00, 0.1107644593582661E+00, 0.1487844153251054E+00, 0.6221478836712087E+00, 0.3739707210550620E+00, 0.6142936216832375E+00, 0.4504419047617665E+00, 0.1390832371836795E+00, 0.9602056283222130E+00, 0.4128383897877478E+00, 0.6202590221465013E+00, 0.5716294881431405E+00, 0.7009876531280159E+00, 0.8556346552408018E+00, 0.4300043005510307E+00, 0.5625488786064613E+00, 0.5236571943623558E+00, 0.2035297706440273E+00, 0.5324677179555473E+00, 0.9854023908952125E+00, 0.8088580870995794E+00, 0.7902887218423563E+00, 0.4196418643524230E+00, 0.5294914665193529E+00, 0.5947417442754066E-01, 0.2753919335549286E+00, 0.8807083336864044E+00, 0.6016279529290567E+00, 0.4144655693858035E-01, 0.4808953029705748E+00, 0.8506686680287934E-01, 0.2145404015834380E+00, 0.3020133878086849E+00, 0.8967140938263458E+00, 0.5344538485865815E+00, 0.2536120629120923E+00, 0.2552452828610304E+00, 0.9211096671641958E+00, 0.9028760680202415E+00, 0.3005599522329846E+00, 0.1197919551028395E+00, 0.3772579707039786E+00, 0.4157715274081910E+00, 0.2203607291065889E+00, 0.1084188329562713E+00, 0.5463193166123409E+00, 0.8107359194268960E+00, 0.6676190072779817E+00, 0.6711454730587799E+00, 0.6360708014875704E-01, 0.8242026716736568E+00, 0.3687006444230088E+00, 0.2216898043026083E-01, 0.4978612409817640E+00, 0.3144452507777135E+00, 0.3412289603988730E+00, 0.3266626310182044E+00, 0.4581662376370765E+00, 0.6985218227047190E+00, 0.6594479039269319E-01, 0.3938130402504401E+00, 0.9907371819490932E+00, 0.2478499678343852E+00, 0.3565435772734814E+00, 0.8420455744018336E+00, 0.2692247454903065E+00, 0.7327570909626056E+00, 0.1752776205164243E+00, 0.3569190164542581E+00, 0.2122621782757903E+00, 0.2056257129895300E+00, 0.6641092684756426E+00, 0.5386917539530447E+00, 0.8420713652275945E+00, 0.3587226239611645E+00, 0.9561844063661247E+00, 0.9126272291387975E+00, 0.5768542567999925E+00, 0.1972168939311342E+00, 0.5763304496236371E+00, 0.9478337554439876E+00}, + n: 21, + zOut: []float64{0.2593664459139222E+01, 0.2338172956520739E+01, 0.1783072679058981E+01, 0.1768637196043293E+01, 0.1688808722758796E+01, 0.1535694950136988E+01, 0.1488691522387158E+01, 0.1290354539321546E+01, 0.1187570436840380E+01, 0.1077679082742636E+01, 0.7925423484101771E+00, 0.6549022645335129E+00, 0.6315653598883190E+00, 0.5184441284206909E+00, 0.3791491409939438E+00, 0.3105722740860607E+00, 0.1128189367670211E+00, 0.7036440937731858E-01, 0.4999153992819697E-01, 0.2730914559941030E-01, 0.7241089204639656E-03, 0.7344040350490801E-18, 0.1828200693350630E-07, 0.2226187377323797E-07, 0.1488691522387158E+01, 0.4586948101010510E-17, 0.3930142187345605E-07, 0.5206893736347286E-07, 0.1290354539321546E+01, 0.6658190007940994E-20, 0.1499933495859733E-06, 0.7910043275590841E-07, 0.1187570436840380E+01, 0.2370536763713858E-16, 0.1192422432592963E-05, 0.6065280015592916E-06, 0.1077679082742636E+01, 0.6803770690793804E-23, 0.5360141282897325E-04, 0.3254990522417721E-04, 0.7925423484101771E+00, 0.8404284270509473E-23, 0.2030073020187486E+02, 0.2030073020187486E+02, 0.9700000000000000E+02, 0.2975056689342404E+01, 0.1030927835051546E+01, 0.1762395614510388E-04, 0.6315653598883190E+00, 0.2034005362457094E-16, 0.3178492515415974E-08, 0.1141868824523976E-08, 0.5184441284206909E+00, 0.1631704231140345E-20, 0.1154759308961600E-04, 0.3555504775624820E-05, 0.3791491409939438E+00, 0.9251916923707874E-19, 0.1302644751785016E-04, 0.1874642271188771E-04, 0.3105722740860607E+00, 0.1235671721938193E-25, 0.8697586673438179E-05, 0.7595546859022038E-05, 0.1128189367670211E+00, 0.1175733067685735E-18, 0.2174688695641498E-03, 0.1411064498403114E-03, 0.7036440937731858E-01, 0.5916456789157589E-30, 0.4997004849851516E-03, 0.7625846015345374E-03, 0.4999153992819697E-01, 0.3710108611279200E-20, 0.2898431160817185E-04, 0.2329024376647231E-03, 0.2730914559941030E-01, 0.1593079290931123E-17, 0.5731904499848677E-04, 0.7071520517918782E-04, 0.7241089204639656E-03, 0.1043820749788443E-25, 0.2096656950463827E-03, 0.4915700720935459E-03}, + info: 0, + }, + { + z: []float64{0.2129092067945103E+00, 0.6174796583507793E+00, 0.2209275310088966E+00, 0.1770681976597738E+00, 0.8468210663920229E+00, 0.7900600194799612E+00, 0.8319584509547915E+00, 0.8077183726155964E+00, 0.7964773509287093E+00, 0.2479492923952727E+00, 0.5169395370002006E-01, 0.6312063121285433E+00, 0.5688486960732374E+00, 0.3049379579822397E+00, 0.3779887662042721E+00, 0.4551165943302187E+00, 0.8807128836121972E+00, 0.1333615670826408E+00, 0.6901278826487529E+00, 0.8360350720177558E+00, 0.4190492004641316E+00, 0.9067077556412378E+00, 0.9762584494767094E+00, 0.9959763915912888E+00, 0.8503724779590973E+00, 0.6671116075685212E+00, 0.8841807167789617E+00, 0.6917331852931945E+00, 0.3414398718690443E+00, 0.2211364241075178E+00, 0.8057250135329493E+00, 0.4405475768508057E+00, 0.9321382353755537E+00, 0.6976358515081519E+00, 0.3254605598548291E+00, 0.1144237265035558E+00, 0.8547099978727912E-01, 0.3131314226614652E+00, 0.6940029038044814E+00, 0.2327469211945017E+00, 0.3523896044562020E+00, 0.6443116162172926E+00, 0.5382708884344491E+00, 0.9378966459649967E+00, 0.7274262519928346E+00, 0.4882092650189528E+00, 0.4497457043638882E+00, 0.8803511251742836E+00, 0.1077837527475992E+00, 0.4760275900323754E+00, 0.9725944612716640E+00, 0.4013370227296387E+00, 0.8188706727711300E+00, 0.7549128555022213E+00, 0.3045373312490215E+00, 0.9776368127163177E+00, 0.5516094182757485E+00, 0.8449472155130459E+00, 0.9309695118211208E+00, 0.6985346927019656E+00, 0.3270836933831586E+00, 0.2305805980953167E+00, 0.9135598850313159E+00, 0.2886818807914165E+00, 0.6607756604738726E+00, 0.7992086772120486E+00, 0.9191714969823802E+00, 0.9956222713515444E+00, 0.1646632133753003E+00, 0.8114783440114911E+00, 0.9650128806412454E+00, 0.1382218488636167E-01, 0.8464890579713791E+00, 0.2866238720970538E+00, 0.4485743907736028E-01, 0.5384705384174762E+00, 0.2996807710312754E-01, 0.7020716858392958E+00, 0.6280049430389886E+00, 0.2750308929159380E+00, 0.1648004007672321E-01, 0.8720570971091830E+00, 0.9962373992422624E+00, 0.8022759164194093E-01}, + n: 21, + zOut: []float64{0.3179557858974794E+01, 0.2694788878259719E+01, 0.2281326093492730E+01, 0.2196001939032204E+01, 0.1828355236773963E+01, 0.1586247682528960E+01, 0.1454772213395289E+01, 0.1286809233158695E+01, 0.1269332746846940E+01, 0.1099355321362049E+01, 0.9971216943768625E+00, 0.8310914612054856E+00, 0.4047131081238095E+00, 0.3869245862172090E+00, 0.3328473924133467E+00, 0.2908704078018756E+00, 0.1880200745280021E+00, 0.5784266149949692E-01, 0.4139216712761701E-01, 0.1651732519409763E-01, 0.3149646326524349E-02, 0.0000000000000000E+00, 0.5227593374295754E-11, 0.1202138413496143E-10, 0.1454772213395289E+01, 0.1393199790273629E-16, 0.1121878363020271E-09, 0.5353121918082171E-10, 0.1286809233158695E+01, 0.8659547037664508E-24, 0.1645814283637519E-08, 0.8601359367531547E-09, 0.1269332746846940E+01, 0.2823844361652584E-22, 0.5929700276768749E-08, 0.1126902625809321E-07, 0.1099355321362049E+01, 0.2358945595467410E-22, 0.2764360194400850E-05, 0.1553001254800959E-05, 0.9971216943768625E+00, 0.4450651748190101E-21, 0.2242703772863968E+02, 0.2242703772863967E+02, 0.1000000000000000E+03, 0.3015873015873016E+01, 0.3000000000000000E+01, 0.2632919892231646E-04, 0.4047131081238095E+00, 0.5820888909768840E-10, 0.2209233784503674E-04, 0.4136287504408153E-04, 0.3869245862172090E+00, 0.6462348535570008E-26, 0.3088379129783557E-03, 0.1528857353804532E-03, 0.3328473924133467E+00, 0.5549599819233453E-15, 0.8893453420684614E-08, 0.8741044673362129E-07, 0.2908704078018756E+00, 0.2289589891313465E-25, 0.5532514209995071E-04, 0.2183152999074702E-03, 0.1880200745280021E+00, 0.6113672015462841E-28, 0.9851023787951559E-03, 0.2769770083415459E-02, 0.5784266149949692E-01, 0.3571962178840741E-24, 0.3360295855593957E-02, 0.3874576703777444E-02, 0.4139216712761701E-01, 0.1555002616371658E-25, 0.3047908004675713E-02, 0.4283880536865950E-02, 0.1651732519409763E-01, 0.1498533807074276E-21, 0.9218134151523294E-06, 0.6993690185531638E-05, 0.3149646326524349E-02, 0.5476587948406352E-25, 0.9434027266146764E-03, 0.1032678112098284E-02}, + info: 0, + }, + { + z: []float64{0.5325973817915391E+00, 0.8075384328404875E+00, 0.2063920576624930E+00, 0.4895050697482526E+00, 0.3224859392283662E+00, 0.4597919629142447E+00, 0.5480240110168966E-01, 0.5228709929272914E+00, 0.9956836568223112E+00, 0.3978480622803672E+00, 0.9124816118920143E-01, 0.3247027355683270E+00, 0.9224658967837341E+00, 0.9984579111484309E+00, 0.8533112174943273E+00, 0.8907006920892125E+00, 0.3659539504394835E+00, 0.5561036191465061E+00, 0.7570794287369270E+00, 0.7781602931894585E+00, 0.8583979385494303E+00, 0.5883490719908564E+00, 0.2958788793535505E+00, 0.8441503484168636E+00, 0.7171074610327245E+00, 0.6324186559935309E+00, 0.6889002812298057E+00, 0.9679449699589238E-01, 0.8071604187540067E+00, 0.5036464295967858E+00, 0.3075050973746345E+00, 0.4354181299061508E+00, 0.5397482510302705E+00, 0.3266316370831254E+00, 0.7127302469392831E+00, 0.7822329043112050E+00, 0.1787867076882754E+00, 0.5059399114486356E+00, 0.1635357104384569E+00, 0.7923616792404551E+00, 0.8527619409672080E+00, 0.6624868870738707E+00, 0.6395827198572863E+00, 0.5045303635733072E+00, 0.5207053335438128E-01, 0.3872927271413512E+00, 0.8590236531191382E+00, 0.8644737695336893E+00, 0.5447620155822054E+00, 0.3420775682173337E+00, 0.1787889858336624E+00, 0.2962040723342502E+00, 0.1197091589896203E+00, 0.2582729465177200E+00, 0.8564224654785235E+00, 0.1003255861450059E+00, 0.5792751794645187E+00, 0.3553877787422808E+00, 0.3515051629979192E+00, 0.7026347035497048E+00, 0.7851727410421285E+00, 0.9451470000488936E+00, 0.1482591966327134E+00, 0.8035088707163867E+00, 0.8018983228501475E-02, 0.5992223740738118E+00, 0.3369698862429809E+00, 0.9971168486495201E+00, 0.7449267587097297E+00, 0.5929357935363798E+00, 0.8575900212486389E+00, 0.8115297023854162E+00, 0.3380359989630263E+00, 0.8328174310878843E+00, 0.8255713836908419E+00, 0.7399149789721748E+00, 0.1725333812438860E+00, 0.6828663265380140E+00, 0.6234367510076171E+00, 0.5628070366267671E+00, 0.8501068267959022E-01, 0.9315797050119701E+00, 0.1842029704669090E+00, 0.9504814303233714E+00}, + n: 21, + zOut: []float64{0.2923425454171414E+01, 0.2535311958925162E+01, 0.2192080092128743E+01, 0.1925146455902099E+01, 0.1841700496719334E+01, 0.1753280727277585E+01, 0.1582442080550360E+01, 0.1581069533140902E+01, 0.1420113611638973E+01, 0.1070153147168429E+01, 0.9980373856163754E+00, 0.9531244298503998E+00, 0.7077665812605668E+00, 0.5659990522281487E+00, 0.3146390113583965E+00, 0.2516605740660456E+00, 0.1663945631562664E+00, 0.1260010860507715E+00, 0.4255237190875141E-01, 0.7100815132372204E-02, 0.1566331927046113E-03, 0.4122332130840440E-22, 0.4572750287882177E-06, 0.8150029788456509E-06, 0.1582442080550360E+01, 0.6246970091107327E-19, 0.1184058245159526E-05, 0.5957129004529113E-06, 0.1581069533140902E+01, 0.2712893915232508E-21, 0.4684400026881307E-05, 0.9374804625040887E-05, 0.1420113611638973E+01, 0.4814409269321697E-22, 0.2425457953812455E-04, 0.3059673263223507E-04, 0.1070153147168429E+01, 0.4457872866361589E-11, 0.2849702090992769E-05, 0.4079444611357521E-05, 0.9980373856163754E+00, 0.2148022614677702E-19, 0.2295815606144379E+02, 0.2295815606144380E+02, 0.9700000000000000E+02, 0.2981859410430839E+01, 0.2061855670103093E+01, 0.4336961109868880E-06, 0.7077665812605668E+00, 0.3355216099479021E-19, 0.2178215603335118E-03, 0.1596478432727446E-03, 0.5659990522281487E+00, 0.3777948407501058E-19, 0.1732350582817826E-03, 0.1687341431970761E-03, 0.3146390113583965E+00, 0.4215672677501087E-24, 0.8708765796225133E-03, 0.5753505295482449E-03, 0.2516605740660456E+00, 0.8872339250080977E-20, 0.2809442395187102E-02, 0.2330568324677941E-02, 0.1663945631562664E+00, 0.1848892746611746E-31, 0.7424955400801435E-06, 0.1353946060853610E-06, 0.1260010860507715E+00, 0.7099748146989106E-27, 0.5320431162642944E-03, 0.1085271179151602E-03, 0.4255237190875141E-01, 0.2808116620904140E-21, 0.1709028753951538E-02, 0.8528114742759547E-03, 0.7100815132372204E-02, 0.4930380657631324E-31, 0.2904056487242609E-02, 0.3026916823887611E-02, 0.1566331927046113E-03, 0.0000000000000000E+00, 0.2549645590833870E-02, 0.2592045976400073E-02}, + info: 0, + }, + { + z: []float64{0.6141085085904113E+00, 0.3421028526671319E+00, 0.2523050636037050E-01, 0.6894939888024587E+00, 0.1106696902059259E+00, 0.3232796216228777E+00, 0.5026462674631121E+00, 0.4061906185674803E+00, 0.2489870821257593E+00, 0.5655528330838598E+00, 0.8215445521378404E+00, 0.6847122058387792E+00, 0.1058838690465073E+00, 0.3150742731806708E+00, 0.6299058795873502E-01, 0.2792122534089967E+00, 0.6156682980944264E+00, 0.6784924553414444E+00, 0.5548029179057333E+00, 0.9875334352131669E+00, 0.7114388615166174E+00, 0.4680838251435693E+00, 0.9939378516921551E+00, 0.9317334719497590E+00, 0.7166727913665860E+00, 0.9133735504519750E+00, 0.6652039093977162E+00, 0.8687642647047388E+00, 0.5616945762819415E+00, 0.3985759546461669E+00, 0.7431799484571856E+00, 0.7126935860242257E+00, 0.1006984098734091E+00, 0.3341210154632034E+00, 0.8752290131259591E+00, 0.9044047683690323E+00, 0.2748574881470656E+00, 0.9153414825361147E+00, 0.1879700367171477E-01, 0.4139829057070108E+00, 0.6163962814716032E+00, 0.4758310984958897E+00, 0.7283265374189019E-01, 0.4293121596195046E+00, 0.1627494487778676E+00, 0.6477819718948226E+00, 0.1769525517070647E-01, 0.8315284238294101E+00, 0.3951374239126071E-01, 0.8607842403091001E+00, 0.4542147501441236E+00, 0.7533183963616871E+00, 0.3860688952521878E+00, 0.7194066659377851E+00, 0.5625319388225433E+00, 0.2666855367146020E+00, 0.1952117588514313E+00, 0.4351982558470283E+00, 0.5735131371596182E+00, 0.6135067797741378E-01, 0.6627925797553079E+00, 0.5958408703801275E+00, 0.1272760770553625E+00, 0.9764806486481753E+00, 0.3738230266231765E+00, 0.8498786384730982E+00, 0.9509621583287799E+00, 0.5442964253426497E+00, 0.1274761736897801E+00, 0.8749459887021185E+00, 0.5319902581507450E+00, 0.4050330112540623E-01, 0.4679445276719574E-01, 0.6398654173496683E+00, 0.1619398995392787E+00, 0.2834692561637309E-01, 0.7369067773846130E+00, 0.2655208002136908E+00, 0.1902643003388997E+00, 0.7054378485643029E+00, 0.8869999325574263E+00, 0.1700725746174213E+00, 0.7638558771240449E+00, 0.3965145662986846E+00}, + n: 21, + zOut: []float64{0.3026266675500349E+01, 0.2485098580281992E+01, 0.2208517136068298E+01, 0.2089817225148914E+01, 0.1987605159106218E+01, 0.1671782272803828E+01, 0.1288709839574181E+01, 0.1226108028801468E+01, 0.1094715872236073E+01, 0.9893293804315401E+00, 0.9470004635866569E+00, 0.8354737908875075E+00, 0.7678170961167213E+00, 0.5139691139127377E+00, 0.3402258729602133E+00, 0.2640682732152568E+00, 0.1814642316568930E+00, 0.9210283120697343E-01, 0.5017295169510767E-01, 0.1311272184039149E-01, 0.2605821149103687E-06, 0.8821141249794507E-26, 0.1703621403540070E-06, 0.1022946688596755E-06, 0.1288709839574181E+01, 0.0000000000000000E+00, 0.7771811135093639E-06, 0.1129025861285597E-05, 0.1226108028801468E+01, 0.8850832554089860E-22, 0.6461044606060110E-07, 0.3214361230688769E-07, 0.1094715872236073E+01, 0.5589172803550431E-19, 0.3128365184192157E-08, 0.1088448901615084E-07, 0.9893293804315401E+00, 0.4249640396990678E-22, 0.2862531707476509E-05, 0.1047704834723032E-05, 0.9470004635866569E+00, 0.2336393132634786E-16, 0.2207335777761344E+02, 0.2207335777761343E+02, 0.1020000000000000E+03, 0.3043083900226757E+01, 0.9803921568627451E+00, 0.1031792375203169E-03, 0.7678170961167213E+00, 0.8633839815190009E-18, 0.1747705279299585E-04, 0.1213546251050483E-04, 0.5139691139127377E+00, 0.2016356967855187E-17, 0.7704963297163309E-04, 0.2063636533685701E-03, 0.3402258729602133E+00, 0.5916456789157589E-30, 0.2417908304509407E-03, 0.2207145059751390E-03, 0.2640682732152568E+00, 0.1479114197289397E-30, 0.1687694376453652E-02, 0.8888286778685235E-03, 0.1814642316568930E+00, 0.1064934658613210E-15, 0.3591290150683059E-02, 0.7604711042910346E-02, 0.9210283120697343E-01, 0.2042102137240287E-23, 0.1463034917919357E-02, 0.1882622569903463E-02, 0.5017295169510767E-01, 0.2551739098626718E-22, 0.3961160948815250E-03, 0.9438210467320612E-03, 0.1311272184039149E-01, 0.1972152263052530E-29, 0.6693623055505279E-03, 0.9046122259092353E-03, 0.2605821149103687E-06, 0.3100321587303656E-14, 0.3978735902689679E-02, 0.4253573989104679E-02}, + info: 0, + }, + { + z: []float64{0.8778106868894964E+00, 0.4777882175260769E+00, 0.1820603962716897E+00, 0.7891460918977841E+00, 0.7131176407472852E+00, 0.2166796106605611E+00, 0.7093860568912320E+00, 0.6747559124413653E+00, 0.1755802732664898E+00, 0.2538529139601842E-01, 0.3839736304139417E+00, 0.4972278527690542E+00, 0.2219918935874782E+00, 0.6587468361459490E+00, 0.6959875726535614E+00, 0.8785259347357933E+00, 0.4385001119617188E+00, 0.2992124106963234E-01, 0.9853525010355352E+00, 0.1842422327604198E-01, 0.7939453301916002E+00, 0.8502867854292200E+00, 0.6683895767567380E+00, 0.8502503508041696E+00, 0.2705991244761674E-02, 0.2273590703395093E+00, 0.1996606140173212E+00, 0.5828845765712893E+00, 0.7928614954547730E+00, 0.1675870051229429E+00, 0.3078809727828886E+00, 0.6073537805183471E-01, 0.3498986727103111E+00, 0.4266607326484094E+00, 0.7790595486765419E+00, 0.6274781693151706E+00, 0.3468808495278470E+00, 0.4002308549977796E+00, 0.8927740819756569E+00, 0.5380209790008849E+00, 0.9944530064668308E+00, 0.8382845348910617E+00, 0.6578833875204938E+00, 0.6784609218227333E-01, 0.9880398702345439E-01, 0.1591591396324092E+00, 0.3625625292925116E-01, 0.7834491156107602E+00, 0.8935128283958205E-01, 0.6534249936105881E+00, 0.9608003610697393E+00, 0.9122649849010867E+00, 0.3064782192618438E+00, 0.6165812021330105E+00, 0.3942978367050161E+00, 0.2389206118855702E+00, 0.4357310309586615E+00, 0.6366539061757281E+00, 0.2487697657706114E+00, 0.3158114775243555E+00, 0.4359459725257834E+00, 0.8521387333399649E+00, 0.7376171834812397E+00, 0.7198918826028659E+00, 0.3787355957929660E+00, 0.5132345781976363E+00, 0.5880413889667653E+00, 0.8394688090887562E+00, 0.3673771632022454E+00, 0.1291928261630060E+00, 0.6552015571219838E+00, 0.7918941075374089E+00, 0.3759434916876330E+00, 0.2131514444401432E+00, 0.5997464643577372E+00, 0.8626895671971565E+00, 0.1962050188754781E+00, 0.6291330853690040E+00, 0.6873926281549517E+00, 0.8949666870308315E-01, 0.1384684788210775E+00, 0.8959871983479050E+00, 0.5967626810459625E+00, 0.6838507108780668E+00}, + n: 21, + zOut: []float64{0.2344484145674817E+01, 0.2205594465347172E+01, 0.2180337141043826E+01, 0.1936893457336740E+01, 0.1819297464222486E+01, 0.1595314798543036E+01, 0.1497965290687764E+01, 0.1192635586559562E+01, 0.1109297670462514E+01, 0.1021894664697417E+01, 0.8474592078637809E+00, 0.7996737801504824E+00, 0.5357931354846659E+00, 0.5077230661246940E+00, 0.4005808269588222E+00, 0.2350964781455809E+00, 0.1732854339186359E+00, 0.5510322151786835E-01, 0.3865442753785928E-01, 0.1308309165665133E-01, 0.1986637888070920E-03, 0.1267902442921281E-19, 0.1632713022477316E-10, 0.9197304681744396E-11, 0.1497965290687764E+01, 0.6540946849634405E-22, 0.1644600422568816E-11, 0.2569557641484267E-11, 0.1192635586559562E+01, 0.1886570321166912E-23, 0.1155544514329289E-09, 0.3178796095468434E-10, 0.1109297670462514E+01, 0.2958228394578794E-30, 0.1814581278982536E-06, 0.5763166468812303E-07, 0.1021894664697417E+01, 0.1648133134119960E-16, 0.5817023408243420E-07, 0.2381874475610022E-07, 0.8474592078637809E+00, 0.5828670879282072E-15, 0.2051036601772319E+02, 0.2051036601772318E+02, 0.1250000000000000E+03, 0.3639455782312925E+01, 0.8800000000000001E+01, 0.1964091724818299E-07, 0.5357931354846659E+00, 0.3518203713570956E-14, 0.1200151291154190E-07, 0.2251426423705210E-07, 0.5077230661246940E+00, 0.6882401190382613E-24, 0.1803872146382089E-06, 0.4763453660743515E-06, 0.4005808269588222E+00, 0.1559915108945621E-18, 0.4978941410546894E-05, 0.5275156660739611E-05, 0.2350964781455809E+00, 0.1004043408045437E-17, 0.5647304839276210E-04, 0.2873291365503010E-04, 0.1732854339186359E+00, 0.2485883728081419E-23, 0.9907264920144563E-04, 0.1293007080503375E-03, 0.5510322151786835E-01, 0.0000000000000000E+00, 0.9623294785827948E-04, 0.7898847596644510E-04, 0.3865442753785928E-01, 0.0000000000000000E+00, 0.2279226510196514E-03, 0.3149968919986460E-03, 0.1308309165665133E-01, 0.4893402802699089E-27, 0.4145854568122489E-03, 0.3196372933697030E-03, 0.1986637888070920E-03, 0.1930680189793120E-17, 0.2183385452652873E-03, 0.3171631588309268E-03}, + info: 0, + }, + { + z: []float64{0.3053504558052776E+00, 0.2234484687205406E+00, 0.6531459952011753E+00, 0.3122060875846019E+00, 0.9991431676363117E+00, 0.2727966396486101E+00, 0.9325466197866266E+00, 0.9368849148298319E+00, 0.8561644447997885E+00, 0.1054815122266185E+00, 0.4923718332155202E-01, 0.9268095624277023E+00, 0.1888864280722891E+00, 0.7655148720572605E+00, 0.1232767826602820E+00, 0.5903563091717590E+00, 0.9248190356569348E+00, 0.5395288290327440E+00, 0.9028402566412551E+00, 0.9500520891471187E-01, 0.8953008781613688E+00, 0.2933361506740548E+00, 0.8453264440546789E+00, 0.5481580781657376E+00, 0.3587646761786403E+00, 0.5176903549368316E+00, 0.7562422108585272E+00, 0.9675296263022207E+00, 0.8986594456301542E+00, 0.5421338625853966E-01, 0.1201688601088308E+00, 0.6190380352364769E+00, 0.5038255434020116E+00, 0.6721007162690862E+00, 0.5702376374225947E+00, 0.9284095682432886E+00, 0.3695163217482177E+00, 0.6039359484498441E-01, 0.4652604684312921E+00, 0.8651698808632446E-01, 0.7546245127264203E+00, 0.7397909213681499E+00, 0.1212064081570199E+00, 0.3507242515197573E+00, 0.1903823153835104E+00, 0.7217789084869874E-01, 0.4631739813227773E+00, 0.4692891642215747E+00, 0.4583968848602870E+00, 0.1862358222844885E+00, 0.2939086301666586E+00, 0.5739509914073745E+00, 0.2602639918141684E+00, 0.7265362515535626E+00, 0.2180031380994948E+00, 0.1132710387386646E+00, 0.7997129355612416E+00, 0.7503609043894605E+00, 0.7921549516519859E+00, 0.2820213454373731E+00, 0.3757885220124352E+00, 0.7700990985029622E+00, 0.7233316318551536E+00, 0.1305854233773539E+00, 0.7245124401476205E+00, 0.5999815977622437E+00, 0.3886468370487757E+00, 0.5608149286383455E+00, 0.4298380566755162E+00, 0.6436590616913128E+00, 0.3743035898091585E-01, 0.4516061963302198E-01, 0.3504820364503235E+00, 0.4814816352089226E+00, 0.5678245050510763E+00, 0.5711961955150159E+00, 0.9549329198325482E+00, 0.8527165734568565E-01, 0.4185783350739758E-01, 0.5702414021975877E-01, 0.2302271730247050E+00, 0.7442529870754924E+00, 0.5366636699040384E+00, 0.8085683101567075E+00}, + n: 21, + zOut: []float64{0.2590499366480712E+01, 0.2541239603587953E+01, 0.2259909426243320E+01, 0.2181782566945434E+01, 0.1886341857097904E+01, 0.1651483296972034E+01, 0.1427705031981996E+01, 0.1248256205386413E+01, 0.1112814709657656E+01, 0.9343995210628773E+00, 0.8379224813887226E+00, 0.8181328249547786E+00, 0.6165308413237942E+00, 0.4939038343854810E+00, 0.4603621358717260E+00, 0.3639045182225083E+00, 0.3137819362841643E+00, 0.1577326270698492E+00, 0.8198100142281199E-01, 0.9578206270736807E-02, 0.4942793252781514E-03, 0.1292469707114106E-22, 0.1980335658106781E-04, 0.1681298419390782E-04, 0.1427705031981996E+01, 0.2584939414228211E-25, 0.8200031816835676E-05, 0.9102296987148495E-05, 0.1248256205386413E+01, 0.4930380657631324E-30, 0.4104488055426074E-09, 0.2576051753309951E-09, 0.1112814709657656E+01, 0.6452508963690269E-19, 0.2339325112754308E-08, 0.4010758969857423E-08, 0.9343995210628773E+00, 0.2041003537989240E-20, 0.4754834042401540E-06, 0.1343807701186157E-06, 0.8379224813887226E+00, 0.2942145729531872E-22, 0.2198875627193616E+02, 0.2198875627193615E+02, 0.1030000000000000E+03, 0.3158730158730159E+01, 0.5825242718446602E+01, 0.2325395492704734E-05, 0.6165308413237942E+00, 0.1475671084242936E-18, 0.4982404846255511E-06, 0.2497087821784679E-06, 0.4939038343854810E+00, 0.1295808538938520E-16, 0.6559194735079054E-05, 0.3408173383041987E-05, 0.4603621358717260E+00, 0.5811344985782108E-17, 0.9559725090946887E-05, 0.1189458663431952E-04, 0.3639045182225083E+00, 0.2913839059670682E-18, 0.4863259217476146E-04, 0.7411068946771063E-04, 0.3137819362841643E+00, 0.2338183723075079E-26, 0.4219303942492233E-03, 0.5983359002845232E-03, 0.1577326270698492E+00, 0.3451266460341927E-30, 0.4370512454739224E-03, 0.2953761682364422E-03, 0.8198100142281199E-01, 0.2482356093574565E-20, 0.7632038538424591E-04, 0.1389505478745866E-03, 0.9578206270736807E-02, 0.1680537859656637E-20, 0.1168521819007177E-01, 0.1200804951998557E-01, 0.4942793252781514E-03, 0.1967697241141140E-19, 0.1184783913560175E-01, 0.1590443390723593E-01}, + info: 0, + }, + { + z: []float64{0.9721612501531746E+00, 0.9226086145236946E+00, 0.6294635256706198E+00, 0.3023176111891041E+00, 0.6049371291087220E+00, 0.2862933293136216E+00, 0.8819078559307578E+00, 0.5258944749310531E+00, 0.1024274135843443E+00, 0.4745865163816484E+00, 0.3569366663070145E+00, 0.5081536020377282E+00, 0.6994675492692721E+00, 0.3184330055525583E+00, 0.4062572718658636E+00, 0.8497577069296732E+00, 0.7686323719242980E+00, 0.8873781649289114E+00, 0.5445815352331720E+00, 0.5465168091072755E+00, 0.2655612328242208E+00, 0.7149116271405493E+00, 0.2779393895548951E+00, 0.1344927254674255E-01, 0.4544708454847078E+00, 0.5332505496545747E-01, 0.3223583007255554E+00, 0.4314145703973596E+00, 0.6194759383350579E+00, 0.9673744275195654E+00, 0.5445933229599376E-01, 0.2359803760372408E+00, 0.4349989237395262E+00, 0.3983243124260842E+00, 0.1549760127081995E+00, 0.6483062457720113E+00, 0.9796384288763583E+00, 0.2088098624466561E-01, 0.7266086220595113E+00, 0.7787182393455840E+00, 0.2714545750078465E+00, 0.3281766266219532E-01, 0.4443206765749519E+00, 0.7385116967559627E+00, 0.4742748966298079E+00, 0.2719801119596308E+00, 0.5535252469642412E+00, 0.6819653774052530E+00, 0.5802197659205470E+00, 0.8706014802153047E+00, 0.7899732601913489E-01, 0.6149130585720997E+00, 0.1184080138409910E+00, 0.7335155686110397E+00, 0.3161056790243246E+00, 0.4751009230144272E+00, 0.6074228340613933E+00, 0.1834459697241099E+00, 0.5602196728537751E+00, 0.6036792416269905E+00, 0.4996379576165632E+00, 0.5762117563802562E+00, 0.4313302593954876E+00, 0.2357090997139660E+00, 0.5266696040444221E+00, 0.4943568418910921E+00, 0.5194970579745682E+00, 0.8729901711287622E+00, 0.1253423978225398E+00, 0.3249303186427334E+00, 0.1476841747547597E+00, 0.8115004890141919E+00, 0.3358761522855614E+00, 0.6267425544884889E+00, 0.8684373664078195E+00, 0.3410509649937432E+00, 0.1223171934609151E+00, 0.6692100819077175E+00, 0.8714060240466885E+00, 0.8435328911476530E+00, 0.3613173587051273E+00, 0.5970888673100956E+00, 0.4814113673780336E+00, 0.9518076426657822E+00}, + n: 21, + zOut: []float64{0.2554276088974017E+01, 0.2353122577016648E+01, 0.1866240795386955E+01, 0.1792222013488891E+01, 0.1776522631286352E+01, 0.1671843747376224E+01, 0.1608565757744856E+01, 0.1413448668253747E+01, 0.9978397039940720E+00, 0.9776727877490632E+00, 0.8701050228770406E+00, 0.6522479060818760E+00, 0.6295532782699175E+00, 0.4076513128864766E+00, 0.3045303763029391E+00, 0.2026925943270836E+00, 0.1597713759311400E+00, 0.1149331809326307E+00, 0.5501161781795570E-01, 0.3472328989596482E-02, 0.1615352262160075E-02, 0.2261810287929078E-15, 0.1434223756681676E-21, 0.1189989751754647E-20, 0.1608565757744856E+01, 0.1068494074045434E-17, 0.1018285523195584E-14, 0.1812446834981097E-15, 0.1413448668253747E+01, 0.8361925595342725E-26, 0.5806129122189708E-11, 0.1848580748818003E-11, 0.9978397039940720E+00, 0.5222833230866609E-21, 0.9842396145073251E-07, 0.4923018478143697E-07, 0.9776727877490632E+00, 0.9540591325261466E-21, 0.1504532523487471E-05, 0.7619936176069947E-06, 0.8701050228770406E+00, 0.2405710216561998E-25, 0.2041333911794964E+02, 0.2041333911794964E+02, 0.1050000000000000E+03, 0.3108843537414966E+01, 0.6666666666666667E+01, 0.1010063659896995E-05, 0.6295532782699175E+00, 0.2958228394578794E-30, 0.7231781167780556E-06, 0.8027785243996724E-06, 0.4076513128864766E+00, 0.2327139670401985E-28, 0.4311361064418766E-06, 0.4365718303993244E-06, 0.3045303763029391E+00, 0.3511198893363720E-17, 0.5813968676396444E-06, 0.4990623034093460E-06, 0.2026925943270836E+00, 0.5787194672316798E-22, 0.1414410322798341E-05, 0.1084116171450400E-05, 0.1597713759311400E+00, 0.3368436065293720E-27, 0.4438807230072854E-05, 0.3295442179394680E-05, 0.1149331809326307E+00, 0.3973698114522315E-22, 0.1450590122472916E-04, 0.1074561246336364E-04, 0.5501161781795570E-01, 0.1153335343143272E-20, 0.9954779132989017E-07, 0.6305695341872095E-07, 0.3472328989596482E-02, 0.7183968878891587E-15, 0.2465868832870137E-03, 0.3524118878925340E-03, 0.1615352262160075E-02, 0.1517768381645227E-26, 0.5410549418889337E-03, 0.6396403869804795E-03}, + info: 0, + }, + { + z: []float64{0.9945523629868341E+00, 0.6311483525653909E+00, 0.7029190400645571E+00, 0.6452581068575963E+00, 0.9353553331334358E+00, 0.1547193049011500E+00, 0.5087511216875095E+00, 0.8821879483245458E+00, 0.5873463835171173E+00, 0.3391476900726194E+00, 0.3121839954924539E+00, 0.2777103145160921E+00, 0.2404463284577694E+00, 0.9114535183484027E+00, 0.4707329974301702E+00, 0.8965398451252625E+00, 0.6082343132413309E+00, 0.6509204493235183E+00, 0.1573499033176421E+00, 0.7416865701488552E+00, 0.1617007503826062E-01, 0.9896605969885931E+00, 0.3427350027671039E+00, 0.9677837053324486E+00, 0.1744936477417883E+00, 0.1063275349300943E+00, 0.7956875801511568E+00, 0.8998967378241718E-01, 0.9957418429488507E-01, 0.2587083053394715E+00, 0.3753593926504107E+00, 0.7537263520315082E+00, 0.1726167393116790E+00, 0.1420490749456633E+00, 0.1475360304745418E+00, 0.3281044300775052E+00, 0.4011897283558843E+00, 0.5039659382748809E+00, 0.8444659776686902E-01, 0.6685320205580927E+00, 0.8425776598223370E+00, 0.6334616337862548E+00, 0.6754035119469365E+00, 0.3594856315188868E+00, 0.4308279252773916E+00, 0.2170629535054914E+00, 0.5040120070238915E+00, 0.3780998968579012E+00, 0.9176188652711103E+00, 0.1603892455353655E+00, 0.2475008720560291E+00, 0.4414989878913728E+00, 0.3466658552370731E+00, 0.3098329951977107E+00, 0.8940921934240968E+00, 0.6686136942966417E+00, 0.4049936818549904E-01, 0.1308695446239941E+00, 0.8770734618597430E+00, 0.7917220872288512E+00, 0.5736823795257117E+00, 0.5474219864141461E+00, 0.3320663514826834E+00, 0.5824816531032581E+00, 0.6748067573570548E+00, 0.8139348519761679E+00, 0.1984641509226878E+00, 0.5557729841117627E+00, 0.1101812804319026E+00, 0.2169710965518002E+00, 0.5846617154920911E+00, 0.9784843983810533E+00, 0.8650267562586114E+00, 0.4041298540058539E+00, 0.9548165813531374E+00, 0.3839697059508718E+00, 0.4296171922210591E+00, 0.9617664542372570E+00, 0.2102779850721345E+00, 0.6135130181658475E+00, 0.3331715196673474E+00, 0.3177082868916457E+00, 0.2836520073686416E+00, 0.4452894940247868E+00}, + n: 21, + zOut: []float64{0.2413112525759640E+01, 0.2309698811549223E+01, 0.1971065496840386E+01, 0.1839093033734385E+01, 0.1586321309986888E+01, 0.1384287501933647E+01, 0.1357349915568794E+01, 0.1342137050614370E+01, 0.1098398899504136E+01, 0.1013688381736709E+01, 0.8838922773071145E+00, 0.7023193003094995E+00, 0.6083268670387161E+00, 0.3967105732701523E+00, 0.3295901758335739E+00, 0.2610566591740404E+00, 0.2254040681461952E+00, 0.1107925081061023E+00, 0.7084089717166595E-01, 0.5790734022898784E-02, 0.1162539701808497E-05, 0.2217532248565769E-17, 0.1400266087055540E-09, 0.1806586784837133E-09, 0.1357349915568794E+01, 0.1160047396826257E-18, 0.1994113072724655E-16, 0.4228494360227003E-16, 0.1342137050614370E+01, 0.1172187884313513E-15, 0.1255075745859590E-14, 0.2503873040081153E-15, 0.1098398899504136E+01, 0.3711182370878063E-20, 0.5744299067797088E-08, 0.4873476684669810E-08, 0.1013688381736709E+01, 0.1283916659070448E-18, 0.9737119066622311E-08, 0.8382615528986061E-08, 0.8838922773071145E+00, 0.3385457556489824E-15, 0.1990987815014785E+02, 0.1990987815014784E+02, 0.1050000000000000E+03, 0.3324263038548753E+01, 0.5714285714285714E+01, 0.5531678096648157E-07, 0.6083268670387161E+00, 0.9327491343333244E-26, 0.3094358165149238E-06, 0.4992693882721107E-06, 0.3967105732701523E+00, 0.1615587133892632E-26, 0.5013465632663534E-06, 0.4474558637993164E-06, 0.3295901758335739E+00, 0.7527343574232552E-22, 0.6917755140723670E-06, 0.9191878134168280E-06, 0.2610566591740404E+00, 0.8992644540970212E-27, 0.3283328599477859E-08, 0.8980185396558612E-09, 0.2254040681461952E+00, 0.2761013168273541E-29, 0.1566859737304233E-05, 0.9651044230345755E-05, 0.1107925081061023E+00, 0.7853700447084989E-18, 0.2494389596499284E-03, 0.3103855763358142E-03, 0.7084089717166595E-01, 0.7910121402691465E-20, 0.9848486231185840E-03, 0.1285663115805527E-02, 0.5790734022898784E-02, 0.1925929944387236E-33, 0.1531134660067926E-02, 0.1103959511478054E-02, 0.1162539701808497E-05, 0.0000000000000000E+00, 0.3553926119432854E-02, 0.1161337136649311E-01}, + info: 0, + }, + { + z: []float64{0.6912525216559012E+00, 0.7535513505900934E+00, 0.9471932644608124E+00, 0.3186447229836621E+00, 0.5324891284853083E+00, 0.8568362673509099E+00, 0.7683599820389093E+00, 0.5584553004793524E+00, 0.5571013534938567E+00, 0.9300192917069305E-01, 0.8580829209571639E+00, 0.7019126526839274E+00, 0.6637712341629651E+00, 0.1211000088170944E+00, 0.6340253546080570E+00, 0.8089912896293909E+00, 0.9056005723453709E+00, 0.8259750504337368E+00, 0.7787230128973186E+00, 0.5552567089885843E+00, 0.1575217143336131E+00, 0.6258385609742768E+00, 0.3943745586872103E+00, 0.2414131111537543E-02, 0.1491577729788018E-01, 0.3231570165180105E+00, 0.6629837458829935E+00, 0.3692715436026686E+00, 0.4217957028148089E+00, 0.9587355452830710E+00, 0.2048474370070816E+00, 0.9514275263988156E+00, 0.6824099372375696E+00, 0.4368303647429550E-01, 0.1779948598152153E+00, 0.8894462775192779E+00, 0.5101271266317630E+00, 0.9448652224292025E+00, 0.2265718177112338E+00, 0.3995811139403516E+00, 0.8380789267629041E+00, 0.6621441253102893E+00, 0.1548712624835822E+00, 0.6028850196944033E+00, 0.6938032609628844E+00, 0.6847684356722229E+00, 0.5160938472467536E+00, 0.2489894297094153E+00, 0.1603949345362032E-01, 0.8469682453172568E+00, 0.1332301650751776E+00, 0.4964641576870391E+00, 0.8955382322295532E+00, 0.8913224930710517E-01, 0.1632933980261509E+00, 0.7671629642421702E+00, 0.1918190416387825E+00, 0.4660642407804531E+00, 0.3421851388276426E+00, 0.6793284417353496E-03, 0.4856583571413033E+00, 0.6596584184483706E+00, 0.3999565195667565E-01, 0.4265147212719423E+00, 0.1721559491949431E-01, 0.4779030554385033E-01, 0.9628058707102425E+00, 0.4575395386200597E+00, 0.3526890078762277E+00, 0.7271726865364773E+00, 0.1741804541232641E+00, 0.3524640041347155E+00, 0.2143698389021181E+00, 0.9553499123803968E+00, 0.7803670081719427E+00, 0.7906509834069840E+00, 0.5939624443460740E+00, 0.5439294231719827E+00, 0.4026522884432556E+00, 0.2400403086558794E+00, 0.1695045416332096E+00, 0.8774151073165960E+00, 0.9528799076371641E-01, 0.6357307125994049E-01}, + n: 21, + zOut: []float64{0.2768602537214622E+01, 0.2449987435840808E+01, 0.2103617452638331E+01, 0.2091492233971247E+01, 0.2040261542124423E+01, 0.1984511273424848E+01, 0.1507960384149227E+01, 0.1491386484166052E+01, 0.1283295633334833E+01, 0.1065640575633715E+01, 0.9760063516861833E+00, 0.9535053549649605E+00, 0.6117733318422185E+00, 0.5156356643703764E+00, 0.4217391763517565E+00, 0.2514332616796913E+00, 0.1056943786041289E+00, 0.6556299181229375E-01, 0.2554189252987301E-01, 0.1599343544217954E-01, 0.7248128851221257E-03, 0.1757582096832414E-26, 0.8938568486456872E-12, 0.7801064326234513E-12, 0.1507960384149227E+01, 0.1792073872399063E-19, 0.2167105506392983E-08, 0.2566615495401212E-08, 0.1491386484166052E+01, 0.2939740300877914E-17, 0.1513553473151668E-08, 0.1292098164447321E-08, 0.1283295633334833E+01, 0.5002192774679673E-18, 0.3422853236655498E-09, 0.3087733884567774E-09, 0.1065640575633715E+01, 0.2649562899583917E-24, 0.1824851422869684E-09, 0.1969539993879423E-09, 0.9760063516861833E+00, 0.4849588587138365E-15, 0.2273036620466689E+02, 0.2273036620466689E+02, 0.1110000000000000E+03, 0.3401360544217687E+01, 0.6306306306306307E+01, 0.7012703734578152E-09, 0.6117733318422185E+00, 0.2636779683484747E-15, 0.8832037497597917E-08, 0.1377654767646391E-07, 0.5156356643703764E+00, 0.0000000000000000E+00, 0.4403364729024244E-07, 0.2921450058151117E-07, 0.4217391763517565E+00, 0.5116160632510206E-16, 0.4627032593211780E-06, 0.6780935482482274E-06, 0.2514332616796913E+00, 0.3477119313860159E-18, 0.8396751469149006E-05, 0.1191099168408868E-04, 0.1056943786041289E+00, 0.3125614770312806E-14, 0.3873238345753621E-04, 0.1564927337192913E-03, 0.6556299181229375E-01, 0.2145521217817673E-17, 0.9476510350371504E-03, 0.9104754488359111E-03, 0.2554189252987301E-01, 0.1508279173816323E-23, 0.1093077353977330E-02, 0.3191708039391989E-03, 0.1599343544217954E-01, 0.1319576415787468E-18, 0.1003863779460019E-02, 0.1271197433268307E-02, 0.7248128851221257E-03, 0.5169135658374832E-21, 0.1128681157512944E-02, 0.4574374031799749E-02}, + info: 0, + }, + { + z: []float64{0.8514967554120231E+00, 0.1903564904561825E+00, 0.9315134585755248E+00, 0.6865565499502658E+00, 0.9874780893034819E+00, 0.4243732836164926E-01, 0.4493254789963134E+00, 0.1218497220886967E+00, 0.3032420422448456E-01, 0.4472006833337416E+00, 0.7764061193501844E+00, 0.2765680149425037E+00, 0.1540380964603436E+00, 0.8227084597523057E+00, 0.1281873340097673E+00, 0.2797045229662546E+00, 0.1723485697940061E+00, 0.5407468670158238E+00, 0.3703892253237170E+00, 0.3275545813562609E+00, 0.1384768695152372E+00, 0.8683661690082241E+00, 0.2417038393999236E+00, 0.1573965961648072E+00, 0.7549703050710239E+00, 0.4197135409081310E+00, 0.5565257749798536E-01, 0.7494783707245707E+00, 0.8342833407960080E+00, 0.7207413539297494E+00, 0.3936911272324267E+00, 0.8307872407436112E-01, 0.5696677800088412E-01, 0.2580569153061851E-01, 0.3976149332803511E+00, 0.4082340292723502E+00, 0.3620800929220623E+00, 0.2078006460748600E+00, 0.6810562489816266E+00, 0.8414616295760738E+00, 0.2053319202340824E+00, 0.7745582586901971E+00, 0.8243869237197288E-01, 0.7513634029365589E+00, 0.8658814490552211E+00, 0.7014202441287165E-01, 0.8786892218281559E+00, 0.2415414918645031E-01, 0.1648367770784782E+00, 0.5852629690413500E+00, 0.6558826026732849E+00, 0.3505171007322015E+00, 0.5959744796861849E+00, 0.6000199298251039E+00, 0.5156931460104713E+00, 0.1010243586499049E-01, 0.2804608587164645E+00, 0.7088599878489240E+00, 0.3159377781412633E+00, 0.1196632783263437E+00, 0.8053993759743566E+00, 0.9537751230670044E+00, 0.6890540876884894E+00, 0.7327967809533995E+00, 0.1752177926983489E-01, 0.1176294169286665E+00, 0.1417165464977135E+00, 0.1128117051181837E+00, 0.4431718138373526E+00, 0.6383761487884151E+00, 0.4394388749172047E+00, 0.4496324720961747E+00, 0.2336818223819791E+00, 0.8283237197456694E+00, 0.5968446077081969E+00, 0.2123688346867825E-03, 0.2316409292069651E+00, 0.4041203764036865E+00, 0.5989557684304492E-01, 0.1751475090786662E+00, 0.3300532749209990E+00, 0.5257653351639615E+00, 0.9423173850128755E+00, 0.5110067889308013E+00}, + n: 21, + zOut: []float64{0.2298367449128524E+01, 0.2183508003369306E+01, 0.1768578955898148E+01, 0.1497740650820804E+01, 0.1451044171656134E+01, 0.1248562072819587E+01, 0.1096241131844911E+01, 0.1047761158237631E+01, 0.1036921434023463E+01, 0.1001878203872264E+01, 0.6028997776208512E+00, 0.5966927468392602E+00, 0.3787547972649039E+00, 0.3164597916816877E+00, 0.2770907680746649E+00, 0.1378928396715414E+00, 0.1008983167754413E+00, 0.7523836829300481E-01, 0.4549396861483578E-01, 0.2905908538794771E-01, 0.1164397397714791E-04, 0.2593449025859535E-11, 0.4028878361793870E-19, 0.4523833078775027E-19, 0.1096241131844911E+01, 0.2254118867995285E-20, 0.6781252758190456E-19, 0.6132859990189332E-19, 0.1047761158237631E+01, 0.2208810534618833E-28, 0.7941399228881527E-19, 0.8755467647203911E-19, 0.1036921434023463E+01, 0.2697904295855860E-27, 0.1193508568348155E-18, 0.1375302458176128E-18, 0.1001878203872264E+01, 0.1808754486438286E-19, 0.1585460437287443E-17, 0.7110442921296878E-18, 0.6028997776208512E+00, 0.1121217470921487E-23, 0.1719109533586889E+02, 0.1719109533586889E+02, 0.1020000000000000E+03, 0.3002267573696145E+01, 0.7843137254901960E+01, 0.6126841018734423E-14, 0.3787547972649039E+00, 0.2514494135391975E-29, 0.3694268515215640E-12, 0.2142184401680204E-12, 0.3164597916816877E+00, 0.2495880173472380E-22, 0.1052194788283320E-11, 0.1801542652052392E-11, 0.2770907680746649E+00, 0.2042405059827892E-23, 0.3416315088185822E-10, 0.1784450556067769E-10, 0.1378928396715414E+00, 0.2231720057459842E-17, 0.5936850868223322E-09, 0.2792901329469146E-09, 0.1008983167754413E+00, 0.4009937753419447E-25, 0.1438568455567306E-07, 0.6376284135652434E-08, 0.7523836829300481E-01, 0.1673899732006569E-23, 0.3811420638095229E-06, 0.1677978014843256E-06, 0.4549396861483578E-01, 0.4108428387966160E-20, 0.9969899927958168E-05, 0.2238705130236833E-04, 0.2905908538794771E-01, 0.5621738354967019E-25, 0.1622697124847995E-03, 0.1340889241809050E-03, 0.1164397397714791E-04, 0.4733165431326071E-29, 0.2205086015306072E-02, 0.1109731617446849E-02}, + info: 0, + }, + { + z: []float64{0.9566341326420642E+00, 0.1368890791339401E+00, 0.1041033686995702E+00, 0.1843288381431366E+00, 0.9983016155690853E+00, 0.1786866722264480E+00, 0.3401743522788719E+00, 0.3857333052582377E+00, 0.5001620282112933E+00, 0.9013417473823726E+00, 0.9483009872337210E+00, 0.8066933876879568E+00, 0.5299205541713562E+00, 0.1746250429119467E-01, 0.9676426134678857E+00, 0.9451210738656991E+00, 0.4964770237154315E+00, 0.7837324008636358E+00, 0.9355959680316486E+00, 0.6160646886859618E+00, 0.3400424465599898E+00, 0.5332164761252830E+00, 0.3086260018745091E+00, 0.7161810741898500E+00, 0.9586563909920308E+00, 0.5072089025298385E+00, 0.5345428289191819E+00, 0.3564033548208417E+00, 0.5073508962435702E-01, 0.5457190349920044E+00, 0.5924351087865416E+00, 0.4551284321479383E+00, 0.1212070325395470E+00, 0.4136992969230449E+00, 0.9668715153070689E+00, 0.5158905905227948E+00, 0.3815356588296225E+00, 0.9643666102790432E+00, 0.2243124357596349E-01, 0.1865949320717719E+00, 0.7081123336136068E+00, 0.8847286955309422E+00, 0.8075237017566694E+00, 0.7058935338718864E+00, 0.8930194548226011E-01, 0.5968683124630468E+00, 0.6423123320238798E+00, 0.4264046421741549E+00, 0.6535060636263267E+00, 0.8848885990305457E+00, 0.1727496532173951E+00, 0.2233116713730792E+00, 0.5179656160482806E+00, 0.8833427955005373E+00, 0.5463392573098168E+00, 0.2339495215057854E+00, 0.2531599269911875E+00, 0.8693933445310196E+00, 0.9904673923253784E+00, 0.5001765262594373E+00, 0.8475066901059425E+00, 0.7747140538451288E+00, 0.8097617518836179E+00, 0.6177833422496881E+00, 0.4294196301939426E+00, 0.8754149021622922E+00, 0.1154777972031917E+00, 0.4002319777705416E+00, 0.8948519482752643E+00, 0.2680092666078437E-01, 0.4982362166797213E+00, 0.8946688039099321E+00, 0.6004540842339657E+00, 0.7864972660235388E+00, 0.5343742612900907E+00, 0.6804570163829448E+00, 0.8534533212497195E+00, 0.6588190749186591E+00, 0.3987256626502571E+00, 0.9641448737959348E+00, 0.8049200655531427E+00, 0.8429466638354991E+00, 0.3173537092974966E+00, 0.2969758130071765E+00}, + n: 21, + zOut: []float64{0.2691092090580979E+01, 0.2651656165852700E+01, 0.2273892452779949E+01, 0.2046491657483657E+01, 0.1856589708219707E+01, 0.1474606896148613E+01, 0.1449970763396692E+01, 0.1157826920722246E+01, 0.1131422765724169E+01, 0.1103316690199991E+01, 0.1081571209422854E+01, 0.8863514547656711E+00, 0.7487688552248520E+00, 0.4946957959671176E+00, 0.3261665336572834E+00, 0.2704116388140369E+00, 0.1035778920187539E+00, 0.8274904671505576E-01, 0.4712842456001845E-01, 0.3463118683574901E-01, 0.5254769424391846E-04, 0.2373014771939845E-22, 0.2238209824420786E-09, 0.1516830937674482E-09, 0.1449970763396692E+01, 0.6496080927593321E-18, 0.4705401432274776E-09, 0.6877602609145650E-09, 0.1157826920722246E+01, 0.9485735114056482E-11, 0.6765447972194981E-08, 0.9075269590011981E-08, 0.1131422765724169E+01, 0.0000000000000000E+00, 0.2115471642425146E-07, 0.1586124232313620E-07, 0.1103316690199991E+01, 0.1685550134725853E-21, 0.9651672077875321E-13, 0.7184159896265294E-12, 0.1081571209422854E+01, 0.5505416081326749E-23, 0.2191297069678434E+02, 0.2191297069678434E+02, 0.1080000000000000E+03, 0.3308390022675737E+01, 0.4629629629629630E+01, 0.3615019372146533E-05, 0.7487688552248520E+00, 0.2711157159063573E-25, 0.1185348717221526E-04, 0.1538970705040117E-04, 0.4946957959671176E+00, 0.7711572887860419E-23, 0.5228762878644057E-04, 0.2140066476035995E-04, 0.3261665336572834E+00, 0.1027012207743053E-16, 0.1058102716324823E-03, 0.1097923206605328E-03, 0.2704116388140369E+00, 0.1419949629397821E-27, 0.3075139383959133E-03, 0.2041016121130936E-03, 0.1035778920187539E+00, 0.1569288801032274E-18, 0.2245437021601444E-03, 0.2161294383881767E-03, 0.8274904671505576E-01, 0.1322963914266329E-22, 0.4098429023844965E-03, 0.2685224923308173E-03, 0.4712842456001845E-01, 0.1972152263052530E-27, 0.1445743106447529E-03, 0.3591079434142046E-04, 0.3463118683574901E-01, 0.1109335647967048E-30, 0.1752604588321185E-04, 0.1168961103966469E-04, 0.5254769424391846E-04, 0.0000000000000000E+00, 0.7596773881065606E-02, 0.6101958366533248E-02}, + info: 0, + }, + { + z: []float64{0.8353120998595153E+00, 0.2762691216596785E+00, 0.4005263075088337E+00, 0.2013066591993183E+00, 0.7159087664363259E+00, 0.6826958051178053E+00, 0.3940626911632166E+00, 0.4990834556070268E+00, 0.6760530863202496E-02, 0.5490926358579395E-01, 0.1673564807759778E+00, 0.6884305772394704E+00, 0.3902830106720901E+00, 0.9394502319309270E+00, 0.1453732258871473E+00, 0.6913382271536774E+00, 0.4797608951630542E+00, 0.8813081041297155E+00, 0.7179153476502249E+00, 0.8684015860527726E+00, 0.4912919359735076E+00, 0.2734537604788182E+00, 0.6687443482830383E+00, 0.1554406884207427E+00, 0.2919860915775756E+00, 0.2642733542167044E+00, 0.8429147529046822E+00, 0.2888320698097314E+00, 0.8826173246454528E+00, 0.8977386905269689E+00, 0.7688524109189127E+00, 0.9833521147086286E+00, 0.9216258197795713E-01, 0.4886212819310254E-01, 0.2266462269156035E+00, 0.3411440109054314E+00, 0.3008601997419669E-01, 0.6174499545648404E+00, 0.5004878789063633E+00, 0.6820549240543587E+00, 0.2697209119346977E-01, 0.5561910637447186E+00, 0.5496066776611622E+00, 0.5185759009159874E+00, 0.1533641991284778E+00, 0.9896294286837857E+00, 0.3752499036369343E+00, 0.6748924776803822E-01, 0.2328081038279309E+00, 0.6721552304404512E+00, 0.5472950056303504E+00, 0.9949773164461492E+00, 0.5646629720515278E+00, 0.4280389734679516E+00, 0.4488723317267336E+00, 0.7263390986042261E+00, 0.2371171913738990E-01, 0.2980895305269504E-01, 0.2561842200752050E+00, 0.2554059142478259E+00, 0.5952758446711104E-01, 0.7921877816291150E+00, 0.2045719212105177E+00, 0.9215889426626128E+00, 0.7130733301970400E+00, 0.1420514661017834E+00, 0.8292002693849506E+00, 0.5327095640926792E+00, 0.9857821333545339E+00, 0.6686900428841760E+00, 0.1963263366455671E+00, 0.2881353528210300E+00, 0.7077457532403378E+00, 0.9075905470440924E+00, 0.1600253949359417E+00, 0.1037543259304946E+00, 0.3343707004174388E+00, 0.7287034220491817E-01, 0.8402900560224008E+00, 0.1343632243665364E+00, 0.8746515522185468E+00, 0.4102434537961821E+00, 0.1922774302984470E+00, 0.7386986269659255E+00}, + n: 21, + zOut: []float64{0.2705701250380865E+01, 0.2517516394575531E+01, 0.1823532784589120E+01, 0.1787562059778101E+01, 0.1543666662169401E+01, 0.1517718677289282E+01, 0.1380407836894782E+01, 0.1248997815711926E+01, 0.1005808190406691E+01, 0.8278526045363968E+00, 0.6708485238929687E+00, 0.6082664705845506E+00, 0.5949155529076431E+00, 0.3419285270749396E+00, 0.2930861537880754E+00, 0.2677590880174420E+00, 0.1897681878114907E+00, 0.4498262444281959E-01, 0.4027859329477797E-01, 0.1212960387301111E-02, 0.4788271754899720E-05, 0.2113479533223326E-17, 0.1072835726919963E-07, 0.2769573896400322E-08, 0.1380407836894782E+01, 0.2075077381359190E-19, 0.2509615479685493E-12, 0.8472237738633739E-13, 0.1248997815711926E+01, 0.8862433277732312E-18, 0.5565142852935547E-10, 0.1115246324111066E-09, 0.1005808190406691E+01, 0.1508363342119467E-20, 0.4766364300104371E-06, 0.1686414207934524E-06, 0.8278526045363968E+00, 0.2958228394578794E-30, 0.1339811587116281E-04, 0.9618739022097639E-05, 0.6708485238929687E+00, 0.5096041447727736E-27, 0.1941181574680586E+02, 0.1941181574680586E+02, 0.1100000000000000E+03, 0.3301587301587301E+01, 0.6363636363636363E+01, 0.2769598741382734E-05, 0.5949155529076431E+00, 0.1660823573641619E-23, 0.5008194680845295E-05, 0.3644576454263968E-05, 0.3419285270749396E+00, 0.8597611808520244E-19, 0.8197192371775147E-05, 0.1495511835801176E-04, 0.2930861537880754E+00, 0.6452008777913547E-22, 0.7613853051650506E-05, 0.9176969716117157E-05, 0.2677590880174420E+00, 0.1626694295438144E-23, 0.2172962611604878E-06, 0.9910144268854854E-06, 0.1897681878114907E+00, 0.5698278443334010E-17, 0.3051734820342141E-03, 0.3112883552318466E-03, 0.4498262444281959E-01, 0.6022708464481807E-24, 0.1205042765713422E-04, 0.1759326252954196E-04, 0.4027859329477797E-01, 0.1150776253123047E-20, 0.1426316484726719E-04, 0.9508927802446297E-05, 0.1212960387301111E-02, 0.3136662420452545E-23, 0.9384394253406367E-03, 0.4268700521479601E-03, 0.4788271754899720E-05, 0.0000000000000000E+00, 0.1227549320701017E-01, 0.5132215250850077E-02}, + info: 0, + }, + { + z: []float64{0.6118263281058917E+00, 0.9095172470423057E+00, 0.3600259528878788E+00, 0.2816648927398081E+00, 0.1399164597780194E+00, 0.8570391268113827E+00, 0.6056165732881742E+00, 0.8852338629006543E+00, 0.5421670517489531E+00, 0.6780884449288360E+00, 0.8758212925230515E+00, 0.8288674605669587E+00, 0.6440226363310471E+00, 0.5894956271378661E+00, 0.5783475018163303E+00, 0.3156005123186516E+00, 0.8703974350876685E+00, 0.2617715240366199E+00, 0.8370578409687427E+00, 0.5560169751702698E+00, 0.7455275952513329E-01, 0.7082615127868872E+00, 0.1297707357428401E-02, 0.3064709066297203E+00, 0.8391571848933236E+00, 0.9253805128965463E+00, 0.1130984054668048E+00, 0.8319072101853607E+00, 0.7799276064931965E+00, 0.8579163369971375E+00, 0.5543120979067712E+00, 0.1549966158329672E+00, 0.2643029344048516E+00, 0.8314141615883028E+00, 0.5782452249644381E+00, 0.6319732449892587E+00, 0.4892864093075822E+00, 0.1584418066385224E+00, 0.1120577745932696E+00, 0.6617954786615949E+00, 0.1159882395495345E+00, 0.2876505945591634E+00, 0.7061058070010036E+00, 0.7252986915993946E+00, 0.6775944839786487E+00, 0.7230010551819884E+00, 0.6571938557215073E+00, 0.7482251296401533E+00, 0.9684494841571512E-01, 0.1940071502680237E+00, 0.8896785746779762E+00, 0.9170179284973872E+00, 0.8053995841969270E+00, 0.9321965525342302E+00, 0.7288973738137661E-01, 0.3849028957514653E+00, 0.4410947536600551E+00, 0.4770808300783691E-01, 0.3690162722923055E+00, 0.1908498348358704E+00, 0.8094133574022262E+00, 0.4809437445509840E+00, 0.1405808283203624E+00, 0.4482801388864215E+00, 0.7023724161235537E+00, 0.5041894616412674E+00, 0.2984594028552712E+00, 0.8510121345026274E+00, 0.7612412832182369E-01, 0.8890771840141870E+00, 0.8611357776125709E+00, 0.7702458212424681E+00, 0.8813091992976040E+00, 0.3838156614335277E+00, 0.1536911508311884E+00, 0.2763378258408019E+00, 0.7613349010649187E+00, 0.4228084592762277E+00, 0.5894002697827440E+00, 0.5744691724607953E-01, 0.3014767112059925E+00, 0.7221203248495245E-01, 0.7619553096876313E+00, 0.5154237548276358E+00}, + n: 21, + zOut: []float64{0.2723457737035386E+01, 0.2426437846006860E+01, 0.2169822787916940E+01, 0.1997417054976096E+01, 0.1928996526776896E+01, 0.1891356815602834E+01, 0.1803418741268920E+01, 0.1442378108645599E+01, 0.1026854281138765E+01, 0.9766368850685674E+00, 0.8449303421617025E+00, 0.7575761304896602E+00, 0.7013909577306906E+00, 0.6362631409338654E+00, 0.3605885444762012E+00, 0.1912852882240109E+00, 0.1837209447646653E+00, 0.1221129878112117E+00, 0.2486838916706533E-01, 0.9765050532318768E-02, 0.3171294864219318E-06, 0.1371236688474761E-19, 0.2987011438498780E-15, 0.8087574764480620E-15, 0.1803418741268920E+01, 0.5451390847569379E-21, 0.7270236634641202E-11, 0.2896404140496822E-11, 0.1442378108645599E+01, 0.6954964380428437E-14, 0.4131395561099005E-08, 0.7275670618661885E-08, 0.1026854281138765E+01, 0.1292469707114106E-25, 0.1838064307199299E-06, 0.1238204560933622E-06, 0.9766368850685674E+00, 0.3388131789017201E-20, 0.3880169268725981E-06, 0.5681289313967714E-06, 0.8449303421617025E+00, 0.6785686819474261E-17, 0.2221927887785774E+02, 0.2221927887785774E+02, 0.1080000000000000E+03, 0.3244897959183673E+01, 0.4629629629629630E+01, 0.3025393053677348E-08, 0.7013909577306906E+00, 0.1341063538875720E-28, 0.3767849368753714E-07, 0.3184959175038880E-07, 0.6362631409338654E+00, 0.8874685183736383E-29, 0.5999352088776256E-07, 0.7114794232343430E-07, 0.3605885444762012E+00, 0.1582265649256097E-24, 0.2391907791779699E-03, 0.3344095791507466E-03, 0.1912852882240109E+00, 0.1130832107634320E-25, 0.4040482702647743E-03, 0.3567248396804949E-03, 0.1837209447646653E+00, 0.4930380657631324E-31, 0.1016317982961682E-02, 0.8970313840717793E-03, 0.1221129878112117E+00, 0.2076836816009399E-16, 0.1892596629513954E-02, 0.2329446640559320E-02, 0.2486838916706533E-01, 0.1713835026472478E-23, 0.3568672048225553E-04, 0.1599561599209249E-03, 0.9765050532318768E-02, 0.0000000000000000E+00, 0.3650779499194616E-03, 0.5712243726145556E-03, 0.3171294864219318E-06, 0.8599783076848839E-19, 0.2181668718924628E-02, 0.9598847336904798E-03}, + info: 0, + }, + { + z: []float64{0.1133237741366075E+00, 0.6519297783748091E+00, 0.1419059404596466E+00, 0.6942573823108688E+00, 0.4899507169502382E-03, 0.4408585439270172E+00, 0.4089484333544855E+00, 0.8087151633238087E+00, 0.7299241994604067E-01, 0.7772039339909241E+00, 0.6160100823712519E+00, 0.1679565169487562E+00, 0.3276744683398485E+00, 0.8481565553508272E+00, 0.5614085421003249E+00, 0.5889702994117808E+00, 0.9865181317193454E+00, 0.5686958983255483E+00, 0.2173616127956169E+00, 0.6617740807852496E+00, 0.1324295788322836E+00, 0.5932751564887147E+00, 0.4417023572495267E+00, 0.8308006832392040E+00, 0.6963900525231828E+00, 0.7023649910778577E+00, 0.2540087053190563E+00, 0.5116605124111596E+00, 0.4580501208371790E+00, 0.9900881058795367E+00, 0.6233054379975522E+00, 0.5093215893644945E+00, 0.8805051397371310E+00, 0.5918749676473295E+00, 0.8024628157090720E+00, 0.1089848141144264E+00, 0.9385822032209372E+00, 0.9676954608704463E+00, 0.7567544231269694E+00, 0.7763472508927070E+00, 0.7544500156824916E+00, 0.7080578938468585E-02, 0.8622695184492650E+00, 0.1268681530179145E+00, 0.2408963669487220E+00, 0.1909503620360825E+00, 0.9251648557888137E-01, 0.4447315055648083E+00, 0.1504005134322962E+00, 0.6245252202415555E+00, 0.8432800589533600E+00, 0.1408178180805120E+00, 0.8538656063298837E+00, 0.6959250082173740E-01, 0.7452290984944354E-01, 0.8186895700534982E+00, 0.4817344889163616E+00, 0.8941802149688474E+00, 0.8277272846279742E+00, 0.3122760515919010E+00, 0.4631046821883726E+00, 0.9939521405533804E+00, 0.5067334594578294E+00, 0.3251044449945518E+00, 0.4514296322650755E+00, 0.9520015267726308E+00, 0.3811787795610073E+00, 0.6466473208499942E+00, 0.1035647165455822E-01, 0.3768739780085785E+00, 0.7301131130949717E+00, 0.6341150979687762E+00, 0.2006486990564113E+00, 0.7995641372737874E+00, 0.3501522989293299E+00, 0.7212117404145123E+00, 0.3724384783514179E+00, 0.2704745802524587E+00, 0.5954948132025037E+00, 0.8796174543237598E+00, 0.2533217117523398E+00, 0.2406431629179949E+00, 0.4238947154458014E+00, 0.1002294321190256E+00}, + n: 21, + zOut: []float64{0.2763722715135843E+01, 0.2473753815483350E+01, 0.2367461218794171E+01, 0.2245079256722998E+01, 0.1833576927640889E+01, 0.1670289128561736E+01, 0.1457654822263786E+01, 0.1350493275779479E+01, 0.1277854548609735E+01, 0.1156481310792204E+01, 0.1106963375568883E+01, 0.8704957369830484E+00, 0.6845380809859644E+00, 0.4950109522946930E+00, 0.4198272059610658E+00, 0.2867476262636770E+00, 0.2180239597616727E+00, 0.1578141753335409E+00, 0.1153511714179556E+00, 0.2506658150747594E-01, 0.5048803894682267E-08, 0.8470329472540474E-20, 0.3080709680328647E-07, 0.2263725078605666E-07, 0.1457654822263786E+01, 0.6882142696441190E-21, 0.4511645736903135E-07, 0.5799182381327367E-07, 0.1350493275779479E+01, 0.3225542408567476E-17, 0.3673248914261325E-08, 0.2431637013515395E-08, 0.1277854548609735E+01, 0.1479114197289397E-30, 0.1457855695816495E-07, 0.1029378003116242E-07, 0.1156481310792204E+01, 0.9441087313685069E-24, 0.4178859307872738E-07, 0.3166226192774972E-07, 0.1106963375568883E+01, 0.1745440919131533E-19, 0.2297620589091097E+02, 0.2297620589091097E+02, 0.9600000000000000E+02, 0.3092970521541950E+01, 0.3125000000000000E+01, 0.2193086683474567E-06, 0.6845380809859644E+00, 0.6815668447404457E-13, 0.1173742870849872E-05, 0.2415236474615244E-05, 0.4950109522946930E+00, 0.4604423331594002E-25, 0.1089056660110428E-04, 0.1249035785040860E-04, 0.4198272059610658E+00, 0.2034864306780130E-21, 0.1807219455044531E-04, 0.1582973453084106E-04, 0.2867476262636770E+00, 0.1157544870450433E-16, 0.1788428346885188E-06, 0.1048647571833164E-05, 0.2180239597616727E+00, 0.2820966597070338E-26, 0.2675556367648033E-04, 0.1965631735302374E-04, 0.1578141753335409E+00, 0.4632909363938796E-19, 0.6657143729168815E-04, 0.2311126907684945E-04, 0.1153511714179556E+00, 0.7089566920435294E-17, 0.2519028315687161E-03, 0.1126597449160621E-03, 0.2506658150747594E-01, 0.1511791266627385E-18, 0.1819059120658101E-02, 0.1223404988252185E-02, 0.5048803894682267E-08, 0.5048803894682267E-08, 0.1176483960189416E-01, 0.7561758166988619E-02}, + info: 0, + }, + { + z: []float64{0.6007483099411913E+00, 0.8757604992442719E+00, 0.3498665716095440E+00, 0.4974125174432915E+00, 0.3942177430818359E+00, 0.4655097178512825E+00, 0.7062255099400584E+00, 0.5955461614709365E+00, 0.5705117921786074E+00, 0.2580859610386106E+00, 0.5213970441770472E+00, 0.3227485215512098E+00, 0.8200431655548257E-01, 0.9521784777464899E+00, 0.9768302381970198E+00, 0.5401259459761943E+00, 0.2876249345369413E+00, 0.9928912621382637E+00, 0.9068004769556834E+00, 0.8136746797372185E+00, 0.6557906174128045E+00, 0.7593059043472016E+00, 0.7306718357524993E+00, 0.7872142480398446E+00, 0.2169453387448870E+00, 0.1236189910537125E+00, 0.4376414329540577E+00, 0.2475974410903709E+00, 0.5743712937757064E+00, 0.8451940172770922E+00, 0.2954362279165403E+00, 0.9333330371592371E+00, 0.7261884685452219E+00, 0.2905925760133674E+00, 0.3022535752338255E+00, 0.6907049310391071E+00, 0.2616870809800952E+00, 0.3758121789769751E+00, 0.7112612645989228E+00, 0.9602233026485287E+00, 0.7212734445945013E+00, 0.9266335266312882E+00, 0.7829804394259932E-01, 0.6683939253194693E+00, 0.3539007443404153E+00, 0.1629995906155713E+00, 0.2470024645126471E+00, 0.7250237828800384E+00, 0.9725422312806663E+00, 0.1983270881451602E+00, 0.2167236969811593E+00, 0.2406674239058443E+00, 0.3811046126380717E+00, 0.6358718370494476E-01, 0.6038903598347725E+00, 0.2622945348536884E+00, 0.4871669697876424E+00, 0.1853788955105938E+00, 0.3471794920367192E+00, 0.9520318129455714E+00, 0.9596274379126818E+00, 0.5893179749928269E+00, 0.8560240909608330E-01, 0.9435308110759013E+00, 0.2058424446004554E+00, 0.2877465111691004E+00, 0.6254635389850627E+00, 0.5518846905281638E-01, 0.1132608874973561E+00, 0.8191427866511807E+00, 0.1031178242713734E+00, 0.1909407653284053E+00, 0.5428362177906626E+00, 0.2973328401307228E+00, 0.6079142025065691E+00, 0.1448090006401505E+00, 0.5807148716343321E+00, 0.2207276122221573E+00, 0.4617526470734991E+00, 0.2133930631010816E-01, 0.8719991154365724E+00, 0.4224743304865443E+00, 0.7012315055540164E+00, 0.9970966526798359E+00}, + n: 21, + zOut: []float64{0.2875734378878489E+01, 0.2344615299508293E+01, 0.2292398069608056E+01, 0.2200897502376554E+01, 0.2016889876654445E+01, 0.1997885510503641E+01, 0.1786196162676624E+01, 0.1505330793574375E+01, 0.1193246823746953E+01, 0.1153847743209180E+01, 0.9864509519829328E+00, 0.8076407462080507E+00, 0.6427729668463894E+00, 0.4808392927305387E+00, 0.3994667257867982E+00, 0.3273321022655395E+00, 0.1654363687174887E+00, 0.1176242694536732E+00, 0.4639514928819789E-01, 0.1592499252046327E-01, 0.3521629889976334E-03, 0.1784216669875992E-16, 0.7121431862167897E-10, 0.2812798494121821E-10, 0.1786196162676624E+01, 0.4108568523994154E-17, 0.4438281217193102E-07, 0.2274689950145052E-07, 0.1505330793574375E+01, 0.7499168293791558E-11, 0.5226296435976747E-05, 0.8641809444662033E-05, 0.1193246823746953E+01, 0.0000000000000000E+00, 0.2628223783350490E-04, 0.3987870710471355E-04, 0.1153847743209180E+01, 0.5865702946789929E-16, 0.1241308452869419E-07, 0.3894882997253744E-08, 0.9864509519829328E+00, 0.7673863643253590E-18, 0.2335727788952568E+02, 0.2335727788952568E+02, 0.1040000000000000E+03, 0.3058956916099773E+01, 0.2884615384615385E+01, 0.3948721236408985E-04, 0.6427729668463894E+00, 0.1028674620408199E-26, 0.2391232675375281E-03, 0.2086678697444007E-03, 0.4808392927305387E+00, 0.3130051437900657E-19, 0.1426864276581422E-03, 0.1522473256880454E-03, 0.3994667257867982E+00, 0.2101777886998446E-24, 0.1526280399103512E-05, 0.7002070790936748E-06, 0.3273321022655395E+00, 0.1242239255406691E-15, 0.1253374424171423E-04, 0.2848254240665514E-04, 0.1654363687174887E+00, 0.2455402723507254E-17, 0.1659752591164777E-02, 0.8476830847116842E-03, 0.1176242694536732E+00, 0.1344218982496604E-26, 0.1195138829435961E-02, 0.1583065192028977E-02, 0.4639514928819789E-01, 0.2205655090997949E-26, 0.2795062437264197E-03, 0.9604240981222648E-03, 0.1592499252046327E-01, 0.6574583373762050E-21, 0.7008887495297913E-02, 0.4078689360266482E-02, 0.3521629889976334E-03, 0.2981894221735425E-26, 0.7785429009218255E-02, 0.8697865294154498E-02}, + info: 0, + }, + { + z: []float64{0.3565428176835072E+00, 0.1947118362244993E+00, 0.7741156920152520E+00, 0.2422304602782238E+00, 0.6344560478781652E+00, 0.6454994272905118E+00, 0.1782236022643452E+00, 0.1761708296759242E+00, 0.4902923959906477E+00, 0.3501715044277058E+00, 0.8606282659620700E+00, 0.4671519599404039E-03, 0.9177061631942818E+00, 0.9869535184930249E+00, 0.9615604930014852E+00, 0.2283553018405985E+00, 0.2470322441623238E+00, 0.5789642646481346E+00, 0.9797717987449011E+00, 0.2628090453859127E+00, 0.1063995753795172E+00, 0.9446865880365994E+00, 0.8109285339456792E+00, 0.4534650679402863E-01, 0.9560542860825706E+00, 0.7338084401822241E+00, 0.4719995459594307E+00, 0.8981162685661518E+00, 0.6088366551058919E+00, 0.4061662134958367E+00, 0.6141507801286759E+00, 0.7683300427463863E+00, 0.2030033710532269E+00, 0.5109903203799075E+00, 0.1295039929316932E-01, 0.1313823831505738E+00, 0.4600541675974348E+00, 0.8052912479215125E+00, 0.7315674921483241E+00, 0.1311059905375703E+00, 0.9372521946935908E-01, 0.2804058432106148E+00, 0.1426401168120447E+00, 0.1302494454623315E-01, 0.9936953989155247E+00, 0.7109841901452127E+00, 0.8438933393801377E+00, 0.5599779486257196E+00, 0.6224094357036947E-01, 0.3722277721927331E+00, 0.2128496963914419E+00, 0.2132595627624145E+00, 0.1761474673379855E+00, 0.5003566260610350E+00, 0.5448249098276142E+00, 0.5701738373290982E+00, 0.5196161461339291E+00, 0.4684002904633344E-01, 0.3091316721875115E+00, 0.9311143262655500E+00, 0.5165589926587729E+00, 0.4230658512580241E+00, 0.1580095970610971E+00, 0.9213403630754643E+00, 0.8395102804227733E+00, 0.6279936637330286E-01, 0.2118369865058433E+00, 0.5654902136914255E+00, 0.8603345552081203E+00, 0.6355651085391135E+00, 0.9504788095745560E+00, 0.4928822316317183E+00, 0.8546738890428598E+00, 0.1506739079739667E+00, 0.7955004699434830E+00, 0.8623803468730415E+00, 0.3328976137523824E+00, 0.6282681071703561E+00, 0.5253150183233042E+00, 0.5508861108006231E+00, 0.8482246434328706E+00, 0.3438184421622726E+00, 0.4546750663905129E+00, 0.2702842147468514E+00}, + n: 21, + zOut: []float64{0.2599043716461175E+01, 0.2392272222815941E+01, 0.1945154273268249E+01, 0.1882117601080557E+01, 0.1808214125087810E+01, 0.1701027479657859E+01, 0.1674631474676720E+01, 0.1432830957842129E+01, 0.1245386641860508E+01, 0.1003047986420639E+01, 0.5925499318269597E+00, 0.5737323778075372E+00, 0.4619197085153934E+00, 0.3795861721644865E+00, 0.2896752472940557E+00, 0.2024598813435771E+00, 0.1753335138277014E+00, 0.8865983947068434E-01, 0.4088280438555415E-01, 0.2271023207656241E-01, 0.3207012114254504E-03, 0.1328658858913301E-22, 0.6931093261583948E-12, 0.1962539051213948E-11, 0.1674631474676720E+01, 0.1972152263052530E-30, 0.1003060686577864E-09, 0.7786971971568132E-10, 0.1432830957842129E+01, 0.3552283923653146E-20, 0.1335875663368593E-08, 0.1098996752778210E-08, 0.1245386641860508E+01, 0.6078417508770261E-16, 0.6005521677860925E-08, 0.4565873133117504E-08, 0.1003047986420639E+01, 0.4907378230941548E-20, 0.6042756667162823E-07, 0.1337733817342293E-06, 0.5925499318269597E+00, 0.7849166006949067E-28, 0.2051155688909552E+02, 0.2051155688909552E+02, 0.1190000000000000E+03, 0.3632653061224490E+01, 0.6722689075630252E+01, 0.9823469248695270E-04, 0.4619197085153934E+00, 0.3582825487703231E-19, 0.4408755124729528E-13, 0.6425665938157879E-14, 0.3795861721644865E+00, 0.3049769924381334E-19, 0.2649002399507504E-08, 0.1284693180187630E-07, 0.2896752472940557E+00, 0.2730342256278547E-24, 0.3857186710932351E-04, 0.7729247272182434E-05, 0.2024598813435771E+00, 0.2411244474478362E-13, 0.9974443273860175E-04, 0.7715885583051736E-04, 0.1753335138277014E+00, 0.1003583340528496E-19, 0.1275804036051463E-05, 0.1384195629265487E-05, 0.8865983947068434E-01, 0.1976477763343393E-17, 0.9250271469637329E-05, 0.1838436200742544E-04, 0.4088280438555415E-01, 0.1570480975080192E-18, 0.1665813744256122E-03, 0.9368787794988337E-04, 0.2271023207656241E-01, 0.1120555887990158E-19, 0.1174000031728850E-02, 0.1217958466428532E-03, 0.3207012114254504E-03, 0.0000000000000000E+00, 0.1126152474028795E-01, 0.4219515300090987E-02}, + info: 0, + }, + { + z: []float64{0.1431540885741494E+00, 0.8417471667062104E+00, 0.3721480902981644E-01, 0.9023772086815021E+00, 0.7374866167630612E-01, 0.8092071841305744E+00, 0.8019394206305236E+00, 0.4350675566733520E+00, 0.8704440278245326E+00, 0.8549104680538234E+00, 0.1422025173760633E+00, 0.8968456705882693E+00, 0.1647179447265090E-01, 0.8994077105608889E-01, 0.8596481603583839E-02, 0.3900328616396558E+00, 0.4012630844305533E+00, 0.8262908556770313E+00, 0.9026062467432411E+00, 0.6485345137550630E+00, 0.5598932241080331E+00, 0.6084992568220661E+00, 0.5039450314115669E+00, 0.3490854750626526E+00, 0.9921372250281116E+00, 0.1522469068827847E-01, 0.9395473455386270E+00, 0.3928498832803473E-01, 0.1672951108814763E+00, 0.9480670302336689E+00, 0.8743929741539138E+00, 0.9201765927311700E-01, 0.8641536356563365E+00, 0.8867562289118487E+00, 0.7156446870854873E+00, 0.5025184567500440E-01, 0.4878799838415181E+00, 0.5568327059782646E+00, 0.4596548235310455E+00, 0.6857902774944131E+00, 0.4795565553491499E-01, 0.4752906527216701E+00, 0.9288351773531449E+00, 0.7419018575576386E+00, 0.9987802353476521E+00, 0.8896105755435116E+00, 0.3190450046252536E+00, 0.9685806853440787E+00, 0.3396383774694021E+00, 0.9164401886915974E+00, 0.1269879571285023E+00, 0.7912318128907188E+00, 0.9987805345221650E+00, 0.4107567957671243E+00, 0.4798441760727139E+00, 0.2357309197085595E+00, 0.3404494185276096E+00, 0.7067865773496134E+00, 0.2931542927088892E+00, 0.6654441577727066E+00, 0.9279529535770864E+00, 0.9667208022109988E+00, 0.5518920376663735E+00, 0.1657487215954807E+00, 0.3897636058410684E+00, 0.9489706352102197E+00, 0.9626390247015670E+00, 0.1020775856599213E+00, 0.3545784768064359E+00, 0.3098089336816090E+00, 0.3791089991258285E+00, 0.6519489570740321E+00, 0.4763523952410913E+00, 0.3754524631080590E+00, 0.9792813089520809E+00, 0.1998301915332230E+00, 0.7618060057813935E+00, 0.1923436350325713E+00, 0.2507012719817848E+00, 0.9704520069999245E-01, 0.2277384851702763E+00, 0.7790727508043876E+00, 0.9105177383528497E+00, 0.9714469561729607E+00}, + n: 21, + zOut: []float64{0.2499720115178021E+01, 0.2371028651009860E+01, 0.2298220416774619E+01, 0.1883765650093571E+01, 0.1735426237683963E+01, 0.1616050162695453E+01, 0.1545275083087796E+01, 0.1187762610175739E+01, 0.1136805332133151E+01, 0.9576839460725933E+00, 0.9184986446054146E+00, 0.7702442640767845E+00, 0.6433137908930019E+00, 0.6160049176831036E+00, 0.3208789970551323E+00, 0.1900871628722621E+00, 0.9670499780074775E-01, 0.7460708611062000E-01, 0.6486083888512703E-01, 0.9966295048259487E-02, 0.4462615269650136E-07, 0.2765885173224186E-23, 0.3446029508568731E-11, 0.2660256849760007E-11, 0.1545275083087796E+01, 0.1351675564459578E-15, 0.5238898174323723E-11, 0.6640890994279970E-11, 0.1187762610175739E+01, 0.1020402561847179E-21, 0.5048392892414130E-10, 0.4263729817754413E-10, 0.1136805332133151E+01, 0.1429794613494979E-24, 0.1140378416083416E-09, 0.8548580688939750E-10, 0.9576839460725933E+00, 0.1302866745903472E-12, 0.1207358062805810E-07, 0.1106598026337004E-07, 0.9184986446054146E+00, 0.3538135823224864E-23, 0.2093690524456137E+02, 0.2093690524456137E+02, 0.1130000000000000E+03, 0.3331065759637188E+01, 0.7964601769911504E+01, 0.4249897555997367E-08, 0.6433137908930019E+00, 0.4627357327667341E-16, 0.5702383148705814E-08, 0.8656383665454304E-08, 0.6160049176831036E+00, 0.0000000000000000E+00, 0.4551987331271016E-07, 0.8434005257711676E-07, 0.3208789970551323E+00, 0.2939872200043623E-13, 0.4894684795516590E-05, 0.8200734504818474E-05, 0.1900871628722621E+00, 0.9080407486043539E-23, 0.2659953011765320E-05, 0.2713538128245964E-05, 0.9670499780074775E-01, 0.1949336478520425E-16, 0.1287973346598181E-04, 0.3266830247798530E-04, 0.7460708611062000E-01, 0.0000000000000000E+00, 0.5588793940970657E-03, 0.8233963212342685E-03, 0.6486083888512703E-01, 0.1680331387617770E-17, 0.5510428852120968E-02, 0.6166917183278490E-02, 0.9966295048259487E-02, 0.9229672591085838E-28, 0.3019065027713110E-04, 0.7674568090533565E-04, 0.4462615269650136E-07, 0.1609276246650864E-27, 0.6212935138424260E-03, 0.6196304337665942E-02}, + info: 0, + }, + { + z: []float64{0.2117689827794353E+00, 0.3469390325266096E+00, 0.8556157513093896E+00, 0.4757820823688597E-01, 0.8174618541686680E+00, 0.7502623797079592E+00, 0.3473865910309967E+00, 0.1102061280439136E+00, 0.3838366632541155E+00, 0.4335750892772081E+00, 0.8350483733926333E+00, 0.8472841724322083E+00, 0.7001411292294977E+00, 0.1602971622162627E+00, 0.8475208106005836E+00, 0.1606731136869689E+00, 0.1282020202063155E+00, 0.7021142414638628E+00, 0.6509542291315448E+00, 0.3403267711628978E+00, 0.2783715946342622E+00, 0.2391807909006515E+00, 0.9326061845277929E+00, 0.8200594229325990E+00, 0.5326312099842309E+00, 0.4390518762985745E+00, 0.9087332134146432E+00, 0.8586305843825174E+00, 0.5289458618923581E+00, 0.6098713986238019E+00, 0.4124733909450122E+00, 0.2730411694523917E+00, 0.8437528550291284E+00, 0.6776322145297138E+00, 0.6772761566308538E+00, 0.6457716484911746E+00, 0.4290441069454122E+00, 0.9486890113840626E+00, 0.1145429178800543E+00, 0.8512453512490206E+00, 0.6435458910126746E+00, 0.6571563420730420E-01, 0.6473933144723745E+00, 0.2355560081089225E+00, 0.1262112692360912E+00, 0.6892345322103945E+00, 0.9088034154559810E-01, 0.5725023743105110E+00, 0.8924086653580375E+00, 0.6645221244511262E+00, 0.7287357579298158E+00, 0.6462379994906295E+00, 0.8254375000545862E+00, 0.2402799002378904E+00, 0.2312499677892260E+00, 0.7164295349077132E-01, 0.1216505240532725E+00, 0.5279275209153104E+00, 0.2010432640871422E+00, 0.2335833224032272E+00, 0.7053869472451330E+00, 0.1271428628255256E-01, 0.5920854820119847E-01, 0.1973220586788875E+00, 0.9024202349843203E+00, 0.2696040474399301E+00, 0.2399100427530529E+00, 0.4936945945994136E+00, 0.7377918193661529E+00, 0.4454167008139350E+00, 0.6822934143143184E+00, 0.1980205964978332E+00, 0.9382259163150929E+00, 0.7952650736079295E+00, 0.2147267423149601E+00, 0.2160850567828982E+00, 0.2063316967709339E-02, 0.4613555480251579E+00, 0.2983741464914229E+00, 0.7653433710630531E+00, 0.9319255930520460E+00, 0.9624604653562387E+00, 0.7921958309630666E+00, 0.3349247737517954E+00}, + n: 21, + zOut: []float64{0.2554012710728313E+01, 0.2350385283314499E+01, 0.2336543487584985E+01, 0.2078331003959482E+01, 0.1819938506810449E+01, 0.1751888604422140E+01, 0.1642765030717598E+01, 0.1391850148176030E+01, 0.1265614265169072E+01, 0.1192296172100378E+01, 0.1118290194286764E+01, 0.7471001949454404E+00, 0.6602310515087256E+00, 0.5223373748122110E+00, 0.3101567956620342E+00, 0.2634177676934227E+00, 0.1468471914237014E+00, 0.9669691105737251E-01, 0.6862527639473751E-01, 0.2251868425683227E-01, 0.2442899974694956E-02, 0.0000000000000000E+00, 0.3247526756203984E-07, 0.3301672636248404E-07, 0.1642765030717598E+01, 0.2849742554922193E-13, 0.2093860354423170E-09, 0.9504157619668633E-09, 0.1391850148176030E+01, 0.5471978423050590E-17, 0.2765846142955850E-06, 0.3763175370346248E-06, 0.1265614265169072E+01, 0.7099748146989106E-29, 0.8629250150360319E-06, 0.7218261937815504E-06, 0.1192296172100378E+01, 0.0000000000000000E+00, 0.1792585742344500E-05, 0.1391262462240339E-05, 0.1118290194286764E+01, 0.2158808112824856E-22, 0.2234228955499889E+02, 0.2234228955499888E+02, 0.1130000000000000E+03, 0.3253968253968254E+01, 0.7079646017699115E+01, 0.1273852622682608E-03, 0.6602310515087256E+00, 0.1370219837932689E-23, 0.6841106514156665E-04, 0.6915431692027581E-04, 0.5223373748122110E+00, 0.8086955524743426E-16, 0.3151324787101243E-03, 0.4936870820060986E-03, 0.3101567956620342E+00, 0.1690864291947714E-17, 0.5342613094053112E-03, 0.4525307423692253E-03, 0.2634177676934227E+00, 0.1569544193046020E-19, 0.8085628512848309E-03, 0.5320256570924908E-03, 0.1468471914237014E+00, 0.1725633230170963E-30, 0.2171574910172427E-04, 0.7393923467130197E-05, 0.9669691105737251E-01, 0.8185725058097063E-19, 0.6259416979424432E-04, 0.7993629240914341E-04, 0.6862527639473751E-01, 0.1144304443709360E-17, 0.8363460972147480E-05, 0.2145990923718838E-04, 0.2251868425683227E-01, 0.3423656328659191E-26, 0.4258124540743150E-02, 0.4456054742147899E-02, 0.2442899974694956E-02, 0.7553929676107889E-20, 0.1657093833399320E-01, 0.2123214045479585E-01}, + info: 0, + }, + { + z: []float64{0.5143465832338334E-01, 0.9671338481452775E+00, 0.2594126021369855E+00, 0.4887933538896223E+00, 0.4809357095031462E+00, 0.1648852435705869E+00, 0.5382296047886386E+00, 0.2404093745709619E+00, 0.5749849863516346E+00, 0.8755417117410101E+00, 0.6479432781744229E+00, 0.8462387170859478E+00, 0.1030360983310576E+00, 0.2790419505795448E+00, 0.2643216914883461E+00, 0.5072751399665939E+00, 0.9813013168637370E+00, 0.5270325239254721E+00, 0.1341185443667956E+00, 0.1666757001787883E+00, 0.8421762037577841E+00, 0.6333707418037352E+00, 0.9714076539879462E+00, 0.8133030640726957E-01, 0.5961674478430062E+00, 0.9962348063653491E+00, 0.9690228851917282E-02, 0.4933763527820312E-01, 0.1005560439675963E+00, 0.9794838233988775E+00, 0.8412211319105695E+00, 0.4530689238841823E+00, 0.9824397821984348E+00, 0.9435184376619912E+00, 0.5899369853858024E+00, 0.3347062982138894E+00, 0.6634688706474758E+00, 0.7781534216536603E+00, 0.5213269680559092E+00, 0.2415498257414400E+00, 0.4153017903771141E+00, 0.6142268391585892E-01, 0.1582256219487426E+00, 0.5180630943028907E+00, 0.2531248086553088E+00, 0.4588063905612799E+00, 0.9850645955475579E-01, 0.4386688206276981E+00, 0.6723312445641013E+00, 0.2417358982121058E+00, 0.9102202020018957E+00, 0.4790528316718639E+00, 0.8645283277006380E+00, 0.5896385561561974E+00, 0.3547186358320912E+00, 0.2570702739547999E+00, 0.8872414069371877E+00, 0.7977277358714381E+00, 0.2283476919840042E+00, 0.5481349489617042E+00, 0.9565429487676439E+00, 0.3941453871538936E-01, 0.2005355998230810E+00, 0.6815820255993522E+00, 0.8827641753074383E+00, 0.3721138471690448E+00, 0.3473678385941080E+00, 0.5958558861949184E+00, 0.5289126915593071E+00, 0.7848410946975201E+00, 0.9380898148044153E+00, 0.4238368524709774E+00, 0.9095202310640094E-01, 0.5205916750079600E+00, 0.3388678441932766E+00, 0.9218715971576251E+00, 0.2785357832665022E+00, 0.7353529037048490E+00, 0.3430576699659011E+00, 0.1583386336396764E-03, 0.1574217518812531E+00, 0.2808549182652627E+00, 0.9165809855463820E+00, 0.2729923295285186E-01}, + n: 21, + zOut: []float64{0.2740279952468604E+01, 0.2296796691149573E+01, 0.2162929780566866E+01, 0.2022438316208162E+01, 0.1971555203048247E+01, 0.1712998698314224E+01, 0.1596820997274643E+01, 0.1536702996895977E+01, 0.1112897445143912E+01, 0.8259900943746278E+00, 0.7751147071242228E+00, 0.6231241133597348E+00, 0.5263220334234422E+00, 0.4481765711163059E+00, 0.4215577615769598E+00, 0.1440581718410880E+00, 0.1296344814538628E+00, 0.5340807481344281E-01, 0.1871489185523312E-01, 0.3434703213692513E-02, 0.2376961512853157E-03, 0.2255238469879073E-22, 0.1711146112720571E-14, 0.5183409008081618E-15, 0.1596820997274643E+01, 0.0000000000000000E+00, 0.1075504130778587E-11, 0.4005497363076952E-12, 0.1536702996895977E+01, 0.1981618593915182E-26, 0.4700742807330894E-10, 0.1164621641126979E-09, 0.1112897445143912E+01, 0.4726602108594632E-24, 0.9459556816770867E-09, 0.1692486098434743E-08, 0.8259900943746278E+00, 0.0000000000000000E+00, 0.4245107391668450E-08, 0.4612248550244559E-08, 0.7751147071242228E+00, 0.8284213834597216E-21, 0.2112319338137411E+02, 0.2112319338137411E+02, 0.1000000000000000E+03, 0.2931972789115646E+01, 0.2000000000000000E+01, 0.1818678155237499E-07, 0.5263220334234422E+00, 0.4246772729828520E-23, 0.1119198730079850E-06, 0.4602199017952358E-06, 0.4481765711163059E+00, 0.1035379938102578E-29, 0.2940687130487931E-04, 0.4282452030972280E-04, 0.4215577615769598E+00, 0.5276311108751726E-20, 0.8277389737129399E-05, 0.6004055084531256E-05, 0.1440581718410880E+00, 0.0000000000000000E+00, 0.8355340113184283E-05, 0.1023986211128489E-04, 0.1296344814538628E+00, 0.1552281967638183E-19, 0.6343521312985942E-05, 0.6697527987420460E-05, 0.5340807481344281E-01, 0.6040133837432384E-17, 0.1556990792688111E-03, 0.3593183434334682E-03, 0.1871489185523312E-01, 0.1153562559317783E-18, 0.8237486079760113E-03, 0.4973426416094711E-03, 0.3434703213692513E-02, 0.0000000000000000E+00, 0.1008741049678482E-02, 0.1888495698860201E-02, 0.2376961512853157E-03, 0.2773339119917620E-31, 0.6098206042824776E-05, 0.1474144332182451E-03}, + info: 0, + }, + { + z: []float64{0.1099031735712288E+00, 0.5724174842808358E+00, 0.3122550743498126E+00, 0.7231231021981217E+00, 0.6175771623314344E+00, 0.5814310193624382E+00, 0.6423493353686718E+00, 0.8309609356975209E+00, 0.6400193102877816E-01, 0.8728840273137624E+00, 0.8682274216885312E+00, 0.7829529646382269E+00, 0.4658588928084396E+00, 0.4997300418007194E+00, 0.5750522308672811E+00, 0.5282811502940782E+00, 0.7877382060309071E+00, 0.2242905591148447E-01, 0.9672168595892823E+00, 0.9229185948074735E+00, 0.7120977511666169E+00, 0.9513613307832994E+00, 0.6495350224590044E+00, 0.1796094611119584E+00, 0.6238202085518583E+00, 0.4056553414984787E-01, 0.2863733551163383E-01, 0.7740758620163646E-01, 0.1652368945937387E+00, 0.5017774327613052E+00, 0.6445125305703996E+00, 0.5670374114090049E-01, 0.1147723121006077E+00, 0.5126855432858525E+00, 0.9526888308153642E+00, 0.1724272641761350E+00, 0.9682495468226523E+00, 0.2579549866163475E+00, 0.5365442422680400E+00, 0.7055455249537391E+00, 0.6510869341601188E+00, 0.6910931676909811E+00, 0.8245356137796966E+00, 0.2467134555988069E+00, 0.2932965007679977E-01, 0.3174819406165880E+00, 0.1008447548759832E+00, 0.7998426243165985E+00, 0.6780870841109060E+00, 0.2896057920811994E+00, 0.9303619290394473E+00, 0.3607716194531815E+00, 0.5211419140438559E+00, 0.1046120770241560E+00, 0.7683871590101677E+00, 0.2147990043395044E+00, 0.6702055898403114E+00, 0.2446830800671760E+00, 0.1275992810549672E+00, 0.9234458715873217E+00, 0.6974016894347440E+00, 0.2461420250226486E+00, 0.2448954779360711E+00, 0.1956976010946661E+00, 0.8608131397075515E+00, 0.7387865940798233E-01, 0.5053692911917109E+00, 0.3354069180988316E+00, 0.4024076719528004E+00, 0.5167351886997615E+00, 0.7829885112810930E-01, 0.3735275576161866E+00, 0.9546718920527260E+00, 0.5321377922787256E+00, 0.6121034951800618E+00, 0.8028222695558183E+00, 0.3295254582685344E+00, 0.5907471536091985E+00, 0.8247143229089846E+00, 0.1329486496858557E+00, 0.9484305946158008E+00, 0.4510190965747323E+00, 0.1159598040227069E+00, 0.7290524870797256E+00}, + n: 21, + zOut: []float64{0.2759844065448739E+01, 0.2469029941309663E+01, 0.2170232676307031E+01, 0.1960369893365743E+01, 0.1773994559660628E+01, 0.1654180064160601E+01, 0.1454572475268221E+01, 0.1398795476174613E+01, 0.1260788731803824E+01, 0.1011169812035994E+01, 0.9032283997666860E+00, 0.7344998632955592E+00, 0.6915613254033124E+00, 0.3097922830021908E+00, 0.2074097203460417E+00, 0.1750683611049406E+00, 0.1335859329381489E+00, 0.1070304609992355E+00, 0.6466361262660925E-01, 0.1024517112836532E-01, 0.4658519939343828E-03, 0.5916456789157589E-30, 0.2414839775472174E-07, 0.1563475838564645E-07, 0.1454572475268221E+01, 0.5710570490785520E-12, 0.1598956453701674E-05, 0.9938094799470723E-06, 0.1398795476174613E+01, 0.7078291130367095E-25, 0.1301105456376455E-06, 0.7650088290739393E-07, 0.1260788731803824E+01, 0.6660939091008025E-19, 0.3865722666202593E-07, 0.5454440035759107E-07, 0.1011169812035994E+01, 0.5414223942436753E-17, 0.3344051754361652E-04, 0.2635566037358100E-04, 0.9032283997666860E+00, 0.5272968833424410E-16, 0.2125052867814009E+02, 0.2125052867814008E+02, 0.1090000000000000E+03, 0.3179138321995465E+01, 0.2752293577981651E+01, 0.8667028517906969E-06, 0.6915613254033124E+00, 0.6016648435007899E-23, 0.2921486269254270E-05, 0.9773987035049091E-05, 0.3097922830021908E+00, 0.6500213859021137E-26, 0.6786203908623285E-05, 0.1231548092049969E-04, 0.2074097203460417E+00, 0.0000000000000000E+00, 0.7819652657144090E-06, 0.1217347772587842E-05, 0.1750683611049406E+00, 0.6582255393164123E-26, 0.1458540666485106E-06, 0.3789967922095048E-07, 0.1335859329381489E+00, 0.1232595164407831E-31, 0.4615373247666497E-05, 0.3177332815969559E-05, 0.1070304609992355E+00, 0.5947376905467984E-20, 0.9914288367235413E-05, 0.1492808588608919E-04, 0.6466361262660925E-01, 0.5865227530883812E-22, 0.3814164765172745E-05, 0.1095283410948310E-05, 0.1024517112836532E-01, 0.3761300629007363E-24, 0.3159730783704485E-04, 0.5907442037524074E-05, 0.4658519939343828E-03, 0.2094421310984266E-20, 0.1426408794386696E-02, 0.1350744215392459E-02}, + info: 0, + }, + { + z: []float64{0.1337238926382778E+00, 0.3106335653974364E+00, 0.8951406789337562E+00, 0.2282076226383426E+00, 0.3559900270036094E+00, 0.1333708564991680E+00, 0.9225357561814306E+00, 0.6383337981459615E+00, 0.7455817572577521E+00, 0.9604635037498299E-01, 0.1362822625756884E+00, 0.7894982141438661E+00, 0.5371956247017955E+00, 0.2757551089818502E+00, 0.9298698100988576E+00, 0.8755382224220718E+00, 0.2542040210765101E+00, 0.1287904754285962E+00, 0.6810846780454294E+00, 0.6526638813043742E+00, 0.5955845877046446E+00, 0.4670096896697419E+00, 0.5475207984291373E+00, 0.6684162034597571E+00, 0.5235410539200527E+00, 0.7337617639827179E+00, 0.8903194008545992E+00, 0.8072217495300122E+00, 0.3881183186356038E+00, 0.9675156751063907E+00, 0.4869149855955625E+00, 0.4861129300486463E+00, 0.5200718178308463E+00, 0.7592798686765068E+00, 0.7809192005748844E+00, 0.9939952535261979E+00, 0.4314053553650160E+00, 0.3880099380329156E+00, 0.9349849386467751E+00, 0.5291872418075704E+00, 0.7655812944336832E+00, 0.7077741471317599E+00, 0.5275519688342463E+00, 0.1415092279196126E+00, 0.1904335663118598E+00, 0.3699272115054363E+00, 0.7445484920377089E+00, 0.8400049615316296E+00, 0.8734700661006028E+00, 0.8683217518669656E+00, 0.8515176384024258E+00, 0.6202080985416659E+00, 0.3604998919630682E+00, 0.2403115969743893E+00, 0.9554672796937618E+00, 0.1693873282831592E+00, 0.5994144523705257E+00, 0.1384422941659869E-01, 0.6596251817370012E+00, 0.5636231004812753E+00, 0.5389166856740800E+00, 0.2607457441602791E+00, 0.5920539595206202E+00, 0.2966504229935458E+00, 0.5816050348468149E+00, 0.9328164339475690E+00, 0.5805507576670368E+00, 0.6771712743677023E+00, 0.9823651336988842E+00, 0.9793282488782439E+00, 0.4667245203343464E+00, 0.7134684364121646E+00, 0.4880671978756712E-01, 0.8383078993270572E+00, 0.7936419849408084E+00, 0.5385800856643647E+00, 0.4634644976924968E+00, 0.3931501879746360E+00, 0.1248524879525928E+00, 0.3152310060096000E+00, 0.9363438862709352E+00, 0.3520470715344234E+00, 0.1429338846554544E+00, 0.1326946626315275E+00}, + n: 21, + zOut: []float64{0.2657315323020249E+01, 0.2572905823883155E+01, 0.2192663626292596E+01, 0.2071095653426940E+01, 0.2044494413445205E+01, 0.1999166174223334E+01, 0.1788414821296782E+01, 0.1468335212647637E+01, 0.1398203839606685E+01, 0.1347197234417596E+01, 0.1032902470665773E+01, 0.6608948302945201E+00, 0.5911878145202527E+00, 0.5378924504889658E+00, 0.3142273934265400E+00, 0.2842363451796606E+00, 0.2019484989227465E+00, 0.1206949829709270E+00, 0.7426269792367300E-01, 0.2567909008435554E-01, 0.2199972943425967E-02, 0.1467781105980630E-22, 0.1166962122444304E-12, 0.3923264640094201E-13, 0.1788414821296782E+01, 0.4047127357551305E-19, 0.1945479305169457E-09, 0.9334440121571419E-10, 0.1468335212647637E+01, 0.0000000000000000E+00, 0.9722951216797492E-08, 0.1689489155058893E-07, 0.1398203839606685E+01, 0.0000000000000000E+00, 0.7669133926546234E-07, 0.4506074380002258E-07, 0.1347197234417596E+01, 0.5319335283638860E-18, 0.5446647026201709E-11, 0.3163064243829271E-10, 0.1032902470665773E+01, 0.4430813007685208E-16, 0.2338591866968101E+02, 0.2338591866968102E+02, 0.1020000000000000E+03, 0.3054421768707483E+01, 0.2941176470588236E+01, 0.1546723845733498E-03, 0.5911878145202527E+00, 0.3652829585034170E-19, 0.1702044288822486E-03, 0.2177596193354961E-03, 0.5378924504889658E+00, 0.1350864780951217E-19, 0.2554902108144373E-06, 0.3466691719880105E-07, 0.3142273934265400E+00, 0.2387932220615686E-11, 0.6740109938598231E-04, 0.1019437079103270E-03, 0.2842363451796606E+00, 0.4338734978715565E-28, 0.4438729696644533E-03, 0.6983868198931385E-03, 0.2019484989227465E+00, 0.2612058427213185E-17, 0.1559412966194519E-03, 0.4467949014161081E-04, 0.1206949829709270E+00, 0.7367960854764250E-27, 0.5572085070843593E-03, 0.6756387538188178E-03, 0.7426269792367300E-01, 0.4936220984925504E-18, 0.5280924471496804E-02, 0.4881438130898638E-02, 0.2567909008435554E-01, 0.4675428386128583E-22, 0.7885638578366546E-02, 0.6344653647355715E-02, 0.2199972943425967E-02, 0.1043187069080892E-15, 0.1144606019330652E-02, 0.5299576363060843E-02}, + info: 0, + }, + { + z: []float64{0.2890643798273074E-01, 0.8912209063965303E+00, 0.7091793456137876E+00, 0.8245039023218966E+00, 0.5191833323605244E+00, 0.9894484508239253E+00, 0.5658659268235589E-01, 0.1289734762146678E+00, 0.3341027001588562E+00, 0.6587235353882195E+00, 0.7097532970603662E+00, 0.5025058684824796E+00, 0.5130835936402325E+00, 0.6692657853529054E+00, 0.2879265169895939E+00, 0.8181258306911487E-01, 0.2380388408780171E+00, 0.1056636973917433E+00, 0.4227669640232596E+00, 0.8862610364887391E+00, 0.3174262171725216E+00, 0.4110634725577023E+00, 0.6279625314936111E+00, 0.2325114979496041E+00, 0.5638889949786475E+00, 0.7596856267416864E+00, 0.8240081240110467E+00, 0.9973320050910897E+00, 0.5587421997876323E+00, 0.4288334013103122E+00, 0.8314043340979348E+00, 0.5650188659610876E+00, 0.2964679109455457E+00, 0.8407175605087841E+00, 0.1058970658656445E+00, 0.6883026296612506E+00, 0.9166830669002658E+00, 0.7992763288082885E+00, 0.5373538962118501E+00, 0.8167960120885054E-01, 0.9998997916538879E+00, 0.1975674901149639E+00, 0.7582212604798201E+00, 0.2860808530483561E+00, 0.5862675745609662E+00, 0.4334284293442484E+00, 0.9545191575190999E+00, 0.5542276060509370E+00, 0.9135493345204525E+00, 0.9597250519108470E+00, 0.4020434518393716E+00, 0.2147209304773570E+00, 0.8396072187357826E+00, 0.5371494282057584E+00, 0.9930506172699961E+00, 0.3818967451326610E+00, 0.8312670748053316E+00, 0.7518558266385443E+00, 0.7897281313428761E+00, 0.4898691976861856E+00, 0.9259118998644267E+00, 0.2411762039549979E+00, 0.3003769542607895E+00, 0.9868194969589331E+00, 0.1841003538786936E+00, 0.1211293694641126E+00, 0.7968556025054743E+00, 0.5500013093928259E+00, 0.1705581246551358E-01, 0.5695318221187962E-02, 0.1626907733376057E+00, 0.3178865594423397E-01, 0.6489383021126400E+00, 0.3661200730578906E-01, 0.9937238435410299E+00, 0.8693948290233534E+00, 0.8108974262339508E-01, 0.4858895290851201E+00, 0.5417752479164495E+00, 0.3742432440371155E+00, 0.4593696265617863E+00, 0.7058043658513553E+00, 0.3505553117224474E+00, 0.9647100571711842E+00}, + n: 21, + zOut: []float64{0.2698643664756728E+01, 0.2430046536911446E+01, 0.2385739474636754E+01, 0.2028138720182182E+01, 0.1901894919230603E+01, 0.1736372633374239E+01, 0.1325608228839813E+01, 0.1300504895564844E+01, 0.1261345481029282E+01, 0.1136052475360616E+01, 0.1031365869480280E+01, 0.7689316276636458E+00, 0.5233321832080760E+00, 0.4817169321317593E+00, 0.3418348106633131E+00, 0.2652183763191593E+00, 0.1871042345023881E+00, 0.9160826173360032E-01, 0.4317601760647842E-01, 0.3303497213448481E-02, 0.1231458285303120E-03, 0.9226440439387837E-18, 0.2555628409159789E-14, 0.2440793084913596E-14, 0.1325608228839813E+01, 0.0000000000000000E+00, 0.5589422112493051E-13, 0.3085898188945034E-13, 0.1300504895564844E+01, 0.7444625512849138E-23, 0.1759654299048522E-12, 0.9781103208866350E-13, 0.1261345481029282E+01, 0.6802337789204302E-18, 0.3650786119252150E-16, 0.3306223266172732E-17, 0.1136052475360616E+01, 0.9063201483067583E-22, 0.4434055300668524E-09, 0.2614666143660316E-09, 0.1031365869480280E+01, 0.2213258132402469E-23, 0.2194206198623719E+02, 0.2194206198623719E+02, 0.1100000000000000E+03, 0.3090702947845805E+01, 0.2727272727272727E+01, 0.1493749053307339E-05, 0.5233321832080760E+00, 0.6795157417200880E-17, 0.4382394072074649E-04, 0.6871024518289093E-04, 0.4817169321317593E+00, 0.6227468015696590E-20, 0.2332676874935389E-03, 0.1644354889791431E-03, 0.3418348106633131E+00, 0.8455074291031222E-24, 0.5211421342985135E-03, 0.2133578004049512E-03, 0.2652183763191593E+00, 0.4572942646937810E-19, 0.1472671843690071E-04, 0.1084821769416695E-04, 0.1871042345023881E+00, 0.4930380657631324E-31, 0.2208706795255935E-03, 0.1179477310012027E-03, 0.9160826173360032E-01, 0.2210123199165121E-23, 0.1806566548732391E-03, 0.1927419907906541E-03, 0.4317601760647842E-01, 0.5416053917983313E-23, 0.1030445327331746E-02, 0.1902956416897231E-02, 0.3303497213448481E-02, 0.8065145389241560E-19, 0.2031248978330205E-02, 0.9946626682395031E-03, 0.1231458285303120E-03, 0.1613264727387662E-23, 0.1026826157383968E-01, 0.7685291223570192E-02}, + info: 0, + }, + { + z: []float64{0.9180725347208115E+00, 0.2301506372544524E+00, 0.2276838071944142E+00, 0.3342400207211600E+00, 0.9639463843013925E+00, 0.5437724527901152E+00, 0.1580993234156807E+00, 0.7877490287014776E+00, 0.3507533849023979E+00, 0.8833112450245699E+00, 0.3185731691946991E-01, 0.4118134066759526E+00, 0.8069686780110494E+00, 0.8681061806796153E-01, 0.6859948674552803E+00, 0.3663178920382139E+00, 0.3720291416615038E+00, 0.8903287156706564E+00, 0.1324429304812152E+00, 0.1008541223140741E+00, 0.8373883396136816E-01, 0.6715628313581425E+00, 0.1594467086953334E+00, 0.5413131938455139E+00, 0.1818140526389971E+00, 0.8685248287187100E+00, 0.5132298455242696E+00, 0.6886095101515632E+00, 0.4005049001067575E+00, 0.6084237383755163E+00, 0.7877676299774720E+00, 0.7102138904901485E+00, 0.6423372229000449E+00, 0.5613660527307726E+00, 0.9158966894941798E+00, 0.4933711427035579E+00, 0.7338439214039514E+00, 0.9908978412238557E+00, 0.5798575644928616E-01, 0.8977291910051136E+00, 0.9253772304099678E+00, 0.3904911857418987E+00, 0.4422593302764081E+00, 0.8489177311215401E+00, 0.7212670509555793E+00, 0.9615617648004515E+00, 0.8226716687395509E+00, 0.9612871412036802E+00, 0.1291974168797438E-01, 0.4488531482063538E+00, 0.2469769340642032E+00, 0.3614360453900619E+00, 0.2074351009622584E+00, 0.7016685284881871E+00, 0.1548060648394445E-01, 0.7311687113133817E+00, 0.9296728393442250E+00, 0.9396166536686752E+00, 0.8501954423645642E+00, 0.4336964896981472E+00, 0.6496017727538979E+00, 0.4464862127725214E+00, 0.4878335970157573E+00, 0.3486784051750773E+00, 0.7455411052079824E+00, 0.5444043691163374E+00, 0.3832092245164885E+00, 0.2030848069834680E+00, 0.9785068556455849E+00, 0.4981273340936699E+00, 0.2968547769748885E+00, 0.8139137104995479E+00, 0.5979876314385963E+00, 0.7890959952347512E+00, 0.1396638856742113E+00, 0.6423356747667288E+00, 0.4204101650717844E+00, 0.3861511203891811E+00, 0.5255853602620404E+00, 0.8105960955427686E+00, 0.1919308380441287E-01, 0.5308532240470543E-01, 0.3836913823972644E+00, 0.5510156269652182E+00}, + n: 21, + zOut: []float64{0.2573005090179951E+01, 0.2214810120454235E+01, 0.1922733254389488E+01, 0.1915272191491466E+01, 0.1796031325760082E+01, 0.1645710570695390E+01, 0.1570469265391087E+01, 0.1354841927194508E+01, 0.1294466452193999E+01, 0.1181212352080131E+01, 0.1084541549607215E+01, 0.7996017680870424E+00, 0.7671322760534200E+00, 0.5413194973828868E+00, 0.4525283650095193E+00, 0.2478901170080125E+00, 0.2160828479985811E+00, 0.1019188530491480E+00, 0.3154199687907010E-01, 0.6039114283538317E-02, 0.2585297601905087E-05, 0.1842779074596284E-25, 0.3846373205279405E-07, 0.1879918241657939E-07, 0.1570469265391087E+01, 0.5301607341005493E-20, 0.5291292043249480E-06, 0.9680604951014117E-06, 0.1354841927194508E+01, 0.4298088920574052E-25, 0.7835178780587823E-04, 0.5534134534297650E-04, 0.1294466452193999E+01, 0.1009741958682895E-27, 0.1198198722705974E-04, 0.2465537083987539E-04, 0.1181212352080131E+01, 0.6309019138365174E-17, 0.1614759348306573E-06, 0.9017894254302745E-07, 0.1084541549607215E+01, 0.2228464273087314E-11, 0.2171715152048637E+02, 0.2171715152048638E+02, 0.1110000000000000E+03, 0.3170068027210884E+01, 0.4504504504504505E+01, 0.2430910851731611E-05, 0.7671322760534200E+00, 0.2706512346053632E-23, 0.6377722122869933E-05, 0.4589261521941547E-05, 0.5413194973828868E+00, 0.6745076284001739E-23, 0.1892848367477632E-04, 0.2486261833151780E-04, 0.4525283650095193E+00, 0.4943696629711454E-24, 0.8902582280300076E-04, 0.6878116767917398E-04, 0.2478901170080125E+00, 0.2843433355651033E-22, 0.3448699135776589E-03, 0.2736188045956721E-03, 0.2160828479985811E+00, 0.6002787666751380E-18, 0.2577148216451160E-04, 0.6049628369117275E-04, 0.1019188530491480E+00, 0.1341063538875720E-28, 0.1448550797531803E-02, 0.1280708514177034E-02, 0.3154199687907010E-01, 0.6162975822039155E-32, 0.1183522807025889E-02, 0.1098677799367788E-02, 0.6039114283538317E-02, 0.2067951531379678E-24, 0.3575820084217755E-02, 0.2195872556012757E-02, 0.2585297601905087E-05, 0.1137373342260413E-23, 0.1063898509008824E-02, 0.9861644892506420E-03}, + info: 0, + }, + { + z: []float64{0.9985296910189717E+00, 0.8831740589213332E+00, 0.2324113848518039E+00, 0.7533238559688371E+00, 0.3064992106368385E+00, 0.3932363212439300E+00, 0.5064743635322475E+00, 0.2720810167440399E+00, 0.1759478514683438E+00, 0.1390889491193166E+00, 0.1132483424706631E+00, 0.7690628781223635E+00, 0.9618570638759271E+00, 0.5440138404508711E+00, 0.4137500693527351E+00, 0.1092888165750733E+00, 0.3873107100859553E+00, 0.6511277223354393E+00, 0.2155123791160785E-02, 0.9398729888067584E+00, 0.6720352720616287E+00, 0.1535603342192503E+00, 0.1531061200685264E+00, 0.7545904619621174E+00, 0.7663253741916968E+00, 0.9523625338296001E+00, 0.7564452546028717E+00, 0.3871338859213032E+00, 0.8414924166180344E+00, 0.9656526120147547E+00, 0.8983142486291256E+00, 0.4931225086134777E+00, 0.2402429523967143E+00, 0.2566457485714786E+00, 0.6291482026295649E+00, 0.3102713820139572E+00, 0.8907835976003569E+00, 0.7576089622962475E+00, 0.4268794706004859E+00, 0.9679759265393412E+00, 0.8761096912299335E+00, 0.8367482459498927E+00, 0.6924039391525048E+00, 0.1390797616032549E+00, 0.4788493402292462E+00, 0.4619292003991998E+00, 0.6108276748986761E+00, 0.4236594210420574E-01, 0.1642264441572165E+00, 0.3019681501044491E+00, 0.6872347566608095E-01, 0.4797791709329366E+00, 0.3191437336153862E+00, 0.4231397520665843E+00, 0.9123119461602809E+00, 0.4032629658718287E+00, 0.3761450089120290E+00, 0.1152232563042578E+00, 0.9954630682646954E+00, 0.5373824202779058E+00, 0.6106178691724040E-01, 0.8364420731639322E-01, 0.8933845816890847E+00, 0.5581653322395922E+00, 0.2899731736068278E-01, 0.1770979452363362E+00, 0.5004901441174880E-01, 0.7090935149513330E+00, 0.6196074778714252E+00, 0.7620558730426811E+00, 0.3663579087238161E+00, 0.7799033559850937E+00, 0.5196335588513137E+00, 0.2674625162438964E+00, 0.2943854187199277E+00, 0.7770221064689762E+00, 0.1654873860303906E+00, 0.1664508117665333E+00, 0.4846990191351895E+00, 0.8900931539882498E+00, 0.1193560423223905E-01, 0.7974122776570580E+00, 0.1940680748090599E+00, 0.6554519288132757E+00}, + n: 21, + zOut: []float64{0.2834962035267250E+01, 0.2457739633394971E+01, 0.2412615740112653E+01, 0.2205350258735166E+01, 0.2102070731548960E+01, 0.1691268502125131E+01, 0.1682341944223941E+01, 0.1365229052855181E+01, 0.1159748452086257E+01, 0.1104152264055237E+01, 0.9082896055849982E+00, 0.8350561719565637E+00, 0.6006322679527780E+00, 0.5944104151258589E+00, 0.3054714512857917E+00, 0.1934898777304675E+00, 0.1070106456037005E+00, 0.7977404013852835E-01, 0.4467492857453391E-01, 0.1796045849894196E-01, 0.1273912617121224E-04, 0.5392013224803094E-11, 0.7047397633000775E-04, 0.4975950204285101E-04, 0.1682341944223941E+01, 0.0000000000000000E+00, 0.1776257168565356E-04, 0.2478687660984077E-04, 0.1365229052855181E+01, 0.2904595710528663E-17, 0.2723859519581362E-08, 0.9106491605280572E-08, 0.1159748452086257E+01, 0.1011100673149366E-15, 0.1332628661445848E-04, 0.5871026575773219E-05, 0.1104152264055237E+01, 0.8308334390451641E-18, 0.8332699889408906E-05, 0.9212653513444334E-05, 0.9082896055849982E+00, 0.3518078502828044E-18, 0.2270226121598308E+02, 0.2270226121598308E+02, 0.1240000000000000E+03, 0.3505668934240363E+01, 0.5645161290322581E+01, 0.2479678732743906E-05, 0.6006322679527780E+00, 0.0000000000000000E+00, 0.7879659138115500E-06, 0.7199236433698600E-06, 0.5944104151258589E+00, 0.3024585909035025E-20, 0.8203337497349541E-06, 0.8765068833865939E-06, 0.3054714512857917E+00, 0.4733165431326071E-26, 0.3737214231038995E-06, 0.3923468144379782E-06, 0.1934898777304675E+00, 0.4260044778133448E-20, 0.3232147542049518E-06, 0.3376352641996194E-06, 0.1070106456037005E+00, 0.3308722450212072E-23, 0.5070207875063323E-06, 0.4107488228647395E-06, 0.7977404013852835E-01, 0.6162975822039155E-32, 0.1529214528521930E-08, 0.6332986682625979E-08, 0.4467492857453391E-01, 0.1074272623509048E-20, 0.2583088473438835E-04, 0.1663016813733052E-04, 0.1796045849894196E-01, 0.7053209140113412E-22, 0.1477449551257491E-03, 0.9547349784916723E-04, 0.1273912617121224E-04, 0.0000000000000000E+00, 0.2066074227952428E-02, 0.2903362394245088E-02}, + info: 0, + }, + { + z: []float64{0.9711900205601530E+00, 0.1638861523026915E+00, 0.1833187318057834E+00, 0.9072755753374127E+00, 0.2283578849017619E+00, 0.7520216236020175E+00, 0.3999380553956507E+00, 0.2624503967963340E+00, 0.4831766333071612E+00, 0.5439216550253211E+00, 0.6414566703448968E+00, 0.4958417903972772E+00, 0.6484413600580574E+00, 0.7544273119845675E+00, 0.7061059155531373E+00, 0.9606326194792012E+00, 0.5067069535242709E+00, 0.3029510615023524E+00, 0.6987030441702768E+00, 0.9783205951302908E+00, 0.1548952654742521E+00, 0.9315036439248046E+00, 0.5516706717897903E+00, 0.5168328579759034E+00, 0.3596295330063849E+00, 0.4476574932894306E-01, 0.9741728325615778E+00, 0.2804678894509116E-01, 0.3902916772468864E+00, 0.8530466945184888E+00, 0.2969904800916723E-01, 0.1860020491995459E+00, 0.7523094177753908E-01, 0.1049676044274535E+00, 0.9260152605248726E+00, 0.4316992548719201E+00, 0.7469073285915341E+00, 0.9833774639100495E+00, 0.4974597252506658E+00, 0.4177634673241238E+00, 0.2822911131407428E+00, 0.8441017127353869E+00, 0.3634452570924520E+00, 0.3139202807660985E+00, 0.3006600055674361E+00, 0.3009046530704764E+00, 0.5749841775931973E+00, 0.8312625997674838E+00, 0.7353697939061690E+00, 0.5347208541042444E+00, 0.3745659295783104E+00, 0.2530774659476339E+00, 0.4186076940004666E+00, 0.9926397860987635E+00, 0.9744627902125954E+00, 0.5156862870399348E-01, 0.9609885826474012E+00, 0.1340044668459911E+00, 0.4269295726396694E+00, 0.1323606439861225E+00, 0.9547002490565327E+00, 0.3235500895339022E+00, 0.9408694232081565E+00, 0.5256315334453321E-01, 0.5435043012268493E+00, 0.8290694048290136E+00, 0.3690485876123201E+00, 0.1315626820984572E+00, 0.7782838224801890E+00, 0.4824080201008953E+00, 0.4904940544366522E+00, 0.7125669967024466E+00, 0.2079010288312985E+00, 0.3154779356788950E+00, 0.8039212621301359E+00, 0.1606576564727077E+00, 0.9470564071979923E+00, 0.9189825217362574E+00, 0.4332760074849629E+00, 0.2823180730446854E+00, 0.8869162317432342E+00, 0.9632623909785668E+00, 0.5010388463829042E+00, 0.4287967421178640E+00}, + n: 21, + zOut: []float64{0.2578695081979337E+01, 0.2397185171350384E+01, 0.2122428254475021E+01, 0.1845603260474165E+01, 0.1680081614592041E+01, 0.1588339204725779E+01, 0.1309467974766432E+01, 0.1299839243529426E+01, 0.1209324813016549E+01, 0.1078225499420584E+01, 0.1021574489264402E+01, 0.8212075951361281E+00, 0.6252200086865959E+00, 0.5691142568406321E+00, 0.4167987738801949E+00, 0.2624912719101158E+00, 0.1530089161378868E+00, 0.6867147881453296E-01, 0.2505166907249862E-01, 0.2349256929716605E-02, 0.7151879759250424E-03, 0.1577721810442024E-29, 0.4511324342265551E-10, 0.2432911773654117E-10, 0.1309467974766432E+01, 0.0000000000000000E+00, 0.2950215161815511E-09, 0.4606013118502744E-09, 0.1299839243529426E+01, 0.0000000000000000E+00, 0.1717787641934460E-08, 0.1104907179077728E-08, 0.1209324813016549E+01, 0.2227112107619961E-25, 0.8047601721100021E-14, 0.3064349892439287E-13, 0.1078225499420584E+01, 0.1519533811285116E-12, 0.1082897652895214E-09, 0.2849698526408556E-09, 0.1021574489264402E+01, 0.9160719227198137E-18, 0.2107539302297835E+02, 0.2107539302297835E+02, 0.1110000000000000E+03, 0.3317460317460318E+01, 0.3603603603603604E+01, 0.1689224645784323E-04, 0.6252200086865959E+00, 0.1615587133892632E-26, 0.8276137867398754E-04, 0.1155304449854771E-03, 0.5691142568406321E+00, 0.1852884571782062E-20, 0.2098842504693311E-03, 0.1630830816462844E-03, 0.4167987738801949E+00, 0.7013543182763534E-16, 0.5750632050789642E-07, 0.3137720527277731E-06, 0.2624912719101158E+00, 0.1295300917428640E-14, 0.8049639874935534E-04, 0.1584688939577041E-03, 0.1530089161378868E+00, 0.3636550670570672E-17, 0.1206768167404478E-03, 0.2128462525136164E-03, 0.6867147881453296E-01, 0.4176548246217679E-19, 0.3626791442965051E-04, 0.6269592722343766E-04, 0.2505166907249862E-01, 0.8628166150854817E-31, 0.1144078296038157E-02, 0.1062123559861287E-02, 0.2349256929716605E-02, 0.1853343815383365E-22, 0.1348818609641394E-03, 0.1209095310981735E-04, 0.7151879759250424E-03, 0.2331746618088476E-23, 0.3639492207606013E-03, 0.1002254703741813E-03}, + info: 0, + }, + { + z: []float64{0.5145122753774686E+00, 0.7453791781450037E+00, 0.4937919697078275E-01, 0.9600912461125237E+00, 0.5558575009096904E+00, 0.9202496102671529E+00, 0.1803962777705234E+00, 0.6732582413383450E+00, 0.3646300420523177E+00, 0.4351523227625338E+00, 0.5258615952095320E+00, 0.2618724553334706E-01, 0.6600255279090639E+00, 0.4323183918305084E+00, 0.2184526174816337E+00, 0.7758998738943313E+00, 0.3700044944947983E+00, 0.9075309916724112E+00, 0.7873590137849384E-02, 0.6422780210226944E+00, 0.7012374235504933E+00, 0.3225317189575561E-01, 0.9626413579028830E+00, 0.2957325301869758E+00, 0.9393912496594896E+00, 0.3122772343061888E+00, 0.3372582329155205E-01, 0.6694758703662361E+00, 0.5160501222108982E-03, 0.9689575293997177E-01, 0.3780626069308365E+00, 0.1243877469635841E+00, 0.3753610862140089E+00, 0.7686454249086220E+00, 0.8958999262270639E+00, 0.9484254659678725E+00, 0.7229120985603210E-01, 0.7282046499931183E+00, 0.1602916509824523E+00, 0.3708722215113680E+00, 0.5328491413896952E+00, 0.7547173918812869E+00, 0.4313535833192655E+00, 0.5849601017371611E+00, 0.5030126650939655E+00, 0.3345267020968724E+00, 0.8264894134567216E+00, 0.3997968176112487E+00, 0.7977852660508306E+00, 0.3214021056175872E+00, 0.4636510192825659E+00, 0.6796405156053968E+00, 0.6279823358542748E+00, 0.1573806073104234E-01, 0.6382889890358745E-01, 0.5417145287154319E+00, 0.2343304174607242E+00, 0.7662339681589646E+00, 0.6291880658725347E+00, 0.5139706179483768E+00, 0.1583956600060378E+00, 0.9391868842090931E+00, 0.2645051239078070E+00, 0.7814123021217941E+00, 0.8945112708258808E+00, 0.7464898217422987E+00, 0.3770460515219444E+00, 0.3622886345531428E+00, 0.2208273216958112E-01, 0.7102940678247979E+00, 0.2735151315490909E+00, 0.4039400600381490E+00, 0.9317363313474538E+00, 0.5754441557390587E+00, 0.5886999087747160E+00, 0.3030246870939485E+00, 0.8507721951782303E+00, 0.3043440840669203E+00, 0.6021496993262363E+00, 0.4505272689007913E+00, 0.3874595231430722E+00, 0.2566155965014733E+00, 0.2521494866083717E+00, 0.7091848125152684E+00}, + n: 21, + zOut: []float64{0.2432728498446405E+01, 0.2127807422546525E+01, 0.1810603620342434E+01, 0.1754551066335428E+01, 0.1442239744319712E+01, 0.1358471286041730E+01, 0.1268104094970585E+01, 0.1166598518949770E+01, 0.1142749842956014E+01, 0.8038795081997708E+00, 0.7842646316799070E+00, 0.7340488722153766E+00, 0.6406325830516326E+00, 0.6326463399427553E+00, 0.4829120798428922E+00, 0.4021501496449236E+00, 0.3628067219099092E+00, 0.1315077965186685E-01, 0.3447035773652165E-02, 0.9829838131645125E-03, 0.5542446906743292E-07, 0.3726944967513355E-18, 0.7775649827661083E-15, 0.4707679240410040E-15, 0.1268104094970585E+01, 0.4204313080465905E-25, 0.2081271826241763E-14, 0.3549560565109884E-14, 0.1166598518949770E+01, 0.0000000000000000E+00, 0.3900682806423283E-13, 0.2423637210496787E-13, 0.1142749842956014E+01, 0.1408856084028437E-16, 0.9605918786201080E-13, 0.6043593726409546E-13, 0.8038795081997708E+00, 0.8160364745046778E-12, 0.9063031760991450E-12, 0.1255592191298957E-11, 0.7842646316799070E+00, 0.2274746684496083E-23, 0.1936477583605892E+02, 0.1936477583605892E+02, 0.1150000000000000E+03, 0.3673469387755102E+01, 0.7826086956521739E+01, 0.1055105767279683E-11, 0.6406325830516326E+00, 0.7534418653829021E-12, 0.2026915084594321E-10, 0.1938443898507311E-10, 0.6326463399427553E+00, 0.7428954317778491E-22, 0.1822158222411987E-10, 0.2310105649781206E-10, 0.4829120798428922E+00, 0.6818472407494482E-21, 0.4806621018591031E-08, 0.3430760494577760E-08, 0.4021501496449236E+00, 0.9407638730741502E-13, 0.4934881466368944E-07, 0.7682525823543034E-07, 0.3628067219099092E+00, 0.4641733924717305E-17, 0.3006332568302334E-06, 0.4841414710438772E-06, 0.1315077965186685E-01, 0.0000000000000000E+00, 0.4649166787994157E-03, 0.6126205080519521E-03, 0.3447035773652165E-02, 0.0000000000000000E+00, 0.8654037114492079E-03, 0.1518309118546661E-02, 0.9829838131645125E-03, 0.2948446519354054E-25, 0.2136365904689920E-10, 0.9493111427282873E-09, 0.5542446906743292E-07, 0.0000000000000000E+00, 0.8210503952597113E-02, 0.1866280792966489E-03}, + info: 0, + }, + { + z: []float64{0.1382149566425072E+00, 0.6575474867299980E+00, 0.6348472674088155E+00, 0.2171300387013793E+00, 0.8255967246227341E+00, 0.3006539504418347E+00, 0.2997341048143420E+00, 0.8472159875058289E+00, 0.6738978429295159E+00, 0.5424646868297128E+00, 0.4120014569672862E+00, 0.8343380028244362E+00, 0.3003911043596160E+00, 0.4710045367840567E+00, 0.4862652198104067E-01, 0.7471894777046170E+00, 0.1793049886163456E+00, 0.7023511329140396E+00, 0.7338019696975340E-02, 0.6396982308318109E+00, 0.9907774162255600E-01, 0.9295761484947797E+00, 0.9648060362942152E+00, 0.9280158186031068E+00, 0.2707915909911263E-01, 0.3838735516497237E+00, 0.1682677327524866E+00, 0.2113105759433432E+00, 0.9045861188128749E+00, 0.7471063495001966E+00, 0.8342180430544732E-01, 0.1412979915701199E+00, 0.8279925714974835E+00, 0.1155895711297670E+00, 0.9231783969041454E+00, 0.3728782651185074E+00, 0.6830046202574890E+00, 0.9069008465878121E+00, 0.9754648591267837E+00, 0.8893150707687680E-01, 0.6771275111272185E+00, 0.9913978119103384E+00, 0.7253101374756428E+00, 0.9967636737323063E+00, 0.8627812047783159E+00, 0.3179382291892185E-01, 0.3971194218951257E+00, 0.1929798662828303E+00, 0.8983406738830656E+00, 0.8696986427722838E+00, 0.1626550211323166E+00, 0.5446758738044107E+00, 0.7791897500950196E+00, 0.5495589328822522E+00, 0.2598162756138545E+00, 0.4878822167962611E+00, 0.1063554708684851E+00, 0.9205986422545666E+00, 0.2525019548845375E+00, 0.6202404757545382E+00, 0.4398012123976176E+00, 0.3367811528280380E+00, 0.2846930465290612E+00, 0.3637854092863660E+00, 0.2816012898088578E+00, 0.8253973364224151E+00, 0.1068693035499244E+00, 0.6335234891165292E+00, 0.4457012705011152E+00, 0.3822128202770037E-01, 0.8044679788500431E-02, 0.1644333417433916E+00, 0.8243501026702226E+00, 0.3724822902257573E+00, 0.3284619434713851E+00, 0.8284230195063381E+00, 0.9834160248288059E+00, 0.5390643127606534E+00, 0.4874602694948874E+00, 0.3393327340444893E+00, 0.9478697182248690E+00, 0.9005921446100461E+00, 0.6870582101064761E+00, 0.8753727823211164E+00}, + n: 21, + zOut: []float64{0.2520205603715150E+01, 0.2467591671122728E+01, 0.2156156465592955E+01, 0.1830603796963098E+01, 0.1688980285573207E+01, 0.1475729352347043E+01, 0.1457403847234258E+01, 0.1216096979409916E+01, 0.1020221539309743E+01, 0.9109792709218910E+00, 0.7786685137433046E+00, 0.6943983149907305E+00, 0.5952732619368740E+00, 0.5747064141061984E+00, 0.4193783470766816E+00, 0.2849493660130012E+00, 0.2000335007304226E+00, 0.1879518797669419E+00, 0.9250201866750386E-01, 0.6720326503698931E-01, 0.2522304426258675E-08, 0.0000000000000000E+00, 0.6146929522129176E-12, 0.1808448588630822E-11, 0.1457403847234258E+01, 0.4890937612370273E-28, 0.1829381779873047E-10, 0.6063479072736104E-11, 0.1216096979409916E+01, 0.3707772472283591E-24, 0.7129364201262979E-09, 0.6841733798178873E-09, 0.1020221539309743E+01, 0.2138261883449577E-21, 0.5257033338238628E-09, 0.5072654023074907E-09, 0.9109792709218910E+00, 0.7953858577580093E-22, 0.4258628064439383E-09, 0.4402488234184115E-09, 0.7786685137433046E+00, 0.2050608176139579E-11, 0.2063903369678094E+02, 0.2063903369678095E+02, 0.1070000000000000E+03, 0.3256235827664399E+01, 0.7476635514018692E+01, 0.2680505535092421E-09, 0.5952732619368740E+00, 0.3490920289236852E-22, 0.2767075275933556E-09, 0.2579359628684292E-09, 0.5747064141061984E+00, 0.6550779105727953E-17, 0.5565909614599560E-09, 0.4340922452181151E-09, 0.4193783470766816E+00, 0.3307688474446419E-20, 0.4344481061547019E-08, 0.2950068756973984E-08, 0.2849493660130012E+00, 0.2114500635677851E-23, 0.2105683914952377E-07, 0.1386409244069912E-07, 0.2000335007304226E+00, 0.2552627671550359E-24, 0.1231406445198996E-06, 0.7724199195397155E-07, 0.1879518797669419E+00, 0.2762617809804602E-19, 0.3259696859933768E-06, 0.5428848805276070E-06, 0.9250201866750386E-01, 0.2465190328815662E-31, 0.5308529636258477E-04, 0.3674504775836459E-04, 0.6720326503698931E-01, 0.4910144116114772E-20, 0.8312610965835068E-03, 0.3682729181838852E-03, 0.2522304426258675E-08, 0.0000000000000000E+00, 0.2850162708346282E-01, 0.1272924532804709E-01}, + info: 0, + }, + { + z: []float64{0.8107097465650837E+00, 0.6284212325752714E-02, 0.8801609468679439E-01, 0.1317925189426976E+00, 0.7816238529622888E+00, 0.5138440552812117E+00, 0.8491910920486024E+00, 0.5354109734403600E-01, 0.9922209940223927E+00, 0.5302203883752287E+00, 0.7634020308181488E-01, 0.1679415943232965E+00, 0.2329711998757648E+00, 0.1414305919938111E+00, 0.1841480420952157E-01, 0.3417588803467335E+00, 0.2555749764808386E+00, 0.5793635436480560E-01, 0.5867939998055902E+00, 0.9699556000711096E+00, 0.2545002439558014E+00, 0.6318762794888357E+00, 0.3917398730545906E+00, 0.5624711052874073E+00, 0.4151753215255505E-01, 0.2323556867603191E+00, 0.8346423132579881E+00, 0.4193569213002444E+00, 0.5070048505400149E+00, 0.9880568155195324E-01, 0.6350898210108906E+00, 0.2370382383359541E+00, 0.3299228061150288E+00, 0.4349239764921071E+00, 0.5262500692361848E+00, 0.5263549923651836E+00, 0.8161052184432745E+00, 0.5568267671289201E+00, 0.7852669932205985E+00, 0.4481607592551184E-01, 0.6290146498792036E+00, 0.9736787804665343E+00, 0.5369941621471508E+00, 0.6750777504837204E+00, 0.9452511173220645E+00, 0.3252402467696922E+00, 0.8149000487070703E+00, 0.8087485664240622E+00, 0.8643101435258340E+00, 0.4683483752594740E+00, 0.5054760923588362E+00, 0.9646412930917844E+00, 0.1611953384510251E+00, 0.6426851941066625E-01, 0.3732266796993424E+00, 0.6384029126799168E+00, 0.3844644469584264E+00, 0.6635273633462982E+00, 0.2553934870916856E+00, 0.7037835913610216E+00, 0.7783327991001192E+00, 0.7381327592761330E+00, 0.2765915485450557E+00, 0.9846188872724937E-01, 0.1992562101416243E+00, 0.2440052895970430E+00, 0.3301477999473963E+00, 0.5338134839029927E+00, 0.5498293871712301E+00, 0.1974401363114953E+00, 0.7407533997655510E+00, 0.6821638940995054E+00, 0.9814777780110351E+00, 0.4891456709117443E+00, 0.6868139367703679E+00, 0.4181531426430654E+00, 0.6623070699739451E+00, 0.9202771282456093E+00, 0.2973080397025486E+00, 0.4403051603022431E+00, 0.1603780540263299E+00, 0.4910562348998989E+00, 0.7838834745165658E+00, 0.1931809149066596E+00}, + n: 21, + zOut: []float64{0.2163023058341640E+01, 0.1906105992609667E+01, 0.1885682431608721E+01, 0.1629672232824707E+01, 0.1530256904983391E+01, 0.1307296833197682E+01, 0.1220997281181084E+01, 0.9674288853031870E+00, 0.8179252376135864E+00, 0.6735586841320580E+00, 0.6320597056120635E+00, 0.5126868322939253E+00, 0.4828683228163860E+00, 0.4745823594217251E+00, 0.3685025909289511E+00, 0.2947763441663148E+00, 0.8912041525268403E-01, 0.6456597576955210E-01, 0.6259461554584676E-01, 0.1853533814873023E-01, 0.2023108580404890E-03, 0.8671199725506423E-13, 0.1722304485286045E-09, 0.1666294529992108E-09, 0.1220997281181084E+01, 0.1774302413926244E-21, 0.1370178691819834E-09, 0.1399340123848638E-09, 0.9674288853031870E+00, 0.4276620702127187E-22, 0.3173068333548179E-09, 0.2274343348931791E-09, 0.8179252376135864E+00, 0.7888609052210118E-30, 0.5644994943584269E-09, 0.8117631577107350E-09, 0.6735586841320580E+00, 0.2962158340816585E-16, 0.9564613436107998E-08, 0.6775718950029066E-08, 0.6320597056120635E+00, 0.4964115825120276E-16, 0.1710244235260994E+02, 0.1710244235260994E+02, 0.1120000000000000E+03, 0.3265306122448980E+01, 0.6250000000000000E+01, 0.5299633299932952E-07, 0.4828683228163860E+00, 0.2680954403830288E-19, 0.1311205982337445E-05, 0.9790063018353157E-06, 0.4745823594217251E+00, 0.5160286279848935E-24, 0.1890785247579508E-05, 0.1394729630636152E-05, 0.3685025909289511E+00, 0.4693722386065020E-28, 0.6031882082954460E-05, 0.2415384446316590E-05, 0.2947763441663148E+00, 0.1882813323774143E-21, 0.7814092950831008E-04, 0.8799876387761915E-04, 0.8912041525268403E-01, 0.1005797654156790E-28, 0.3017726164846613E-06, 0.1278833151586840E-06, 0.6456597576955210E-01, 0.4635851024992188E-19, 0.2982580055136947E-07, 0.4759731822531787E-07, 0.6259461554584676E-01, 0.4490807166402986E-22, 0.9170799331172770E-06, 0.3025792024297308E-06, 0.1853533814873023E-01, 0.4985600920996795E-27, 0.9814614537388964E-04, 0.3116488226164178E-03, 0.2023108580404890E-03, 0.0000000000000000E+00, 0.9878507322060364E-03, 0.9125548412055403E-03}, + info: 0, + }, + { + z: []float64{0.4943635351465083E+00, 0.1295760812930432E+00, 0.7491711827268356E+00, 0.8583007697336751E+00, 0.8597988452333791E+00, 0.9020619105716389E+00, 0.2915077046929524E+00, 0.2667690273281318E+00, 0.2640508133196529E-01, 0.6592981688042527E+00, 0.5004017812459820E+00, 0.7056211227388411E+00, 0.2254860841977465E+00, 0.8570117342825790E+00, 0.6863131135194549E+00, 0.6029337708611949E+00, 0.6631267757314846E+00, 0.5332167960220966E+00, 0.3047497072553197E+00, 0.3019927731659721E+00, 0.6244714872283929E+00, 0.3204566006732108E+00, 0.9437738905138152E+00, 0.4462876020196550E+00, 0.6693016494515551E+00, 0.5687239407477801E+00, 0.5130358959101252E+00, 0.1634623710980615E+00, 0.6356065394794165E+00, 0.9187737904031696E+00, 0.8612817405760382E+00, 0.1602125514297330E+00, 0.5297426144233635E+00, 0.3699984812614213E+00, 0.3455622529703073E+00, 0.9962779456692529E+00, 0.3564481259772661E+00, 0.2073475342531472E-01, 0.5839325153640170E+00, 0.6856088547326490E+00, 0.1606020836922776E+00, 0.2475573692197572E+00, 0.8169030104559274E+00, 0.1727021335202554E+00, 0.8794153095346040E+00, 0.1052546999951709E-01, 0.4332903851899277E+00, 0.4302943891085251E+00, 0.6360909664440160E+00, 0.1924830187263967E+00, 0.6792019925733094E+00, 0.7328300669715262E+00, 0.8282900281692296E+00, 0.1586820387506954E+00, 0.5999731076117462E+00, 0.4873494502000296E+00, 0.4446262392098149E+00, 0.6430807880043099E-01, 0.4949024386471711E+00, 0.7324156973660632E+00, 0.4547667791304575E+00, 0.7542985454738853E+00, 0.3755946849636591E+00, 0.7135765429513076E+00, 0.7888131931751277E+00, 0.6384460726826821E+00, 0.4685063200928931E+00, 0.1343379262734882E+00, 0.8857603211032115E+00, 0.5798608180272281E+00, 0.8765662925729737E+00, 0.2107645345329755E+00, 0.7032612644639602E-01, 0.2672549085142431E+00, 0.5322118352980683E+00, 0.4697779217142906E-01, 0.1959612687762308E+00, 0.7346288295330818E+00, 0.4373432557584073E+00, 0.2514178299506654E+00, 0.7845430350805238E+00, 0.7823648156079857E+00, 0.6098686444303012E+00, 0.2687771415020881E+00}, + n: 21, + zOut: []float64{0.2638973127799410E+01, 0.2299941431214051E+01, 0.2280019421450360E+01, 0.2103910562764817E+01, 0.1753406216295798E+01, 0.1675269066003242E+01, 0.1419658234290438E+01, 0.1365959224584141E+01, 0.1187696680558471E+01, 0.1126073702945326E+01, 0.8926412592525027E+00, 0.7715773240739381E+00, 0.5428647577479762E+00, 0.4329885186763779E+00, 0.3589145864992100E+00, 0.2461266947628802E+00, 0.1802035742271595E+00, 0.1083562693061272E+00, 0.7909884021715781E-01, 0.2853616071040153E-01, 0.1859995500862765E-03, 0.5169878828456423E-25, 0.7099412452593561E-13, 0.1129160994681896E-12, 0.1419658234290438E+01, 0.7523863534922662E-17, 0.1645873945742296E-11, 0.1162641799741134E-11, 0.1365959224584141E+01, 0.3171195595439500E-23, 0.6168272840237550E-11, 0.8582511762369885E-11, 0.1187696680558471E+01, 0.8519789992808060E-16, 0.1934844654065141E-10, 0.2568816579510325E-10, 0.1126073702945326E+01, 0.8564308176121538E-22, 0.5690968370753065E-10, 0.7456610067231580E-10, 0.8926412592525027E+00, 0.4500097668303756E-13, 0.2149240165292988E+02, 0.2149240165292987E+02, 0.1030000000000000E+03, 0.2950113378684807E+01, 0.4854368932038835E+01, 0.1146501122497315E-08, 0.5428647577479762E+00, 0.2966117003631004E-27, 0.2887486457338918E-08, 0.3484100742696835E-08, 0.4329885186763779E+00, 0.9478952637135678E-26, 0.8311221870318503E-08, 0.6953572191921854E-08, 0.3589145864992100E+00, 0.2375820297137957E-16, 0.1629548458200623E-07, 0.1368379043565619E-07, 0.2461266947628802E+00, 0.1012567897168591E-16, 0.3168042687452701E-07, 0.3807114536183845E-07, 0.1802035742271595E+00, 0.8688408444571280E-16, 0.7017919615597339E-07, 0.9241973720004823E-07, 0.1083562693061272E+00, 0.3747089299799806E-28, 0.3320058009883818E-06, 0.6266972429387508E-06, 0.7909884021715781E-01, 0.9269115636346889E-29, 0.6452918276099027E-05, 0.1508443954686445E-04, 0.2853616071040153E-01, 0.2499111347740165E-24, 0.3360677328899296E-03, 0.1546059694047028E-03, 0.1859995500862765E-03, 0.1972152263052530E-28, 0.5448826922428762E-03, 0.1724316467181159E-02}, + info: 0, + }, + { + z: []float64{0.5641760158025995E+00, 0.2227931624220032E+00, 0.1040729150876691E+00, 0.7228520011975436E+00, 0.2490915552877161E+00, 0.4463107957028827E+00, 0.6882435259034004E+00, 0.2173580561342540E+00, 0.8146865135594571E+00, 0.3630549548424193E+00, 0.2813912484076728E+00, 0.7560034280086618E+00, 0.7800835186160227E-01, 0.9984316063995433E+00, 0.2057310185040729E+00, 0.4428139729521006E+00, 0.1946530136132755E+00, 0.8953866467149748E+00, 0.5910093704925600E+00, 0.9736056943014803E+00, 0.7342559355497796E+00, 0.5630651274913434E+00, 0.3586901690989497E+00, 0.1859950386974873E-01, 0.4012559193852120E+00, 0.5767984160414075E-01, 0.3379735138652440E+00, 0.6337834884220164E+00, 0.8830566914548466E-01, 0.2985048049064926E+00, 0.9820684138520455E+00, 0.1144932752938616E+00, 0.5905532956519596E+00, 0.4757653978696945E+00, 0.1997612463043563E-01, 0.6356348606671800E+00, 0.8478495728965164E+00, 0.4997410778119411E+00, 0.6861774168985810E+00, 0.6912919871514965E+00, 0.1276032443467088E+00, 0.2695430969348002E+00, 0.9446688115451145E+00, 0.5104603739010690E+00, 0.8863068797328323E+00, 0.3347723354379355E+00, 0.2977917172311930E+00, 0.9464871506253476E+00, 0.4279639349386329E+00, 0.6378279454376028E+00, 0.2778621310060349E+00, 0.6971058794896068E-01, 0.6309805553452471E+00, 0.3447281367207256E-01, 0.8480855191050544E+00, 0.6700112511333863E+00, 0.1616260465745026E+00, 0.7744510887458210E+00, 0.8408544531170117E+00, 0.8444763755373497E-01, 0.3286971575766536E+00, 0.8244867044222992E+00, 0.8036107174439190E+00, 0.4654902702844697E+00, 0.8300602115903392E+00, 0.5911511948645825E+00, 0.5734805041784674E+00, 0.6046912223886362E+00, 0.4400460907177143E+00, 0.4069795298963303E+00, 0.2413714645456244E+00, 0.7838758775665940E+00, 0.1371288591293247E+00, 0.8435169936355635E-01, 0.4867567406491472E+00, 0.2914527168883616E+00, 0.7540094160758792E+00, 0.6792178828893637E+00, 0.8924641252729165E+00, 0.2188072300242774E+00, 0.1899571860965691E+00, 0.7806965639263314E+00, 0.8706240780095753E-01, 0.7170634647198669E+00}, + n: 21, + zOut: []float64{0.2553381332090116E+01, 0.2166390759033473E+01, 0.1737362408504838E+01, 0.1528419999405254E+01, 0.1507484707859341E+01, 0.1334735890703865E+01, 0.1222641790395049E+01, 0.1186722126839839E+01, 0.1073660052771764E+01, 0.9488489095119069E+00, 0.9141860725715962E+00, 0.7726247731371300E+00, 0.6075856291402457E+00, 0.5409244297850613E+00, 0.4230641503671385E+00, 0.2356839373494127E+00, 0.1583434617720056E+00, 0.3187519618749328E-01, 0.2747107248999187E-01, 0.1480095837386152E-02, 0.5569185181399456E-04, 0.3215260779752862E-17, 0.2284971140234050E-13, 0.6915955898032105E-13, 0.1222641790395049E+01, 0.9860761315262648E-31, 0.9831000121605633E-10, 0.3802561298586086E-10, 0.1186722126839839E+01, 0.2066815571679051E-27, 0.6142487424703478E-09, 0.1524532000885779E-08, 0.1073660052771764E+01, 0.3155443620884047E-29, 0.1933670198753400E-07, 0.4311109498288097E-07, 0.9488489095119069E+00, 0.6613963504021090E-17, 0.7125410558010122E-07, 0.6137903750393884E-07, 0.9141860725715962E+00, 0.2713620929442760E-22, 0.1897294248760472E+02, 0.1897294248760472E+02, 0.1070000000000000E+03, 0.3233560090702948E+01, 0.4672897196261682E+01, 0.2313496546014482E-05, 0.6075856291402457E+00, 0.2008094738046662E-26, 0.6354651604911740E-04, 0.4633045629030685E-04, 0.5409244297850613E+00, 0.2465190328815662E-30, 0.8082164119218066E-03, 0.5151838483992701E-03, 0.4230641503671385E+00, 0.3299331849996360E-25, 0.9881103085087938E-03, 0.1036550305023510E-02, 0.2356839373494127E+00, 0.2111622871095604E-25, 0.1203513003711909E-02, 0.1300398061184096E-02, 0.1583434617720056E+00, 0.1737664936697394E-23, 0.8260928074113359E-03, 0.9484297179228856E-03, 0.3187519618749328E-01, 0.0000000000000000E+00, 0.1785275423606748E-03, 0.4485462762371783E-03, 0.2747107248999187E-01, 0.8804949879714635E-25, 0.5200632154389635E-08, 0.3234666977722410E-08, 0.1480095837386152E-02, 0.5399595124056782E-24, 0.5661901580915454E-02, 0.5860254353052324E-02, 0.5569185181399456E-04, 0.0000000000000000E+00, 0.1190560893471898E-01, 0.9131404251707014E-02}, + info: 0, + }, + { + z: []float64{0.7290518158132969E+00, 0.5196659176766039E-03, 0.6083923160589086E+00, 0.3459319602615154E+00, 0.3277021139736517E+00, 0.6020592719504614E-01, 0.4608784204502808E+00, 0.8430478676154098E+00, 0.3856212930081542E+00, 0.6602823264317716E+00, 0.4451601253283373E+00, 0.4130313322309198E-01, 0.7414750648249350E+00, 0.1630235543068703E-01, 0.6004925370465983E+00, 0.6953287054569501E+00, 0.7809046354974044E+00, 0.7892746585788727E+00, 0.8348704064067982E+00, 0.5999411739898802E+00, 0.5502575606089829E+00, 0.4392206918044746E+00, 0.7984758158185817E+00, 0.9084185319619590E+00, 0.1786837110145214E+00, 0.2414921532322530E+00, 0.5630913108462098E+00, 0.7820323704275389E+00, 0.5523326888742272E+00, 0.9015512185421630E+00, 0.6659841765947113E+00, 0.2845604319423287E+00, 0.3491764093356571E+00, 0.9628247275953050E-01, 0.6976897044251388E+00, 0.2960314575787897E+00, 0.5554565606281359E-01, 0.3558757052257084E+00, 0.9341850945519581E+00, 0.6665938574616496E+00, 0.9614102712845256E+00, 0.8607214960584614E+00, 0.4038740733880183E+00, 0.8195623831081322E+00, 0.6129183541897144E+00, 0.7215327066311872E-01, 0.5031970254369666E-01, 0.1396452298202989E+00, 0.9662061833347503E+00, 0.1270920838674061E+00, 0.4311106155362532E+00, 0.8052749852152479E+00, 0.4015794631208873E+00, 0.9090852867289334E-01, 0.6606775367976888E+00, 0.1481179966505828E+00, 0.9638580924515038E+00, 0.9709844996525795E+00, 0.1150673643193312E-01, 0.1429293205078334E+00, 0.2900042758147406E+00, 0.9072348766684573E+00, 0.5781273728635536E+00, 0.5436950045999074E+00, 0.1857622262967125E+00, 0.9164714647876027E+00, 0.1370982861482903E+00, 0.4992756875010576E+00, 0.1554652709586491E+00, 0.3126479857720679E+00, 0.4107075699045055E+00, 0.2895846225773548E+00, 0.6273125726015746E+00, 0.2838905730735005E+00, 0.5809021463377108E+00, 0.7647718231557297E+00, 0.2069816461533343E+00, 0.3140055757156704E+00, 0.1235726138058405E+00, 0.4368723232060789E-01, 0.7675622822273089E+00, 0.9898297711455730E+00, 0.5845844813092991E+00, 0.3724928805727834E+00}, + n: 21, + zOut: []float64{0.2656606156715505E+01, 0.2361088067613179E+01, 0.2270460825471249E+01, 0.2122871466419806E+01, 0.1864972075992565E+01, 0.1483766917780093E+01, 0.1313593002893207E+01, 0.1121546276208008E+01, 0.1100149868182268E+01, 0.9659264313206680E+00, 0.7624972132947719E+00, 0.7289080649182198E+00, 0.6752163576811447E+00, 0.6611764720975886E+00, 0.5004340625462813E+00, 0.2440674815088013E+00, 0.2171809202435314E+00, 0.1235497606154792E+00, 0.3737121186344041E-01, 0.2834840406904476E-01, 0.5846755428136478E-02, 0.7443896006885402E-16, 0.5016677150024004E-07, 0.3707799983650212E-07, 0.1313593002893207E+01, 0.2958228394578794E-29, 0.1581957950672119E-06, 0.2298083114979900E-06, 0.1121546276208008E+01, 0.1915993820645148E-16, 0.4749045639556273E-06, 0.4145613346073258E-06, 0.1100149868182268E+01, 0.9026685982667287E-18, 0.2821283116535875E-06, 0.3158894087015811E-06, 0.9659264313206680E+00, 0.2037048580685469E-20, 0.2246093425341190E-06, 0.2076005360058006E-06, 0.7624972132947719E+00, 0.1234566306928925E-21, 0.2124557779286299E+02, 0.2124557779286298E+02, 0.1010000000000000E+03, 0.3002267573696145E+01, 0.2970297029702970E+01, 0.4897987464996691E-04, 0.6752163576811447E+00, 0.7461812581271996E-18, 0.7761124913531668E-04, 0.7483244468930916E-04, 0.6611764720975886E+00, 0.1038114253693458E-19, 0.1582094808245393E-03, 0.1235322388201987E-03, 0.5004340625462813E+00, 0.1010613662291919E-16, 0.2610534203903574E-03, 0.4450812691210283E-03, 0.2440674815088013E+00, 0.1110435042389887E-20, 0.5668320309921573E-04, 0.5311544381771655E-04, 0.2171809202435314E+00, 0.4733165431326071E-27, 0.6599010146996593E-04, 0.7896621041843452E-04, 0.1235497606154792E+00, 0.3155385912111625E-18, 0.1746230697391169E-01, 0.1331928313395539E-01, 0.3737121186344041E-01, 0.7395570986446986E-31, 0.1364698415102933E-02, 0.9400709901879650E-03, 0.2834840406904476E-01, 0.1581043861486090E-22, 0.9826835453665868E-03, 0.1307033404080312E-02, 0.5846755428136478E-02, 0.5593364605928029E-23, 0.6675960788692170E-02, 0.6853670175678725E-02}, + info: 0, + }, + { + z: []float64{0.4059771234161322E+00, 0.9607215623246773E+00, 0.2458768097786967E-01, 0.2349999394464353E-01, 0.5195584553698999E+00, 0.4267565401751807E+00, 0.5653505726897825E+00, 0.1993982232067181E+00, 0.7123509462851438E+00, 0.7322091078130321E+00, 0.6397865818692764E+00, 0.7795245712118530E+00, 0.9924677795119503E+00, 0.9446777193650685E+00, 0.9161440637569995E+00, 0.4356325057978820E+00, 0.6968317286853016E+00, 0.8623411680463823E+00, 0.8789901991689911E+00, 0.3964880116495537E+00, 0.3452640838632506E+00, 0.2457053330236874E+00, 0.3088650440709877E+00, 0.3819576657222301E+00, 0.3428589632713919E-01, 0.5108638376023356E-01, 0.1646491337519898E+00, 0.4402398340108123E+00, 0.6741907107293844E+00, 0.8399512836956711E+00, 0.5689849385173426E+00, 0.5208530271268840E+00, 0.1800472375386978E+00, 0.7659410457647264E+00, 0.2320702606914905E+00, 0.1105800266048680E+00, 0.9555355666039600E-02, 0.1859192596152662E+00, 0.7825627400019242E-02, 0.5286418396370182E+00, 0.2569279638014341E+00, 0.5549104171411018E+00, 0.7406835450501670E+00, 0.8319568443444482E+00, 0.1523286720686696E+00, 0.6741822248281739E+00, 0.7686049385045001E+00, 0.7046090895325479E+00, 0.5187887151753254E+00, 0.1082987708911324E+00, 0.1267838014025160E+00, 0.1115865001832446E+00, 0.9799554493413084E+00, 0.2112830058825086E+00, 0.1414836977037485E+00, 0.6416690587599562E+00, 0.7257743058080667E+00, 0.5941533679852271E+00, 0.2889670048515264E+00, 0.2352763591376699E+00, 0.4250778140801711E+00, 0.1017573282390372E-01, 0.7592168685641336E+00, 0.1236630021486789E+00, 0.3794258137484455E+00, 0.3894249799986492E+00, 0.3467719607731882E+00, 0.5651244918121399E+00, 0.7941305753999619E+00, 0.7160004674307343E+00, 0.6194397297375442E+00, 0.1453439098617406E+00, 0.3817157280391337E-03, 0.9381666563671931E+00, 0.8543357988390619E+00, 0.4675645670082479E+00, 0.8133557631373793E+00, 0.1160066189475003E+00, 0.6551894700973839E+00, 0.6157191087148942E+00, 0.4651705119652626E+00, 0.2935400080400429E+00, 0.4317648586994048E+00, 0.8522331953027451E-01}, + n: 21, + zOut: []float64{0.3090946182879871E+01, 0.2427731098824810E+01, 0.2178358732328273E+01, 0.1944657148720347E+01, 0.1388313875420951E+01, 0.1366009016577358E+01, 0.1254539813854158E+01, 0.1096743376160052E+01, 0.8976114875705017E+00, 0.7925182471468240E+00, 0.7633415317747125E+00, 0.5940562138773567E+00, 0.3406702196684873E+00, 0.2541261981011808E+00, 0.2081990106830526E+00, 0.1967266434974441E+00, 0.8212572008660911E-01, 0.6231598248219099E-01, 0.2121611392818772E-01, 0.6627852439078377E-02, 0.2020564063973749E-05, 0.5156511541642804E-17, 0.3563959083802911E-09, 0.2193664839500192E-09, 0.1254539813854158E+01, 0.5107396913706617E-17, 0.2245013704648247E-08, 0.3514139913607919E-08, 0.1096743376160052E+01, 0.1770166510860316E-21, 0.1137128600534393E-07, 0.7589514151253922E-08, 0.8976114875705017E+00, 0.3631375006656261E-16, 0.1027683956127825E-09, 0.1703981899256795E-09, 0.7925182471468240E+00, 0.0000000000000000E+00, 0.2692111438183261E-08, 0.1491447500870467E-08, 0.7633415317747125E+00, 0.3655079503368504E-18, 0.1896683648658551E+02, 0.1896683648658551E+02, 0.9800000000000000E+02, 0.2941043083900227E+01, 0.3061224489795918E+01, 0.1473194721443778E-07, 0.3406702196684873E+00, 0.8487843002529896E-19, 0.1107295924775035E-05, 0.6897939613884539E-06, 0.2541261981011808E+00, 0.8699892772041781E-19, 0.4010969039165872E-05, 0.5564243023106877E-05, 0.2081990106830526E+00, 0.1258849778182470E-17, 0.2192657884798391E-05, 0.1921286515322920E-05, 0.1967266434974441E+00, 0.1498835719919922E-28, 0.3181611995531238E-06, 0.2328457188758453E-05, 0.8212572008660911E-01, 0.9162137014768053E-16, 0.4655593170815260E-04, 0.2906458517213153E-04, 0.6231598248219099E-01, 0.7111877894410489E-19, 0.1084455050840344E-03, 0.4940544045928809E-04, 0.2121611392818772E-01, 0.1296887328183343E-24, 0.1059468102013224E-02, 0.9250155264543548E-03, 0.6627852439078377E-02, 0.2014616961124939E-22, 0.1082171160654875E-03, 0.1415095048461561E-03, 0.2020564063973749E-05, 0.0000000000000000E+00, 0.6572087989553770E-04, 0.6490933881766271E-04}, + info: 0, + }, + { + z: []float64{0.3515867373170093E+00, 0.6900024519663606E-01, 0.2562617636787797E+00, 0.4448144612254716E+00, 0.1882829208975508E+00, 0.5473764707914393E+00, 0.2385465140832452E+00, 0.1069888484826550E+00, 0.6650479699038470E+00, 0.5577458834974632E+00, 0.3827016483759793E-01, 0.2430476485682098E-01, 0.4730689827049095E-01, 0.7028807845337007E+00, 0.2183345614483843E+00, 0.4504620631941809E+00, 0.4989666416356805E+00, 0.3524179690092576E+00, 0.2245980971932510E+00, 0.4235501615333767E+00, 0.5262756658101302E+00, 0.9543218824354944E+00, 0.7932768470961233E+00, 0.6115989702914060E-01, 0.5090745247561921E+00, 0.6231416396947956E+00, 0.5848645563028462E+00, 0.4261243979220120E-01, 0.7488050001299923E+00, 0.1371419590365067E+00, 0.2276573560104874E+00, 0.3333510148295767E+00, 0.8801005866377587E+00, 0.1783788042757909E+00, 0.7167665061134074E+00, 0.8328416386285911E+00, 0.3239179761297745E+00, 0.3396256067647054E+00, 0.3124818554244235E-01, 0.3558253686357221E+00, 0.3434895378785284E+00, 0.5623459587025392E-01, 0.2638452014850361E+00, 0.8291744484791080E+00, 0.1974847584119865E+00, 0.7319795333910079E+00, 0.2610606436005336E+00, 0.5710127034520260E+00, 0.1439281438102160E+00, 0.9086761346521347E+00, 0.8079247890865698E+00, 0.9018578929430654E+00, 0.4900454364738460E+00, 0.8138610668520670E+00, 0.6711229676830790E+00, 0.5055629692453131E+00, 0.7743169767236130E+00, 0.4534345901632091E+00, 0.9064089158232752E+00, 0.4827899713942460E+00, 0.7358703780808750E+00, 0.9369729458478693E-02, 0.8597279323370060E+00, 0.7253136203352766E+00, 0.9571052925069841E+00, 0.2164676786228616E+00, 0.5574107740713430E-05, 0.7154716238932374E+00, 0.1141135068223202E+00, 0.6209438587853456E+00, 0.7851847140042024E+00, 0.4215540797089058E+00, 0.9132020640887749E+00, 0.1510454496157759E+00, 0.4172986352579149E+00, 0.5037450189692434E+00, 0.4485087403424131E+00, 0.5740668076879305E+00, 0.2978796610784261E+00, 0.6581099078338648E-01, 0.8930273171304047E+00, 0.8152477689300778E+00, 0.1069556485483132E+00, 0.6932157626522990E+00}, + n: 21, + zOut: []float64{0.2205969711876647E+01, 0.1949821527895322E+01, 0.1555841877124327E+01, 0.1396030697440207E+01, 0.1339074151471965E+01, 0.1304928492707023E+01, 0.1082549957806062E+01, 0.9163938874206132E+00, 0.8887122139609793E+00, 0.7285328536138327E+00, 0.6136134334950112E+00, 0.5962413214799335E+00, 0.4250735423840991E+00, 0.3604939377250871E+00, 0.2295486599338548E+00, 0.1443459206161604E+00, 0.1184188267216090E+00, 0.7075746168152415E-01, 0.2006576919306350E-01, 0.3756273174580983E-02, 0.4503973951446061E-03, 0.2214970142320351E-19, 0.1258326061053631E-10, 0.9003557400980630E-11, 0.1082549957806062E+01, 0.1308878013942703E-25, 0.3368372626791194E-10, 0.2572022209508410E-10, 0.9163938874206132E+00, 0.7614331624527915E-16, 0.1049500061330476E-08, 0.2928487158224854E-08, 0.8887122139609793E+00, 0.1203547791264655E-21, 0.7079518778653070E-07, 0.2057204985301009E-06, 0.7285328536138327E+00, 0.1084769825180869E-21, 0.6504687546036223E-07, 0.2011551828019932E-07, 0.6136134334950112E+00, 0.1678480469223895E-16, 0.1595062091511705E+02, 0.1595062091511705E+02, 0.1020000000000000E+03, 0.3156462585034014E+01, 0.2941176470588236E+01, 0.1336032003974816E-08, 0.4250735423840991E+00, 0.1033222323690773E-11, 0.1230907576002882E-05, 0.1377773980605759E-05, 0.3604939377250871E+00, 0.5435093612356237E-21, 0.5904438579725169E-05, 0.1247176535660427E-04, 0.2295486599338548E+00, 0.3794809073678436E-22, 0.8654598111714590E-03, 0.7607233838455693E-03, 0.1443459206161604E+00, 0.2335329392584174E-18, 0.9486551585203510E-04, 0.5848864829043123E-04, 0.1184188267216090E+00, 0.2421802979028506E-27, 0.4440929582264130E-04, 0.3669242548994226E-04, 0.7075746168152415E-01, 0.1891688450719986E-26, 0.5237855019006247E-04, 0.2468105637453731E-04, 0.2006576919306350E-01, 0.1180787648903814E-27, 0.8134126440113327E-03, 0.8865157422262554E-03, 0.3756273174580983E-02, 0.2581152881883151E-26, 0.5819544721666204E-02, 0.3152501351079271E-02, 0.4503973951446061E-03, 0.0000000000000000E+00, 0.5880303886253363E-04, 0.1585743718762697E-03}, + info: 0, + }, + { + z: []float64{0.5610544265871693E+00, 0.3865731523333528E+00, 0.8792353035941016E+00, 0.8523516652694250E+00, 0.1444314813898040E-01, 0.8826603847895033E+00, 0.6868176286586357E+00, 0.1885799699020001E+00, 0.8756021324147915E+00, 0.9000748303342890E+00, 0.6057362077051875E+00, 0.7116572505145777E+00, 0.4651180401287146E+00, 0.2732222796277717E-01, 0.4226433912686857E+00, 0.2137613193249559E+00, 0.8364980217841237E+00, 0.7760779616422476E+00, 0.4204777290352190E+00, 0.6224635225380051E+00, 0.2764474942580449E+00, 0.3783169947455127E+00, 0.5180995217194659E+00, 0.3065081068358929E+00, 0.7865831746887696E+00, 0.1478697978858728E+00, 0.9439830303880672E+00, 0.8253272390565236E-01, 0.3067445628749279E+00, 0.7129198739696287E+00, 0.1655397340526111E+00, 0.1744497852178990E+00, 0.8123176080018479E-01, 0.7468152661528306E+00, 0.8702942511684653E-01, 0.2665897748347560E+00, 0.9213749341388631E+00, 0.1523897006311256E+00, 0.9645030292913545E+00, 0.9612618327522493E-01, 0.4802656873918926E+00, 0.9400504426452867E+00, 0.4625574582408437E+00, 0.7387695442245192E+00, 0.7695082904503155E+00, 0.1394488941705607E+00, 0.4086909510206329E+00, 0.8420266381115991E+00, 0.9564685490270811E+00, 0.7091850518571272E+00, 0.5799173993611073E+00, 0.1780919033120022E+00, 0.4196947685163247E+00, 0.9892865772966106E+00, 0.5502405891255741E+00, 0.7805747931381838E+00, 0.8443114386354278E-01, 0.3818004737775779E+00, 0.5006744900666209E+00, 0.8330036981446504E+00, 0.6972526215524509E+00, 0.5997317354738497E+00, 0.6745658299087246E+00, 0.2369187863883299E+00, 0.4162907871251388E+00, 0.3987550165661536E+00, 0.3127240434721901E+00, 0.9587921004875174E+00, 0.9734600215022703E+00, 0.9507333301136496E+00, 0.3445022862066339E+00, 0.6240012410156072E+00, 0.3036264632031094E-01, 0.6999839547669153E+00, 0.4672138296892350E+00, 0.4669965382645248E+00, 0.7561275857160221E-01, 0.9250454776547237E+00, 0.8620177110728862E+00, 0.5266728805873626E+00, 0.6377535363121675E+00, 0.6098026285363055E+00, 0.8075088997828720E+00, 0.8486821693163010E+00}, + n: 21, + zOut: []float64{0.2468092632282687E+01, 0.2093427673862981E+01, 0.2055392019191517E+01, 0.1647867143267642E+01, 0.1615849876515927E+01, 0.1589328968238607E+01, 0.1271214388518367E+01, 0.1121382381594411E+01, 0.1069461264755295E+01, 0.1002295596318809E+01, 0.8815764834354939E+00, 0.8051252546404786E+00, 0.6374343329196452E+00, 0.5469723867709347E+00, 0.4015178604185544E+00, 0.3707602923265790E+00, 0.1795105850679969E+00, 0.1400595531050117E+00, 0.2548349514639473E-01, 0.1561366451013735E-02, 0.1155321273825210E-02, 0.3137752941767923E-22, 0.1448569525610494E-09, 0.1682297708320945E-10, 0.1271214388518367E+01, 0.3747089299799806E-29, 0.3127891707973917E-07, 0.1432924100618686E-07, 0.1121382381594411E+01, 0.1829309924661015E-19, 0.1414348814679943E-06, 0.1338467241717145E-06, 0.1069461264755295E+01, 0.2814655709828570E-26, 0.1421706541245010E-06, 0.1494636997707923E-06, 0.1002295596318809E+01, 0.2555408239179452E-16, 0.1745096068338993E-06, 0.1639215185470380E-06, 0.8815764834354939E+00, 0.5195421261043265E-21, 0.1992546887610216E+02, 0.1992546887610217E+02, 0.1040000000000000E+03, 0.3263038548752835E+01, 0.3846153846153846E+01, 0.5490557769901970E-06, 0.6374343329196452E+00, 0.1696050946225175E-28, 0.4391959465127471E-06, 0.4441570425561870E-06, 0.5469723867709347E+00, 0.4122920742224575E-16, 0.4792107785920969E-06, 0.5244422797027597E-06, 0.4015178604185544E+00, 0.4437342591868191E-30, 0.1189624719598388E-05, 0.1545254324980458E-05, 0.3707602923265790E+00, 0.0000000000000000E+00, 0.3830671301160838E-05, 0.5436396467135237E-05, 0.1795105850679969E+00, 0.1558228073167050E-14, 0.5423210427919237E-04, 0.1228583690085413E-03, 0.1400595531050117E+00, 0.8832743148296122E-19, 0.1395228897382397E-04, 0.1537585917376726E-04, 0.2548349514639473E-01, 0.0000000000000000E+00, 0.8277350694369951E-03, 0.9528953717632958E-03, 0.1561366451013735E-02, 0.2465190328815662E-31, 0.7095009159403311E-03, 0.6952609237045969E-03, 0.1155321273825210E-02, 0.1309509102666880E-27, 0.9046555260897671E-03, 0.1226313636978587E-02}, + info: 0, + }, + { + z: []float64{0.1242522906682814E+00, 0.6390609620209767E+00, 0.4481822861180138E+00, 0.4850355616354706E+00, 0.4018997557884576E+00, 0.7075817751574985E+00, 0.3076496509717662E+00, 0.9845619472128853E+00, 0.4421050939804582E+00, 0.3472138710835164E+00, 0.7694977672753175E+00, 0.4786944038481857E+00, 0.6974278852457209E+00, 0.5004517708240744E+00, 0.7658513494839985E+00, 0.7508522623862479E-01, 0.8645614962374704E-02, 0.2513671118506070E+00, 0.9355687048630774E+00, 0.2836435232395548E+00, 0.8653687008315966E+00, 0.3043727382738487E+00, 0.8973655399535756E+00, 0.7135517870607274E+00, 0.4956863425678929E+00, 0.8362506849216409E+00, 0.9829450079482006E+00, 0.9413718361369072E+00, 0.2542921002853715E-01, 0.5951158954104814E+00, 0.9317747763384295E+00, 0.9085271053958202E+00, 0.9993466426511500E+00, 0.2497009223772528E-01, 0.8726460080387569E+00, 0.3868463012727243E+00, 0.5820757557404177E-01, 0.7974577837432384E-01, 0.8242609714155934E+00, 0.1887913799920241E+00, 0.3268225406700475E+00, 0.2264596835393817E+00, 0.4020160264981738E+00, 0.8597685353848280E+00, 0.5429598215579996E+00, 0.4134507486351844E+00, 0.8781720494573462E+00, 0.3655827200857601E+00, 0.2876763179222336E+00, 0.9193112804533413E+00, 0.3958413207165046E-01, 0.7980401670837647E+00, 0.5101422689515223E-01, 0.2194050847732673E+00, 0.6115669547384739E-02, 0.9036470382476453E+00, 0.6696681747677364E+00, 0.1689100553906829E+00, 0.9284887836539969E+00, 0.8748192507086142E+00, 0.7181738874264668E+00, 0.8990747837549429E-01, 0.7166811698029575E+00, 0.8712804839027968E+00, 0.2571898936326318E+00, 0.2264160460654618E+00, 0.6364724288557849E+00, 0.9550337894922362E+00, 0.8995892333665090E+00, 0.3728949594240628E+00, 0.6496276036419958E+00, 0.7218580021816370E+00, 0.2620053580399828E+00, 0.8492826434932900E+00, 0.1090756692624820E+00, 0.1230806328807070E+00, 0.5326342483791896E+00, 0.3425391815117244E+00, 0.4714474424671373E+00, 0.9044440560476328E+00, 0.2298320061743346E+00, 0.7771450381369926E+00, 0.4623588499686800E+00, 0.8996441805847293E+00}, + n: 21, + zOut: []float64{0.2749036998648791E+01, 0.2657147938200912E+01, 0.2156780738808330E+01, 0.2057290308234013E+01, 0.1910481192038085E+01, 0.1550197528741744E+01, 0.1531663815430223E+01, 0.1307411568456853E+01, 0.1180055477995477E+01, 0.1145160315453326E+01, 0.8462599780670359E+00, 0.8196023258344234E+00, 0.7505058481318937E+00, 0.3802378569170251E+00, 0.3493658644293456E+00, 0.2733852715996189E+00, 0.1920071438579977E+00, 0.3602127141457542E-01, 0.1503353393017178E-01, 0.5047074669949666E-02, 0.4814167031169938E-03, 0.1615587133892632E-26, 0.3701495167228324E-14, 0.8166164251788096E-14, 0.1531663815430223E+01, 0.5400326177233737E-21, 0.8345943934662111E-13, 0.3845954584916692E-13, 0.1307411568456853E+01, 0.2270604060615577E-17, 0.1098158814550649E-11, 0.6011774632275279E-12, 0.1180055477995477E+01, 0.6617444900424221E-23, 0.1039362721731823E-10, 0.1780733867152956E-10, 0.1145160315453326E+01, 0.3193234771665464E-17, 0.8582967920523009E-10, 0.1451582492090454E-09, 0.8462599780670359E+00, 0.4268426102972081E-16, 0.2191317346756291E+02, 0.2191317346756291E+02, 0.1100000000000000E+03, 0.3303854875283447E+01, 0.6363636363636363E+01, 0.9730504757902699E-07, 0.7505058481318937E+00, 0.1718125187449148E-14, 0.1758342086676891E-05, 0.2642640058729254E-05, 0.3802378569170251E+00, 0.9047523974206004E-14, 0.3754566725544834E-04, 0.5673943129185001E-04, 0.3493658644293456E+00, 0.2726303288443817E-26, 0.2006689219611138E-03, 0.1777791597062721E-03, 0.2733852715996189E+00, 0.1852245405458936E-26, 0.4273484804153724E-06, 0.2289494629295668E-05, 0.1920071438579977E+00, 0.7673537210642012E-17, 0.3631464818839244E-02, 0.3052322482564877E-02, 0.3602127141457542E-01, 0.1402889840288648E-17, 0.2065820498676818E-02, 0.7907462477517949E-03, 0.1503353393017178E-01, 0.3588277137446075E-19, 0.9842420036565967E-03, 0.4295497278130008E-03, 0.5047074669949666E-02, 0.1100487290795119E-18, 0.2169791314757801E-02, 0.2746294001732303E-02, 0.4814167031169938E-03, 0.9926167349879280E-23, 0.2524480967032520E-02, 0.1685323473608901E-02}, + info: 0, + }, + { + z: []float64{0.4452569544189223E+00, 0.3712416527218666E+00, 0.4540009468556715E+00, 0.9149505778015055E-01, 0.9825460881415958E+00, 0.8144387623295611E+00, 0.4257438310114644E+00, 0.4055209729019219E+00, 0.1358301754544711E-01, 0.6660365069195171E+00, 0.4791028777450690E-01, 0.3657122138300755E+00, 0.9244230955293443E+00, 0.2570776992045346E+00, 0.5718524872194095E+00, 0.6959027703199671E+00, 0.8022093165313721E+00, 0.4495167304148069E+00, 0.4533829141769831E+00, 0.4399857636092745E+00, 0.8343772053001745E+00, 0.5841091089133705E+00, 0.9225724116024000E+00, 0.3646730358635919E+00, 0.4342402996301750E+00, 0.1979669913465428E+00, 0.2710080252534286E+00, 0.4064878156937679E+00, 0.1329017000110605E+00, 0.3577863781516848E+00, 0.7737638611946227E+00, 0.3628629851888825E+00, 0.6191378950237536E+00, 0.9181610808896479E-01, 0.3164967052049129E+00, 0.1800354212961807E+00, 0.5261304159866632E+00, 0.2095779664090124E+00, 0.4734470785970568E+00, 0.8233700542774806E+00, 0.1405149000531442E+00, 0.5739228235076023E+00, 0.4484023224779539E+00, 0.7953415183519565E+00, 0.5683020712105596E+00, 0.3828815589637512E+00, 0.9478512018818865E+00, 0.9398576744287683E+00, 0.6799918835962694E+00, 0.9795978835389229E+00, 0.9415167003494995E+00, 0.9804631144197878E+00, 0.4529282233852833E+00, 0.6987441800620822E+00, 0.1071819561656476E+00, 0.6287695276127018E+00, 0.2573913359217608E+00, 0.5283299892256954E-01, 0.1312057002484920E+00, 0.2566822109082798E+00, 0.5022596747022927E+00, 0.3755634037822867E+00, 0.7687685406410046E+00, 0.9286257388850563E+00, 0.2460950353669618E+00, 0.4615682752011302E+00, 0.2668978314403934E+00, 0.9526334220011422E+00, 0.7113266960956600E+00, 0.8033610237680390E+00, 0.2049912091857929E+00, 0.9104136201043411E+00, 0.9905140155095393E+00, 0.5284892163797259E+00, 0.4617116226676921E-01, 0.7638541825257228E+00, 0.8058860223281950E-01, 0.6562405799504624E+00, 0.4217948031372573E+00, 0.8444441663937204E+00, 0.4135300708069887E+00, 0.3992676961789670E+00, 0.9443059736340937E+00, 0.4697907769676380E+00}, + n: 21, + zOut: []float64{0.2339652518244840E+01, 0.2127240999798084E+01, 0.2122097736373912E+01, 0.1640409192349226E+01, 0.1522936721900112E+01, 0.1513900850773956E+01, 0.1190428480890818E+01, 0.1098839257111754E+01, 0.9060499827420537E+00, 0.8483833633939547E+00, 0.7423625631343986E+00, 0.6441873762582893E+00, 0.5561064852023264E+00, 0.5332801819376103E+00, 0.3323799891685881E+00, 0.2356658160961767E+00, 0.1910001776595044E+00, 0.1052937995306845E+00, 0.3493206724380617E-01, 0.1582963148293342E-01, 0.1362410302334481E-03, 0.2902907641693595E-19, 0.1235088787739235E-18, 0.5938156039510254E-18, 0.1190428480890818E+01, 0.2366582715663035E-29, 0.1736669751992271E-12, 0.4479686287025860E-12, 0.1098839257111754E+01, 0.4930380657631324E-31, 0.6845104399398104E-11, 0.1631652613834293E-10, 0.9060499827420537E+00, 0.3623410171350593E-13, 0.4397239464622790E-08, 0.8783797026819435E-08, 0.8483833633939547E+00, 0.1680831004707752E-20, 0.6292544501750849E-07, 0.1207646260809090E-06, 0.7423625631343986E+00, 0.1044536639065691E-17, 0.1870111343232326E+02, 0.1870111343232326E+02, 0.1030000000000000E+03, 0.3002267573696145E+01, 0.3883495145631068E+01, 0.8796985420666049E-06, 0.5561064852023264E+00, 0.6232001151245993E-28, 0.4765675419124029E-06, 0.5281771988202168E-06, 0.5332801819376103E+00, 0.5995342879679690E-28, 0.3211676631039122E-06, 0.3513325837054497E-06, 0.3323799891685881E+00, 0.2177256098409993E-25, 0.1826919937583927E-06, 0.1747056528730059E-06, 0.2356658160961767E+00, 0.1311326116357865E-17, 0.1784537561302489E-06, 0.2175474607275274E-06, 0.1910001776595044E+00, 0.3862262991962074E-24, 0.9127544222909640E-06, 0.4962248419758332E-06, 0.1052937995306845E+00, 0.1072850831100576E-26, 0.2872845137271569E-03, 0.1413151427897814E-03, 0.3493206724380617E-01, 0.8028654523313936E-17, 0.5779626756191757E-04, 0.4784930511330926E-04, 0.1582963148293342E-01, 0.9359045779542084E-26, 0.9339546012110267E-04, 0.6206712854083305E-04, 0.1362410302334481E-03, 0.4535950205020818E-29, 0.1799327870469576E-03, 0.1621654177500190E-02}, + info: 0, + }, + { + z: []float64{0.6327743759434090E-01, 0.8874473183212240E+00, 0.1587228549487630E+00, 0.1869853022948459E+00, 0.1852952724381735E+00, 0.2190328352455733E+00, 0.7936705141328082E+00, 0.1573124860628259E+00, 0.2446308768539528E+00, 0.2441044501798444E+00, 0.4435884001235265E+00, 0.1783624365771731E+00, 0.6874700271616803E+00, 0.4796486989431838E+00, 0.2471425348644392E+00, 0.4391077480264999E+00, 0.9973269002312380E+00, 0.4770343529783838E+00, 0.3451566405930041E+00, 0.5011834710046675E+00, 0.8072188861666797E+00, 0.5748577907200507E+00, 0.2986003422862493E+00, 0.4760318526964945E+00, 0.5838957192070238E-01, 0.1760621214885278E+00, 0.7926085978219721E+00, 0.3379849703418611E+00, 0.6012719579585296E+00, 0.1130783704430351E+00, 0.5590675745254436E-01, 0.8616930340961984E+00, 0.9917564091315376E+00, 0.4219575368674273E+00, 0.1044382974319413E+00, 0.1886528536659160E-01, 0.9337085742573710E+00, 0.6447952074628677E+00, 0.7158824182577913E+00, 0.3883216757352448E+00, 0.2116568255149501E+00, 0.9819105316462939E+00, 0.8471687522868032E-01, 0.2785996362910685E+00, 0.8775405646426044E+00, 0.5671584270354416E+00, 0.4912868754910720E+00, 0.5767395813214109E+00, 0.7327323379759062E+00, 0.8184048812627022E+00, 0.3325270745990432E+00, 0.3026500963479654E+00, 0.7228591188664935E+00, 0.1094677581261434E+00, 0.5280482398171430E+00, 0.9974727380694979E+00, 0.5087630734843742E+00, 0.6953603638889684E+00, 0.9103967979863506E+00, 0.2584730811693510E+00, 0.5498750728524477E+00, 0.9758543899455846E+00, 0.8309066632970131E+00, 0.4311646442586020E+00, 0.4732818688792167E+00, 0.4096051739313099E+00, 0.7479697576436509E+00, 0.9369473766445329E+00, 0.7380538090811954E+00, 0.1199951604231148E+00, 0.5672128274092054E+00, 0.7150763241893471E+00, 0.6134240647991112E+00, 0.7095501841622953E-01, 0.1510080432732774E-01, 0.2912426074708729E+00, 0.1611746025295486E+00, 0.3946903662654964E+00, 0.7408818971566200E-01, 0.3978128748254128E+00, 0.3580504147215868E+00, 0.2603799996304434E-01, 0.8990784999913340E+00, 0.1985602490013758E+00}, + n: 21, + zOut: []float64{0.2139906798692060E+01, 0.2104052265745164E+01, 0.2080474521860817E+01, 0.1784368581097839E+01, 0.1501145759273247E+01, 0.1395549430074518E+01, 0.1236063891814824E+01, 0.1123736402991315E+01, 0.8211474325690415E+00, 0.7411912844479571E+00, 0.7336682913123216E+00, 0.5274366057326734E+00, 0.3715621485686555E+00, 0.3171624722931449E+00, 0.2809062056956198E+00, 0.1668884413843382E+00, 0.9744092162322979E-01, 0.7613224124753509E-01, 0.1665106039654164E-01, 0.4700366860927376E-02, 0.1401918312945850E-02, 0.1084683744678891E-29, 0.4021673570416241E-08, 0.3931910860092540E-08, 0.1236063891814824E+01, 0.1439956010332256E-19, 0.3626387646080745E-08, 0.3543555828237728E-08, 0.1123736402991315E+01, 0.3006506681978320E-24, 0.3371387381785702E-08, 0.3448854867663729E-08, 0.8211474325690415E+00, 0.6197291271416269E-26, 0.2831422041774839E-08, 0.2886341750444270E-08, 0.7411912844479571E+00, 0.0000000000000000E+00, 0.2880306038760265E-08, 0.2936321908308739E-08, 0.7336682913123216E+00, 0.2406371799476454E-20, 0.1752158704199472E+02, 0.1752158704199472E+02, 0.1050000000000000E+03, 0.3111111111111111E+01, 0.7619047619047619E+01, 0.3652487989473621E-08, 0.3715621485686555E+00, 0.1451701975030564E-21, 0.4296538801302010E-08, 0.3992227758256396E-08, 0.3171624722931449E+00, 0.6162975822039155E-31, 0.5151357395533313E-08, 0.5974032086218965E-08, 0.2809062056956198E+00, 0.2039658356197591E-16, 0.1134165265363298E-07, 0.1513934018844884E-07, 0.1668884413843382E+00, 0.2400943524542200E-24, 0.1781584505522029E-06, 0.1218300442987205E-06, 0.9744092162322979E-01, 0.6162975822039155E-31, 0.9557876398738343E-06, 0.5872690889712619E-06, 0.7613224124753509E-01, 0.5074727415413836E-17, 0.2309052370169074E-04, 0.5924498773169641E-04, 0.1665106039654164E-01, 0.1400228106767296E-28, 0.5116509326795711E-04, 0.5154480234673206E-04, 0.4700366860927376E-02, 0.1956855682120442E-20, 0.1061141342429108E-03, 0.9755516139369119E-04, 0.1401918312945850E-02, 0.0000000000000000E+00, 0.1229085807195224E-02, 0.8009097549502667E-02}, + info: 0, + }, + { + z: []float64{0.7225493913848618E+00, 0.3268825038779278E+00, 0.2580957584922012E+00, 0.4222896610254372E+00, 0.8243187922209068E+00, 0.3973391932422579E+00, 0.3700698452657641E+00, 0.2073422474585492E+00, 0.3071746797249822E+00, 0.2370168833330754E+00, 0.7779583030993944E+00, 0.4350651843345934E+00, 0.7867543754352369E+00, 0.3439673345654075E+00, 0.3736479358698906E+00, 0.8450641599616520E+00, 0.3880138308747846E+00, 0.2479782080134303E+00, 0.3220864609073060E+00, 0.8460149388339712E+00, 0.6082870752479030E+00, 0.3396261004129498E+00, 0.1231305479976765E+00, 0.6514493424347317E+00, 0.4987273421671501E-01, 0.2199653339283912E+00, 0.5626339029868159E+00, 0.6755574738917364E+00, 0.7016850168758351E+00, 0.7957347983005405E+00, 0.3394687111682781E-01, 0.1490794513934588E+00, 0.9837873705641814E+00, 0.5038299137267350E+00, 0.8394265886439850E+00, 0.1438624872728633E-01, 0.4444190467253504E+00, 0.1489248400425094E+00, 0.6410535698206483E+00, 0.2739267916732867E+00, 0.6522097474411971E+00, 0.9086492388715542E+00, 0.1949071722314141E+00, 0.7176724675018002E+00, 0.9247176136838016E+00, 0.4929580602677628E+00, 0.3824418236647242E+00, 0.2425574232540663E+00, 0.7085287909144397E+00, 0.2574302555167504E+00, 0.6093160252921369E+00, 0.2417561032032995E+00, 0.4795262420397247E+00, 0.4658200993830509E+00, 0.9033699918994937E+00, 0.1295021719769064E+00, 0.6219991535812029E+00, 0.7040800557612208E+00, 0.8644629036591867E-01, 0.5129394685202899E+00, 0.7988983132437487E+00, 0.8322467913624354E+00, 0.9905487172695071E-01, 0.7093832076693246E+00, 0.1992462440538834E-01, 0.6378263512182120E+00, 0.5823949252324323E-02, 0.7826279628890456E+00, 0.5919828344466795E+00, 0.3815528510244244E+00, 0.6537355893096064E-01, 0.6459825623191251E-01, 0.4466210788758083E+00, 0.6620124961190184E+00, 0.6318809895815939E+00, 0.8145861476435108E+00, 0.5938169865214039E+00, 0.8092284578140500E+00, 0.5378701643349270E+00, 0.1648044346935199E+00, 0.9874291179811017E+00, 0.3210667070512012E+00, 0.6809988920516613E+00, 0.6410080963943865E+00}, + n: 21, + zOut: []float64{0.2108032684782400E+01, 0.1971253922847928E+01, 0.1952878543820764E+01, 0.1839982524288513E+01, 0.1730503177731785E+01, 0.1509287569836986E+01, 0.1316544049683026E+01, 0.1117715356834192E+01, 0.9058841126016787E+00, 0.8452427684353671E+00, 0.7582219581243467E+00, 0.6392786878439012E+00, 0.5749674919024932E+00, 0.5111167278611346E+00, 0.3859485208834002E+00, 0.2295319067023061E+00, 0.2262113890497363E+00, 0.1122658486667464E+00, 0.7234153262002044E-01, 0.4527048542558528E-01, 0.8319414807792288E-04, 0.2547288901631409E-13, 0.9052716547280089E-04, 0.7818093042872877E-04, 0.1316544049683026E+01, 0.0000000000000000E+00, 0.2537869832861900E-04, 0.2058109204222074E-04, 0.1117715356834192E+01, 0.0000000000000000E+00, 0.1154377886785102E-04, 0.1215574110748570E-04, 0.9058841126016787E+00, 0.8843729980912407E-17, 0.1391102994778336E-08, 0.5248885105740662E-08, 0.8452427684353671E+00, 0.2445468806185137E-28, 0.2192473584471834E-06, 0.3792344586441173E-06, 0.7582219581243467E+00, 0.6480317173221865E-17, 0.1885256245409039E+02, 0.1885256245409039E+02, 0.1090000000000000E+03, 0.3303854875283447E+01, 0.3669724770642202E+01, 0.3715603111278862E-08, 0.5749674919024932E+00, 0.4928548884551519E-18, 0.2515491583997865E-07, 0.9138389520203617E-08, 0.5111167278611346E+00, 0.6587911462745685E-21, 0.7857712130631377E-05, 0.2298529163657988E-05, 0.3859485208834002E+00, 0.6162975822039155E-32, 0.1022329296046741E-03, 0.8680151473672892E-04, 0.2295319067023061E+00, 0.0000000000000000E+00, 0.4616464530663241E-04, 0.3877924919889212E-04, 0.2262113890497363E+00, 0.5522026336547083E-29, 0.2365660345682357E-03, 0.1990352708186489E-03, 0.1122658486667464E+00, 0.9015102222917331E-20, 0.6825572508936817E-03, 0.6443371781720532E-03, 0.7234153262002044E-01, 0.1168271446196110E-24, 0.1518594231951364E-05, 0.3554999772664582E-05, 0.4527048542558528E-01, 0.1023373475125114E-24, 0.5037539097182833E-02, 0.4761613742874584E-02, 0.8319414807792288E-04, 0.1479114197289397E-30, 0.9105689905446296E-02, 0.4825995872157137E-02}, + info: 0, + }, + { + z: []float64{0.3256696334281521E+00, 0.7530856859911462E+00, 0.8853989127988440E+00, 0.4058112879440673E+00, 0.4296659748141172E+00, 0.5414662225246791E-01, 0.7727106089758434E+00, 0.8219533891865206E+00, 0.8804898818241804E+00, 0.2701661776792790E+00, 0.3062100113053869E+00, 0.7616550925245322E+00, 0.7441861437457686E+00, 0.1208643477044503E+00, 0.1894387751691341E+00, 0.5502297763300060E+00, 0.7033314588214317E+00, 0.9049640752657374E+00, 0.7642474001418834E+00, 0.6461873559439021E+00, 0.7323555348666727E+00, 0.6137344390498661E+00, 0.4469041036073067E+00, 0.6120974783290001E+00, 0.3695185251601272E+00, 0.9332999793731735E+00, 0.3981597952563400E+00, 0.5926926060619504E+00, 0.2218776156238759E+00, 0.5556127447847847E-01, 0.2642041684868913E+00, 0.3100431241269808E-01, 0.7617158805289858E+00, 0.5576464290832684E+00, 0.1499291988028689E+00, 0.6071627267784354E+00, 0.2903444085740193E+00, 0.8982141027722228E+00, 0.3437740722392461E+00, 0.5257340992985249E-02, 0.9772197173932363E+00, 0.2743313505008338E-01, 0.5939995532981283E+00, 0.8125099455585232E+00, 0.8394050677385213E+00, 0.2410326841076476E+00, 0.6066214991817382E+00, 0.1828025638429278E+00, 0.5406675263078469E+00, 0.1108622672142920E+00, 0.2412280709874803E+00, 0.5713495470758625E+00, 0.6315445401927943E+00, 0.2035563756883153E+00, 0.8696814083183412E+00, 0.2313134367709406E+00, 0.4474447231170641E+00, 0.6238312383525342E+00, 0.4961806049996582E+00, 0.8121574484576765E+00, 0.8702938949430352E+00, 0.4187164629520156E+00, 0.9204090241956668E+00, 0.8587176140225750E-02, 0.5171057705188283E+00, 0.5195595031109387E+00, 0.1704600468811621E+00, 0.3205951022793651E+00, 0.5643494948239225E-01, 0.9895063272544601E+00, 0.5554681247022339E+00, 0.6098243547887802E+00, 0.4730289261335907E+00, 0.1850396134174421E+00, 0.9997475966289492E+00, 0.6812817712215841E+00, 0.8515433432907883E+00, 0.7377047940023331E+00, 0.2280516830782600E+00, 0.7204549837953970E+00, 0.6096260713045146E+00, 0.9381128478076188E+00, 0.8446173293023428E+00, 0.6255387686605924E+00}, + n: 21, + zOut: []float64{0.2655567567233002E+01, 0.2307219644143945E+01, 0.2068899090176533E+01, 0.2040332602619700E+01, 0.1742115921396612E+01, 0.1681856112031183E+01, 0.1680515965675234E+01, 0.1379580829731510E+01, 0.1074312270120212E+01, 0.9816962393879983E+00, 0.7217300335876665E+00, 0.6931029681515243E+00, 0.5680300928567689E+00, 0.5098239945058581E+00, 0.4280073603039590E+00, 0.2868581986899945E+00, 0.1650069923584772E+00, 0.9685136354131559E-01, 0.5953175886938158E-01, 0.1010639579838301E-01, 0.1940920539235378E-02, 0.0000000000000000E+00, 0.6683246174917478E-10, 0.4267275295503314E-10, 0.1680515965675234E+01, 0.3510431028233503E-28, 0.1660414363340253E-09, 0.1048896312812690E-09, 0.1379580829731510E+01, 0.1462018530271286E-15, 0.3421106985799154E-06, 0.1788748688597153E-06, 0.1074312270120212E+01, 0.6708481546523056E-14, 0.2133146148219686E-04, 0.4629406838917969E-04, 0.9816962393879983E+00, 0.1747667198202037E-19, 0.5113942524303023E-03, 0.6287577911928029E-03, 0.7217300335876665E+00, 0.3213860550383917E-17, 0.2115308632171850E+02, 0.2115308632171849E+02, 0.1090000000000000E+03, 0.3217687074829932E+01, 0.4587155963302752E+01, 0.4202140396420195E-04, 0.5680300928567689E+00, 0.4489765112701642E-21, 0.3523329095202763E-09, 0.1167512512099963E-08, 0.5098239945058581E+00, 0.1652551767516096E-21, 0.2872281528375301E-06, 0.1040291448945555E-06, 0.4280073603039590E+00, 0.3262461795428160E-16, 0.6249760558326680E-04, 0.5475920486023645E-04, 0.2868581986899945E+00, 0.1568256893218114E-20, 0.1414968677825121E-03, 0.1814031293335571E-03, 0.1650069923584772E+00, 0.8677469957431130E-28, 0.6720068122740940E-03, 0.4975589868187537E-03, 0.9685136354131559E-01, 0.5127595883936577E-29, 0.9260272777115331E-03, 0.1730290225790419E-02, 0.5953175886938158E-01, 0.7227833914448031E-23, 0.5968169418548035E-04, 0.1670361992731526E-04, 0.1010639579838301E-01, 0.1295106991551472E-19, 0.1213518994781533E-03, 0.2534883535393275E-03, 0.1940920539235378E-02, 0.0000000000000000E+00, 0.1005634135102979E-02, 0.2318000467665894E-02}, + info: 0, + }, + { + z: []float64{0.1944566011999833E+00, 0.2181910996636003E+00, 0.3150099357031281E+00, 0.2091722274105127E+00, 0.6593858021341683E+00, 0.9426815336068497E+00, 0.5288011644568881E+00, 0.7784091503839152E+00, 0.1751638954124558E+00, 0.6164772800195180E+00, 0.6225196859922683E+00, 0.2786175486675760E+00, 0.1945914328217568E+00, 0.5779085626077999E+00, 0.5568218939451671E+00, 0.5170566254269496E+00, 0.5742861029155353E+00, 0.6923056150383281E+00, 0.5876692361605969E+00, 0.4295639666640205E+00, 0.8612105519992207E+00, 0.9963836880013683E+00, 0.2692934182903581E+00, 0.6181020857251435E+00, 0.1251902537663725E+00, 0.2838625146280274E+00, 0.2999174442521634E+00, 0.7258439193048929E+00, 0.2048904835805728E+00, 0.1174987481558037E+00, 0.6887427109309550E+00, 0.7409107864964065E+00, 0.5306892441542433E+00, 0.6214581212205206E-01, 0.1234501953117273E-01, 0.2038789370511589E+00, 0.6180963044354376E+00, 0.2820746320472540E+00, 0.4643004781082601E+00, 0.2642696366861867E+00, 0.4102198269957935E-01, 0.1495900075045802E+00, 0.2060405615637534E+00, 0.3399183002928583E+00, 0.7918555051917199E+00, 0.9699614514519834E+00, 0.2922678000248715E+00, 0.1376674512222148E+00, 0.2496993200590716E+00, 0.3432539555227123E+00, 0.5835005548357151E+00, 0.4094205671447549E+00, 0.4876670000237163E+00, 0.7973523995663028E+00, 0.8851386592921134E+00, 0.1523554028450115E+00, 0.7049520832902729E+00, 0.4689643982524618E+00, 0.4347705823917429E+00, 0.8152140283905303E+00, 0.9259201525760803E+00, 0.3175789772106010E+00, 0.3950010049586650E+00, 0.7107346574834400E+00, 0.8109922991383097E+00, 0.6889072760433030E+00, 0.7861311781839575E-02, 0.7751963519893628E+00, 0.7382950156197396E+00, 0.9729693586970557E+00, 0.7283826758396350E+00, 0.1269651196972527E+00, 0.3530947260257147E+00, 0.2061448083515627E-01, 0.5931058475369740E+00, 0.9689379021952851E+00, 0.3254887771415839E+00, 0.2808523639662175E-01, 0.6211468186653845E+00, 0.6037463613076512E+00, 0.8746435454108382E+00, 0.5300695323546331E+00, 0.5276801989236730E+00, 0.2128951663669798E-01}, + n: 21, + zOut: []float64{0.2424279264689105E+01, 0.2270324150901105E+01, 0.1935128898096250E+01, 0.1814500336114905E+01, 0.1538233405195664E+01, 0.1297421320254112E+01, 0.1267282488999314E+01, 0.1249158514677014E+01, 0.9155076211264116E+00, 0.8242950831432680E+00, 0.5949232544739386E+00, 0.5630079212779312E+00, 0.4530053256303904E+00, 0.3458193312768856E+00, 0.2146623096050983E+00, 0.1686454472303586E+00, 0.1155214217797334E+00, 0.5180948935108346E-01, 0.2789744048901975E-01, 0.8268186305777192E-02, 0.6680158028153346E-04, 0.0000000000000000E+00, 0.3986945646893946E-08, 0.7023072825762287E-08, 0.1267282488999314E+01, 0.0000000000000000E+00, 0.2355158572444734E-07, 0.1877711213087836E-07, 0.1249158514677014E+01, 0.3384506411488746E-20, 0.2648360770785381E-11, 0.1741394977127960E-10, 0.9155076211264116E+00, 0.3299177303725225E-12, 0.2487861145673591E-05, 0.4028407591944186E-05, 0.8242950831432680E+00, 0.2441420600100056E-16, 0.1869515956083083E-05, 0.1842279235203962E-05, 0.5949232544739386E+00, 0.2024938139529812E-20, 0.1807975801219765E+02, 0.1807975801219765E+02, 0.9300000000000000E+02, 0.2836734693877551E+01, 0.1075268817204301E+01, 0.9521662195121400E-05, 0.4530053256303904E+00, 0.1259501632163109E-23, 0.1468124594065504E-05, 0.4670591953230941E-05, 0.3458193312768856E+00, 0.7975064420889996E-22, 0.1308295990671250E-06, 0.6690001990389955E-07, 0.2146623096050983E+00, 0.1927976052360153E-26, 0.3812574759844485E-05, 0.3580340604691736E-05, 0.1686454472303586E+00, 0.3739200690747596E-27, 0.6844384387279355E-05, 0.5557405125771409E-05, 0.1155214217797334E+00, 0.7506098603421864E-21, 0.2139339757899294E-04, 0.3026575107963825E-04, 0.5180948935108346E-01, 0.3886068668379982E-20, 0.1983680974127293E-03, 0.1336830557694390E-03, 0.2789744048901975E-01, 0.1991084924777834E-26, 0.4443273484877918E-03, 0.6821022035819646E-03, 0.8268186305777192E-02, 0.1921747358113822E-20, 0.1778955160858100E-05, 0.3048292256883238E-06, 0.6680158028153346E-04, 0.7915528772828604E-21, 0.4499131616906370E-02, 0.1547765737453591E-02}, + info: 0, + }, + { + z: []float64{0.3849545441014558E+00, 0.9201984078647510E+00, 0.4611893507512446E+00, 0.9426704990067624E+00, 0.4513996483425642E+00, 0.3546824995764211E+00, 0.2673932938327498E+00, 0.2250322436282782E+00, 0.3003875396759296E+00, 0.8637078150569484E+00, 0.2463125523040188E-01, 0.6381498516846796E+00, 0.9054059378226459E+00, 0.9211368359293561E+00, 0.6899055937753183E+00, 0.6469675067081565E+00, 0.2524386712411693E+00, 0.4816130873217878E+00, 0.8437265349008123E+00, 0.8843672501609817E+00, 0.3917808232071412E+00, 0.4109107468556734E+00, 0.6294664210780233E+00, 0.5231064834871043E+00, 0.6006449315760222E+00, 0.2321330919598237E+00, 0.9857216391074231E-01, 0.5246894901632879E+00, 0.2429723268334654E+00, 0.3385437000243748E+00, 0.1784805178646218E+00, 0.8008314854810928E+00, 0.3388059467143087E+00, 0.4957241256656372E+00, 0.6108069077503485E+00, 0.8350989375447051E+00, 0.1087391555565628E+00, 0.5847974581188020E+00, 0.8316850716702742E+00, 0.8921011586703487E+00, 0.1947070853010260E+00, 0.1394928972102342E+00, 0.7929088249487071E+00, 0.4078510186300481E+00, 0.6849316610029904E+00, 0.1436003498260631E+00, 0.5673845335495399E+00, 0.7998164012861997E-01, 0.6667892725157643E+00, 0.7612117828169483E+00, 0.8195812739875934E+00, 0.1507277483884870E+00, 0.6683936863561600E+00, 0.1889659251016290E+00, 0.7979363461805246E+00, 0.9481151487908223E+00, 0.3017570036067704E+00, 0.2677628114499495E+00, 0.4479716416042271E+00, 0.3773062273227097E+00, 0.1756267436681674E+00, 0.6251009447636316E+00, 0.3010990216120933E+00, 0.6044916624270988E+00, 0.3012752666004853E+00, 0.7113839134297870E+00, 0.7355680503868338E+00, 0.1830572310895536E+00, 0.2065116792960049E+00, 0.2432895898830973E+00, 0.9615089470298006E+00, 0.3137165160357294E+00, 0.5335631824040450E+00, 0.8324142824771229E+00, 0.9749825715503555E+00, 0.3108065469391890E+00, 0.2584483510692804E+00, 0.5679665509067858E+00, 0.9084113884935793E+00, 0.3061643504016712E+00, 0.1856860631474661E+00, 0.4086356189591027E+00, 0.2761517708925276E+00, 0.9203155374121844E+00}, + n: 21, + zOut: []float64{0.2651616639993538E+01, 0.2278042999629812E+01, 0.2198077975076974E+01, 0.2185608493228643E+01, 0.1866238785250178E+01, 0.1694317687161655E+01, 0.1314780820581521E+01, 0.1267230115137409E+01, 0.1165102366599241E+01, 0.1094106513205574E+01, 0.9375639320451692E+00, 0.7228525903025090E+00, 0.5063995930233953E+00, 0.4433597755655621E+00, 0.3782868675227946E+00, 0.2710178897462153E+00, 0.1447594933682902E+00, 0.1060101050946834E+00, 0.8449698031014202E-01, 0.1468593250969371E-01, 0.8406928034951682E-06, 0.3591986573571771E-20, 0.3864386735331416E-10, 0.3252595492372177E-10, 0.1314780820581521E+01, 0.1447952803137974E-21, 0.5374081097788385E-10, 0.4849713226733927E-10, 0.1267230115137409E+01, 0.2958228394578794E-29, 0.8017357434413146E-10, 0.7063808972759981E-10, 0.1165102366599241E+01, 0.1139115147139141E-26, 0.1961041727821929E-09, 0.1374026522849091E-09, 0.1094106513205574E+01, 0.3915388343685865E-19, 0.1756082891845291E-08, 0.3338672481507716E-08, 0.9375639320451692E+00, 0.4870203640784043E-16, 0.2132455639604580E+02, 0.2132455639604580E+02, 0.9900000000000000E+02, 0.2972789115646258E+01, 0.5050505050505050E+01, 0.1300256830939750E-04, 0.5063995930233953E+00, 0.4338734978715565E-29, 0.3205424704587136E-04, 0.3879495859639124E-04, 0.4433597755655621E+00, 0.9466330862652142E-25, 0.6653798840082298E-04, 0.6266988927201412E-04, 0.3782868675227946E+00, 0.2274100449667269E-22, 0.3059080514749475E-04, 0.2450157710629126E-04, 0.2710178897462153E+00, 0.2739429933906694E-24, 0.4451877567018950E-05, 0.2739439060253447E-05, 0.1447594933682902E+00, 0.1897052704875489E-25, 0.3311215248867682E-05, 0.2822048496282046E-05, 0.1060101050946834E+00, 0.7924889161564951E-19, 0.2588042287900903E-05, 0.3305698843095029E-05, 0.8449698031014202E-01, 0.2523395625690618E-18, 0.1425730854724969E-04, 0.2612802087529877E-04, 0.1468593250969371E-01, 0.7520086356827106E-20, 0.6278930605158724E-03, 0.1193309863751681E-02, 0.8406928034951682E-06, 0.0000000000000000E+00, 0.8769018979884540E-02, 0.6748334476252631E-02}, + info: 0, + }, + { + z: []float64{0.5539290016733247E+00, 0.6936589108803458E+00, 0.1862325586311042E-01, 0.3903593359823143E+00, 0.1387446022374186E+00, 0.9230050933369500E+00, 0.1655735508788293E+00, 0.5464594833562775E+00, 0.4407574799078734E+00, 0.7597516703282015E+00, 0.3240675365298944E+00, 0.8527429657828770E+00, 0.6134024974884296E+00, 0.1359668624923763E+00, 0.8589771621484943E+00, 0.8334002673394481E+00, 0.3811010712979018E+00, 0.4518439634289880E+00, 0.4121953913957921E-01, 0.1499929777106017E+00, 0.7537932319194001E+00, 0.1137770685080763E+00, 0.9362285670837264E+00, 0.2284833451474525E+00, 0.4661006612092690E+00, 0.3461611111488332E+00, 0.1608705680575839E-01, 0.9250298701911358E+00, 0.5983544857783111E+00, 0.9400090024445320E+00, 0.6595514287179831E+00, 0.2725099566160494E+00, 0.6509556024164401E+00, 0.8851211780351773E+00, 0.5925872091724521E+00, 0.5318402341230010E+00, 0.3225952236300995E+00, 0.6233031538827258E+00, 0.1806586091116282E+00, 0.9476369741031940E+00, 0.6784219735316235E+00, 0.6934023884718178E+00, 0.5000312772557033E+00, 0.6725383579734943E+00, 0.6771923299216058E+00, 0.9125469473100194E+00, 0.9862018367238429E+00, 0.7259311136907298E+00, 0.9021849324334038E+00, 0.6032549715715884E+00, 0.9017706724408630E+00, 0.8975979926873651E+00, 0.5949035726420406E+00, 0.6903449880442312E+00, 0.7574844360343417E+00, 0.2889632382233942E-01, 0.9428474184445177E+00, 0.5555118914598791E+00, 0.8663544108664935E+00, 0.6853450780608091E+00, 0.1464483859238053E+00, 0.6491672315887742E+00, 0.2994712877436206E+00, 0.3101752077576794E+00, 0.4920466664329196E+00, 0.2135103260181662E+00, 0.3809190441316870E+00, 0.8437350743416491E+00, 0.5443983884818225E+00, 0.7426189539459086E+00, 0.1055227287563778E+00, 0.3059118205598027E+00, 0.8189910523272392E+00, 0.9773505795713493E+00, 0.7305661438576656E+00, 0.6062516615534109E+00, 0.4660033490547544E+00, 0.5413353206637471E+00, 0.2388208915142312E+00, 0.6428463909118429E+00, 0.2982699820336984E+00, 0.2856298024316706E-01, 0.5487207914459959E+00, 0.4464180688275057E+00}, + n: 21, + zOut: []float64{0.2448593467642387E+01, 0.2141330855004301E+01, 0.2126430153924173E+01, 0.1907639051889359E+01, 0.1812500110390200E+01, 0.1510069013602020E+01, 0.1441897976798092E+01, 0.1263171337642769E+01, 0.1138107892295268E+01, 0.1088450894719558E+01, 0.9398511957468885E+00, 0.8468227425873083E+00, 0.6124964740092524E+00, 0.5436278175488470E+00, 0.4066256939946141E+00, 0.3972422051503922E+00, 0.2390787026361968E+00, 0.4848296808782174E-01, 0.2905803980602126E-01, 0.1302961362478940E-02, 0.3616542154739030E-05, 0.3187755557432356E-18, 0.8836722322771784E-05, 0.6065531139006927E-05, 0.1441897976798092E+01, 0.7730421460348975E-16, 0.3574427637238573E-07, 0.1935178018527985E-07, 0.1263171337642769E+01, 0.8058524406205312E-18, 0.1418632976070110E-05, 0.4069026170914173E-05, 0.1138107892295268E+01, 0.1371633476674845E-23, 0.4721385684453755E-04, 0.3623692584267971E-04, 0.1088450894719558E+01, 0.1790018845564752E-20, 0.4055026077404345E-04, 0.2446096735206838E-04, 0.9398511957468885E+00, 0.3178330447896772E-25, 0.2094278317138010E+02, 0.2094278317138010E+02, 0.1040000000000000E+03, 0.3031746031746032E+01, 0.4807692307692307E+01, 0.8138465546053722E-05, 0.6124964740092524E+00, 0.1019617235038814E-22, 0.4736809894069740E-03, 0.1915264360566004E-03, 0.5436278175488470E+00, 0.2004410489406572E-21, 0.1259085689345719E-03, 0.2338760337361548E-03, 0.4066256939946141E+00, 0.1231392444306089E-15, 0.6226403214695822E-04, 0.7644683470656998E-04, 0.3972422051503922E+00, 0.5914962592392188E-17, 0.1887068321547840E-03, 0.1345267246510674E-03, 0.2390787026361968E+00, 0.1936824017247308E-20, 0.7333182971373067E-03, 0.1062997506116107E-02, 0.4848296808782174E-01, 0.3799154119544393E-26, 0.1269933545612727E-03, 0.1297822869175177E-03, 0.2905803980602126E-01, 0.8465676581597317E-24, 0.5642309440908588E-03, 0.2732446225021143E-03, 0.1302961362478940E-02, 0.2467375723434259E-18, 0.9177892725485271E-03, 0.8034707353774361E-03, 0.3616542154739030E-05, 0.2761013168273541E-28, 0.6531167933367503E-03, 0.6727959129527735E-03}, + info: 0, + }, + { + z: []float64{0.7455810318731756E+00, 0.1881309445499726E+00, 0.6290241532486281E+00, 0.9426231091333456E+00, 0.1402641401457146E+00, 0.5545071521563689E+00, 0.3467970399972181E+00, 0.6378935846273492E-01, 0.8187242451993508E+00, 0.8444039716090014E+00, 0.8807815832461214E+00, 0.6871811349512845E+00, 0.6041217734774926E+00, 0.2285364565760638E+00, 0.6287288909172152E+00, 0.5441550558534458E+00, 0.6062929607453951E+00, 0.1528830611582420E+00, 0.7289323622783690E+00, 0.8693274251763169E+00, 0.1210720262902459E+00, 0.4752572018677603E+00, 0.8160358228459934E+00, 0.5003926181135285E+00, 0.2800920281530351E+00, 0.3817159580569316E+00, 0.1419563352692587E+00, 0.9738793587569783E+00, 0.2402077997739175E+00, 0.5021080238100061E+00, 0.5325521311583831E+00, 0.7002793445871702E+00, 0.2004913666518293E-01, 0.6858750037076770E+00, 0.5705320248969311E+00, 0.6000416876176061E+00, 0.9254592880635680E+00, 0.2987366812581649E+00, 0.8838368946481180E+00, 0.7495294261248863E+00, 0.2516401660161148E+00, 0.5770724542103510E+00, 0.8689432882806168E+00, 0.3108844333247283E+00, 0.7611598373381380E+00, 0.9533545884676758E+00, 0.6146629999183371E+00, 0.7337933880625785E+00, 0.1335018938357140E+00, 0.4054745880121539E+00, 0.9816031767048012E+00, 0.5190257866591561E+00, 0.9457220484783406E+00, 0.2563725588490263E+00, 0.8953616129834293E+00, 0.1343673038869742E+00, 0.1198867110907023E+00, 0.7765966504091196E+00, 0.1685346783514826E+00, 0.9322265874533907E+00, 0.4968937019786546E+00, 0.3933065437909874E+00, 0.7046190939244956E-01, 0.5772052710604483E+00, 0.1220174671595003E+00, 0.3586914192309758E+00, 0.4743117898783903E+00, 0.1205436116155321E+00, 0.2068106627971966E-01, 0.5035688415619853E+00, 0.2656792568844590E-01, 0.4951625786650252E+00, 0.1600264513881963E+00, 0.4218870487180432E+00, 0.4847863747130776E-01, 0.9478135093620923E+00, 0.1811694594266104E+00, 0.5311488460048615E+00, 0.2296061187775216E+00, 0.9932681440344262E+00, 0.2007921586496573E+00, 0.9684478357621775E+00, 0.9322927111902295E+00, 0.6234102172880590E+00}, + n: 21, + zOut: []float64{0.2617080551859897E+01, 0.2305187568066598E+01, 0.1942735806791493E+01, 0.1834812272403632E+01, 0.1760060933961288E+01, 0.1720372963502770E+01, 0.1676173250234917E+01, 0.1530300579122039E+01, 0.1214313538868506E+01, 0.1146550683576815E+01, 0.9555081169996513E+00, 0.8235353939361046E+00, 0.7281321711646775E+00, 0.5964515885643180E+00, 0.4105953672636856E+00, 0.2154672622243388E+00, 0.1469861329023305E+00, 0.1350631498164301E+00, 0.8120368457133148E-01, 0.1548517647968005E-01, 0.1861612641330624E-04, 0.6389970231972139E-21, 0.6259229043737505E-18, 0.1065975851985723E-17, 0.1676173250234917E+01, 0.1398996249446581E-17, 0.1485385179581525E-16, 0.5390878377546583E-16, 0.1530300579122039E+01, 0.1934286939601921E-26, 0.4995235293268131E-13, 0.1480097232724468E-13, 0.1214313538868506E+01, 0.1393981231259665E-11, 0.4031414073293921E-10, 0.9065983401759033E-10, 0.1146550683576815E+01, 0.7754818242684634E-25, 0.9068533370171412E-09, 0.1932480064220526E-08, 0.9555081169996513E+00, 0.5937598997073433E-12, 0.2185603480843691E+02, 0.2185603480843692E+02, 0.1010000000000000E+03, 0.3183673469387755E+01, 0.2970297029702970E+01, 0.4106209724092858E-05, 0.7281321711646775E+00, 0.2221432309102369E-26, 0.2012416535197213E-04, 0.1179395510019159E-04, 0.5964515885643180E+00, 0.6492360922940637E-17, 0.6055695087058826E-05, 0.1676327789285107E-04, 0.4105953672636856E+00, 0.1174834768927548E-24, 0.8526024871833974E-05, 0.9608606324255413E-05, 0.2154672622243388E+00, 0.1186446801452402E-26, 0.9887524717240814E-05, 0.1072842889916555E-04, 0.1469861329023305E+00, 0.0000000000000000E+00, 0.1666923382276663E-04, 0.2139923074663986E-04, 0.1350631498164301E+00, 0.4860988391194038E-18, 0.4968094868839375E-08, 0.1325007303324406E-08, 0.8120368457133148E-01, 0.5476819983069490E-18, 0.5501364953991437E-04, 0.1068949633822309E-04, 0.1548517647968005E-01, 0.6621786174648700E-13, 0.4934492558904634E-03, 0.7815729865935395E-03, 0.1861612641330624E-04, 0.0000000000000000E+00, 0.2047621357235247E-01, 0.1218736604744046E-01}, + info: 0, + }, + { + z: []float64{0.1913768959569714E+00, 0.7347223265181069E+00, 0.9087350122086006E+00, 0.8876448886267929E-02, 0.1794058368310475E+00, 0.3375830657319635E+00, 0.4153249303964603E+00, 0.3079259326141542E+00, 0.5095638682609168E+00, 0.6300946130469818E+00, 0.5367870439046851E-02, 0.6082577193589970E+00, 0.6096872650047096E+00, 0.8098482943683755E+00, 0.4018780482667224E+00, 0.1612961166583111E+00, 0.4165836183710623E+00, 0.6711774659609234E+00, 0.1871437048914691E+00, 0.2043648411447756E+00, 0.4603921058522200E+00, 0.5138380788557162E-01, 0.3299651081607302E+00, 0.5178779891127856E+00, 0.8488474652006981E+00, 0.4000528745818374E+00, 0.7038372186752184E-01, 0.1091866126814279E+00, 0.4601541814804277E-01, 0.2814862519917873E+00, 0.5969661695911915E+00, 0.1111325580672384E+00, 0.1377964900539917E+00, 0.4488655138014651E+00, 0.5793089439934721E+00, 0.4068390675279384E+00, 0.3141858292757815E-01, 0.3803058398371814E+00, 0.6865263808463873E-01, 0.6565571596516916E+00, 0.4227763797508006E+00, 0.9281332433572439E+00, 0.2549706813172651E+00, 0.1472316879439791E+00, 0.8389980826186394E+00, 0.4949206978487660E+00, 0.8778524239605636E+00, 0.8125876339222501E+00, 0.6384442407604712E+00, 0.6297206683503800E+00, 0.1074594814776241E+00, 0.4635106216187717E+00, 0.2149027083261391E+00, 0.2926633791426133E+00, 0.8718806127632718E+00, 0.9358351753143842E+00, 0.5812389276262170E+00, 0.8361764419241092E+00, 0.1334582685582402E+00, 0.6700349085889619E+00, 0.1370175035793201E+00, 0.2605729802823288E+00, 0.7055670307426516E+00, 0.1974656950667419E-01, 0.9516894704106690E+00, 0.7509460514650641E+00, 0.9770872584819335E-01, 0.1679929405438133E+00, 0.2605432695744189E+00, 0.7255281751885829E+00, 0.2060091110826470E+00, 0.5123028703888126E+00, 0.5392241233948379E+00, 0.3215743887975069E+00, 0.4306560982435532E+00, 0.9326432909148183E+00, 0.1891146429259456E+00, 0.5585690444839775E+00, 0.8103752159402208E+00, 0.3850798219907741E+00, 0.6027394925107610E-01, 0.6960376568363590E+00, 0.6132631218829975E+00, 0.5859904896405407E+00}, + n: 21, + zOut: []float64{0.1948845699194504E+01, 0.1757754653408917E+01, 0.1739740003489702E+01, 0.1427189755042558E+01, 0.1354312190162734E+01, 0.1300861212306309E+01, 0.1144086431430055E+01, 0.9728683413380136E+00, 0.7924660843958955E+00, 0.7190108168957414E+00, 0.5334843173898538E+00, 0.4234595469843583E+00, 0.3840099969172215E+00, 0.2310167712576353E+00, 0.1706582281146164E+00, 0.1481114719972525E+00, 0.9844570800522298E-01, 0.8643465546688130E-01, 0.2116850399857309E-01, 0.1490679637756442E-02, 0.9506251872618699E-05, 0.0000000000000000E+00, 0.3139247800552953E-11, 0.1114956279480716E-10, 0.1144086431430055E+01, 0.2611946364919696E-16, 0.1910542599593587E-05, 0.1867627468366115E-05, 0.9728683413380136E+00, 0.3548331964791209E-13, 0.9422609200466975E-06, 0.3861796048985941E-05, 0.7924660843958955E+00, 0.4543838814073028E-27, 0.1545075054473009E-06, 0.2314398440634665E-06, 0.7190108168957414E+00, 0.1033975765689929E-24, 0.9239329035775786E-07, 0.1002180390059042E-06, 0.5334843173898538E+00, 0.0000000000000000E+00, 0.1525542457368567E+02, 0.1525542457368567E+02, 0.1120000000000000E+03, 0.3308390022675737E+01, 0.5357142857142857E+01, 0.1175851227353848E-05, 0.3840099969172215E+00, 0.1009741958682895E-27, 0.6285056589702800E-05, 0.7777675415159152E-05, 0.2310167712576353E+00, 0.4642054879586336E-19, 0.2707022647265855E-04, 0.1462219920606713E-04, 0.1706582281146164E+00, 0.0000000000000000E+00, 0.1442808298792521E-03, 0.1499267314065209E-03, 0.1481114719972525E+00, 0.1784642171583157E-21, 0.9060208842449760E-06, 0.2604899516157433E-05, 0.9844570800522298E-01, 0.3285517707584525E-17, 0.4009882974094740E-08, 0.9813054658490708E-08, 0.8643465546688130E-01, 0.1441804758967627E-17, 0.1005867330167897E-05, 0.3548177460196556E-06, 0.2116850399857309E-01, 0.1161145423573808E-16, 0.4264476922944564E-04, 0.6523019800084465E-04, 0.1490679637756442E-02, 0.5282426871388410E-23, 0.4120097727637851E-03, 0.5256559484655862E-03, 0.9506251872618699E-05, 0.7858215819253763E-23, 0.4122429400478702E-03, 0.4195795458123320E-03}, + info: 0, + }, + { + z: []float64{0.8707866955342474E+00, 0.7817747598907121E-01, 0.3395074897480099E-01, 0.4299950297507704E+00, 0.8088090483755312E+00, 0.8059665333356031E+00, 0.8715468955879169E-01, 0.7726332912417854E+00, 0.8113440783694211E+00, 0.3884398998833286E+00, 0.2376236729669906E+00, 0.1163685212573567E+00, 0.9165435854442110E+00, 0.6267984817484763E+00, 0.9624876615834328E+00, 0.3034180669232360E+00, 0.2061796047621195E+00, 0.5768621491208505E+00, 0.9925917678590149E+00, 0.6443157924817072E+00, 0.5967958277754652E+00, 0.6529032825080359E+00, 0.2463148548215904E+00, 0.3434579503978075E+00, 0.9563439871443443E+00, 0.2121028540747388E+00, 0.7195547303990343E+00, 0.2508441805243417E+00, 0.1006260142041168E+00, 0.8893309100691102E+00, 0.5028754540045453E+00, 0.8271029410166070E+00, 0.1744058577319449E+00, 0.1497291367846938E+00, 0.9760674104574272E+00, 0.1217237467828105E+00, 0.5182991497218187E+00, 0.9638099804000833E-01, 0.3920754919448237E+00, 0.5405769677178972E+00, 0.2099631365577761E+00, 0.7305783624173950E+00, 0.5230361650507421E+00, 0.3249231142539155E+00, 0.6943021078034506E+00, 0.8039502137729849E+00, 0.5430939865698426E+00, 0.5802454813209417E+00, 0.4521353811622019E+00, 0.6022646695138674E+00, 0.5085578584349214E+00, 0.2084880202460930E+00, 0.7893764544854661E+00, 0.8499187425465698E+00, 0.6507732600828079E+00, 0.6030189256946239E+00, 0.2748834677816949E+00, 0.7991444375081345E+00, 0.3953548021356785E+00, 0.8063610109500122E+00, 0.9322494176165492E+00, 0.2295756744488692E+00, 0.9380170922026533E+00, 0.6349173046266506E+00, 0.8138238710526029E+00, 0.1723717901392456E+00, 0.7436778507578146E+00, 0.9748296910217159E+00, 0.9719004334667378E+00, 0.1097372829332979E+00, 0.6782829454939702E+00, 0.5097404868982898E+00, 0.9485025358778609E+00, 0.7313319469015522E-01, 0.6156780373408383E+00, 0.8764490831370680E+00, 0.2737186188000360E+00, 0.3500606337779347E+00, 0.7029831161979777E+00, 0.1747477098480691E+00, 0.8887436470613648E+00, 0.8441051781034927E+00, 0.3534934185139980E+00, 0.9278581973721739E+00}, + n: 21, + zOut: []float64{0.2399590582568773E+01, 0.2223029747781157E+01, 0.2028465681071774E+01, 0.1928601105940012E+01, 0.1734632538043284E+01, 0.1705587556623443E+01, 0.1335586809119933E+01, 0.1201248979220471E+01, 0.1103973785860777E+01, 0.9516762968928613E+00, 0.8501027578146555E+00, 0.7334218559333251E+00, 0.5694462065979470E+00, 0.4616704914677346E+00, 0.3869349008726894E+00, 0.2370229392379994E+00, 0.1895639186923105E+00, 0.6837204156138489E-01, 0.3336561258733767E-01, 0.4796873010443177E-02, 0.8309969413683648E-03, 0.1974829088984998E-20, 0.1178494024155901E-08, 0.8095343015842228E-09, 0.1335586809119933E+01, 0.2220446049250313E-15, 0.1020576889344504E-06, 0.1802026823995536E-06, 0.1201248979220471E+01, 0.0000000000000000E+00, 0.6243063866214613E-06, 0.3862955415798747E-06, 0.1103973785860777E+01, 0.6981113564263453E-22, 0.3544097463307990E-10, 0.1357364267827356E-10, 0.9516762968928613E+00, 0.9072531498765813E-25, 0.7979152396248553E-09, 0.3946058728874109E-09, 0.8501027578146555E+00, 0.3130538746543124E-14, 0.2014792167783968E+02, 0.2014792167783968E+02, 0.1020000000000000E+03, 0.3129251700680272E+01, 0.5882352941176471E+01, 0.5818593578868780E-05, 0.5694462065979470E+00, 0.1588643710672175E-16, 0.4031382989989102E-05, 0.4054337523014161E-05, 0.4616704914677346E+00, 0.4437342591868191E-30, 0.3922192530785082E-05, 0.4209867122852495E-05, 0.3869349008726894E+00, 0.1490631566505624E-25, 0.4185837521330395E-06, 0.8450171931154743E-06, 0.2370229392379994E+00, 0.9509832565716118E-20, 0.2486232683772935E-03, 0.1020105306066691E-03, 0.1895639186923105E+00, 0.4152563805083406E-26, 0.4122104994398350E-03, 0.2603466333914367E-03, 0.6837204156138489E-01, 0.2482703040911568E-24, 0.1451022916339763E-02, 0.8718585538326752E-03, 0.3336561258733767E-01, 0.7888609052210118E-30, 0.3124612722893384E-02, 0.2800832977531187E-02, 0.4796873010443177E-02, 0.5945360652724886E-23, 0.1330631700030230E-06, 0.1700369028500688E-07, 0.8309969413683648E-03, 0.0000000000000000E+00, 0.1665788949608015E-02, 0.1927727749653244E-02}, + info: 0, + }, + { + z: []float64{0.5557143146495949E+00, 0.5989968816903124E+00, 0.2940668070493605E+00, 0.6865591553636113E+00, 0.2538362881116337E+00, 0.8562930572057048E-01, 0.8935270452331215E+00, 0.2427258280604294E-01, 0.8872146530392093E+00, 0.8383596820641517E+00, 0.7298494135137694E+00, 0.5456106579379609E+00, 0.5284508278981448E+00, 0.4551015440756836E+00, 0.8310297436868961E+00, 0.2533050402685522E+00, 0.8204820449217906E+00, 0.3961557150240700E+00, 0.9768702237400030E+00, 0.2370292739142171E+00, 0.2559318188841475E-02, 0.9750517337670606E-01, 0.4332045279801727E+00, 0.9393777930670477E+00, 0.1401411199977110E-01, 0.6412771440674316E+00, 0.3992540155849937E+00, 0.6710909099058460E+00, 0.7286319488310415E+00, 0.2796269361967505E+00, 0.7441899058930037E+00, 0.6626826587793098E+00, 0.9214594500725222E+00, 0.3161807402236700E+00, 0.5522479249937589E+00, 0.8328895958825197E+00, 0.3188368475648113E+00, 0.7495883496609020E+00, 0.7525354981370723E+00, 0.4819658709067065E-01, 0.8655147680740739E+00, 0.9438778396406793E+00, 0.2488475915004000E+00, 0.6823535213934872E+00, 0.1937525404626215E+00, 0.5005903164733780E+00, 0.8863816362271992E-01, 0.8279647895785316E+00, 0.7576076924432378E+00, 0.7026499641621615E+00, 0.4430381204856144E+00, 0.7250369983032848E+00, 0.6848785243425647E+00, 0.4460397323983623E+00, 0.4708648248777212E+00, 0.2715064773162834E+00, 0.3027887490966231E+00, 0.7428389405348396E+00, 0.4450045451144832E+00, 0.4683793136386452E+00, 0.2207684946192057E+00, 0.2427030064074031E+00, 0.9554840783351275E+00, 0.4627007756736100E+00, 0.2498171419709001E+00, 0.6457883819068694E+00, 0.9852852516910280E+00, 0.1549706320399313E-01, 0.5863698153730145E+00, 0.8639664213849532E+00, 0.3535803218615043E+00, 0.5300900503312423E+00, 0.6390014357018353E+00, 0.7961857807391770E+00, 0.2691637990251612E+00, 0.5302467438659471E+00, 0.3050412123368091E+00, 0.6256487701731338E+00, 0.3334512397543001E+00, 0.4160884062357342E+00, 0.1255438899512573E+00, 0.1645317210625844E+00, 0.3238197294562333E+00, 0.8765325383521217E+00}, + n: 21, + zOut: []float64{0.2427342887003738E+01, 0.2350720031505609E+01, 0.2023223336640000E+01, 0.1998000565720247E+01, 0.1766392007527096E+01, 0.1571733737439641E+01, 0.1560415852981921E+01, 0.1417948678305651E+01, 0.1258973312710257E+01, 0.1056655934390461E+01, 0.8835393928887348E+00, 0.8723851974669989E+00, 0.7820423442972025E+00, 0.7419840433476598E+00, 0.4998280519834369E+00, 0.4045332331022956E+00, 0.9795545665796999E-01, 0.6816976350034422E-01, 0.5040003524610775E-01, 0.3066447317814986E-01, 0.1707038609221110E-04, 0.0000000000000000E+00, 0.7788285758834551E-10, 0.4967814553062384E-10, 0.1560415852981921E+01, 0.2584939414223288E-25, 0.2197123097785426E-09, 0.1273532664170934E-09, 0.1417948678305651E+01, 0.1666074231826777E-26, 0.1275101209751314E-13, 0.3690153580151478E-13, 0.1258973312710257E+01, 0.3205217501722064E-17, 0.9823174457391989E-10, 0.2521354047663225E-09, 0.1056655934390461E+01, 0.7258232531419596E-14, 0.3712131332588551E-06, 0.9470624651125662E-06, 0.8835393928887348E+00, 0.1013078509970455E-14, 0.2186292540627962E+02, 0.2186292540627962E+02, 0.1200000000000000E+03, 0.3639455782312925E+01, 0.8333333333333334E+01, 0.8044662327724623E-11, 0.7820423442972025E+00, 0.1609007833004439E-16, 0.1435272653873044E-05, 0.2709954877521105E-06, 0.7419840433476598E+00, 0.7040565915227063E-17, 0.3841536774665796E-05, 0.2871402006582635E-05, 0.4998280519834369E+00, 0.2100142105025380E-22, 0.2079096157763567E-04, 0.3245111531694086E-04, 0.4045332331022956E+00, 0.1391829401523057E-17, 0.6737785910120600E-04, 0.9764140649613147E-04, 0.9795545665796999E-01, 0.0000000000000000E+00, 0.6779864796214124E-03, 0.3130513090482015E-03, 0.6816976350034422E-01, 0.2326445472805242E-24, 0.3547436816484852E-02, 0.2240007954218211E-02, 0.5040003524610775E-01, 0.1487168151587342E-22, 0.3710761871988309E-06, 0.2590766399899962E-07, 0.3066447317814986E-01, 0.7395570986446986E-31, 0.2806228106658499E-03, 0.1300265719680322E-02, 0.1707038609221110E-04, 0.5107323294632100E-21, 0.5584126334680110E-02, 0.2863707539154273E-03}, + info: 0, + }, + { + z: []float64{0.8091224458140820E+00, 0.8008972278830493E+00, 0.2578176398184776E+00, 0.1256248089219657E+00, 0.6581359192692769E+00, 0.2304361454551056E+00, 0.7582551898966047E+00, 0.1757884371165862E+00, 0.3186400696162690E+00, 0.7479165768101737E+00, 0.3726824047207358E+00, 0.8797387692666324E+00, 0.5750380180879821E+00, 0.5660816893967801E+00, 0.4438713938433396E+00, 0.1758644078670230E+00, 0.5631776732547016E+00, 0.3584358301396408E+00, 0.9436101806256550E+00, 0.5626737326978751E+00, 0.6424649400467324E+00, 0.8481112336470399E+00, 0.5655978701315552E+00, 0.8705727446437589E+00, 0.2336253154027212E-01, 0.5296192722406249E+00, 0.2416414888807097E+00, 0.8901032371078870E+00, 0.6213866196646989E+00, 0.7130035148592161E+00, 0.7957781913464947E+00, 0.8476792055481847E+00, 0.9456821938668590E+00, 0.9119251640705257E+00, 0.6793496748825844E+00, 0.1959111178023272E+00, 0.1712010119398182E+00, 0.1826738976471362E+00, 0.2526159624017289E+00, 0.1636253698204285E+00, 0.5186411299293459E+00, 0.9760895321955887E-01, 0.6893646610477002E+00, 0.9919227436537437E-01, 0.3790249398464486E+00, 0.9060767708258410E+00, 0.1329141344440885E+00, 0.8748053076614649E+00, 0.3613991427617499E+00, 0.1317424493721138E+00, 0.1676759484196766E-01, 0.7195688942861501E+00, 0.7508197149131951E+00, 0.1084062966598669E+00, 0.7799888885196686E+00, 0.8731271868042269E+00, 0.7281667421703623E+00, 0.5506096404209293E+00, 0.2344365678709384E+00, 0.8253982006984435E+00, 0.6925029659724733E+00, 0.2137159289768908E+00, 0.6304949708624844E+00, 0.2263541700174215E+00, 0.3731966957484361E+00, 0.4056710443895672E-01, 0.1518575777839423E+00, 0.7000182640684851E+00, 0.5207195688041865E+00, 0.3546513077756396E+00, 0.5223091585165126E+00, 0.1312526670646489E+00, 0.6075518716591177E+00, 0.7815133160786110E+00, 0.1466092133856621E+00, 0.6908403097208041E+00, 0.5289383481177163E+00, 0.3060973141340825E+00, 0.2719751878023001E+00, 0.4367099092855503E+00, 0.1678669773704986E+00, 0.2384522838837465E+00, 0.7578135131488263E+00, 0.2260651503779529E+00}, + n: 21, + zOut: []float64{0.3001718609114466E+01, 0.2461580649918252E+01, 0.2139800724137603E+01, 0.2110198913058292E+01, 0.1773285881581521E+01, 0.1731854037718996E+01, 0.1434868444776101E+01, 0.1292334845681036E+01, 0.1202898865215905E+01, 0.9074690574580867E+00, 0.8145281637318031E+00, 0.6833997197084192E+00, 0.6303801796404412E+00, 0.5115989792032534E+00, 0.4365028215455523E+00, 0.3347059637856380E+00, 0.2704761845997483E+00, 0.1007567293499011E+00, 0.7404356572986662E-01, 0.2225224658576705E-01, 0.1003499792335912E-03, 0.1163915500165708E-19, 0.5702083577853931E-06, 0.6235005324467382E-06, 0.1434868444776101E+01, 0.7352183636659830E-27, 0.3221030091629643E-04, 0.6932009635225803E-04, 0.1292334845681036E+01, 0.1547654926086715E-20, 0.2859096049606110E-03, 0.1689403705904475E-03, 0.1202898865215905E+01, 0.5187952724823741E-19, 0.3457740509453089E-04, 0.1548723988845099E-04, 0.9074690574580867E+00, 0.1883346903736854E-18, 0.4924250006037621E-06, 0.3064183963004930E-06, 0.8145281637318031E+00, 0.7436271633171000E-16, 0.2193475493251988E+02, 0.2193475493251988E+02, 0.9400000000000000E+02, 0.2913832199546485E+01, 0.3191489361702128E+01, 0.6928384721316203E-06, 0.6303801796404412E+00, 0.4344707644406440E-17, 0.8243004381261832E-06, 0.1242944619712133E-05, 0.5115989792032534E+00, 0.1321342016245195E-28, 0.6830327722875946E-05, 0.4610227507804771E-05, 0.4365028215455523E+00, 0.7922538128148438E-16, 0.5185315150043044E-04, 0.9574812800552337E-04, 0.3347059637856380E+00, 0.4042912139257686E-29, 0.6190562688247171E-03, 0.1111720505727282E-02, 0.2704761845997483E+00, 0.1659171176970474E-17, 0.3895087988050344E-03, 0.1929449868539905E-03, 0.1007567293499011E+00, 0.2919870821923328E-23, 0.2088900906409071E-03, 0.1786849109209585E-03, 0.7404356572986662E-01, 0.6310887241768094E-28, 0.1266951898160773E-03, 0.1217799054154213E-03, 0.2225224658576705E-01, 0.3697785493223493E-31, 0.1828672832615040E-03, 0.2196698921083079E-03, 0.1003499792335912E-03, 0.0000000000000000E+00, 0.1256202468809242E-02, 0.9158129895566399E-03}, + info: 0, + }, + { + z: []float64{0.7473165994595915E+00, 0.9383144044637891E+00, 0.9705766820209645E+00, 0.3093136353727625E+00, 0.7158638842786125E+00, 0.8927477442087851E+00, 0.5846837014009232E-02, 0.2823227977987499E+00, 0.4656399961948744E+00, 0.1783480145929806E-01, 0.8517241739910267E+00, 0.2968236367983081E+00, 0.3828703962512207E+00, 0.1618551942929359E+00, 0.8422815023410849E+00, 0.9667213467147939E+00, 0.1872774458350456E+00, 0.9673785609387944E+00, 0.1668393270938346E+00, 0.1793363294699661E+00, 0.3882509817575230E+00, 0.9322497724034516E+00, 0.1678634979113953E+00, 0.4000730353927472E+00, 0.1370854040387474E+00, 0.1383728853360747E+00, 0.8728086099072359E+00, 0.7142605368034651E+00, 0.1298497843576266E+00, 0.4890695005398649E+00, 0.6561831309305255E+00, 0.2551502145039813E+00, 0.3137603328050955E+00, 0.4725573834392259E+00, 0.1864194559915778E+00, 0.2476903242862807E+00, 0.3016682498100809E-01, 0.6028908129301045E+00, 0.9699532639034771E+00, 0.6804787742392342E+00, 0.5085224418131328E+00, 0.8160312832212636E+00, 0.4537844508149779E+00, 0.7698002058576117E+00, 0.9102837491884663E-01, 0.7957963901796614E+00, 0.4129806172970929E+00, 0.1183929303892000E+00, 0.7231979382284242E+00, 0.6908050716155305E+00, 0.9129211251463741E+00, 0.8407226028232299E+00, 0.7511043357392063E+00, 0.6614037096770188E+00, 0.5816383867961591E+00, 0.9508597818692400E+00, 0.6671834981267941E+00, 0.5353731249555691E+00, 0.8270836995328532E+00, 0.4748649574057349E+00, 0.7310961648034807E+00, 0.5329698192925740E+00, 0.5537463638220994E+00, 0.8202244086458278E+00, 0.3089778794417031E-01, 0.8347421543151022E+00, 0.7341688304615497E+00, 0.6293051268804178E+00, 0.9685330131023850E-01, 0.2218306173097127E+00, 0.4005982063157664E+00, 0.8004209862846372E+00, 0.9322471342744776E-02, 0.5252230232113276E+00, 0.8078446044346348E+00, 0.8663675770089085E-02, 0.4174348230921995E+00, 0.5316704871571061E+00, 0.8080873214304936E+00, 0.3191328650837369E+00, 0.2265528787275422E+00, 0.1299687059183835E+00, 0.5606006275148095E+00, 0.2716326223111132E+00}, + n: 21, + zOut: []float64{0.2557856639061994E+01, 0.2221569823028635E+01, 0.2113175506056959E+01, 0.1791034203034858E+01, 0.1626866366713385E+01, 0.1553853827140545E+01, 0.1378038738404736E+01, 0.1313711478279983E+01, 0.1103021858691488E+01, 0.8924372074434684E+00, 0.7465727975101516E+00, 0.5658880123536838E+00, 0.5427616116084486E+00, 0.3934406603234193E+00, 0.3139076008306549E+00, 0.2922956394268174E+00, 0.1324157743308766E+00, 0.8492495339426936E-01, 0.1726019296564064E-01, 0.1478900502211735E-02, 0.3047316799617542E-04, 0.0000000000000000E+00, 0.2209423397088722E-18, 0.1230851536694111E-18, 0.1378038738404736E+01, 0.4653537180464338E-22, 0.4724643033910209E-17, 0.2943893377745906E-17, 0.1313711478279983E+01, 0.2193156221990361E-16, 0.1119006893822957E-16, 0.1741431705208298E-16, 0.1103021858691488E+01, 0.2831227495869906E-12, 0.2860829853751284E-15, 0.4129571258389818E-15, 0.8924372074434684E+00, 0.1711229892219076E-22, 0.2249832739645017E-14, 0.3254005212313171E-14, 0.7465727975101516E+00, 0.5231751935973153E-19, 0.1964254226427022E+02, 0.1964254226427022E+02, 0.1110000000000000E+03, 0.3285714285714286E+01, 0.8108108108108109E+01, 0.1373504512438542E-12, 0.5427616116084486E+00, 0.0000000000000000E+00, 0.2663664432452481E-11, 0.1451131289962852E-11, 0.3934406603234193E+00, 0.3021704178298789E-14, 0.8991877456137337E-10, 0.1576401145017008E-09, 0.3139076008306549E+00, 0.2274554202459952E-24, 0.7202855721215940E-08, 0.4214854283718170E-08, 0.2922956394268174E+00, 0.3975858962313899E-27, 0.6024353396932969E-07, 0.1022672043122323E-06, 0.1324157743308766E+00, 0.6969933701296916E-21, 0.1098572510799548E-05, 0.1404105143401733E-05, 0.8492495339426936E-01, 0.6511321020566649E-24, 0.5604469692434887E-06, 0.6104659421650381E-06, 0.1726019296564064E-01, 0.9860761315262648E-31, 0.7747760678878360E-06, 0.1026260244983655E-05, 0.1478900502211735E-02, 0.1334496117765360E-28, 0.5102973157105362E-05, 0.1258609455819239E-04, 0.3047316799617542E-04, 0.0000000000000000E+00, 0.4753862314998056E-03, 0.1863315015192667E-02}, + info: 0, + }, + { + z: []float64{0.2548672807470598E-01, 0.1495421137012933E+00, 0.6637277283391485E-01, 0.6233200993667132E-01, 0.4958061473131723E+00, 0.9804571594196556E+00, 0.5741929121502225E+00, 0.9319350517768583E+00, 0.5154498317218548E-01, 0.4165283024496188E+00, 0.9821854184367015E+00, 0.7510033276340442E+00, 0.2648151368970406E+00, 0.9698327797382789E-01, 0.1433813304773114E+00, 0.1687421369042604E+00, 0.6230509959313209E+00, 0.8106153730403777E+00, 0.5719487513699320E+00, 0.5761793262532514E+00, 0.4983158430615118E+00, 0.8860830618783583E+00, 0.7136722399358287E+00, 0.6310350013419201E+00, 0.5509601824732582E+00, 0.5806336147624858E-01, 0.1818648959869262E+00, 0.2346005241916651E+00, 0.5346851174706903E+00, 0.4444466121668155E+00, 0.8418378722202517E+00, 0.6164532479196363E+00, 0.4298553148227666E+00, 0.2296849794057675E+00, 0.3620982682376475E+00, 0.3645096805309075E+00, 0.9980228064491022E+00, 0.7106112428543574E+00, 0.6651697421094976E+00, 0.9830151455980368E+00, 0.3483046917749841E+00, 0.3668589729383628E+00, 0.5655614401040915E+00, 0.8891526728148491E+00, 0.9164649086142118E+00, 0.4065736846475075E+00, 0.1470436468080603E+00, 0.5802557267939668E+00, 0.8272597245263099E+00, 0.7163617706554632E+00, 0.3488790096540706E+00, 0.6404227109073246E+00, 0.1472796557920839E+00, 0.8764536863696604E-02, 0.5020645462548778E-01, 0.6906675094909457E+00, 0.4668434450047272E+00, 0.7886435616506033E+00, 0.8775817704321313E+00, 0.4246952359284411E+00, 0.1646609549881360E+00, 0.6697681588293083E+00, 0.7914692739599321E+00, 0.1396674072195736E-01, 0.5167232939537366E+00, 0.9374340964740459E+00, 0.4228531365925756E+00, 0.9727064517088465E+00, 0.5765501520393458E+00, 0.5648508784605104E+00, 0.3049637657479770E+00, 0.3063190445223624E+00, 0.5204528216889723E+00, 0.8180178920731451E+00, 0.4938773599630263E+00, 0.8975563911549045E-01, 0.5983688838646251E+00, 0.3698925131813697E+00, 0.2992530973981942E+00, 0.7463539101278609E+00, 0.8005980511688328E+00, 0.7944834752945218E-01, 0.3132925544163919E+00, 0.8866951016419623E+00}, + n: 21, + zOut: []float64{0.2548744028948828E+01, 0.2439584200134194E+01, 0.2276898263864132E+01, 0.2083856178014486E+01, 0.2039342663979975E+01, 0.1949418505713503E+01, 0.1425638870874207E+01, 0.1087729835971203E+01, 0.9667696375323971E+00, 0.8022433247488755E+00, 0.5846254874613492E+00, 0.5355025899480791E+00, 0.3940805795947064E+00, 0.2663780336330241E+00, 0.2413081251593111E+00, 0.1817740817404329E+00, 0.1073144197241267E+00, 0.4327520903789019E-01, 0.3141654146246065E-01, 0.2017433957164045E-01, 0.3181705377209195E-03, 0.2778526523712400E-12, 0.1839247883012458E-10, 0.2248848580297948E-10, 0.1425638870874207E+01, 0.4660214926831417E-16, 0.5684400877302917E-10, 0.6387162891082867E-10, 0.1087729835971203E+01, 0.6729715978266918E-13, 0.1741585337702246E-09, 0.2256709509706825E-09, 0.9667696375323971E+00, 0.8583633357857125E-17, 0.5122248377584688E-09, 0.7095864943104643E-09, 0.8022433247488755E+00, 0.1479114197289397E-30, 0.3545102092401686E-08, 0.2547082836533246E-08, 0.5846254874613492E+00, 0.1684748530176799E-17, 0.2002639308765254E+02, 0.2002639308765254E+02, 0.9900000000000000E+02, 0.2829931972789116E+01, 0.2020202020202020E+01, 0.1450844904575395E-08, 0.3940805795947064E+00, 0.8431345355002174E-26, 0.2834737824482197E-07, 0.1323731756234205E-07, 0.2663780336330241E+00, 0.1205202152489745E-19, 0.2553256673132341E-06, 0.1983391491151363E-06, 0.2413081251593111E+00, 0.5052150994009667E-21, 0.4174664103103917E-06, 0.5361294231508838E-06, 0.1817740817404329E+00, 0.4777592300362271E-19, 0.1103166278762495E-05, 0.1411552925870387E-05, 0.1073144197241267E+00, 0.1369462531463676E-25, 0.4868310689385493E-05, 0.3749559753873054E-05, 0.4327520903789019E-01, 0.6517810995642209E-18, 0.3308901711413922E-04, 0.5021439046381042E-04, 0.3141654146246065E-01, 0.3980258690751375E-19, 0.2091355707842741E-03, 0.1263714817696205E-03, 0.2017433957164045E-01, 0.9608259223012324E-19, 0.2907989762339014E-03, 0.3270695437261140E-04, 0.3181705377209195E-03, 0.2078018254813854E-20, 0.5046681645946245E-02, 0.5971971384809690E-02}, + info: 0, + }, + { + z: []float64{0.7556699778432414E+00, 0.9264145479756024E+00, 0.2732571748073197E+00, 0.6411921070422063E+00, 0.9885815056247259E+00, 0.3723918099656685E+00, 0.8347397513753253E+00, 0.1449609854320509E+00, 0.7237973270068254E+00, 0.7937879503069174E+00, 0.1580314367294657E+00, 0.6183123759968190E-01, 0.8526562423479169E+00, 0.4515796037285547E+00, 0.4273610709781387E+00, 0.9916977661043136E-01, 0.6106106148524300E+00, 0.8331371477897991E+00, 0.3226596180395027E+00, 0.9411873968460633E+00, 0.4713107215814810E+00, 0.2408559451890391E-01, 0.8159283865403915E+00, 0.2484819964854622E+00, 0.9053457264816500E-01, 0.7765873412573800E+00, 0.6903393919382517E-01, 0.4737861094943234E+00, 0.2953181034757211E+00, 0.1455852388723616E+00, 0.3595484224812872E+00, 0.7546693773577520E+00, 0.2176499262400425E+00, 0.2180463762362660E+00, 0.4619066216292487E+00, 0.9195384505328125E+00, 0.7817199663072332E+00, 0.7252058550809327E+00, 0.7231496659924924E+00, 0.4997135548263443E+00, 0.7857040551775740E-01, 0.9096915224111880E+00, 0.5048166916632318E+00, 0.9737715836828489E+00, 0.6597329703373522E+00, 0.1262659377119990E-01, 0.3525536903406803E+00, 0.6167857219758321E+00, 0.7408468432196044E+00, 0.7867196986400673E+00, 0.2313289425583596E+00, 0.8524506859175643E+00, 0.1392061690435467E+00, 0.4799927308227143E+00, 0.5988201473645773E+00, 0.8148615971957359E+00, 0.9991849415795491E+00, 0.4062458282025133E+00, 0.8021012361110058E-01, 0.7041715844729369E+00, 0.9319571339573152E-01, 0.9303801779957639E+00, 0.6825635414858495E+00, 0.2651022334979941E+00, 0.2966022780498856E-01, 0.2756350604456157E+00, 0.3996117016882065E+00, 0.4084803031952775E+00, 0.7693093419592285E+00, 0.5425247266459055E+00, 0.7317803042615013E+00, 0.9398853135227920E+00, 0.5923013015298344E+00, 0.6749323490534131E-01, 0.2677632908794654E+00, 0.1468441510303787E+00, 0.1088650133568649E+00, 0.2179701521651023E+00, 0.8673093102161434E+00, 0.5667697713082290E+00, 0.5061732946886482E+00, 0.4707781162637231E+00, 0.4572852405093119E+00, 0.2817384205908577E+00}, + n: 21, + zOut: []float64{0.2549866140639053E+01, 0.2289692363298807E+01, 0.2042824675422646E+01, 0.1807091836494319E+01, 0.1608583829794490E+01, 0.1518595775727545E+01, 0.1431682400757094E+01, 0.1278141352537376E+01, 0.1218077200015686E+01, 0.1115746594519385E+01, 0.9489661418934578E+00, 0.7950491688285616E+00, 0.6705557578092293E+00, 0.4223587911677574E+00, 0.3211641543143434E+00, 0.1395786344205778E+00, 0.9463219952875908E-01, 0.4563841563552573E-01, 0.3718976888616738E-01, 0.2766660139323238E-01, 0.2861060880329385E-03, 0.1489369389057270E-25, 0.4009456273839574E-11, 0.5913965075566282E-11, 0.1431682400757094E+01, 0.9808641529204798E-18, 0.1658075466067222E-10, 0.2375182467377229E-10, 0.1278141352537376E+01, 0.1561716996498461E-20, 0.5563872147228742E-10, 0.4003249215027731E-10, 0.1218077200015686E+01, 0.8198555146385643E-18, 0.1047304739332037E-09, 0.1509388346471184E-09, 0.1115746594519385E+01, 0.6804594514014344E-21, 0.1132515351796206E-08, 0.7305070647547987E-09, 0.9489661418934578E+00, 0.6324297261214257E-19, 0.2036338790917205E+02, 0.2036338790917205E+02, 0.1050000000000000E+03, 0.3147392290249433E+01, 0.2857142857142857E+01, 0.1188392639382130E-06, 0.6705557578092293E+00, 0.2287929633195320E-19, 0.1283168907741916E-05, 0.1048613283787068E-05, 0.4223587911677574E+00, 0.1189072130544977E-23, 0.1798535669474704E-05, 0.2477367923932174E-05, 0.3211641543143434E+00, 0.8187795594567816E-23, 0.5813187502570164E-05, 0.4274698539216166E-05, 0.1395786344205778E+00, 0.4387796946624011E-14, 0.1512969274311187E-04, 0.4383088766938462E-04, 0.9463219952875908E-01, 0.2802074325023381E-22, 0.1713816584845726E-03, 0.1715892923902221E-03, 0.4563841563552573E-01, 0.8331483361628599E-18, 0.1806157324013782E-06, 0.1193242630586832E-05, 0.3718976888616738E-01, 0.1396316416906445E-20, 0.3480495660704905E-03, 0.4402048010276426E-03, 0.2766660139323238E-01, 0.1504073756330590E-24, 0.6353091961964474E-03, 0.1317363577877200E-03, 0.2861060880329385E-03, 0.4589883047388968E-23, 0.3883745848947868E-02, 0.5358907697572753E-02}, + info: 0, + }, + { + z: []float64{0.8456683250225028E-01, 0.3058015837199188E+00, 0.4317902183064470E-01, 0.3671979469896071E+00, 0.3595487854233631E+00, 0.8791524368561765E+00, 0.1256853689373587E+00, 0.3494000337993621E+00, 0.2131672180923028E+00, 0.4488324680055523E+00, 0.9452502344450827E+00, 0.7197446096567599E+00, 0.8918071015747069E+00, 0.5551949519753436E+00, 0.5627883747367335E+00, 0.6930858113379974E+00, 0.7026202611250518E+00, 0.3856840921343180E+00, 0.4453224782611998E+00, 0.9627551339340559E+00, 0.6255469039377685E+00, 0.6093210861157965E+00, 0.1297243619022892E-01, 0.2745425059216151E+00, 0.5902573930769862E+00, 0.3658719785914519E+00, 0.8179101736936932E+00, 0.4251816548465440E+00, 0.3319568042078717E+00, 0.8294675656951641E+00, 0.1906193594777114E+00, 0.6862699206380130E+00, 0.6832362040809048E+00, 0.8968537122850908E+00, 0.3753636108676777E+00, 0.9926770667520373E+00, 0.7473790867948205E-01, 0.3653635034012445E+00, 0.6553100464759598E-01, 0.1045856631958887E+00, 0.2265961870023414E+00, 0.3205967446655300E-01, 0.1845082884370131E+00, 0.2250092498055734E+00, 0.5876866067653603E+00, 0.2146512915654570E+00, 0.3937206506545190E+00, 0.4110924225795073E+00, 0.3228836105384403E+00, 0.3531543308069818E-01, 0.9472843614842231E+00, 0.2348052564069324E+00, 0.1315455878409307E+00, 0.2246729768637089E+00, 0.8445861542610614E+00, 0.9528962673528295E+00, 0.4907499555456967E+00, 0.9420172239501383E+00, 0.4896535244350841E-01, 0.5088622551995382E+00, 0.1789066474661110E+00, 0.3566730680524121E+00, 0.4279936896698711E-01, 0.5241586506933626E-02, 0.9191361995860731E+00, 0.7666474814508011E+00, 0.8302596584023555E+00, 0.4738482866502817E+00, 0.2085735695866969E+00, 0.3976808123484415E+00, 0.4364253757027529E+00, 0.2407360056333678E+00, 0.4002772343201099E+00, 0.7717338386755229E+00, 0.5023514841326452E+00, 0.8988902694804358E+00, 0.4259852339101408E+00, 0.2067093317010162E+00, 0.8456128611542781E+00, 0.1290027044731792E+00, 0.2598901078235174E+00, 0.5836006873243835E+00, 0.9777637054617091E+00, 0.4896357840832322E+00}, + n: 21, + zOut: []float64{0.2625813250937807E+01, 0.2316814186652984E+01, 0.2239421861777163E+01, 0.1853308891402210E+01, 0.1827033391537137E+01, 0.1481398580531558E+01, 0.1385699025778513E+01, 0.1101045596651604E+01, 0.1077490875294086E+01, 0.6790358065311344E+00, 0.6361857378195889E+00, 0.5095707085100130E+00, 0.4739579905788711E+00, 0.4209497658895578E+00, 0.3012142858983374E+00, 0.2432742659092710E+00, 0.2088674538811938E+00, 0.1664409530858738E+00, 0.2606656040091844E-01, 0.1205810631995507E-01, 0.9325512290661112E-07, 0.1292469707114106E-24, 0.1719039818430849E-04, 0.1845080438772963E-04, 0.1385699025778513E+01, 0.2224123229986848E-19, 0.6819642419856913E-05, 0.9079053758699490E-05, 0.1101045596651604E+01, 0.6054420446023063E-14, 0.5392861994521241E-06, 0.8422816920290823E-06, 0.1077490875294086E+01, 0.7330726620037819E-25, 0.4290042344637304E-06, 0.3471234449409943E-06, 0.6790358065311344E+00, 0.1969273319091676E-18, 0.8635424232755040E-07, 0.8294124288205587E-07, 0.6361857378195889E+00, 0.4466775307674635E-22, 0.1958564738864290E+02, 0.1958564738864290E+02, 0.9700000000000000E+02, 0.2927437641723356E+01, 0.2061855670103093E+01, 0.4284285350948107E-09, 0.4739579905788711E+00, 0.4844247598072386E-17, 0.1501956526577450E-07, 0.4599310764980267E-07, 0.4209497658895578E+00, 0.5697556379758414E-13, 0.1468884761079027E-05, 0.1935721204206928E-05, 0.3012142858983374E+00, 0.3414189997796539E-26, 0.7129394687116921E-05, 0.9262068822983554E-05, 0.2432742659092710E+00, 0.2465190328815662E-31, 0.3320148255009530E-04, 0.2563439348523979E-04, 0.2088674538811938E+00, 0.8874685183736383E-29, 0.9377671959730327E-04, 0.7166613903737452E-04, 0.1664409530858738E+00, 0.1175218723307338E-19, 0.5883141447281398E-03, 0.4140832085136277E-03, 0.2606656040091844E-01, 0.2634795423438179E-27, 0.4797918408258123E-02, 0.4833036765864798E-02, 0.1205810631995507E-01, 0.6530371216255944E-19, 0.7811358433513861E-02, 0.1392611548870054E-01, 0.9325512290661112E-07, 0.1190420191421466E-12, 0.6274023555637595E-01, 0.1241063086176471E-01}, + info: 0, + }, + { + z: []float64{0.6345014789904082E+00, 0.9828013844807603E+00, 0.5292373213190880E+00, 0.3345627500234365E+00, 0.9345959669050260E+00, 0.5873733336147081E+00, 0.8888462128293518E+00, 0.1044020545901757E+00, 0.9375280272458696E+00, 0.1233411973951652E+00, 0.3330283913003940E+00, 0.2432208394685875E-01, 0.6106490172620382E+00, 0.9136489477065954E+00, 0.8250850334045809E+00, 0.7866479843500775E+00, 0.1629924039124250E+00, 0.2349971551206693E+00, 0.1024684774133804E+00, 0.7852727749024598E+00, 0.1427984573527686E+00, 0.4315181982028241E+00, 0.6564047419338838E+00, 0.5555590030741936E+00, 0.8205569452257172E+00, 0.4368031922318115E+00, 0.2897575605849890E+00, 0.6163386054890784E+00, 0.7016794584968877E+00, 0.7265422079630662E+00, 0.6393115149906525E+00, 0.7552597718778955E+00, 0.5029129969011173E+00, 0.4874732646810529E+00, 0.5094624150009296E+00, 0.4766369914172104E+00, 0.9003818070855094E+00, 0.6813014247956244E+00, 0.2988296447575162E+00, 0.6597790416796705E+00, 0.5646192150605487E+00, 0.3275024686793908E+00, 0.2725061169408716E-01, 0.8098076662320616E+00, 0.3345276190659139E+00, 0.1812780354242056E+00, 0.1997802571871318E+00, 0.5440765633504190E+00, 0.9774510594766147E+00, 0.1863483792916641E+00, 0.5910097330685633E+00, 0.2734489448477760E+00, 0.4395818444416557E+00, 0.9022786559097939E+00, 0.1029995124123335E+00, 0.9437933734967648E+00, 0.1226746192846208E+00, 0.1122541771291640E+00, 0.1756516455268763E+00, 0.9109529416432673E+00, 0.3050345572159197E-01, 0.1746678233544180E+00, 0.3750993781268622E+00, 0.4476224977918100E+00, 0.5437446694835568E+00, 0.3729575052852190E+00, 0.3542378566336749E+00, 0.7449948633772266E+00, 0.3157555204945224E+00, 0.7753984984296890E+00, 0.3284038993889418E+00, 0.5159361949232710E-01, 0.4529339074400007E-01, 0.5693581512511349E+00, 0.2213156237057901E+00, 0.9395831428155459E+00, 0.3843047271617620E+00, 0.2968653921042081E+00, 0.6156090467550724E+00, 0.3170556612853570E-01, 0.8265655132088339E+00, 0.3165750369023552E+00, 0.7055602587055542E+00, 0.8365600455841105E+00}, + n: 21, + zOut: []float64{0.2473859321883559E+01, 0.2422834159796051E+01, 0.2342770718537345E+01, 0.2190393245355733E+01, 0.2048748874742353E+01, 0.1880327408972340E+01, 0.1569014269461521E+01, 0.1302496773444914E+01, 0.1193514796722045E+01, 0.1150651682141956E+01, 0.8969794111087930E+00, 0.8226581338194529E+00, 0.6917042463755413E+00, 0.5972139808466055E+00, 0.3480375932216391E+00, 0.2932789944580818E+00, 0.2090971942801221E+00, 0.1221616224423389E+00, 0.1000478595340333E+00, 0.3412207557320287E-01, 0.3160927987836547E-03, 0.2386777554836693E-25, 0.1787847554062023E-08, 0.1930667016131883E-08, 0.1569014269461521E+01, 0.5039432348921582E-18, 0.3047636948536222E-07, 0.1223330280849913E-07, 0.1302496773444914E+01, 0.0000000000000000E+00, 0.7408697490815375E-06, 0.1498788057488595E-05, 0.1193514796722045E+01, 0.6273021918317486E-26, 0.8867922405978688E-08, 0.3710956866722375E-08, 0.1150651682141956E+01, 0.1462883977034466E-17, 0.2681277488017278E-06, 0.6188429230273071E-06, 0.8969794111087930E+00, 0.4930380657631324E-31, 0.2269022845551642E+02, 0.2269022845551641E+02, 0.1110000000000000E+03, 0.3215419501133787E+01, 0.4504504504504505E+01, 0.4606971433208740E-07, 0.6917042463755413E+00, 0.7123549154360197E-18, 0.1197511514786163E-07, 0.1386949181837661E-07, 0.5972139808466055E+00, 0.4652335183636722E-20, 0.1082703076660205E-07, 0.1003906263016573E-07, 0.3480375932216391E+00, 0.3573127201018094E-16, 0.2388210318135170E-06, 0.5694782222336181E-06, 0.2932789944580818E+00, 0.7601337464964823E-24, 0.7791755144624492E-05, 0.3242296896441773E-05, 0.2090971942801221E+00, 0.1663630656286764E-22, 0.9916420504550920E-06, 0.3916254919710180E-05, 0.1221616224423389E+00, 0.1406614427791829E-18, 0.1356917845842480E-04, 0.1379449187478977E-04, 0.1000478595340333E+00, 0.2800456213534592E-28, 0.3213444959426999E-04, 0.2790230345312924E-04, 0.3412207557320287E-01, 0.1075846717720530E-17, 0.8531299184272352E-03, 0.1419520770966347E-02, 0.3160927987836547E-03, 0.1848892746611746E-31, 0.7376316906583622E-02, 0.6546496744187779E-02}, + info: 0, + }, + { + z: []float64{0.7781991870339823E+00, 0.3799726947828087E+00, 0.8225406656461727E+00, 0.4322410258771066E+00, 0.4965834581857734E+00, 0.1642548945285990E+00, 0.4773703559733889E+00, 0.7580746486223987E+00, 0.9220155673403277E+00, 0.1624062232083541E+00, 0.5664470130564820E+00, 0.7367013127895712E+00, 0.4720756942873998E+00, 0.8695958825780965E+00, 0.6045812450089678E+00, 0.8503421320137978E+00, 0.7291568033584502E+00, 0.9563602214514951E+00, 0.1245752972610169E+00, 0.2621011209284912E+00, 0.8642265339858576E+00, 0.9528021036615359E+00, 0.9515862784178062E+00, 0.2632504807072628E+00, 0.8585529108378003E+00, 0.3025834513231899E+00, 0.7125877353473579E+00, 0.9221275053156179E+00, 0.9787992369955746E+00, 0.8789465750552752E+00, 0.9318675804398889E+00, 0.8827440896392771E+00, 0.3124337393280541E+00, 0.3124656972853590E-01, 0.5860766227864144E+00, 0.9812515177915087E+00, 0.4480000254042209E+00, 0.5121903109069345E+00, 0.1837298514334742E+00, 0.2680410429176278E+00, 0.5529294510898309E+00, 0.3627557909974974E+00, 0.9282219359125773E+00, 0.2173723036967439E+00, 0.7593665130145739E+00, 0.6245533364325671E+00, 0.1767680905493787E+00, 0.3823356866170564E+00, 0.5171578058722374E+00, 0.5376155024979712E+00, 0.5280269975706942E-01, 0.7947058949878518E+00, 0.1214716509814368E+00, 0.6840110600217510E+00, 0.7041243787921371E+00, 0.6945194787199669E+00, 0.8184844284849127E+00, 0.3440855810599863E+00, 0.1619958520504678E+00, 0.6990470088709023E+00, 0.3532225659848430E+00, 0.8229090368317697E+00, 0.8349696782028652E+00, 0.6932180266797183E-01, 0.6880274120498576E+00, 0.7566065163897195E+00, 0.2981422921509080E-01, 0.8636153925759227E-02, 0.7928093803058089E-01, 0.3096144259285381E+00, 0.6829886066202427E+00, 0.8246144682759358E+00, 0.2007259621364732E+00, 0.8710862365466575E+00, 0.6898755422119236E+00, 0.9105030198433044E+00, 0.8974818523094739E+00, 0.8909991694059211E+00, 0.8084341913662618E-01, 0.6072211485624930E+00, 0.9680950749726419E+00, 0.3932275197607872E+00, 0.8781208296025552E+00, 0.5527043030768199E+00}, + n: 21, + zOut: []float64{0.3158195987040060E+01, 0.2674397094280163E+01, 0.2611167345511754E+01, 0.2117792657212280E+01, 0.2026395303611904E+01, 0.1943316400161173E+01, 0.1877195462180231E+01, 0.1801757023901512E+01, 0.1273111869927408E+01, 0.1088705127135854E+01, 0.9559661931705944E+00, 0.9013607966201198E+00, 0.6445742634037150E+00, 0.5446175180211763E+00, 0.4486902226406620E+00, 0.3854842198344371E+00, 0.2741584921777233E+00, 0.1210105287753585E+00, 0.6940868812740908E-01, 0.2059029850850508E-01, 0.3673564803695461E-02, 0.8077935669463161E-25, 0.2195808487174199E-10, 0.8449955132778232E-10, 0.1877195462180231E+01, 0.1633831636278255E-19, 0.3497961877980620E-08, 0.7650955873935623E-08, 0.1801757023901512E+01, 0.4072241987713803E-24, 0.2126842707416970E-06, 0.1130018646589442E-06, 0.1273111869927408E+01, 0.1740941751301712E-20, 0.3388039768888790E-03, 0.2863573324805332E-03, 0.1088705127135854E+01, 0.2858227958137079E-16, 0.2905468688553340E-03, 0.2787380120464217E-03, 0.9559661931705944E+00, 0.1315475667900737E-21, 0.2494156905704573E+02, 0.2494156905704573E+02, 0.1010000000000000E+03, 0.3074829931972789E+01, 0.1980198019801980E+01, 0.2647338938369395E-05, 0.6445742634037150E+00, 0.2341846562030201E-22, 0.2667503836084351E-03, 0.1510510164587073E-03, 0.5446175180211763E+00, 0.2242636890234710E-24, 0.5495840118850513E-05, 0.4810476319752364E-05, 0.4486902226406620E+00, 0.3552400222016096E-16, 0.2740332708518062E-05, 0.2562621073339741E-05, 0.3854842198344371E+00, 0.1036641484462207E-22, 0.2248949759797675E-05, 0.2492010005917310E-05, 0.2741584921777233E+00, 0.6071156729318302E-20, 0.4130294607665845E-03, 0.1141603094124651E-03, 0.1210105287753585E+00, 0.2468629837810345E-16, 0.7230132634032991E-02, 0.6618694284253705E-02, 0.6940868812740908E-01, 0.5487745597049798E-23, 0.4151017130761703E-02, 0.4525758324635968E-02, 0.2059029850850508E-01, 0.6083695301064443E-26, 0.3095027772299370E-02, 0.3218440937246976E-02, 0.3673564803695461E-02, 0.6106717417722413E-22, 0.6443405665983428E-02, 0.1622720765285148E-02}, + info: 0, + }, + { + z: []float64{0.1985414918961074E+00, 0.4386372064833388E-01, 0.9272679997999695E+00, 0.9276564660006267E+00, 0.9509373652834754E+00, 0.6247274629358034E+00, 0.4838472987754385E+00, 0.6222976111124274E+00, 0.4248800474043221E+00, 0.9755567793536163E+00, 0.8912410754920851E+00, 0.2313492132656925E-01, 0.1563015923526294E+00, 0.7905214363406186E+00, 0.4927898149840948E+00, 0.5370919594301193E+00, 0.4644799081842790E+00, 0.9960946978984735E+00, 0.2493095982292803E+00, 0.3814725574373231E+00, 0.2940816225707878E+00, 0.6535898793246008E+00, 0.2084037192546966E+00, 0.5132959253232522E+00, 0.4251209694264122E+00, 0.9378579353373483E+00, 0.9786807729708236E+00, 0.7781441628535176E+00, 0.3951333405907657E+00, 0.3920742203259495E+00, 0.1500883321285087E+00, 0.9121803806188729E+00, 0.8516361075320147E+00, 0.6824417668614835E-01, 0.1390781730568696E+00, 0.3112124735573820E+00, 0.2535919561468232E+00, 0.7644352497405866E+00, 0.9218252733114815E+00, 0.9901458352558505E+00, 0.3279511469507669E+00, 0.8365860218696105E+00, 0.3198677553816687E+00, 0.6133665370063144E+00, 0.2580491557527305E+00, 0.6586714927743139E+00, 0.3933698458458805E+00, 0.7194383869235133E-01, 0.2213903901048253E-02, 0.1496106697134404E+00, 0.6766438239122079E+00, 0.7197724372602395E+00, 0.4797148651858846E+00, 0.5998154083597278E+00, 0.5590962662612089E+00, 0.6336887670809047E+00, 0.1072453740736307E+00, 0.7505878626477551E+00, 0.1427362910235584E+00, 0.6016163404777434E+00, 0.9488238354107547E+00, 0.4206748665323531E+00, 0.4473756257202280E+00, 0.2658295729210566E+00, 0.2340075619597504E+00, 0.9617320234413022E+00, 0.5962761690405762E+00, 0.8519099982463364E+00, 0.5571747680961063E+00, 0.1982921114470393E-01, 0.2779304562486129E-01, 0.7924439389736488E+00, 0.9672136382383878E-01, 0.8417095886148459E+00, 0.7473598542298929E+00, 0.9746159458640847E+00, 0.5038819873190444E+00, 0.9169242656654556E+00, 0.5252626769192049E+00, 0.5100979601115528E+00, 0.2790149607164115E+00, 0.4554892778467722E+00, 0.9762420639370454E+00, 0.9832519154713986E+00}, + n: 21, + zOut: []float64{0.2773247209998878E+01, 0.2684570079202721E+01, 0.2535407140485478E+01, 0.2251849067745984E+01, 0.2036533658934636E+01, 0.1904369707782458E+01, 0.1446171755624304E+01, 0.1299751831669502E+01, 0.1269533063987320E+01, 0.1007664938847636E+01, 0.8251797533661941E+00, 0.5818474246453018E+00, 0.5486201168977923E+00, 0.3772420051451134E+00, 0.3380340897724159E+00, 0.2023767003460897E+00, 0.1840234711841343E+00, 0.9225167203340243E-01, 0.4232592978815707E-01, 0.2771262583534443E-01, 0.7321455618534900E-04, 0.2977163580658995E-22, 0.3752078887401622E-10, 0.4179376226086309E-10, 0.1446171755624304E+01, 0.2236367039610280E-12, 0.1299965948722022E-10, 0.1595321259646779E-10, 0.1299751831669502E+01, 0.9926167350636332E-23, 0.8604643146515003E-10, 0.1864418628665438E-09, 0.1269533063987320E+01, 0.1306353659045996E-24, 0.1991121186029356E-08, 0.8983175437487846E-09, 0.1007664938847636E+01, 0.1213184768518325E-22, 0.3444432736029153E-07, 0.6437805745712839E-07, 0.8251797533661941E+00, 0.7772022937681214E-16, 0.2242878545784906E+02, 0.2242878545784905E+02, 0.1000000000000000E+03, 0.3024943310657596E+01, 0.3000000000000000E+01, 0.1709907812443784E-06, 0.5486201168977923E+00, 0.2972680326362443E-23, 0.1350081364219064E-06, 0.1255933647347444E-06, 0.3772420051451134E+00, 0.8046381233254320E-28, 0.7022416754922569E-08, 0.2768431074740138E-07, 0.3380340897724159E+00, 0.1719716773381806E-27, 0.7079953450794871E-07, 0.6648251035830866E-07, 0.2023767003460897E+00, 0.1940724044588524E-24, 0.4764709677102475E-07, 0.4597049352360845E-07, 0.1840234711841343E+00, 0.3459682911934042E-21, 0.4438757837191216E-07, 0.4402069254647340E-07, 0.9225167203340243E-01, 0.2596900924099520E-17, 0.8125925620122143E-07, 0.6770863964779914E-07, 0.4232592978815707E-01, 0.1280067631025782E-15, 0.3584234088053806E-06, 0.4822962810861105E-06, 0.2771262583534443E-01, 0.1012934875847350E-18, 0.1556396151524861E-05, 0.2916279508701459E-05, 0.7321455618534900E-04, 0.1540743955509789E-32, 0.4190434742116713E-02, 0.1362677535010021E-02}, + info: 0, + }, + { + z: []float64{0.6703344952482478E+00, 0.3577116069291627E+00, 0.8432263018920840E+00, 0.9584130033491455E+00, 0.2861685401430958E+00, 0.9668570623620085E+00, 0.6957796127156375E+00, 0.7603022900919236E+00, 0.7677099838587329E+00, 0.2702658617954818E+00, 0.9607212720070546E-01, 0.3973573502375266E+00, 0.8455511814548733E+00, 0.6862903202354254E-01, 0.1789860417278408E+00, 0.1112926642215833E+00, 0.8320621955974556E+00, 0.2637090148175287E+00, 0.7109403389502641E+00, 0.6494529820495407E+00, 0.8828985636942858E+00, 0.9098303542318168E+00, 0.1777489928582532E+00, 0.8977650882542143E-01, 0.7154356412046237E-01, 0.2693107133832517E-01, 0.7956794415059365E-02, 0.8852594037406200E+00, 0.2162284138438216E+00, 0.9216829080200467E+00, 0.9874282279096652E+00, 0.6087745498247736E+00, 0.7694028142872190E+00, 0.5918349824988693E+00, 0.1915561020798640E+00, 0.1135335598824661E-01, 0.6670902390154858E+00, 0.6601113994758983E+00, 0.7779237148990382E+00, 0.9023999203058302E+00, 0.1848842750705929E+00, 0.6120355291150891E+00, 0.7209828136916797E+00, 0.3124354740483853E+00, 0.9520753904353354E+00, 0.9694533109968584E+00, 0.6869212426966154E+00, 0.3510392134251344E+00, 0.7696249856763533E+00, 0.9203915575905880E+00, 0.4616165896255233E+00, 0.6796681592119477E+00, 0.9261196886552191E+00, 0.4511929507295228E+00, 0.5162093776469306E+00, 0.3093101029632945E+00, 0.1162653262260159E+00, 0.1951366360676013E+00, 0.7945099687545387E+00, 0.9707806531485516E+00, 0.4161172559602336E+00, 0.5813461713597171E+00, 0.8442974147064882E+00, 0.9135490286183924E+00, 0.3261094875410662E+00, 0.7080588637364270E+00, 0.3833080381406134E+00, 0.9095051028453779E+00, 0.6909172438403831E+00, 0.5187928284332267E+00, 0.5783778059525303E+00, 0.9615928062069277E+00, 0.2127624116065856E+00, 0.7254035177440832E+00, 0.2587362009618467E+00, 0.7570212065831576E+00, 0.2401238007004233E+00, 0.2744934873404078E+00, 0.9420426561890750E+00, 0.7098059460475599E+00, 0.2691363643891775E+00, 0.4536316870833661E+00, 0.6839445343274818E+00, 0.9336823543434762E+00}, + n: 21, + zOut: []float64{0.2634467575625416E+01, 0.2594635276829839E+01, 0.2463070407655619E+01, 0.2293127065694029E+01, 0.2072673505384417E+01, 0.1459936798288049E+01, 0.1378497856793854E+01, 0.1333239471494390E+01, 0.1102542278566289E+01, 0.8930469384549427E+00, 0.8520787727779708E+00, 0.6953298055150813E+00, 0.6847648677749263E+00, 0.2185116940651705E+00, 0.2008337976176149E+00, 0.1757551361146239E+00, 0.1271484717317025E+00, 0.5049064582277562E-01, 0.3515271339576785E-01, 0.7966224551514293E-02, 0.1685389559757755E-03, 0.1635721388548769E-22, 0.3551032227485648E-11, 0.3089325791958004E-11, 0.1378497856793854E+01, 0.6463020148652660E-17, 0.4439365591922079E-11, 0.5247211770454983E-11, 0.1333239471494390E+01, 0.8616343098037817E-25, 0.4343651596456738E-10, 0.2452653826174233E-10, 0.1102542278566289E+01, 0.9876517884224792E-16, 0.1549700306365952E-08, 0.1012434062383302E-08, 0.8930469384549427E+00, 0.4606319384654338E-19, 0.1115188986357716E-08, 0.1237013304894199E-08, 0.8520787727779708E+00, 0.1447566071967798E-23, 0.2127343784310997E+02, 0.2127343784310997E+02, 0.1270000000000000E+03, 0.3675736961451247E+01, 0.9448818897637794E+01, 0.2782364756724027E-11, 0.6847648677749263E+00, 0.6100457017578579E-23, 0.1535488071926541E-09, 0.5733950833190260E-09, 0.2185116940651705E+00, 0.6436934318898579E-12, 0.5207333190112868E-06, 0.4302907440331721E-06, 0.2008337976176149E+00, 0.1972152263052530E-30, 0.2421587237749379E-06, 0.2920528765870267E-06, 0.1757551361146239E+00, 0.8101601496619791E-27, 0.1434500575863456E-11, 0.9045851929625007E-13, 0.1271484717317025E+00, 0.1560107593833772E-17, 0.1620731838764033E-06, 0.1206839073349329E-06, 0.5049064582277562E-01, 0.3155443620884047E-29, 0.7221494757183839E-05, 0.4279630756550309E-05, 0.3515271339576785E-01, 0.0000000000000000E+00, 0.2092539651031481E-04, 0.3641666945464839E-04, 0.7966224551514293E-02, 0.1018583906139065E-23, 0.4276808715243643E-05, 0.6380573645111411E-06, 0.1685389559757755E-03, 0.0000000000000000E+00, 0.2828744147621957E-02, 0.2649548441232189E-02}, + info: 0, + }, + { + z: []float64{0.7647749557731113E+00, 0.1439440544256733E+00, 0.7500486933916728E+00, 0.6414832886183546E+00, 0.8122572937542115E+00, 0.9529234674941257E+00, 0.3352470221802866E+00, 0.6936226545338587E+00, 0.9931729574752579E-01, 0.3187856199297912E-01, 0.1671537284832858E+00, 0.6799274061730229E+00, 0.8177446911383146E+00, 0.5321042755342652E+00, 0.1611635863708949E+00, 0.1556305029012977E+00, 0.8064987994430675E+00, 0.6086425937675999E-01, 0.9539387771768112E+00, 0.5483826791143146E+00, 0.1624656726546599E+00, 0.8604262189788422E+00, 0.3348601405085260E+00, 0.6512790728986305E+00, 0.3357978279833680E+00, 0.7104789129438286E+00, 0.4161092786312924E+00, 0.8790797243791704E+00, 0.1469866181354552E+00, 0.7277776395098579E-01, 0.4317417806367096E-01, 0.8731968970940820E+00, 0.4856440529809196E+00, 0.2315660100703048E+00, 0.2955911335168215E+00, 0.4119299294790694E+00, 0.4565975215473586E+00, 0.8915397570999283E+00, 0.1639735129501203E+00, 0.5055946074157277E+00, 0.9530743160791620E+00, 0.9836351183281582E+00, 0.2913429799811792E+00, 0.9289008959282562E+00, 0.5996674664338365E+00, 0.6609996028219567E+00, 0.7317528474660470E+00, 0.9903648665746729E+00, 0.3982305249886617E+00, 0.3563571411857538E+00, 0.8851540908639802E+00, 0.8253410045707608E+00, 0.8085297859672740E+00, 0.3918185712378985E+00, 0.7922842941861202E+00, 0.7487878715845681E+00, 0.3117744132747395E+00, 0.7135433852632408E+00, 0.8969220948763633E+00, 0.5840741001028926E+00, 0.3261515465187765E+00, 0.5368137772779212E+00, 0.6371156779602756E+00, 0.5575308178040213E+00, 0.1319054467962255E+00, 0.6274305773732142E+00, 0.9230553933157697E+00, 0.3589158151867838E+00, 0.1429059780004028E+00, 0.6433214640390554E+00, 0.9159704795536289E+00, 0.8998439182451070E+00, 0.5665265465351250E+00, 0.4290736239553739E+00, 0.4923118412965143E+00, 0.3733795042755129E+00, 0.4008465132226234E+00, 0.8630963810875470E+00, 0.2835407905147469E+00, 0.8431337072866282E+00, 0.7450545748778526E+00, 0.2948369760127234E+00, 0.6896108484670013E+00, 0.1073791710993542E+00}, + n: 21, + zOut: []float64{0.2492440020550355E+01, 0.1951232214041701E+01, 0.1924880150346451E+01, 0.1800337146913507E+01, 0.1731259644349016E+01, 0.1515025732591961E+01, 0.1392131403063820E+01, 0.1337121843604905E+01, 0.1335944341051471E+01, 0.9695979508906304E+00, 0.8602855628657217E+00, 0.7598736716193354E+00, 0.5663438341779535E+00, 0.4991982558529897E+00, 0.3900147250500268E+00, 0.2612685334229408E+00, 0.1040703325016068E+00, 0.5095987426708586E-01, 0.4270469018444285E-01, 0.6313950453962554E-02, 0.4526318588114864E-04, 0.1623810366421630E-16, 0.5786287269352850E-19, 0.2440824886543042E-19, 0.1392131403063820E+01, 0.1972152263052530E-30, 0.1305662432930495E-17, 0.2687054746502436E-17, 0.1337121843604905E+01, 0.6807276388656606E-23, 0.2125450465832215E-16, 0.4166517172824519E-16, 0.1335944341051471E+01, 0.3971441341244662E-25, 0.3131313418539388E-15, 0.1598422579069803E-15, 0.9695979508906304E+00, 0.2612707318091991E-24, 0.3703169268599905E-13, 0.5897085302084673E-13, 0.8602855628657217E+00, 0.3944304526105059E-30, 0.1999104914098575E+02, 0.1999104914098576E+02, 0.1050000000000000E+03, 0.3185941043083900E+01, 0.4761904761904762E+01, 0.3815530651290367E-11, 0.5663438341779535E+00, 0.4442864618204738E-26, 0.2314135864505331E-10, 0.3280099800133426E-10, 0.4991982558529897E+00, 0.2524354896707238E-28, 0.8792792965154248E-10, 0.6284153656438893E-10, 0.3900147250500268E+00, 0.2716911819042188E-17, 0.6371083763388994E-09, 0.9063994743331422E-09, 0.2612685334229408E+00, 0.7682295356186976E-14, 0.2615630848198228E-07, 0.4934681155229334E-07, 0.1040703325016068E+00, 0.3134368286722418E-21, 0.1338644268367565E-05, 0.2571041054206291E-05, 0.5095987426708586E-01, 0.6829203137199389E-20, 0.1734538060272007E-04, 0.9160403953625247E-05, 0.4270469018444285E-01, 0.5620633949699709E-29, 0.1970936154220316E-07, 0.7875060113736862E-07, 0.6313950453962554E-02, 0.1074365444038600E-22, 0.1950342748319920E-02, 0.1960570817697857E-02, 0.4526318588114864E-04, 0.5045801736573469E-22, 0.2719687288170513E-02, 0.7229547441545878E-02}, + info: 0, + }, + { + z: []float64{0.6830594937182136E+00, 0.2806903427821971E+00, 0.3842580501524426E+00, 0.7113293946876786E+00, 0.6120481717427926E+00, 0.4087522624125913E+00, 0.2683959794755927E+00, 0.1982680719912362E+00, 0.5503761648124630E+00, 0.9947639519912582E+00, 0.4817851020535202E-01, 0.1841410650783141E+00, 0.7364485595361944E+00, 0.2204876163244174E+00, 0.8785531172976315E+00, 0.3900984044089164E+00, 0.9898399332392419E+00, 0.4652324815840650E+00, 0.6574114801218780E+00, 0.6641201888165797E+00, 0.5371222655177923E+00, 0.2241732155112269E+00, 0.6726821610374456E-01, 0.2361953456198683E+00, 0.5602287124209401E+00, 0.7836687903368798E+00, 0.2633616918428828E+00, 0.9669553142730151E+00, 0.3692579170869618E+00, 0.5395054150347700E-01, 0.4776047537674022E-01, 0.5691410116455676E+00, 0.1304181940038973E+00, 0.2107738642513712E+00, 0.5434523182333528E-01, 0.4019375962886824E+00, 0.7125153526157032E+00, 0.5305712841430671E+00, 0.1164846974244694E+00, 0.2037577925839799E+00, 0.2045617511271008E+00, 0.6122054957321945E+00, 0.5114531146106966E+00, 0.2882478115017332E+00, 0.5304873168821023E+00, 0.1796380649103803E+00, 0.9949092378946756E-01, 0.5448372048900864E+00, 0.1971761401002603E+00, 0.9487011110186927E+00, 0.8526405089060669E+00, 0.4533764477818548E+00, 0.8410819408489681E+00, 0.7592016862970913E+00, 0.8131142938762341E+00, 0.1445496351282255E+00, 0.6614974180377753E+00, 0.3394841721225367E+00, 0.4878107636737276E+00, 0.5499609605641745E+00, 0.1789798083030991E+00, 0.2008397619575961E+00, 0.5247567247775218E+00, 0.7394478154071386E+00, 0.6713478520024037E+00, 0.3894295843862983E+00, 0.9099978858741096E+00, 0.9872931573704680E-01, 0.5370559804237263E+00, 0.8492599321050560E+00, 0.4671993983916084E+00, 0.6397070306147701E+00, 0.2884512208824136E+00, 0.5002881141083532E+00, 0.3356213102526899E+00, 0.4102730364689955E+00, 0.8172446941984062E+00, 0.1463391840674726E+00, 0.6374760821459636E+00, 0.2986995049911381E+00, 0.6932950085590186E+00, 0.8475246239619540E+00, 0.3550038162879430E+00, 0.9747731646460122E+00}, + n: 21, + zOut: []float64{0.2302037253547019E+01, 0.1904432769194928E+01, 0.1838629010091233E+01, 0.1679631021950300E+01, 0.1638588328999231E+01, 0.1556939208705248E+01, 0.1154775776884602E+01, 0.1123025367728587E+01, 0.1005963210310813E+01, 0.7892040895461047E+00, 0.6171474041407791E+00, 0.5107385873854940E+00, 0.4745466376069911E+00, 0.2987072329916590E+00, 0.2518976395749056E+00, 0.1562926917018191E+00, 0.1208002043434920E+00, 0.1117929648180551E+00, 0.3025264937486962E-01, 0.5461437067005637E-02, 0.3901591662109151E-04, 0.2028008633963607E-17, 0.1197298285059118E-05, 0.1163352934520667E-05, 0.1154775776884602E+01, 0.2502221352972909E-22, 0.7438201518083012E-06, 0.8784873727121712E-06, 0.1123025367728587E+01, 0.2368236188315088E-19, 0.3676741199329849E-11, 0.3039307086935086E-11, 0.1005963210310813E+01, 0.2065553394230697E-24, 0.6686270095375819E-11, 0.8550052948388210E-11, 0.7892040895461047E+00, 0.1239058396467615E-20, 0.2067843352216928E-06, 0.6687212675645054E-07, 0.6171474041407791E+00, 0.2620094590259913E-21, 0.1757090250187976E+02, 0.1757090250187975E+02, 0.9500000000000000E+02, 0.2798185941043084E+01, 0.1052631578947368E+01, 0.6997553999213272E-08, 0.4745466376069911E+00, 0.5994838008700348E-24, 0.1052996378646298E-04, 0.6312169743031761E-04, 0.2987072329916590E+00, 0.9860761315262648E-30, 0.1466875513591431E-03, 0.1024839055944592E-03, 0.2518976395749056E+00, 0.7516632826070909E-17, 0.5524256710713082E-08, 0.1151290676113078E-07, 0.1562926917018191E+00, 0.1348952147927930E-27, 0.1222984298841777E-06, 0.3042067118561864E-06, 0.1208002043434920E+00, 0.4760428464210509E-23, 0.9492582004636672E-05, 0.3402727365723720E-04, 0.1117929648180551E+00, 0.7018716354804804E-22, 0.2431231599464108E-03, 0.1315672135071063E-03, 0.3025264937486962E-01, 0.4377821080194221E-21, 0.1333575496853992E-02, 0.6988231628130009E-03, 0.5461437067005637E-02, 0.2193916840728260E-24, 0.1845211740639344E-02, 0.8881725247692956E-03, 0.3901591662109151E-04, 0.2067951531382569E-23, 0.6469870796864946E-02, 0.1027022788337614E-01}, + info: 0, + }, + { + z: []float64{0.3270384527330652E+00, 0.4068565573647237E+00, 0.5445258191923925E+00, 0.9571802305689175E+00, 0.1840747434207346E-01, 0.8759261930487382E+00, 0.3018283835341639E+00, 0.4754674889513868E+00, 0.9620709342523251E+00, 0.3596342978433105E+00, 0.1820397917245298E+00, 0.9562190617892271E+00, 0.8004073710305811E+00, 0.9503584926946729E+00, 0.1634422399578277E+00, 0.3053134184266467E+00, 0.3871438286377282E+00, 0.1225252880124038E+00, 0.5955538022158587E+00, 0.9831372787057571E+00, 0.2130378801829313E+00, 0.1502296787149880E+00, 0.5120891507658710E+00, 0.2769158347903287E+00, 0.6740978559159013E+00, 0.6671510755324899E+00, 0.5252429573239310E+00, 0.7312875683466940E+00, 0.6359518339326128E+00, 0.3635213813950466E-01, 0.7509704695539338E+00, 0.2796455326190517E+00, 0.3929933998036216E+00, 0.2441550702438192E+00, 0.5181887041338979E+00, 0.2149631476903890E-01, 0.1922157358558590E+00, 0.8352708839021310E+00, 0.2143118694803675E+00, 0.8099207585987700E+00, 0.4013415573783083E+00, 0.8990854368069680E+00, 0.2274365144039603E-01, 0.1574221848735892E+00, 0.5021896402707141E+00, 0.6811320055313477E+00, 0.4008235511220088E+00, 0.2607115591315068E+00, 0.8396807341169598E+00, 0.3393611517447541E+00, 0.3095200315094494E+00, 0.8849677836408325E+00, 0.3309280721041051E+00, 0.2177939175852258E+00, 0.7396054658394657E-02, 0.5387313739545944E+00, 0.5592732178453728E+00, 0.4422242955757759E+00, 0.6010599951901635E+00, 0.2729214395073326E+00, 0.8861412244709392E+00, 0.3303460134234409E+00, 0.3230906405176623E+00, 0.5979281304041633E+00, 0.1747480524852378E+00, 0.5019201598522602E+00, 0.3041629115671023E+00, 0.7344252813174572E+00, 0.5145018596354390E+00, 0.7032668540687012E+00, 0.4542245378490408E+00, 0.6883469599293311E+00, 0.7365046871633816E+00, 0.6892200550994384E+00, 0.9612097768268251E+00, 0.3687306903044788E+00, 0.4902139977664450E+00, 0.4004732628576805E+00, 0.2121831569752699E+00, 0.3483027732062219E+00, 0.4140454821962284E+00, 0.5590476647584736E+00, 0.1191647727722587E+00, 0.7126611758207085E+00}, + n: 21, + zOut: []float64{0.2451808019367049E+01, 0.2128252216129400E+01, 0.1884015768998821E+01, 0.1793403527862625E+01, 0.1731698897481475E+01, 0.1605979322764491E+01, 0.1346135733575790E+01, 0.1222183737737495E+01, 0.1054517637460965E+01, 0.8541696661721662E+00, 0.8335553929836017E+00, 0.7643627371640215E+00, 0.6493538020248019E+00, 0.5117674171078171E+00, 0.4801902398267136E+00, 0.1830481952424627E+00, 0.1336751260833609E+00, 0.7548204386515513E-01, 0.4276641694583261E-01, 0.1152852330305948E-01, 0.4825291327526518E-04, 0.1046558665109411E-21, 0.5148060409033168E-10, 0.1742874021361670E-10, 0.1346135733575790E+01, 0.3944304526105059E-30, 0.1177385120842054E-08, 0.5739784145251797E-09, 0.1222183737737495E+01, 0.5228352308675503E-16, 0.2817945521555932E-11, 0.1891433639936970E-11, 0.1054517637460965E+01, 0.1775328283321620E-16, 0.9506244555381454E-11, 0.6780149876052939E-11, 0.8541696661721662E+00, 0.4289572169691169E-11, 0.3560204585171959E-10, 0.5552509181949502E-10, 0.8335553929836017E+00, 0.8925278809447169E-21, 0.1975794267501038E+02, 0.1975794267501038E+02, 0.9900000000000000E+02, 0.3029478458049887E+01, 0.2020202020202020E+01, 0.4057773458399609E-09, 0.6493538020248019E+00, 0.3196600703119960E-17, 0.4936238682205707E-06, 0.2172173957444601E-06, 0.5117674171078171E+00, 0.2475160268480207E-20, 0.1127880382626992E-04, 0.1031817493791828E-04, 0.4801902398267136E+00, 0.2327139670401985E-28, 0.8359957951383868E-05, 0.8045173068477057E-05, 0.1830481952424627E+00, 0.2763487036072314E-23, 0.1049648761427048E-04, 0.8607871065540926E-05, 0.1336751260833609E+00, 0.6392286336815055E-18, 0.5478798785309189E-04, 0.3178071334079827E-04, 0.7548204386515513E-01, 0.1886324196564483E-25, 0.4604839715747456E-05, 0.3206078546562559E-04, 0.4276641694583261E-01, 0.2130807968310579E-24, 0.2160396768988393E-02, 0.2401524776593251E-02, 0.1152852330305948E-01, 0.4597153189491485E-23, 0.1577121702032026E-02, 0.1548884890976950E-02, 0.4825291327526518E-04, 0.0000000000000000E+00, 0.1144436370534878E-01, 0.4805213857273134E-02}, + info: 0, + }, + { + z: []float64{0.1204296195656108E+00, 0.2644532009534747E+00, 0.2981945708465356E+00, 0.3379851046426219E-01, 0.5872157683391875E+00, 0.3661495849020495E+00, 0.2783310889774259E+00, 0.8471009797765506E+00, 0.6087926721027869E+00, 0.7227374835926721E+00, 0.1157491272838733E+00, 0.5565144099551486E+00, 0.8949691253636921E+00, 0.4271566773654165E+00, 0.6387841251831913E+00, 0.3125047228733280E-01, 0.2092736013478247E-01, 0.9188324418961444E+00, 0.2275180796997284E+00, 0.4519662960462961E+00, 0.1155877493866434E+00, 0.3574940735178409E+00, 0.1489772525039219E+00, 0.3847908470095970E+00, 0.4780110568180811E+00, 0.3489586723075616E+00, 0.2559758537216194E+00, 0.7015930720521131E+00, 0.6512181083044030E+00, 0.1619173394771481E+00, 0.5094142654629881E+00, 0.9037662631759247E+00, 0.8829671919577533E+00, 0.5739200804260277E+00, 0.6584413366512047E+00, 0.7174965427568090E+00, 0.2705911606916550E+00, 0.6519148889036277E+00, 0.8284421625450799E+00, 0.1417109678591228E+00, 0.8472265674806589E-01, 0.3638971914001953E+00, 0.8802661885427909E-01, 0.5730596475071164E+00, 0.6156880168413905E+00, 0.3769532609458294E+00, 0.6302840487845919E+00, 0.8652028697564479E+00, 0.5886269364510055E-01, 0.9901772381773877E-01, 0.9679961670969370E+00, 0.9025028618130532E+00, 0.2858592550914936E+00, 0.4523960301168739E-01, 0.9961073801516410E+00, 0.5404176614913075E+00, 0.2161216977420954E+00, 0.6517643909270738E+00, 0.1408193879882935E-01, 0.2323315528058443E+00, 0.4040647670376405E+00, 0.5063393857452272E+00, 0.2149141182072994E+00, 0.8405813011731451E+00, 0.8044826512704509E+00, 0.5364711289689184E+00, 0.2922476360373625E+00, 0.9518940562302493E+00, 0.1980063292193738E+00, 0.6243757640305569E-01, 0.3641799792979717E+00, 0.4781083740929701E+00, 0.3488268687432241E+00, 0.8284107864073382E+00, 0.5855039308834178E+00, 0.2593007284605915E+00, 0.9998845891621441E+00, 0.5048349794999019E+00, 0.5828201446782487E+00, 0.8921301000231074E+00, 0.2672402237051515E+00, 0.3352853759971494E+00, 0.5977528180071631E+00, 0.1151194604047919E+00}, + n: 21, + zOut: []float64{0.2557315455353142E+01, 0.2083235685800309E+01, 0.1875944452104717E+01, 0.1852714062580819E+01, 0.1643995946812320E+01, 0.1314218355716144E+01, 0.1293789198407225E+01, 0.1108624029644386E+01, 0.1060866236520538E+01, 0.6893140608436983E+00, 0.6265017468006577E+00, 0.6169803536834606E+00, 0.4472638275156540E+00, 0.3909824987049766E+00, 0.2990543016857948E+00, 0.1644755201813542E+00, 0.1145158516686298E+00, 0.6240413476421734E-01, 0.2540980528285533E-01, 0.1114684260186565E-01, 0.3077034058364147E-04, 0.1514612938024343E-27, 0.1068838715614041E-10, 0.1816953714834036E-10, 0.1293789198407225E+01, 0.1634858280249726E-16, 0.1546152805249061E-09, 0.7139985980503436E-10, 0.1108624029644386E+01, 0.1852295205932338E-17, 0.2931760870340471E-08, 0.5717158524063146E-08, 0.1060866236520538E+01, 0.1656986554198631E-24, 0.3897819821179759E-07, 0.2050786216968739E-07, 0.6893140608436983E+00, 0.1054613376713825E-21, 0.1114796130440952E-06, 0.1754727955273104E-06, 0.6265017468006577E+00, 0.0000000000000000E+00, 0.1823878313701335E+02, 0.1823878313701335E+02, 0.1020000000000000E+03, 0.3172335600907029E+01, 0.3921568627450980E+01, 0.4944285541926277E-08, 0.4472638275156540E+00, 0.7188113412291574E-19, 0.5360570179815202E-09, 0.5055207828345367E-09, 0.3909824987049766E+00, 0.7011182861561962E-17, 0.5424596001050196E-08, 0.1149191082508281E-07, 0.2990543016857948E+00, 0.1397964075969312E-24, 0.2148922978775398E-05, 0.1039924072201963E-05, 0.1644755201813542E+00, 0.1424715207546021E-19, 0.1286356681922344E-03, 0.6709371685087021E-04, 0.1145158516686298E+00, 0.1923558431290915E-24, 0.1040681698574874E-03, 0.9690504707177204E-04, 0.6240413476421734E-01, 0.3021337266996475E-27, 0.3740811812377314E-06, 0.8725750691496404E-06, 0.2540980528285533E-01, 0.6622271595176623E-28, 0.2937391640354928E-03, 0.1148070460566611E-03, 0.1114684260186565E-01, 0.3845696912952433E-29, 0.9582588059437623E-03, 0.1284334386264186E-02, 0.3077034058364147E-04, 0.1610185014413679E-23, 0.1713355521956925E-01, 0.1560043716021792E-01}, + info: 0, + }, + { + z: []float64{0.6550531738065145E+00, 0.9006303757888976E+00, 0.9204609778380736E+00, 0.4658341923257867E+00, 0.5436644687290008E+00, 0.2908556755036122E+00, 0.1209811495723523E+00, 0.6227378829506942E+00, 0.3843019792679099E+00, 0.4431829610151485E+00, 0.4903210952175132E+00, 0.4210264133022774E+00, 0.3200750839632230E+00, 0.2252794777033682E+00, 0.5128630958928748E-01, 0.5136099492114639E+00, 0.4906286803922755E+00, 0.1747340137845675E+00, 0.6367238354860758E+00, 0.7515407582129341E+00, 0.4275500565044866E+00, 0.2014278558825494E+00, 0.7137603260056157E+00, 0.8686875192977085E+00, 0.7169591605793454E+00, 0.9050302202813415E+00, 0.9899533400874350E-01, 0.9969046692447475E+00, 0.6121260436585757E+00, 0.6518683331715626E+00, 0.5607404970528083E+00, 0.4000687152662108E-03, 0.1221862374388689E+00, 0.4484923714483016E+00, 0.4074629631039243E+00, 0.2322333097032281E-01, 0.4732551077558298E+00, 0.7342979327909982E+00, 0.3458749207719752E+00, 0.7729568887054280E+00, 0.2047858477824707E+00, 0.7991048365911296E+00, 0.5370237056253078E+00, 0.2233168849800682E-01, 0.5135288197983614E+00, 0.9129664417816657E+00, 0.9407166870649586E+00, 0.4321958081203685E+00, 0.5563774896630214E-01, 0.9494906037764664E+00, 0.9674063566885983E+00, 0.2302624676329315E+00, 0.1506811640032519E+00, 0.4445855507514112E+00, 0.6038782945102905E-01, 0.4499742519338505E+00, 0.1940991655604004E+00, 0.6493052482066142E-01, 0.2902929850901331E+00, 0.2876163569026815E+00, 0.9140475482126542E+00, 0.7006705577674063E+00, 0.2819386709216735E+00, 0.9125816873773608E+00, 0.9433170896498744E-01, 0.1632821600392161E+00, 0.3150556796654537E+00, 0.4051206017420083E+00, 0.2687493393481850E+00, 0.5768057516945001E+00, 0.4306858988251338E+00, 0.3827211690774009E+00, 0.3593520435650671E+00, 0.5610694397953092E+00, 0.7151178950427733E+00, 0.7138830385076256E-01, 0.5281951083990266E-01, 0.4880677722651299E+00, 0.9334247489037772E+00, 0.6764242544288053E+00, 0.8551178347453967E+00, 0.1876923010834376E+00, 0.7408118952029578E+00, 0.7967219280126981E+00}, + n: 21, + zOut: []float64{0.2493394334366539E+01, 0.2460477172068809E+01, 0.2083159145455880E+01, 0.1779228959307519E+01, 0.1724095029781113E+01, 0.1560812668654360E+01, 0.1120482054552078E+01, 0.1088744749350826E+01, 0.9613598859526896E+00, 0.9456175481954929E+00, 0.9119552728538921E+00, 0.7767939725863090E+00, 0.6893167116879397E+00, 0.4408717103973492E+00, 0.2706330695081346E+00, 0.2343515836463984E+00, 0.6795401725828518E-01, 0.6600498464192311E-01, 0.2004873521291848E-01, 0.1421097732958122E-01, 0.4015560238058376E-03, 0.2226481018895784E-25, 0.2564499425740104E-12, 0.2658329977886514E-12, 0.1120482054552078E+01, 0.4315813836253463E-23, 0.1335501643346940E-12, 0.1368307862991113E-12, 0.1088744749350826E+01, 0.3926080427856238E-18, 0.1185565636052547E-12, 0.1214013431095007E-12, 0.9613598859526896E+00, 0.2719992401202049E-26, 0.9906513980413714E-13, 0.1012398200894782E-12, 0.9456175481954929E+00, 0.3937993638863291E-26, 0.9389079133840153E-13, 0.9189527811944332E-13, 0.9119552728538921E+00, 0.1580250204306566E-21, 0.1970991413883184E+02, 0.1970991413883184E+02, 0.1080000000000000E+03, 0.3401360544217687E+01, 0.8333333333333334E+01, 0.6496201881821226E-13, 0.6893167116879397E+00, 0.2040319821514109E-19, 0.6886568712781699E-13, 0.6342531805840532E-13, 0.4408717103973492E+00, 0.9116462109840799E-16, 0.6575726430673280E-12, 0.1146915438924438E-11, 0.2706330695081346E+00, 0.6100742213737356E-14, 0.5548784478521690E-10, 0.9411844035493366E-10, 0.2343515836463984E+00, 0.2464780121144947E-24, 0.1267470050081896E-08, 0.7549586177318002E-09, 0.6795401725828518E-01, 0.6058451752097371E-27, 0.2494439518946058E-07, 0.4030144639288306E-07, 0.6600498464192311E-01, 0.1931466728993349E-20, 0.1742718098912744E-06, 0.1063050845015484E-06, 0.2004873521291848E-01, 0.2078695185822955E-22, 0.1365398583912438E-05, 0.6056776980192580E-06, 0.1421097732958122E-01, 0.3944304526105059E-30, 0.8436693551699617E-06, 0.8772483974218289E-06, 0.4015560238058376E-03, 0.5424456586666688E-20, 0.1372662528173007E-02, 0.2323379424199439E-03}, + info: 0, + }, + { + z: []float64{0.5955158028190186E+00, 0.9601282390728449E-01, 0.2944266054820921E+00, 0.3924250378682403E+00, 0.4462256781176310E-01, 0.5690757232665151E+00, 0.7855339329019884E-01, 0.8681545225840360E+00, 0.7288006955920397E+00, 0.2963229749240101E+00, 0.2728029241156386E+00, 0.4237536504971896E+00, 0.9003368942847588E+00, 0.7357957067011865E+00, 0.4901129309073038E-01, 0.4716171621744532E+00, 0.4890099406800087E+00, 0.3570165784460172E+00, 0.7160897857565474E-01, 0.6109824519907316E+00, 0.1221913259189585E+00, 0.1847302629402909E+00, 0.4009366884871202E-01, 0.9703472440233364E+00, 0.6369052870991366E+00, 0.5580400433416689E+00, 0.9024815855223057E+00, 0.1227045689636573E+00, 0.9668897094172768E+00, 0.5989409973498315E+00, 0.9709139844325040E+00, 0.9532564522700616E+00, 0.6239574483953332E+00, 0.7056703505253071E+00, 0.9506691238320553E-01, 0.7998586962365666E+00, 0.6556519136464994E+00, 0.4181856697120553E+00, 0.9478314170226607E+00, 0.3832663309972284E-01, 0.4257218688507075E+00, 0.2049443327129853E+00, 0.9168853967010917E+00, 0.5423988966788751E-02, 0.3002879152136316E+00, 0.7743151012217909E+00, 0.5154350917338609E+00, 0.9658560730800175E+00, 0.6314599250676610E+00, 0.5584937104443134E+00, 0.4741445335250092E+00, 0.3157508358915576E+00, 0.4349529093465575E+00, 0.7860003715032308E+00, 0.8695087804152180E-02, 0.3920445280700808E+00, 0.3765485221235618E+00, 0.4334604109656897E+00, 0.1636117026415890E+00, 0.3006093728066712E+00, 0.2129148932459900E+00, 0.3092975700919495E+00, 0.1986761620686717E-01, 0.9075541031649185E+00, 0.9781911433730479E+00, 0.6945955075731600E+00, 0.9959584477684137E+00, 0.7505944883792014E+00, 0.7627854018352902E+00, 0.1267035334952504E+00, 0.8056780234474171E+00, 0.4507060196586773E+00, 0.1799397964631048E+00, 0.7554691089798000E+00, 0.3012534688386570E+00, 0.9612172487804931E+00, 0.4056708256608614E+00, 0.6648221051068217E+00, 0.1966051207552482E+00, 0.6661008672469584E+00, 0.6875730168317549E+00, 0.9591133633640367E+00, 0.8995318056907078E+00, 0.1435403265941513E+00}, + n: 21, + zOut: []float64{0.2826953331143077E+01, 0.2184946373215138E+01, 0.2011432985807930E+01, 0.1983939371799505E+01, 0.1783403572375380E+01, 0.1527291743334771E+01, 0.1218359458122959E+01, 0.1031625203087357E+01, 0.9141017580644314E+00, 0.8935891545682184E+00, 0.7995009441187808E+00, 0.6760292370761557E+00, 0.5375939998175604E+00, 0.5031272745805969E+00, 0.4136950654384539E+00, 0.4077555149266558E+00, 0.1977184484214556E+00, 0.1172157517521918E+00, 0.4197144528461013E-01, 0.1336078057720851E-01, 0.3545889291755145E-06, 0.2544082546855865E-16, 0.2583036406189355E-05, 0.3206950450307273E-05, 0.1218359458122959E+01, 0.6512835633504673E-25, 0.5241867641497365E-06, 0.5644106780290774E-06, 0.1031625203087357E+01, 0.0000000000000000E+00, 0.4305359229680111E-07, 0.8271940560154021E-07, 0.9141017580644314E+00, 0.0000000000000000E+00, 0.3911233321019150E-06, 0.2241550799736728E-06, 0.8935891545682184E+00, 0.2385737520619250E-22, 0.4206034452718400E-11, 0.9899461762377114E-11, 0.7995009441187808E+00, 0.9331359083488707E-16, 0.2008361176810137E+02, 0.2008361176810137E+02, 0.1130000000000000E+03, 0.3444444444444445E+01, 0.6194690265486726E+01, 0.1651034509856568E-04, 0.5375939998175604E+00, 0.1421716677825516E-23, 0.1528222338287967E-04, 0.2433829126418849E-04, 0.5031272745805969E+00, 0.6632003279205155E-19, 0.4757657931696731E-05, 0.2751276356124619E-05, 0.4136950654384539E+00, 0.1680371209901916E-16, 0.1318069984220972E-06, 0.1659409431372840E-06, 0.4077555149266558E+00, 0.2554525986432683E-22, 0.5944173486813264E-06, 0.1429245864393051E-05, 0.1977184484214556E+00, 0.1494891415393817E-27, 0.8465737022131437E-03, 0.4160790916597339E-03, 0.1172157517521918E+00, 0.6780166836549887E-20, 0.3655496023749206E-04, 0.5562211290196199E-04, 0.4197144528461013E-01, 0.1803076020780872E-22, 0.2337686132102848E-02, 0.5241185550833300E-02, 0.1336078057720851E-01, 0.3234329711406148E-27, 0.6369386968947829E-02, 0.2727172056719641E-02, 0.3545889291755145E-06, 0.0000000000000000E+00, 0.6135698199493001E-02, 0.4453215245051444E-02}, + info: 0, + }, + { + z: []float64{0.5256994769563229E+00, 0.4751970954150097E+00, 0.5550798296722601E+00, 0.3565746805143110E+00, 0.3971523551134015E-01, 0.7088262788771817E+00, 0.6369448567868402E+00, 0.6372974860231623E+00, 0.5963599363854956E+00, 0.7996832763398349E+00, 0.7266271077857295E+00, 0.3813393981851099E+00, 0.8884393254050771E-01, 0.8685934834267716E+00, 0.3797066359545181E+00, 0.4541910736411658E+00, 0.6285354031372432E+00, 0.5295256159852654E+00, 0.8908170817260027E+00, 0.5793264969983637E+00, 0.6056871126785802E+00, 0.6045507124525907E+00, 0.9734230310286895E-01, 0.9482358811543057E+00, 0.8804820874856442E+00, 0.4472263119108183E+00, 0.5843860139759072E+00, 0.5372922689923049E+00, 0.5799351791336661E+00, 0.5116182356749631E+00, 0.3816355069915517E+00, 0.6475808331559241E+00, 0.8746013736579017E-02, 0.8411650861050215E+00, 0.2992737481736951E-01, 0.6246901010621124E+00, 0.3123078564554325E+00, 0.7411164234121632E+00, 0.5960432842954070E+00, 0.8102594121204127E+00, 0.3552957522458323E+00, 0.6235337320803771E+00, 0.5962195242077326E+00, 0.4845790335098474E+00, 0.4045953379382708E+00, 0.2452522545656534E+00, 0.2743318280596185E+00, 0.2023077390748810E+00, 0.4206973723636350E+00, 0.4039949452544738E+00, 0.9114680949622015E+00, 0.7779482986378454E+00, 0.6812819304160683E+00, 0.5580962104642140E-01, 0.4287711156774094E+00, 0.9817581515129085E+00, 0.4431516884275333E+00, 0.6237912221093689E-01, 0.8364254576520689E+00, 0.8759899245723605E+00, 0.8787473635901457E+00, 0.4702211826699049E+00, 0.8284521047414805E+00, 0.2041855966018515E+00, 0.8060130309143703E+00, 0.5501723689038956E+00, 0.2188842792675016E-01, 0.5672241818001204E+00, 0.6450459353754012E+00, 0.2431902854401001E+00, 0.5193698672717711E+00, 0.1962120228423043E+00, 0.6361488000943472E-01, 0.5342761659162559E+00, 0.1758994081846166E-01, 0.7459187699999678E+00, 0.5953394313659540E+00, 0.9379918174958790E+00, 0.4032831592210619E+00, 0.7704238877222783E+00, 0.9410981148731864E+00, 0.8355998775704846E+00, 0.7904637124553195E+00, 0.4324126135288506E+00}, + n: 21, + zOut: []float64{0.2360605380677641E+01, 0.2349812365456326E+01, 0.2259072978559188E+01, 0.2074669549844899E+01, 0.1734529465065066E+01, 0.1635336277856887E+01, 0.1535245292061319E+01, 0.1453596007978833E+01, 0.1156130097482147E+01, 0.1084746900314168E+01, 0.1034520391904089E+01, 0.8201881896309742E+00, 0.6191782955028541E+00, 0.5267433243518804E+00, 0.4355086546946592E+00, 0.4155619327338856E+00, 0.3396295360604018E+00, 0.9317218785919168E-01, 0.5773665727788814E-01, 0.1842462732727454E-01, 0.2018232369069597E-07, 0.4517585523147273E-24, 0.2167663685989129E-10, 0.1523023581682742E-10, 0.1535245292061319E+01, 0.1340432450151543E-25, 0.8069500146896454E-10, 0.1279555645700667E-09, 0.1453596007978833E+01, 0.6673291668607916E-16, 0.1337219714947293E-07, 0.4537550993048733E-08, 0.1156130097482147E+01, 0.2388039732285047E-25, 0.6170125127971897E-05, 0.1353762614268721E-04, 0.1084746900314168E+01, 0.3862470231561244E-18, 0.2338329578753200E-04, 0.2318969913953679E-04, 0.1034520391904089E+01, 0.6409494854920721E-30, 0.2200440813282189E+02, 0.2200440813282190E+02, 0.9400000000000000E+02, 0.2857142857142857E+01, 0.0000000000000000E+00, 0.2156912239043876E-04, 0.6191782955028541E+00, 0.4311940021813490E-19, 0.2098085305628239E-04, 0.2047701462113856E-04, 0.5267433243518804E+00, 0.7292491488692259E-18, 0.2483658471590867E-04, 0.2278231239253353E-04, 0.4355086546946592E+00, 0.6335396825622830E-16, 0.5560492899787359E-04, 0.8068766398366361E-04, 0.4155619327338856E+00, 0.7336406418555410E-28, 0.3220618566867426E-03, 0.1956958209756436E-03, 0.3396295360604018E+00, 0.1297676189088564E-27, 0.4121897802138222E-02, 0.2587205720417875E-02, 0.9317218785919168E-01, 0.7651950780643815E-28, 0.2826512581544380E-02, 0.2814359488753958E-02, 0.5773665727788814E-01, 0.4923437167052441E-21, 0.1821079370679042E-04, 0.2969056479875054E-04, 0.1842462732727454E-01, 0.4842851680813876E-21, 0.4217326450522519E-02, 0.5738852897157041E-02, 0.2018232369069597E-07, 0.2018232369069597E-07, 0.3702854219118327E-02, 0.7091388009151286E-02}, + info: 0, + }, + { + z: []float64{0.5196081465664333E+00, 0.1450873999446859E+00, 0.1902498073897446E+00, 0.9459083122514356E-01, 0.6971960507146802E-01, 0.2126447963850432E+00, 0.1693138701795316E-01, 0.6615449591751588E-01, 0.6671851537110856E+00, 0.7116922416084167E+00, 0.7735840319989629E+00, 0.8593705742984634E+00, 0.6060015557980403E+00, 0.1071620560007485E+00, 0.6056582690297291E+00, 0.2064801115284116E+00, 0.4992099275808294E+00, 0.9056413330105546E+00, 0.6051575714193578E+00, 0.1395071235858423E+00, 0.3386142237730057E+00, 0.2065895571122717E+00, 0.2774285740015214E-01, 0.4649920904615868E+00, 0.9062834189437683E+00, 0.3022801499192989E+00, 0.2125071125007829E+00, 0.2366624610094756E+00, 0.3232052419625674E+00, 0.5879745505340277E+00, 0.3212955913685801E+00, 0.9110441809347004E+00, 0.2144184579231917E+00, 0.5617161155671668E-01, 0.9725855527757206E+00, 0.9798782363582490E+00, 0.9666637418953663E+00, 0.1842420381101751E+00, 0.9810363127661145E+00, 0.4061071205983764E+00, 0.4929437214282740E+00, 0.3087398230344144E+00, 0.8692083335886002E+00, 0.7401065606674918E+00, 0.6829833274325647E+00, 0.9797795404622264E+00, 0.6101846761247042E+00, 0.7796537878703258E+00, 0.4568641605073986E-01, 0.1752946998854403E+00, 0.7558659638245062E+00, 0.4081915619381170E+00, 0.5344465439920063E+00, 0.3199118710728778E+00, 0.3613720388280138E+00, 0.1409062127217534E+00, 0.2811520826338662E+00, 0.9462348779627723E+00, 0.4911007415294493E+00, 0.2488061765237712E+00, 0.1661818317483100E+00, 0.1203910774987040E+00, 0.4544163143251944E+00, 0.8767242907488393E+00, 0.6688224142601292E+00, 0.2497550267789769E+00, 0.2658845545571695E+00, 0.4072601097670568E+00, 0.5517137496493807E+00, 0.4206663434956901E+00, 0.3655154771809294E+00, 0.6509199815744504E-01, 0.6480911975614350E+00, 0.1271267318339999E+00, 0.8874102966539428E+00, 0.9607257650026479E+00, 0.8902777005093224E+00, 0.7074702462790970E+00, 0.5045879991550398E+00, 0.3357826713243962E+00, 0.9303671751018463E+00, 0.3667268693834904E+00, 0.7709773173263057E+00, 0.1274123220614284E+00}, + n: 21, + zOut: []float64{0.2669666350125788E+01, 0.2458073928301015E+01, 0.1960648799383531E+01, 0.1674511937828339E+01, 0.1629444569956276E+01, 0.1605168511500282E+01, 0.1169506153633164E+01, 0.8378899015114316E+00, 0.8214470290652885E+00, 0.7290022816300561E+00, 0.5956393798847858E+00, 0.5147057006185641E+00, 0.3415078453317431E+00, 0.3316800239182673E+00, 0.2245847640277715E+00, 0.1981086483360383E+00, 0.1729134064527326E+00, 0.1081292683666610E+00, 0.4856623040087921E-01, 0.2705373732739987E-02, 0.9745444154776346E-03, 0.7298616502634276E-19, 0.4601636530183765E-14, 0.3001385089664378E-13, 0.1169506153633164E+01, 0.5522026336547083E-28, 0.9439817212889541E-12, 0.1534086358433234E-11, 0.8378899015114316E+00, 0.7174347921301560E-11, 0.1095021852663145E-10, 0.1580074435702411E-10, 0.8214470290652885E+00, 0.3131705799125763E-20, 0.2247124942125492E-10, 0.3228253356903498E-10, 0.7290022816300561E+00, 0.6063934311659721E-18, 0.3794147471177530E-13, 0.3318524623173314E-12, 0.5956393798847858E+00, 0.3765687391680646E-13, 0.1809487464842083E+02, 0.1809487464842083E+02, 0.1050000000000000E+03, 0.3215419501133787E+01, 0.3809523809523809E+01, 0.2077325438490571E-07, 0.3415078453317431E+00, 0.1645262238367970E-20, 0.7912752069326401E-07, 0.6053132028546428E-07, 0.3316800239182673E+00, 0.4184118241292247E-26, 0.1343987419983520E-06, 0.1754397466154310E-06, 0.2245847640277715E+00, 0.3340387958036406E-22, 0.6150231447604006E-06, 0.4780001259056422E-06, 0.1981086483360383E+00, 0.1070733604161610E-20, 0.1003229473607176E-05, 0.1287291281183416E-05, 0.1729134064527326E+00, 0.1298955481663118E-20, 0.1611116216931278E-05, 0.3807035614938680E-06, 0.1081292683666610E+00, 0.4901279578837721E-23, 0.3565927169328702E-03, 0.2312261838015572E-03, 0.4856623040087921E-01, 0.3325573155747123E-13, 0.4389787505319806E-03, 0.9715248586459800E-03, 0.2705373732739987E-02, 0.1348432029845013E-20, 0.7371401467208961E-04, 0.2975668602269332E-04, 0.9745444154776346E-03, 0.4135903062570168E-24, 0.7273370201297700E-04, 0.3602244970122637E-04}, + info: 0, + }, + { + z: []float64{0.3441168249350421E+00, 0.7064572711980356E+00, 0.6589781374655990E+00, 0.8687841598825752E+00, 0.7811747459515918E+00, 0.7470750719206745E+00, 0.7591454338662803E+00, 0.7956934079357347E-01, 0.3416983743372617E+00, 0.3365394610260509E+00, 0.8635365040683821E+00, 0.4793906833418223E+00, 0.9394584418725971E+00, 0.7354375226759881E+00, 0.3959912256877245E+00, 0.4088558388864650E+00, 0.6899389113237457E+00, 0.6329180251180861E+00, 0.6760812245614891E+00, 0.1743991444245150E+00, 0.3881927716152306E+00, 0.2103848624556167E+00, 0.5309784956583943E+00, 0.5758384660199964E+00, 0.6542468116269122E+00, 0.2141275453071043E+00, 0.4917208240158387E+00, 0.6996271491850585E+00, 0.7074081025976766E+00, 0.1896811377589238E+00, 0.4872676647104760E+00, 0.8987347035581787E+00, 0.1651654313203957E+00, 0.7969431328829826E+00, 0.8979672856778195E+00, 0.2621352236509209E+00, 0.2994430908669790E+00, 0.8412000921937168E+00, 0.6910228781616401E-01, 0.9849719192333963E+00, 0.2835195798153757E+00, 0.6126955834278749E+00, 0.9957514180764350E+00, 0.4133859474205875E+00, 0.2126790023013077E+00, 0.9230696247878700E-01, 0.5165813646587417E+00, 0.9232126059423650E+00, 0.6160486127374017E+00, 0.5529065454633691E+00, 0.6862175458708878E+00, 0.2677675454795836E-01, 0.6729513992144193E+00, 0.8612993184178528E+00, 0.5455358966165057E+00, 0.2518716982253303E+00, 0.5312849864208884E+00, 0.7551228210749875E+00, 0.1095520838657484E+00, 0.8767983608629261E+00, 0.9578119141004069E+00, 0.6878921114137557E+00, 0.2890574974795965E+00, 0.9851780344062913E+00, 0.9392886821673129E+00, 0.4125982690623264E+00, 0.6817912182549608E+00, 0.7805388095263401E+00, 0.1567802887930034E+00, 0.1901362770322003E+00, 0.5155717108920093E+00, 0.5470641908290981E+00, 0.9496522047623522E+00, 0.4367251554723609E+00, 0.7016249991347693E+00, 0.6652534390290816E+00, 0.3892590437090979E+00, 0.1464591367640408E+00, 0.9179795596761495E+00, 0.1527313083317114E+00, 0.8661173016992874E+00, 0.8044520995141484E+00, 0.4399581275677011E+00, 0.6590078920726725E+00}, + n: 21, + zOut: []float64{0.2654671686308588E+01, 0.2409077903364995E+01, 0.2090082174851482E+01, 0.1940605709090538E+01, 0.1909776782011245E+01, 0.1629990303184568E+01, 0.1566043989638403E+01, 0.1473218419964192E+01, 0.1321200673977518E+01, 0.1275771383585936E+01, 0.9826159405158056E+00, 0.8184731809209335E+00, 0.6715230178331039E+00, 0.5669018352800101E+00, 0.3641671875118937E+00, 0.2699135892930649E+00, 0.1446269090001342E+00, 0.8937359624216266E-01, 0.5860931848549461E-01, 0.3094108728329079E-01, 0.6182329613034853E-03, 0.9233403587623171E-22, 0.2552413399194827E-12, 0.1309204970235786E-12, 0.1566043989638403E+01, 0.2003762315848454E-18, 0.9222125989396634E-12, 0.1831545934750265E-11, 0.1473218419964192E+01, 0.1899959664962892E-11, 0.5682525570474145E-10, 0.1113952503246639E-09, 0.1321200673977518E+01, 0.5311918312726658E-16, 0.2115322762070563E-08, 0.1208354514490733E-08, 0.1275771383585936E+01, 0.1424261829852281E-16, 0.6059411460508015E-08, 0.1032477558436010E-07, 0.9826159405158056E+00, 0.5397353496908506E-22, 0.2226820292130466E+02, 0.2226820292130466E+02, 0.9500000000000000E+02, 0.2927437641723356E+01, 0.1052631578947368E+01, 0.2555943178691847E-06, 0.6715230178331039E+00, 0.1218922493912602E-18, 0.4789189736721279E-06, 0.5466231772857101E-06, 0.5669018352800101E+00, 0.1893266172530428E-27, 0.9952011217509916E-06, 0.1128113648538554E-05, 0.3641671875118937E+00, 0.1993230626440035E-24, 0.2427606592544749E-05, 0.2156829827516489E-05, 0.2699135892930649E+00, 0.2761013168273541E-29, 0.3900010091178873E-05, 0.3393761026267541E-05, 0.1446269090001342E+00, 0.2150416673893778E-15, 0.8242388755752233E-05, 0.1105863902029246E-04, 0.8937359624216266E-01, 0.2934562567422164E-27, 0.3455780897358792E-04, 0.2250328346305790E-04, 0.5860931848549461E-01, 0.8147325136863849E-21, 0.2346512312055719E-04, 0.8962661529405173E-05, 0.3094108728329079E-01, 0.2460979885389816E-17, 0.5238375287742530E-03, 0.1080192509223090E-02, 0.6182329613034853E-03, 0.8383483586160605E-23, 0.7400552677463828E-02, 0.1581674273722876E-01}, + info: 0, + }, + { + z: []float64{0.7940281584071446E+00, 0.8540600349699839E+00, 0.8158431165852809E-01, 0.5431841788581357E+00, 0.3696613346727944E+00, 0.2343742079469738E+00, 0.4891909888056500E-01, 0.6769876984160987E+00, 0.4777767465052760E+00, 0.1867381312399053E+00, 0.2018744873845245E+00, 0.5511201479607295E+00, 0.6938788283912793E+00, 0.8167542438070282E+00, 0.7904606414789531E+00, 0.9443564310071292E+00, 0.7287247677237652E-01, 0.8645122013586991E+00, 0.1884651475116826E+00, 0.3844755283611681E+00, 0.9959264361467982E+00, 0.6424370932833342E+00, 0.1972122925077952E+00, 0.2842024247377670E+00, 0.9819646913482807E+00, 0.9118347224008859E+00, 0.8184691845197246E+00, 0.7051587281589254E+00, 0.7604703230109544E+00, 0.6312964755149379E+00, 0.5240863862347888E+00, 0.3442050916384676E-01, 0.2415614308212055E+00, 0.2814868323669945E+00, 0.6529284673126197E+00, 0.3727305084153835E+00, 0.5033733868757848E+00, 0.2317122058804952E+00, 0.7555584130128312E+00, 0.5854566742645219E+00, 0.5481204696337160E+00, 0.8479425268049923E+00, 0.2310874615764000E+00, 0.1250993726775007E-01, 0.6243285982203539E-01, 0.8533587246073391E+00, 0.9203815588639257E+00, 0.9256849509751471E+00, 0.6691405057262187E+00, 0.8847091531299658E+00, 0.6783572983386376E+00, 0.4701257141291857E+00, 0.8976078424378102E+00, 0.8575018884445876E+00, 0.4119363561363949E+00, 0.2824477027676924E+00, 0.2787507690368071E+00, 0.7994878185780909E+00, 0.6141832897278305E+00, 0.6772728066124333E+00, 0.1568652581579784E+00, 0.8025492691231176E+00, 0.2609459151100056E+00, 0.4956700691019098E+00, 0.1008839464621498E+00, 0.6129709499983976E+00, 0.4551038858718992E-02, 0.8382785474023564E+00, 0.9327452694814308E+00, 0.9710431593941808E+00, 0.3785578217695214E+00, 0.9620839159000718E+00, 0.3183561960196257E-01, 0.9167635157854341E+00, 0.8989971039988554E+00, 0.2723769512210017E-01, 0.4176537489735596E+00, 0.9619881273217982E+00, 0.8761769579995293E+00, 0.6385245520487358E+00, 0.6821739872929905E+00, 0.3927943300877799E+00, 0.3299501391296433E-01, 0.6026481165267817E+00}, + n: 21, + zOut: []float64{0.2841529467847260E+01, 0.2556740368064117E+01, 0.2029069210305357E+01, 0.1816492749229813E+01, 0.1807397947918166E+01, 0.1724050761249482E+01, 0.1394683696862690E+01, 0.1363282300837870E+01, 0.1235317529564993E+01, 0.1007821728138393E+01, 0.9728972767837659E+00, 0.8110838192609224E+00, 0.6190683239156912E+00, 0.3314348466978195E+00, 0.2969816495631171E+00, 0.2506421226611442E+00, 0.1551624233480766E+00, 0.1141049603637759E+00, 0.6806098279643324E-01, 0.4065442795375918E-01, 0.1509783792061944E-04, 0.2745446733802996E-19, 0.2334033424405603E-14, 0.7232047343832039E-15, 0.1394683696862690E+01, 0.7652022750203868E-17, 0.1502464319787860E-09, 0.5990324067027169E-10, 0.1363282300837870E+01, 0.5511008105786353E-19, 0.1215529748555577E-07, 0.3576186028975079E-08, 0.1235317529564993E+01, 0.6271335389136957E-17, 0.2589527811059762E-05, 0.3563684464760320E-05, 0.1007821728138393E+01, 0.6928731028484552E-15, 0.2286607739649456E-04, 0.2916328836696281E-04, 0.9728972767837659E+00, 0.4013724285764508E-25, 0.2143649169120057E+02, 0.2143649169120056E+02, 0.1080000000000000E+03, 0.3174603174603174E+01, 0.5555555555555555E+01, 0.5006788488237952E-04, 0.6190683239156912E+00, 0.1272779738919789E-24, 0.5392273695714327E-05, 0.6586751690782050E-05, 0.3314348466978195E+00, 0.9952016744778614E-24, 0.4588114650322476E-05, 0.4104030919118472E-05, 0.2969816495631171E+00, 0.1254277227268884E-20, 0.1579210272170037E-05, 0.2523508055026877E-05, 0.2506421226611442E+00, 0.1514835081255253E-22, 0.9117975197333799E-05, 0.1415311657319248E-04, 0.1551624233480766E+00, 0.3272195034856757E-26, 0.3128414626489953E-04, 0.4770966856082524E-04, 0.1141049603637759E+00, 0.7575261888623807E-20, 0.6277758538102519E-05, 0.4644422903178713E-05, 0.6806098279643324E-01, 0.3715389965619895E-21, 0.5956965112658162E-05, 0.4447744978930882E-05, 0.4065442795375918E-01, 0.1972152263052530E-30, 0.2965586553650948E-04, 0.1900611263569203E-04, 0.1509783792061944E-04, 0.1009741958682895E-26, 0.1608958133772104E-02, 0.9583670521235791E-03}, + info: 0, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + + info := impl.Dlasq2(test.n, z) + if !floats.EqualApprox(test.zOut, z, dTol) { + diff := make([]float64, len(z)) + floats.SubTo(diff, z, test.zOut) + for i := range diff { + diff[i] = math.Abs(diff[i]) + } + t.Errorf("Case %v, Z Mismatch", c) + } + if test.info != info { + t.Errorf("Info mismatch. Want %v, got %v", test.info, info) + } + } + + rnd := rand.New(rand.NewSource(1)) + // Perform a bunch of random tests to check for access out of bounds or + // infinite loops. + // TODO(btracey): Implement direct tests. + // bi := blas64.Implementation() + for _, n := range []int{5, 8, 20, 25} { + for k := 0; k < 10; k++ { + z := make([]float64, 4*n) + for i := range z { + z[i] = rnd.Float64() + } + zCopy := make([]float64, len(z)) + copy(zCopy, z) + + // Compute the eigenvalues + impl.Dlasq2(n, z) + + // Below is the code to test the eigenvalues. Eventually implement + // real tests. + // The code below is missing the transformation from L and U into + // the symmetric tridiagonal matrix. + // See discussion http://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=5&t=4839 + // for format. + + /* + ldl := n + ldu := n + u := make([]float64, n*n) + for i := 0; i < n; i++ { + u[i*ldu+i] = zCopy[2*i] + if i != n-1 { + u[i*ldu+i+1] = 1 + } + } + l := make([]float64, n*n) + for i := 0; i < n; i++ { + l[i*ldl+i] = 1 + if i != n-1 { + l[(i+1)*ldl+i] = zCopy[2*i+1] + } + } + + ldTriDi := n + triDi := make([]float64, n*n) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, l, ldl, u, ldu, 0, triDi, ldTriDi) + + tridi2 := make([]float64, n*n) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, triDi, n, triDi, n, 0, tridi2, n) + + // Eigenvalues have the property that det(A - lambda I ) = 0 + triDiCopy := make([]float64, len(triDi)) + copy(triDiCopy, triDi) + for _, lambda := range z[1:n] { + copy(triDi, triDiCopy) + for i := 0; i < n; i++ { + triDi[i*n+i] -= lambda + } + + // Compute LU + //ipiv := make([]int, n) + //impl.Dgetrf(n, n, triDi, n, ipiv) + ok := impl.Dpotrf(blas.Upper, n, triDi, n) + fmt.Println(ok) + + var det float64 + for i := 0; i < n; i++ { + det += math.Log(math.Abs(triDi[i*n+i])) + } + fmt.Println("det = ", math.Exp(det)) + } + */ + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq3.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq3.go new file mode 100644 index 00000000..f48bad17 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq3.go @@ -0,0 +1,2703 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasq3er interface { + Dlasq3(i0, n0 int, z []float64, pp int, dmin, sigma, desig, qmax float64, nFail, iter, nDiv int, ttype int, dmin1, dmin2, dn, dn1, dn2, g, tau float64) ( + i0Out, n0Out, ppOut int, dminOut, sigmaOut, desigOut, qmaxOut float64, nFailOut, iterOut, nDivOut, ttypeOut int, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64) +} + +type dlasq3teststruct struct { + z []float64 + i0, n0, pp int + dmin, desig, sigma, qmax float64 + nFail, iter, nDiv, ttype int + dmin1, dmin2, dn, dn1, dn2, g, tau float64 + + zOut []float64 + i0Out, n0Out, ppOut int + dminOut, desigOut, sigmaOut, qmaxOut float64 + nFailOut, iterOut, nDivOut, ttypeOut int + dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64 +} + +func Dlasq3Test(t *testing.T, impl Dlasq3er) { + dTol := 1e-14 + // Tests computed from calling the netlib Dlasq + for _, test := range []dlasq3teststruct{ + { + i0: 1, + n0: 21, + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + pp: 0, + dmin: -0.0000000000000000, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: 0, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 2, + sigma: 0.0000000000000000, + nDiv: 40, + zOut: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 2.1175426017541180E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 3, + nDivOut: 62, + ttypeOut: -1, + dmin1Out: 4.4311601260836921E-002, + dmin2Out: 4.4311601260836921E-002, + dnOut: 2.1175426017541180E-005, + dn1Out: 0.33915960483100382, + dn2Out: 0.16428924199195991, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03}, + pp: 1, + dmin: 2.1175426017541180E-005, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -1, + dmin1: 4.4311601260836921E-002, + dmin2: 4.4311601260836921E-002, + dn: 2.1175426017541180E-005, + dn1: 0.33915960483100382, + dn2: 0.16428924199195991, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 3, + sigma: 0.0000000000000000, + nDiv: 62, + zOut: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 2.1175425069176302E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 4, + nDivOut: 84, + ttypeOut: -4, + dmin1Out: 2.9944624525135358E-002, + dmin2Out: 2.9944624525135358E-002, + dnOut: 2.1175425069176302E-005, + dn1Out: 7.2928780948497918E-002, + dn2Out: 0.16065460645225654, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + pp: 0, + dmin: 2.1175425069176302E-005, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -4, + dmin1: 2.9944624525135358E-002, + dmin2: 2.9944624525135358E-002, + dn: 2.1175425069176302E-005, + dn1: 7.2928780948497918E-002, + dn2: 0.16065460645225654, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 4, + sigma: 0.0000000000000000, + nDiv: 84, + zOut: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 1.1127325659669794E-010, + desigOut: 0.0000000000000000, + sigmaOut: 2.1175313795360271E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 5, + nDivOut: 106, + ttypeOut: -4, + dmin1Out: 3.1433071595911154E-002, + dmin2Out: 3.1433071595911154E-002, + dnOut: 1.1127325659669794E-010, + dn1Out: 3.5896964560873705E-002, + dn2Out: 0.25842281720128102, + gOut: 0.0000000000000000, + tauOut: 2.1175313795360271E-005, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03}, + pp: 1, + dmin: 1.1127325659669794E-010, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -4, + dmin1: 3.1433071595911154E-002, + dmin2: 3.1433071595911154E-002, + dn: 1.1127325659669794E-010, + dn1: 3.5896964560873705E-002, + dn2: 0.25842281720128102, + g: 0.0000000000000000, + tau: 2.1175313795360271E-005, + nFail: 0, + iter: 5, + sigma: 2.1175313795360271E-005, + nDiv: 106, + zOut: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 0.0000000000000000, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 7, + nDivOut: 150, + ttypeOut: -15, + dmin1Out: 2.9139336744737766E-002, + dmin2Out: 4.9426557292086552E-002, + dnOut: -2.0808762284537102E-024, + dn1Out: 2.9139336744737766E-002, + dn2Out: 0.15959234211062134, + gOut: 0.0000000000000000, + tauOut: 1.1127325659669789E-010, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + pp: 0, + dmin: 0.0000000000000000, + desig: -5.1698788284564230E-026, + qmax: 2.1637041623952107, + ttype: -15, + dmin1: 2.9139336744737766E-002, + dmin2: 4.9426557292086552E-002, + dn: -2.0808762284537102E-024, + dn1: 2.9139336744737766E-002, + dn2: 0.15959234211062134, + g: 0.0000000000000000, + tau: 1.1127325659669789E-010, + nFail: 1, + iter: 7, + sigma: 2.1175425068616867E-005, + nDiv: 150, + zOut: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 0.0000000000000000, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 8, + nDivOut: 172, + ttypeOut: -1, + dmin1Out: 2.7016889331018056E-002, + dmin2Out: 5.3061698118516694E-002, + dnOut: 0.0000000000000000, + dn1Out: 2.7016889331018056E-002, + dn2Out: 8.6018658784156071E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 0.0000000000000000, + desig: -5.1698788284564230E-026, + qmax: 2.1637041623952107, + ttype: -1, + dmin1: 2.7016889331018056E-002, + dmin2: 5.3061698118516694E-002, + dn: 0.0000000000000000, + dn1: 2.7016889331018056E-002, + dn2: 8.6018658784156071E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 1, + iter: 8, + sigma: 2.1175425068616867E-005, + nDiv: 172, + zOut: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.0000000000000000E+00, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 2.5763383633962696E-002, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 9, + nDivOut: 193, + ttypeOut: -1, + dmin1Out: 4.3622798915905092E-002, + dmin2Out: 7.4536672467372611E-002, + dnOut: 2.5763383633962696E-002, + dn1Out: 4.3622798915905092E-002, + dn2Out: 9.8141518071882677E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 2.5763383633962696E-002, + desig: -5.1698788284564230E-026, + qmax: 2.4715692224139039, + ttype: -1, + dmin1: 4.3622798915905092E-002, + dmin2: 7.4536672467372611E-002, + dn: 2.5763383633962696E-002, + dn1: 4.3622798915905092E-002, + dn2: 9.8141518071882677E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 1, + iter: 9, + sigma: 2.1175425068616867E-005, + nDiv: 193, + zOut: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 1.8576185384092288E-002, + desigOut: 2.6427422784455342E-019, + sigmaOut: 5.0413140237881371E-003, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 11, + nDivOut: 235, + ttypeOut: -15, + dmin1Out: 1.8576185384092288E-002, + dmin2Out: 5.2365600435162571E-002, + dnOut: 1.9114649409197451E-002, + dn1Out: 1.8576185384092288E-002, + dn2Out: 5.2365600435162571E-002, + gOut: 0.0000000000000000, + tauOut: 5.0201385987195205E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.8576185384092288E-002, + desig: 2.6427422784455342E-019, + qmax: 2.4715692224139039, + ttype: -15, + dmin1: 1.8576185384092288E-002, + dmin2: 5.2365600435162571E-002, + dn: 1.9114649409197451E-002, + dn1: 1.8576185384092288E-002, + dn2: 5.2365600435162571E-002, + g: 0.0000000000000000, + tau: 5.0201385987195205E-003, + nFail: 2, + iter: 11, + sigma: 5.0413140237881371E-003, + nDiv: 235, + zOut: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 9.5622848228283271E-003, + desigOut: -6.0308751014385013E-019, + sigmaOut: 1.0518227355316156E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 12, + nDivOut: 256, + ttypeOut: -4, + dmin1Out: 9.5622848228283271E-003, + dmin2Out: 6.9533978479808370E-002, + dnOut: 1.0856003705186750E-002, + dn1Out: 9.5622848228283271E-003, + dn2Out: 6.9533978479808370E-002, + gOut: 0.0000000000000000, + tauOut: 5.4769133315280185E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 9.5622848228283271E-003, + desig: -6.0308751014385013E-019, + qmax: 2.4715692224139039, + ttype: -4, + dmin1: 9.5622848228283271E-003, + dmin2: 6.9533978479808370E-002, + dn: 1.0856003705186750E-002, + dn1: 9.5622848228283271E-003, + dn2: 6.9533978479808370E-002, + g: 0.0000000000000000, + tau: 5.4769133315280185E-003, + nFail: 2, + iter: 12, + sigma: 1.0518227355316156E-002, + nDiv: 256, + zOut: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 2.0601312480394186E-003, + desigOut: 0.0000000000000000, + sigmaOut: 1.5639833716481661E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 13, + nDivOut: 277, + ttypeOut: -4, + dmin1Out: 5.4371870398960158E-003, + dmin2Out: 8.0023511442426670E-002, + dnOut: 2.0601312480394186E-003, + dn1Out: 5.4371870398960158E-003, + dn2Out: 8.0023511442426670E-002, + gOut: 0.0000000000000000, + tauOut: 5.1216063611655054E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.0601312480394186E-003, + desig: 0.0000000000000000, + qmax: 2.4715692224139039, + ttype: -4, + dmin1: 5.4371870398960158E-003, + dmin2: 8.0023511442426670E-002, + dn: 2.0601312480394186E-003, + dn1: 5.4371870398960158E-003, + dn2: 8.0023511442426670E-002, + g: 0.0000000000000000, + tau: 5.1216063611655054E-003, + nFail: 2, + iter: 13, + sigma: 1.5639833716481661E-002, + nDiv: 277, + zOut: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.0731361153288982E-005, + desigOut: 1.7347234759768071E-018, + sigmaOut: 1.6921621533398150E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 14, + nDivOut: 298, + ttypeOut: -2, + dmin1Out: 6.8738708636769136E-003, + dmin2Out: 8.1489512892123819E-002, + dnOut: 6.0731361153288982E-005, + dn1Out: 6.8738708636769136E-003, + dn2Out: 8.1489512892123819E-002, + gOut: 0.0000000000000000, + tauOut: 1.2817878169164906E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.0731361153288982E-005, + desig: 1.7347234759768071E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.8738708636769136E-003, + dmin2: 8.1489512892123819E-002, + dn: 6.0731361153288982E-005, + dn1: 6.8738708636769136E-003, + dn2: 8.1489512892123819E-002, + g: 0.0000000000000000, + tau: 1.2817878169164906E-003, + nFail: 2, + iter: 14, + sigma: 1.6921621533398150E-002, + nDiv: 298, + zOut: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 3.1568086081919418E-009, + desigOut: 4.7433845046240819E-020, + sigmaOut: 1.6978458774649190E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 15, + nDivOut: 319, + ttypeOut: -2, + dmin1Out: 1.0483100129151506E-002, + dmin2Out: 8.1316774559040517E-002, + dnOut: 3.1568086081919418E-009, + dn1Out: 1.0483100129151506E-002, + dn2Out: 8.1316774559040517E-002, + gOut: 0.0000000000000000, + tauOut: 5.6837241251038845E-005, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 3.1568086081919418E-009, + desig: 4.7433845046240819E-020, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.0483100129151506E-002, + dmin2: 8.1316774559040517E-002, + dn: 3.1568086081919418E-009, + dn1: 1.0483100129151506E-002, + dn2: 8.1316774559040517E-002, + g: 0.0000000000000000, + tau: 5.6837241251038845E-005, + nFail: 2, + iter: 15, + sigma: 1.6978458774649190E-002, + nDiv: 319, + zOut: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.9684975813366743E-017, + desigOut: 1.5445815365207740E-018, + sigmaOut: 1.6978461930361368E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 16, + nDivOut: 340, + ttypeOut: -2, + dmin1Out: 1.1199576261102989E-002, + dmin2Out: 8.1067607231828140E-002, + dnOut: 6.9684975813366743E-017, + dn1Out: 1.1199576261102989E-002, + dn2Out: 8.1067607231828140E-002, + gOut: 0.0000000000000000, + tauOut: 3.1557121791797713E-009, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.9684975813366743E-017, + desig: 1.5445815365207740E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1199576261102989E-002, + dmin2: 8.1067607231828140E-002, + dn: 6.9684975813366743E-017, + dn1: 1.1199576261102989E-002, + dn2: 8.1067607231828140E-002, + g: 0.0000000000000000, + tau: 3.1557121791797713E-009, + nFail: 2, + iter: 16, + sigma: 1.6978461930361368E-002, + nDiv: 340, + zOut: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 6.1629758220391547E-032, + desigOut: -1.6288286479578371E-018, + sigmaOut: 1.6978461930361441E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 17, + nDivOut: 361, + ttypeOut: -2, + dmin1Out: 1.1203310405167735E-002, + dmin2Out: 8.0927116373146771E-002, + dnOut: 6.1629758220391547E-032, + dn1Out: 1.1203310405167735E-002, + dn2Out: 8.0927116373146771E-002, + gOut: 0.0000000000000000, + tauOut: 6.9684975806547287E-017, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 6.1629758220391547E-032, + desig: -1.6288286479578371E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1203310405167735E-002, + dmin2: 8.0927116373146771E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203310405167735E-002, + dn2: 8.0927116373146771E-002, + g: 0.0000000000000000, + tau: 6.9684975806547287E-017, + nFail: 2, + iter: 17, + sigma: 1.6978461930361441E-002, + nDiv: 361, + zOut: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26, 0.6162975822039155E-31, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.1629758220391547E-032, + desigOut: -1.6288286479578371E-018, + sigmaOut: 1.6978461930361441E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 18, + nDivOut: 382, + ttypeOut: -2, + dmin1Out: 1.1203288675083998E-002, + dmin2Out: 8.0846453894262649E-002, + dnOut: 6.1629758220391547E-032, + dn1Out: 1.1203288675083998E-002, + dn2Out: 8.0846453894262649E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26, 0.6162975822039155E-31, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.1629758220391547E-032, + desig: -1.6288286479578371E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1203288675083998E-002, + dmin2: 8.0846453894262649E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203288675083998E-002, + dn2: 8.0846453894262649E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 18, + sigma: 1.6978461930361441E-002, + nDiv: 382, + zOut: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 8.9043085058082561E-010, + desigOut: 1.7347234759768071E-018, + sigmaOut: 2.8181746216274728E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 19, + nDivOut: 402, + ttypeOut: -7, + dmin1Out: 6.9585227169791292E-002, + dmin2Out: 0.11373841371027797, + dnOut: 8.9043085058082561E-010, + dn1Out: 6.9585227169791292E-002, + dn2Out: 0.11373841371027797, + gOut: 0.0000000000000000, + tauOut: 1.1203284285913290E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9043085058082561E-010, + desig: 1.7347234759768071E-018, + qmax: 2.4715692224139039, + ttype: -7, + dmin1: 6.9585227169791292E-002, + dmin2: 0.11373841371027797, + dn: 8.9043085058082561E-010, + dn1: 6.9585227169791292E-002, + dn2: 0.11373841371027797, + g: 0.0000000000000000, + tau: 1.1203284285913290E-002, + nFail: 2, + iter: 19, + sigma: 2.8181746216274728E-002, + nDiv: 402, + zOut: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.3962105636374437E-019, + desigOut: -1.5687885635568321E-018, + sigmaOut: 2.8181747106705537E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 20, + nDivOut: 422, + ttypeOut: -2, + dmin1Out: 6.9544122471813200E-002, + dmin2Out: 9.8247027562672340E-002, + dnOut: 1.3962105636374437E-019, + dn1Out: 6.9544122471813200E-002, + dn2Out: 9.8247027562672340E-002, + gOut: 0.0000000000000000, + tauOut: 8.9043080564395014E-010, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.3962105636374437E-019, + desig: -1.5687885635568321E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.9544122471813200E-002, + dmin2: 9.8247027562672340E-002, + dn: 1.3962105636374437E-019, + dn1: 6.9544122471813200E-002, + dn2: 9.8247027562672340E-002, + g: 0.0000000000000000, + tau: 8.9043080564395014E-010, + nFail: 2, + iter: 20, + sigma: 2.8181747106705537E-002, + nDiv: 422, + zOut: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.1396210563637444E-18, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.3962105636374430E-019, + desigOut: -1.5687885635568321E-018, + sigmaOut: 2.8181747106705537E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 21, + nDivOut: 442, + ttypeOut: -2, + dmin1Out: 6.9512134440652351E-002, + dmin2Out: 8.9358776708560295E-002, + dnOut: 1.3962105636374430E-019, + dn1Out: 6.9512134440652351E-002, + dn2Out: 8.9358776708560295E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.1396210563637444E-18, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.3962105636374430E-019, + desig: -1.5687885635568321E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.9512134440652351E-002, + dmin2: 8.9358776708560295E-002, + dn: 1.3962105636374430E-019, + dn1: 6.9512134440652351E-002, + dn2: 8.9358776708560295E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 21, + sigma: 2.8181747106705537E-002, + nDiv: 442, + zOut: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.8997910999570377E-34, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 1.2643548659038301E-003, + desigOut: -5.0382355155104463E-018, + sigmaOut: 9.6270319212300656E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 22, + nDivOut: 461, + ttypeOut: -8, + dmin1Out: 1.3935943135754067E-002, + dmin2Out: 9.9495800084882416E-002, + dnOut: 1.2643548659038301E-003, + dn1Out: 1.3935943135754067E-002, + dn2Out: 9.9495800084882416E-002, + gOut: 0.0000000000000000, + tauOut: 6.8088572105595116E-002, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.2643548659038301E-003, + desig: -5.0382355155104463E-018, + qmax: 2.3847059974280183, + ttype: -8, + dmin1: 1.3935943135754067E-002, + dmin2: 9.9495800084882416E-002, + dn: 1.2643548659038301E-003, + dn1: 1.3935943135754067E-002, + dn2: 9.9495800084882416E-002, + g: 0.0000000000000000, + tau: 6.8088572105595116E-002, + nFail: 2, + iter: 22, + sigma: 9.6270319212300656E-002, + nDiv: 461, + zOut: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 0, + dminOut: 1.2236274461701734E-006, + desigOut: -3.2526065174565133E-018, + sigmaOut: 9.7516636666659787E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 23, + nDivOut: 480, + ttypeOut: -2, + dmin1Out: 1.1812799375517376E-002, + dmin2Out: 0.10597947881780349, + dnOut: 1.2236274461701734E-006, + dn1Out: 1.1812799375517376E-002, + dn2Out: 0.10597947881780349, + gOut: 0.0000000000000000, + tauOut: 1.2463174543591322E-003, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.2236274461701734E-006, + desig: -3.2526065174565133E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1812799375517376E-002, + dmin2: 0.10597947881780349, + dn: 1.2236274461701734E-006, + dn1: 1.1812799375517376E-002, + dn2: 0.10597947881780349, + g: 0.0000000000000000, + tau: 1.2463174543591322E-003, + nFail: 2, + iter: 23, + sigma: 9.7516636666659787E-002, + nDiv: 480, + zOut: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 9.5986727915820745E-012, + desigOut: 6.4755668817591261E-018, + sigmaOut: 9.7517858554454467E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 24, + nDivOut: 499, + ttypeOut: -2, + dmin1Out: 1.1875197612370336E-002, + dmin2Out: 0.11291768719739126, + dnOut: 9.5986727915820745E-012, + dn1Out: 1.1875197612370336E-002, + dn2Out: 0.11291768719739126, + gOut: 0.0000000000000000, + tauOut: 1.2218877946904154E-006, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 9.5986727915820745E-012, + desig: 6.4755668817591261E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1875197612370336E-002, + dmin2: 0.11291768719739126, + dn: 9.5986727915820745E-012, + dn1: 1.1875197612370336E-002, + dn2: 0.11291768719739126, + g: 0.0000000000000000, + tau: 1.2218877946904154E-006, + nFail: 2, + iter: 24, + sigma: 9.7517858554454467E-002, + nDiv: 499, + zOut: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 0, + dminOut: 6.6174125886815435E-022, + desigOut: -5.0906815225379586E-018, + sigmaOut: 9.7517858564053150E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 25, + nDivOut: 518, + ttypeOut: -2, + dmin1Out: 1.1882019541390456E-002, + dmin2Out: 0.11366976186212303, + dnOut: 6.6174125886815435E-022, + dn1Out: 1.1882019541390456E-002, + dn2Out: 0.11366976186212303, + gOut: 0.0000000000000000, + tauOut: 9.5986713933289272E-012, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 6.6174125886815435E-022, + desig: -5.0906815225379586E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1882019541390456E-002, + dmin2: 0.11366976186212303, + dn: 6.6174125886815435E-022, + dn1: 1.1882019541390456E-002, + dn2: 0.11366976186212303, + g: 0.0000000000000000, + tau: 9.5986713933289272E-012, + nFail: 2, + iter: 25, + sigma: 9.7517858564053150E-002, + nDiv: 518, + zOut: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17, 0.6617412588681543E-21, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 6.6174125886815426E-022, + desigOut: -5.0906815225379586E-018, + sigmaOut: 9.7517858564053150E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 26, + nDivOut: 537, + ttypeOut: -2, + dmin1Out: 1.1880977265773463E-002, + dmin2Out: 0.11370904624558997, + dnOut: 6.6174125886815426E-022, + dn1Out: 1.1880977265773463E-002, + dn2Out: 0.11370904624558997, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17, 0.6617412588681543E-21, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.6174125886815426E-022, + desig: -5.0906815225379586E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1880977265773463E-002, + dmin2: 0.11370904624558997, + dn: 6.6174125886815426E-022, + dn1: 1.1880977265773463E-002, + dn2: 0.11370904624558997, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 26, + sigma: 9.7517858564053150E-002, + nDiv: 537, + zOut: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 0, + dminOut: 2.3287035572430725E-008, + desigOut: 1.7347234759768071E-018, + sigmaOut: 0.10939869071976092, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 27, + nDivOut: 555, + ttypeOut: -7, + dmin1Out: 0.10181720511285566, + dmin2Out: 0.30482311636216664, + dnOut: 2.3287035572430725E-008, + dn1Out: 0.10181720511285566, + dn2Out: 0.30482311636216664, + gOut: 0.0000000000000000, + tauOut: 1.1880832155707781E-002, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.3287035572430725E-008, + desig: 1.7347234759768071E-018, + qmax: 2.3847059974280183, + ttype: -7, + dmin1: 0.10181720511285566, + dmin2: 0.30482311636216664, + dn: 2.3287035572430725E-008, + dn1: 0.10181720511285566, + dn2: 0.30482311636216664, + g: 0.0000000000000000, + tau: 1.1880832155707781E-002, + nFail: 2, + iter: 27, + sigma: 0.10939869071976092, + nDiv: 555, + zOut: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 1, + dminOut: 2.6961654281145418E-018, + desigOut: -3.8251180717391650E-018, + sigmaOut: 0.10939871400676864, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 28, + nDivOut: 573, + ttypeOut: -2, + dmin1Out: 0.10181121275944585, + dmin2Out: 0.30487633314418217, + dnOut: 2.6961654281145418E-018, + dn1Out: 0.10181121275944585, + dn2Out: 0.30487633314418217, + gOut: 0.0000000000000000, + tauOut: 2.3287007705477136E-008, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 2.6961654281145418E-018, + desig: -3.8251180717391650E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 0.10181121275944585, + dmin2: 0.30487633314418217, + dn: 2.6961654281145418E-018, + dn1: 0.10181121275944585, + dn2: 0.30487633314418217, + g: 0.0000000000000000, + tau: 2.3287007705477136E-008, + nFail: 2, + iter: 28, + sigma: 0.10939871400676864, + nDiv: 573, + zOut: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.2696165428114542E-17, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 0, + dminOut: 2.6961654281138038E-018, + desigOut: -3.8251180717391650E-018, + sigmaOut: 0.10939871400676864, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 29, + nDivOut: 591, + ttypeOut: -2, + dmin1Out: 0.10180899282350273, + dmin2Out: 0.30489636738914000, + dnOut: 2.6961654281138038E-018, + dn1Out: 0.10180899282350273, + dn2Out: 0.30489636738914000, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.2696165428114542E-17, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.6961654281138038E-018, + desig: -3.8251180717391650E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 0.10180899282350273, + dmin2: 0.30489636738914000, + dn: 2.6961654281138038E-018, + dn1: 0.10180899282350273, + dn2: 0.30489636738914000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 29, + sigma: 0.10939871400676864, + nDiv: 591, + zOut: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.7379175991216932E-30, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 1, + dminOut: 1.3142485785350155E-006, + desigOut: 0.0000000000000000, + sigmaOut: 0.21120521870940451, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 30, + nDivOut: 608, + ttypeOut: -7, + dmin1Out: 0.20309651253108729, + dmin2Out: 0.57610166617362735, + dnOut: 1.3142485785350155E-006, + dn1Out: 0.20309651253108729, + dn2Out: 0.81137144083676127, + gOut: 0.0000000000000000, + tauOut: 0.10180650470263587, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.3142485785350155E-006, + desig: 0.0000000000000000, + qmax: 2.2697722926067549, + ttype: -7, + dmin1: 0.20309651253108729, + dmin2: 0.57610166617362735, + dn: 1.3142485785350155E-006, + dn1: 0.20309651253108729, + dn2: 0.81137144083676127, + g: 0.0000000000000000, + tau: 0.10180650470263587, + nFail: 2, + iter: 30, + sigma: 0.21120521870940451, + nDiv: 608, + zOut: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 0, + dminOut: 8.4118841991824567E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 31, + nDivOut: 625, + ttypeOut: -2, + dmin1Out: 0.20309744276965425, + dmin2Out: 0.50018599148866161, + dnOut: 8.4118841991824567E-018, + dn1Out: 0.20309744276965425, + dn2Out: 0.75834178007645303, + gOut: 0.0000000000000000, + tauOut: 1.3142409824136984E-006, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.4118841991824567E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309744276965425, + dmin2: 0.50018599148866161, + dn: 8.4118841991824567E-018, + dn1: 0.20309744276965425, + dn2: 0.75834178007645303, + g: 0.0000000000000000, + tau: 1.3142409824136984E-006, + nFail: 2, + iter: 31, + sigma: 0.21120653295038691, + nDiv: 625, + zOut: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 1, + dminOut: 8.4118841988678429E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 32, + nDivOut: 642, + ttypeOut: -2, + dmin1Out: 0.20309858884628909, + dmin2Out: 0.53283137411117854, + dnOut: 8.4118841988678429E-018, + dn1Out: 0.20309858884628909, + dn2Out: 0.71080515929391042, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.4118841988678429E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309858884628909, + dmin2: 0.53283137411117854, + dn: 8.4118841988678429E-018, + dn1: 0.20309858884628909, + dn2: 0.71080515929391042, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 32, + sigma: 0.21120653295038691, + nDiv: 642, + zOut: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.8411884198867843E-17, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 0, + dminOut: 8.4118841988678429E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 33, + nDivOut: 659, + ttypeOut: -2, + dmin1Out: 0.20309858045029386, + dmin2Out: 0.51860540644834729, + dnOut: 8.4118841988678429E-018, + dn1Out: 0.20309858045029386, + dn2Out: 0.67176795876146822, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.8411884198867843E-17, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.4118841988678429E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309858045029386, + dmin2: 0.51860540644834729, + dn: 8.4118841988678429E-018, + dn1: 0.20309858045029386, + dn2: 0.67176795876146822, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 33, + sigma: 0.21120653295038691, + nDiv: 659, + zOut: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.1303059324279677E-43, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 15, + ppOut: 1, + dminOut: 0.10154928703201281, + desigOut: 0.0000000000000000, + sigmaOut: 0.31275582317553385, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 34, + nDivOut: 675, + ttypeOut: -9, + dmin1Out: 0.32391205918605420, + dmin2Out: 0.32391205918605420, + dnOut: 0.10154928703201281, + dn1Out: 0.53450854002684800, + dn2Out: 0.69531980574199759, + gOut: 0.0000000000000000, + tauOut: 0.10154929022514693, + }, + { + i0: 1, + n0: 15, + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 0.10154928703201281, + desig: 0.0000000000000000, + qmax: 2.1682216902523144, + ttype: -9, + dmin1: 0.32391205918605420, + dmin2: 0.32391205918605420, + dn: 0.10154928703201281, + dn1: 0.53450854002684800, + dn2: 0.69531980574199759, + g: 0.0000000000000000, + tau: 0.10154929022514693, + nFail: 2, + iter: 34, + sigma: 0.31275582317553385, + nDiv: 675, + zOut: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 15, + ppOut: 0, + dminOut: 8.2800215414347011E-006, + desigOut: -1.3877787807814457E-017, + sigmaOut: 0.41429682935692197, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 35, + nDivOut: 691, + ttypeOut: -4, + dmin1Out: 0.16866357962181588, + dmin2Out: 0.16866357962181588, + dnOut: 8.2800215414347011E-006, + dn1Out: 0.39110725789187228, + dn2Out: 0.42026820370851276, + gOut: 0.0000000000000000, + tauOut: 0.10154100618138810, + }, + { + i0: 1, + n0: 11, + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.7649302792337775E-015, + desig: 4.8519526217661568E-017, + qmax: 2.1682216902523144, + ttype: -2, + dmin1: 0.18866996369915248, + dmin2: 0.27322036360404983, + dn: 2.7649302792337775E-015, + dn1: 0.18866996369915248, + dn2: 0.27322036360404983, + g: 0.0000000000000000, + tau: 2.4554370888251911E-008, + nFail: 2, + iter: 57, + sigma: 0.91543762594185796, + nDiv: 1001, + zOut: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13, 0.3470987982972452E-28, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 11, + ppOut: 1, + dminOut: 3.4709879829724519E-029, + desigOut: 3.7892243888322520E-017, + sigmaOut: 0.91543762594186073, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 58, + nDivOut: 1013, + ttypeOut: -2, + dmin1Out: 0.18507826404867261, + dmin2Out: 0.27717487004787600, + dnOut: 3.4709879829724519E-029, + dn1Out: 0.18507826404867261, + dn2Out: 0.27858872904535659, + gOut: 0.0000000000000000, + tauOut: 2.7649302792335523E-015, + }, + { + i0: 1, + n0: 11, + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13, 0.3470987982972452E-28, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 3.4709879829724519E-029, + desig: 3.7892243888322520E-017, + qmax: 2.1682216902523144, + ttype: -2, + dmin1: 0.18507826404867261, + dmin2: 0.27717487004787600, + dn: 3.4709879829724519E-029, + dn1: 0.18507826404867261, + dn2: 0.27858872904535659, + g: 0.0000000000000000, + tau: 2.7649302792335523E-015, + nFail: 2, + iter: 58, + sigma: 0.91543762594186073, + nDiv: 1013, + zOut: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 8.9088074504151571E-002, + desigOut: -4.1633363423443370E-017, + sigmaOut: 1.0079767579661971, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 59, + nDivOut: 1024, + ttypeOut: -9, + dmin1Out: 0.17705256406949207, + dmin2Out: 0.17705256406949207, + dnOut: 8.9088074504151571E-002, + dn1Out: 0.18903428744201686, + dn2Out: 0.28613205491191551, + gOut: 0.0000000000000000, + tauOut: 9.2539132024336307E-002, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9088074504151571E-002, + desig: -4.1633363423443370E-017, + qmax: 2.1682216902523144, + ttype: -9, + dmin1: 0.17705256406949207, + dmin2: 0.17705256406949207, + dn: 8.9088074504151571E-002, + dn1: 0.18903428744201686, + dn2: 0.28613205491191551, + g: 0.0000000000000000, + tau: 9.2539132024336307E-002, + nFail: 2, + iter: 59, + sigma: 1.0079767579661971, + nDiv: 1024, + zOut: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 1.1106216559126303E-002, + desigOut: -4.1633363423443370E-017, + sigmaOut: 1.0833646797982348, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 60, + nDivOut: 1035, + ttypeOut: -4, + dmin1Out: 0.10021441433509834, + dmin2Out: 0.10021441433509834, + dnOut: 1.1106216559126303E-002, + dn1Out: 0.11507463320059727, + dn2Out: 0.21320388392650824, + gOut: 0.0000000000000000, + tauOut: 7.5387921832037685E-002, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.1106216559126303E-002, + desig: -4.1633363423443370E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 0.10021441433509834, + dmin2: 0.10021441433509834, + dn: 1.1106216559126303E-002, + dn1: 0.11507463320059727, + dn2: 0.21320388392650824, + g: 0.0000000000000000, + tau: 7.5387921832037685E-002, + nFail: 2, + iter: 60, + sigma: 1.0833646797982348, + nDiv: 1035, + zOut: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 1.6452860548183366E-003, + desigOut: 7.9797279894933126E-017, + sigmaOut: 1.0925653435343534, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 61, + nDivOut: 1046, + ttypeOut: -4, + dmin1Out: 9.0837695870445614E-002, + dmin2Out: 9.0837695870445614E-002, + dnOut: 1.6452860548183366E-003, + dn1Out: 0.10809563217808144, + dn2Out: 0.20642195434625446, + gOut: 0.0000000000000000, + tauOut: 9.2006637361187298E-003, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.6452860548183366E-003, + desig: 7.9797279894933126E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 9.0837695870445614E-002, + dmin2: 9.0837695870445614E-002, + dn: 1.6452860548183366E-003, + dn1: 0.10809563217808144, + dn2: 0.20642195434625446, + g: 0.0000000000000000, + tau: 9.2006637361187298E-003, + nFail: 2, + iter: 61, + sigma: 1.0925653435343534, + nDiv: 1046, + zOut: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 8.1926049685687600E-005, + desigOut: -9.9312918999672206E-017, + sigmaOut: 1.0941247654737283, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 62, + nDivOut: 1057, + ttypeOut: -4, + dmin1Out: 8.9258234858565516E-002, + dmin2Out: 8.9258234858565516E-002, + dnOut: 8.1926049685687600E-005, + dn1Out: 0.10847668953277810, + dn2Out: 0.20701876553386761, + gOut: 0.0000000000000000, + tauOut: 1.5594219393746818E-003, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.1926049685687600E-005, + desig: -9.9312918999672206E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9258234858565516E-002, + dmin2: 8.9258234858565516E-002, + dn: 8.1926049685687600E-005, + dn1: 0.10847668953277810, + dn2: 0.20701876553386761, + g: 0.0000000000000000, + tau: 1.5594219393746818E-003, + nFail: 2, + iter: 62, + sigma: 1.0941247654737283, + nDiv: 1057, + zOut: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 5.0612658152462498E-007, + desigOut: -9.3553094958342964E-017, + sigmaOut: 1.0942061824183187, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 63, + nDivOut: 1068, + ttypeOut: -4, + dmin1Out: 8.9177229293753768E-002, + dmin2Out: 8.9177229293753768E-002, + dnOut: 5.0612658152462498E-007, + dn1Out: 0.10831524323681536, + dn2Out: 0.20814970454128662, + gOut: 0.0000000000000000, + tauOut: 8.1416944590412474E-005, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 5.0612658152462498E-007, + desig: -9.3553094958342964E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9177229293753768E-002, + dmin2: 8.9177229293753768E-002, + dn: 5.0612658152462498E-007, + dn1: 0.10831524323681536, + dn2: 0.20814970454128662, + g: 0.0000000000000000, + tau: 8.1416944590412474E-005, + nFail: 2, + iter: 63, + sigma: 1.0942061824183187, + nDiv: 1068, + zOut: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 8.6071246971392626E-011, + desigOut: 7.0901951641105278E-017, + sigmaOut: 1.0942066884588149, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 64, + nDivOut: 1079, + ttypeOut: -4, + dmin1Out: 8.9183660885577137E-002, + dmin2Out: 8.9183660885577137E-002, + dnOut: 8.6071246971392626E-011, + dn1Out: 0.10814239569959758, + dn2Out: 0.20876277035564564, + gOut: 0.0000000000000000, + tauOut: 5.0604049633765406E-007, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.6071246971392626E-011, + desig: 7.0901951641105278E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9183660885577137E-002, + dmin2: 8.9183660885577137E-002, + dn: 8.6071246971392626E-011, + dn1: 0.10814239569959758, + dn2: 0.20876277035564564, + g: 0.0000000000000000, + tau: 5.0604049633765406E-007, + nFail: 2, + iter: 64, + sigma: 1.0942066884588149, + nDiv: 1079, + zOut: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 3.1678834699165494E-017, + desigOut: -8.6057196331979189E-017, + sigmaOut: 1.0942066885448862, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 65, + nDivOut: 1090, + ttypeOut: -4, + dmin1Out: 8.9200650586607991E-002, + dmin2Out: 8.9200650586607991E-002, + dnOut: 3.1678834699165494E-017, + dn1Out: 0.10805126770967630, + dn2Out: 0.20900961033533805, + gOut: 0.0000000000000000, + tauOut: 8.6071215292546838E-011, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.1278200095129901E-005, + desig: 1.1991276027689679E-016, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11438652178302365, + dmin2: 0.11438652178302365, + dn: 1.1278200095129901E-005, + dn1: 0.18342236422755959, + dn2: 0.11438652178302365, + g: 0.0000000000000000, + tau: 1.0942861809085330E-003, + nFail: 3, + iter: 99, + sigma: 2.3665909917188244, + nDiv: 1347, + zOut: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 8.9549629620034135E-009, + desigOut: -3.3964327119002935E-017, + sigmaOut: 2.3666022609571851, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 100, + nDivOut: 1351, + ttypeOut: -4, + dmin1Out: 0.11437525254466312, + dmin2Out: 0.11437525254466312, + dnOut: 8.9549629620034135E-009, + dn1Out: 0.18342936716409974, + dn2Out: 0.11437525254466312, + gOut: 0.0000000000000000, + tauOut: 1.1269238360546607E-005, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9549629620034135E-009, + desig: -3.3964327119002935E-017, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437525254466312, + dmin2: 0.11437525254466312, + dn: 8.9549629620034135E-009, + dn1: 0.18342936716409974, + dn2: 0.11437525254466312, + g: 0.0000000000000000, + tau: 1.1269238360546607E-005, + nFail: 3, + iter: 100, + sigma: 2.3666022609571851, + nDiv: 1351, + zOut: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 5.5753269291151117E-014, + desigOut: 1.3632246356731358E-016, + sigmaOut: 2.3666022699120921, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 101, + nDivOut: 1355, + ttypeOut: -4, + dmin1Out: 0.11437524358975594, + dmin2Out: 0.11437524358975594, + dnOut: 5.5753269291151117E-014, + dn1Out: 0.18342946834334006, + dn2Out: 0.11437524358975594, + gOut: 0.0000000000000000, + tauOut: 8.9549072084035346E-009, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 5.5753269291151117E-014, + desig: 1.3632246356731358E-016, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437524358975594, + dmin2: 0.11437524358975594, + dn: 5.5753269291151117E-014, + dn1: 0.18342946834334006, + dn2: 0.11437524358975594, + g: 0.0000000000000000, + tau: 8.9549072084035346E-009, + nFail: 3, + iter: 101, + sigma: 2.3666022699120921, + nDiv: 1355, + zOut: []float64{0.1143752435897560E+00, 0.1143752435897003E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.1834294683501117E+00, 0.1834294683500558E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.5575326929115112E-13, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 7.6696244203643861E-023, + desigOut: -6.5648763085702813E-017, + sigmaOut: 2.3666022699121481, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 102, + nDivOut: 1359, + ttypeOut: -4, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dn1Out: 0.18342946835005580, + dn2Out: 0.11437524358970023, + gOut: 0.0000000000000000, + tauOut: 5.5753269214454873E-014, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143752435897560E+00, 0.1143752435897003E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.1834294683501117E+00, 0.1834294683500558E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.5575326929115112E-13, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 7.6696244203643861E-023, + desig: -6.5648763085702813E-017, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437524358970023, + dmin2: 0.11437524358970023, + dn: 7.6696244203643861E-023, + dn1: 0.18342946835005580, + dn2: 0.11437524358970023, + g: 0.0000000000000000, + tau: 5.5753269214454873E-014, + nFail: 3, + iter: 102, + sigma: 2.3666022699121481, + nDiv: 1359, + zOut: []float64{0.2550031738262204E+01, 0.1834294683500561E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.2480977513501848E+01, 0.1143752435897001E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.2366602269912148E+01, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 0, + ppOut: 1, + dminOut: 7.6696244203643861E-023, + desigOut: -6.5648763085702813E-017, + sigmaOut: 2.3666022699121481, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 102, + nDivOut: 1359, + ttypeOut: -4, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dn1Out: 0.18342946835005580, + dn2Out: 0.11437524358970023, + gOut: 0.0000000000000000, + tauOut: 5.5753269214454873E-014, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + pp: 0, + dmin: -0.0000000000000000, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: 0, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 2, + sigma: 0.0000000000000000, + nDiv: 40, + zOut: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 7.8766827084626452E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 3, + nDivOut: 62, + ttypeOut: -1, + dmin1Out: 1.2363512593342330E-003, + dmin2Out: 1.2363512593342330E-003, + dnOut: 7.8766827084626452E-005, + dn1Out: 4.3867054272813191E-003, + dn2Out: 3.7622286348031123E-003, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02}, + pp: 1, + dmin: 7.8766827084626452E-005, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -1, + dmin1: 1.2363512593342330E-003, + dmin2: 1.2363512593342330E-003, + dn: 7.8766827084626452E-005, + dn1: 4.3867054272813191E-003, + dn2: 3.7622286348031123E-003, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 3, + sigma: 0.0000000000000000, + nDiv: 62, + zOut: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 7.8192294615504193E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 4, + nDivOut: 84, + ttypeOut: -4, + dmin1Out: 7.2365102959979382E-004, + dmin2Out: 1.7075768415239889E-002, + dnOut: 7.8192294615504193E-005, + dn1Out: 7.2365102959979382E-004, + dn2Out: 1.7075768415239889E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + pp: 0, + dmin: 7.8192294615504193E-005, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -4, + dmin1: 7.2365102959979382E-004, + dmin2: 1.7075768415239889E-002, + dn: 7.8192294615504193E-005, + dn1: 7.2365102959979382E-004, + dn2: 1.7075768415239889E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 4, + sigma: 0.0000000000000000, + nDiv: 84, + zOut: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 3.6610242528964756E-008, + desigOut: 0.0000000000000000, + sigmaOut: 7.8083356181667918E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 5, + nDivOut: 106, + ttypeOut: -2, + dmin1Out: 6.2053891278358614E-004, + dmin2Out: 2.9611625055501498E-002, + dnOut: 3.6610242528964756E-008, + dn1Out: 6.2053891278358614E-004, + dn2Out: 9.1148025223602810E-002, + gOut: 0.0000000000000000, + tauOut: 7.8083356181667918E-005, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02}, + pp: 1, + dmin: 3.6610242528964756E-008, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2053891278358614E-004, + dmin2: 2.9611625055501498E-002, + dn: 3.6610242528964756E-008, + dn1: 6.2053891278358614E-004, + dn2: 9.1148025223602810E-002, + g: 0.0000000000000000, + tau: 7.8083356181667918E-005, + nFail: 0, + iter: 5, + sigma: 7.8083356181667918E-005, + nDiv: 106, + zOut: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 4.0593516462113082E-015, + desigOut: 4.3344264097778650E-021, + sigmaOut: 7.8119962155206313E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 6, + nDivOut: 128, + ttypeOut: -2, + dmin1Out: 6.2079410376128833E-004, + dmin2Out: 4.5102919754957636E-002, + dnOut: 4.0593516462113082E-015, + dn1Out: 6.2079410376128833E-004, + dn2Out: 6.6633580933131861E-002, + gOut: 0.0000000000000000, + tauOut: 3.6605973538398975E-008, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + pp: 0, + dmin: 4.0593516462113082E-015, + desig: 4.3344264097778650E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2079410376128833E-004, + dmin2: 4.5102919754957636E-002, + dn: 4.0593516462113082E-015, + dn1: 6.2079410376128833E-004, + dn2: 6.6633580933131861E-002, + g: 0.0000000000000000, + tau: 3.6605973538398975E-008, + nFail: 0, + iter: 6, + sigma: 7.8119962155206313E-005, + nDiv: 128, + zOut: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 3.7865323450608567E-029, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 7, + nDivOut: 150, + ttypeOut: -2, + dmin1Out: 6.2086198711654151E-004, + dmin2Out: 3.9492996735707858E-002, + dnOut: 3.7865323450608567E-029, + dn1Out: 6.2086198711654151E-004, + dn2Out: 3.9492996735707858E-002, + gOut: 0.0000000000000000, + tauOut: 4.0593516183260787E-015, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 3.7865323450608567E-029, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2086198711654151E-004, + dmin2: 3.9492996735707858E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086198711654151E-004, + dn2: 3.9492996735707858E-002, + g: 0.0000000000000000, + tau: 4.0593516183260787E-015, + nFail: 0, + iter: 7, + sigma: 7.8119962159265674E-005, + nDiv: 150, + zOut: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22, 0.3786532345060857E-28, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 3.7865323450608567E-029, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 8, + nDivOut: 172, + ttypeOut: -2, + dmin1Out: 6.2086189351765679E-004, + dmin2Out: 2.8198643003083550E-002, + dnOut: 3.7865323450608567E-029, + dn1Out: 6.2086189351765679E-004, + dn2Out: 2.8198643003083550E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22, 0.3786532345060857E-28, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 3.7865323450608567E-029, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2086189351765679E-004, + dmin2: 2.8198643003083550E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086189351765679E-004, + dn2: 2.8198643003083550E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 8, + sigma: 7.8119962159265674E-005, + nDiv: 172, + zOut: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 6.2086189110482101E-004, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 9, + nDivOut: 193, + ttypeOut: -7, + dmin1Out: 2.5181951038433764E-002, + dmin2Out: 8.7297525620826724E-002, + dnOut: 6.2086189110482101E-004, + dn1Out: 2.5181951038433764E-002, + dn2Out: 9.4282269055547374E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.2086189110482101E-004, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -7, + dmin1: 2.5181951038433764E-002, + dmin2: 8.7297525620826724E-002, + dn: 6.2086189110482101E-004, + dn1: 2.5181951038433764E-002, + dn2: 9.4282269055547374E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 9, + sigma: 7.8119962159265674E-005, + nDiv: 193, + zOut: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 3.2573770070154495E-015, + desigOut: 2.1703803823424652E-020, + sigmaOut: 6.9898185319802297E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 10, + nDivOut: 214, + ttypeOut: -2, + dmin1Out: 2.3851725145806461E-002, + dmin2Out: 8.6019261441467765E-002, + dnOut: 3.2573770070154495E-015, + dn1Out: 2.3851725145806461E-002, + dn2Out: 0.10407400868154487, + gOut: 0.0000000000000000, + tauOut: 6.2086189103875732E-004, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 3.2573770070154495E-015, + desig: 2.1703803823424652E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3851725145806461E-002, + dmin2: 8.6019261441467765E-002, + dn: 3.2573770070154495E-015, + dn1: 2.3851725145806461E-002, + dn2: 0.10407400868154487, + g: 0.0000000000000000, + tau: 6.2086189103875732E-004, + nFail: 0, + iter: 10, + sigma: 6.9898185319802297E-004, + nDiv: 214, + zOut: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 9.4663308626521417E-029, + desigOut: 2.1703795093889875E-020, + sigmaOut: 6.9898185320128035E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 11, + nDivOut: 235, + ttypeOut: -2, + dmin1Out: 2.3692824533332088E-002, + dmin2Out: 7.0611780886194908E-002, + dnOut: 9.4663308626521417E-029, + dn1Out: 2.3692824533332088E-002, + dn2Out: 0.10576950347767239, + gOut: 0.0000000000000000, + tauOut: 3.2573770070067200E-015, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 9.4663308626521417E-029, + desig: 2.1703795093889875E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3692824533332088E-002, + dmin2: 7.0611780886194908E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3692824533332088E-002, + dn2: 0.10576950347767239, + g: 0.0000000000000000, + tau: 3.2573770070067200E-015, + nFail: 0, + iter: 11, + sigma: 6.9898185320128035E-004, + nDiv: 235, + zOut: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26, 0.9466330862652142E-28, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 9.4663308626521417E-029, + desigOut: 2.1703795093889875E-020, + sigmaOut: 6.9898185320128035E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 12, + nDivOut: 256, + ttypeOut: -2, + dmin1Out: 2.3656857476986041E-002, + dmin2Out: 7.0305173122617720E-002, + dnOut: 9.4663308626521417E-029, + dn1Out: 2.3656857476986041E-002, + dn2Out: 0.10451478588027406, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26, 0.9466330862652142E-28, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 9.4663308626521417E-029, + desig: 2.1703795093889875E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3656857476986041E-002, + dmin2: 7.0305173122617720E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3656857476986041E-002, + dn2: 0.10451478588027406, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 12, + sigma: 6.9898185320128035E-004, + nDiv: 256, + zOut: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.1818926896585069E-002, + desigOut: 3.4696444683954120E-019, + sigmaOut: 1.2527410591694300E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 13, + nDivOut: 276, + ttypeOut: -9, + dmin1Out: 5.9707584261797009E-002, + dmin2Out: 5.9707584261797009E-002, + dnOut: 1.1818926896585069E-002, + dn1Out: 8.9511673871889130E-002, + dn2Out: 5.9707584261797009E-002, + gOut: 0.0000000000000000, + tauOut: 1.1828428738493020E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 1.1818926896585069E-002, + desig: 3.4696444683954120E-019, + qmax: 1.8900334961849885, + ttype: -9, + dmin1: 5.9707584261797009E-002, + dmin2: 5.9707584261797009E-002, + dn: 1.1818926896585069E-002, + dn1: 8.9511673871889130E-002, + dn2: 5.9707584261797009E-002, + g: 0.0000000000000000, + tau: 1.1828428738493020E-002, + nFail: 0, + iter: 13, + sigma: 1.2527410591694300E-002, + nDiv: 276, + zOut: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.2789903011516807E-004, + desigOut: 0.0000000000000000, + sigmaOut: 2.4216884496671885E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 14, + nDivOut: 296, + ttypeOut: -4, + dmin1Out: 4.9975042235645591E-002, + dmin2Out: 4.9975042235645591E-002, + dnOut: 1.2789903011516807E-004, + dn1Out: 7.2258424646843816E-002, + dn2Out: 4.9975042235645591E-002, + gOut: 0.0000000000000000, + tauOut: 1.1689473904977585E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.2789903011516807E-004, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -4, + dmin1: 4.9975042235645591E-002, + dmin2: 4.9975042235645591E-002, + dn: 1.2789903011516807E-004, + dn1: 7.2258424646843816E-002, + dn2: 4.9975042235645591E-002, + g: 0.0000000000000000, + tau: 1.1689473904977585E-002, + nFail: 0, + iter: 14, + sigma: 2.4216884496671885E-002, + nDiv: 296, + zOut: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 7.7577072096399712E-010, + desigOut: -5.4210108624275222E-020, + sigmaOut: 2.4344779705352607E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 1, + iterOut: 16, + nDivOut: 336, + ttypeOut: -15, + dmin1Out: 5.3179116896294863E-002, + dmin2Out: 5.3179116896294863E-002, + dnOut: 7.7577072096399712E-010, + dn1Out: 6.5255212904451090E-002, + dn2Out: 5.3179116896294863E-002, + gOut: 0.0000000000000000, + tauOut: 1.2789520868072135E-004, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 7.7577072096399712E-010, + desig: -5.4210108624275222E-020, + qmax: 1.8900334961849885, + ttype: -15, + dmin1: 5.3179116896294863E-002, + dmin2: 5.3179116896294863E-002, + dn: 7.7577072096399712E-010, + dn1: 6.5255212904451090E-002, + dn2: 5.3179116896294863E-002, + g: 0.0000000000000000, + tau: 1.2789520868072135E-004, + nFail: 1, + iter: 16, + sigma: 2.4344779705352607E-002, + nDiv: 336, + zOut: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.0135599141977102E-019, + desigOut: 2.7104744119407903E-020, + sigmaOut: 2.4344780481123287E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 2, + iterOut: 18, + nDivOut: 376, + ttypeOut: -15, + dmin1Out: 5.8414457514939733E-002, + dmin2Out: 5.8777374831867304E-002, + dnOut: 1.0135599141977102E-019, + dn1Out: 5.8414457514939733E-002, + dn2Out: 5.8777374831867304E-002, + gOut: 0.0000000000000000, + tauOut: 7.7577068041483555E-010, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.0135599141977102E-019, + desig: 2.7104744119407903E-020, + qmax: 1.8900334961849885, + ttype: -15, + dmin1: 5.8414457514939733E-002, + dmin2: 5.8777374831867304E-002, + dn: 1.0135599141977102E-019, + dn1: 5.8414457514939733E-002, + dn2: 5.8777374831867304E-002, + g: 0.0000000000000000, + tau: 7.7577068041483555E-010, + nFail: 2, + iter: 18, + sigma: 2.4344780481123287E-002, + nDiv: 376, + zOut: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.1013559914197710E-18, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.0135599141977093E-019, + desigOut: 2.7104744119407903E-020, + sigmaOut: 2.4344780481123287E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 2, + iterOut: 19, + nDivOut: 396, + ttypeOut: -2, + dmin1Out: 5.1614639267802333E-002, + dmin2Out: 5.1614639267802333E-002, + dnOut: 1.0135599141977093E-019, + dn1Out: 5.2901697084955956E-002, + dn2Out: 6.5660305799035965E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.4301480751548441E-012, + desig: -2.0633404957759536E-016, + qmax: 1.6602870234255678, + ttype: -2, + dmin1: 8.9268528752914328E-002, + dmin2: 8.9268528752914328E-002, + dn: 6.4301480751548441E-012, + dn1: 0.31536922601351364, + dn2: 8.9268528752914328E-002, + g: 0.49975000000000003, + tau: 1.5862205428611591E-006, + nFail: 5, + iter: 102, + sigma: 2.0015106747272648, + nDiv: 1395, + zOut: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 4, + ppOut: 1, + dminOut: 1.7877912110675335E-015, + desigOut: -3.7836067586147711E-017, + sigmaOut: 2.0015106747336930, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 103, + nDivOut: 1400, + ttypeOut: -4, + dmin1Out: 8.9268528747146109E-002, + dmin2Out: 8.9268528747146109E-002, + dnOut: 1.7877912110675335E-015, + dn1Out: 0.32005377571968785, + dn2Out: 8.9268528747146109E-002, + gOut: 0.49975000000000003, + tauOut: 6.4283598105616478E-012, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.7877912110675335E-015, + desig: -3.7836067586147711E-017, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 8.9268528747146109E-002, + dmin2: 8.9268528747146109E-002, + dn: 1.7877912110675335E-015, + dn1: 0.32005377571968785, + dn2: 8.9268528747146109E-002, + g: 0.49975000000000003, + tau: 6.4283598105616478E-012, + nFail: 5, + iter: 103, + sigma: 2.0015106747336930, + nDiv: 1400, + zOut: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.1787791211067534E-14, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 4, + ppOut: 0, + dminOut: 2.2279522444840209E-024, + desigOut: -2.6401698146816920E-017, + sigmaOut: 2.0015106747336948, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 104, + nDivOut: 1405, + ttypeOut: -4, + dmin1Out: 8.9268528749476481E-002, + dmin2Out: 8.9268528749476481E-002, + dnOut: 2.2279522444840209E-024, + dn1Out: 0.32005379925180094, + dn2Out: 8.9268528749476481E-002, + gOut: 0.49975000000000003, + tauOut: 1.7877912088395813E-015, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.1787791211067534E-14, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 2.2279522444840209E-024, + desig: -2.6401698146816920E-017, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 8.9268528749476481E-002, + dmin2: 8.9268528749476481E-002, + dn: 2.2279522444840209E-024, + dn1: 0.32005379925180094, + dn2: 8.9268528749476481E-002, + g: 0.49975000000000003, + tau: 1.7877912088395813E-015, + nFail: 5, + iter: 104, + sigma: 2.0015106747336948, + nDiv: 1405, + zOut: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 6.6951396570468849E-002, + desigOut: -1.0061396160665481E-016, + sigmaOut: 2.0238278069210640, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 105, + nDivOut: 1409, + ttypeOut: -9, + dmin1Out: 6.6951396570468849E-002, + dmin2Out: 0.62588280745004166, + dnOut: 0.29773666692112338, + dn1Out: 6.6951396570468849E-002, + dn2Out: 0.62588280745004166, + gOut: 0.49975000000000003, + tauOut: 2.2317132187369120E-002, + }, + { + i0: 1, + n0: 3, + z: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 6.6951396570468849E-002, + desig: -1.0061396160665481E-016, + qmax: 1.6602870234255678, + ttype: -9, + dmin1: 6.6951396570468849E-002, + dmin2: 0.62588280745004166, + dn: 0.29773666692112338, + dn1: 6.6951396570468849E-002, + dn2: 0.62588280745004166, + g: 0.49975000000000003, + tau: 2.2317132187369120E-002, + nFail: 5, + iter: 105, + sigma: 2.0238278069210640, + nDiv: 1409, + zOut: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 6.6400430513702258E-007, + desigOut: 1.9428902930940239E-016, + sigmaOut: 2.0907785395172058, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 106, + nDivOut: 1413, + ttypeOut: -4, + dmin1Out: 6.6400430513702258E-007, + dmin2Out: 0.55893207485389951, + dnOut: 0.23072168931229292, + dn1Out: 6.6400430513702258E-007, + dn2Out: 0.55893207485389951, + gOut: 0.49975000000000003, + tauOut: 6.6950732596142107E-002, + }, + { + i0: 1, + n0: 3, + z: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.6400430513702258E-007, + desig: 1.9428902930940239E-016, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 6.6400430513702258E-007, + dmin2: 0.55893207485389951, + dn: 0.23072168931229292, + dn1: 6.6400430513702258E-007, + dn2: 0.55893207485389951, + g: 0.49975000000000003, + tau: 6.6950732596142107E-002, + nFail: 5, + iter: 106, + sigma: 2.0907785395172058, + nDiv: 1413, + zOut: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 9.5878878222950548E-008, + desigOut: -9.3233975295464906E-017, + sigmaOut: 2.0907791077859414, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 108, + nDivOut: 1421, + ttypeOut: -15, + dmin1Out: 9.5878878222950548E-008, + dmin2Out: 0.55893150658516422, + dnOut: 3.4324631347444829E-004, + dn1Out: 9.5878878222950548E-008, + dn2Out: 0.55893150658516422, + gOut: 0.49975000000000003, + tauOut: 5.6826873533591094E-007, + }, + { + i0: 1, + n0: 3, + z: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 9.5878878222950548E-008, + desig: -9.3233975295464906E-017, + qmax: 1.6602870234255678, + ttype: -15, + dmin1: 9.5878878222950548E-008, + dmin2: 0.55893150658516422, + dn: 3.4324631347444829E-004, + dn1: 9.5878878222950548E-008, + dn2: 0.55893150658516422, + g: 0.49975000000000003, + tau: 5.6826873533591094E-007, + nFail: 6, + iter: 108, + sigma: 2.0907791077859414, + nDiv: 1421, + zOut: []float64{0.5589315065851642E+00, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.6434089156657428E-04, 0.2304421214097475E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.3432463134744483E-03, 0.1484300435548105E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 1.4843004355481051E-009, + desigOut: -1.6593817482031092E-016, + sigmaOut: 2.0907792019978437, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 109, + nDivOut: 1425, + ttypeOut: -4, + dmin1Out: 6.4246679664367451E-005, + dmin2Out: 0.55893141237326205, + dnOut: 1.4843004355481051E-009, + dn1Out: 6.4246679664367451E-005, + dn2Out: 0.55893141237326205, + gOut: 0.49975000000000003, + tauOut: 9.4211902206835373E-008, + }, + { + i0: 1, + n0: 3, + z: []float64{0.5589315065851642E+00, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.6434089156657428E-04, 0.2304421214097475E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.3432463134744483E-03, 0.1484300435548105E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 1.4843004355481051E-009, + desig: -1.6593817482031092E-016, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 6.4246679664367451E-005, + dmin2: 0.55893141237326205, + dn: 1.4843004355481051E-009, + dn1: 6.4246679664367451E-005, + dn2: 0.55893141237326205, + g: 0.49975000000000003, + tau: 9.4211902206835373E-008, + nFail: 6, + iter: 109, + sigma: 2.0907792019978437, + nDiv: 1425, + zOut: []float64{0.2649710614371106E+01, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.2321564474027070E+01, 0.2307852720292263E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.2090779203479937E+01, 0.1482093454966231E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 0, + ppOut: 1, + dminOut: 1.4843004355481051E-009, + desigOut: -1.6593817482031092E-016, + sigmaOut: 2.0907792019978437, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 109, + nDivOut: 1425, + ttypeOut: -4, + dmin1Out: 6.4246679664367451E-005, + dmin2Out: 0.55893141237326205, + dnOut: 1.4843004355481051E-009, + dn1Out: 6.4246679664367451E-005, + dn2Out: 0.55893141237326205, + gOut: 0.49975000000000003, + tauOut: 9.4211902206835373E-008, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + i0 := test.i0 - 1 // zero index + n0 := test.n0 - 1 // zero index + + i0Out, n0Out, ppOut, dminOut, sigmaOut, desigOut, qmaxOut, nFailOut, iterOut, nDivOut, ttypeOut, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut := + impl.Dlasq3(i0, n0, z, test.pp, test.dmin, test.sigma, test.desig, test.qmax, test.nFail, test.iter, test.nDiv, test.ttype, test.dmin1, test.dmin2, test.dn, test.dn1, test.dn2, test.g, test.tau) + + if !floats.EqualApprox(z, test.zOut, dTol) { + t.Error("Z mismatch") + } + if i0Out != test.i0Out-1 { + t.Errorf("i0 mismatch. Want %v, got %v", test.n0Out, n0Out) + } + if n0Out != test.n0Out-1 { + t.Errorf("n0 mismatch. Want %v, got %v", test.n0Out, n0Out) + } + if ppOut != test.ppOut { + t.Errorf("pp mismatch. Want %v, got %v", test.ppOut, ppOut) + } + if !floats.EqualWithinAbsOrRel(dminOut, test.dminOut, dTol, dTol) { + t.Errorf("dmin mismatch. Want %v, got %v", test.dminOut, dminOut) + } + if !floats.EqualWithinAbsOrRel(desigOut, test.desigOut, dTol, dTol) { + t.Errorf("desig mismatch. Want %v, got %v", test.desigOut, desigOut) + } + if !floats.EqualWithinAbsOrRel(sigmaOut, test.sigmaOut, dTol, dTol) { + t.Errorf("sigma mismatch. Want %v, got %v", test.sigmaOut, sigmaOut) + } + if !floats.EqualWithinAbsOrRel(qmaxOut, test.qmaxOut, dTol, dTol) { + t.Errorf("qmax mismatch. Want %v, got %v", test.qmaxOut, qmaxOut) + } + if nFailOut != test.nFailOut { + t.Errorf("nFail mismatch. Want %v, got %v", test.nFailOut, nFailOut) + } + if iterOut != test.iterOut { + t.Errorf("iter mismatch. Want %v, got %v", test.iterOut, iterOut) + } + if nDivOut != test.nDivOut { + t.Errorf("nFail mismatch. Want %v, got %v", test.nDivOut, nDivOut) + } + if ttypeOut != test.ttypeOut { + t.Errorf("ttype mismatch. Want %v, got %v", test.ttypeOut, ttypeOut) + } + if !floats.EqualWithinAbsOrRel(dmin1Out, test.dmin1Out, dTol, dTol) { + t.Errorf("dmin1 mismatch. Want %v, got %v", test.dmin1Out, dmin1Out) + } + if !floats.EqualWithinAbsOrRel(dmin2Out, test.dmin2Out, dTol, dTol) { + t.Errorf("dmin2 mismatch. Want %v, got %v", test.dmin2Out, dmin2Out) + } + if !floats.EqualWithinAbsOrRel(dnOut, test.dnOut, dTol, dTol) { + t.Errorf("dn mismatch. Want %v, got %v", test.dnOut, dnOut) + } + if !floats.EqualWithinAbsOrRel(dn1Out, test.dn1Out, dTol, dTol) { + t.Errorf("dn1 mismatch. Want %v, got %v", test.dn1Out, dn1Out) + } + if !floats.EqualWithinAbsOrRel(dn2Out, test.dn2Out, dTol, dTol) { + t.Errorf("dn2 mismatch. Want %v, got %v", test.dn2Out, dn2Out) + } + if !floats.EqualWithinAbsOrRel(gOut, test.gOut, dTol, dTol) { + t.Errorf("g mismatch. Want %v, got %v", test.gOut, gOut) + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("tau mismatch. Want %v, got %v", test.tauOut, tauOut) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq4.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq4.go new file mode 100644 index 00000000..03d71946 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq4.go @@ -0,0 +1,3101 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +type dlasq4teststruct struct { + z []float64 + i0, n0, pp, n0in int + dmin, dmin1, dmin2, dn, dn1, dn2, tau float64 + ttype int + g float64 + + zOut []float64 + tauOut float64 + ttypeOut int + gOut float64 +} + +type Dlasq4er interface { + Dlasq4(i0, n0 int, z []float64, pp int, n0in int, dmin, dmin1, dmin2, dn, dn1, dn2, tau float64, ttype int, g float64) (tauOut float64, ttypeOut int, gOut float64) +} + +func Dlasq4Test(t *testing.T, impl Dlasq4er) { + dTol := 1e-14 + // Tests computed from calling the netlib Dlasq + for cas, test := range []dlasq4teststruct{ + { + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: -0.0000000000000000, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + tau: 0.0000000000000000, + ttype: 0, + g: 0.0000000000000000, + zOut: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + tauOut: 0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 2.1175426017541180E-005, + dmin1: 4.4311601260836921E-002, + dmin2: 4.4311601260836921E-002, + dn: 2.1175426017541180E-005, + dn1: 0.33915960483100382, + dn2: 0.16428924199195991, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + tauOut: 0.0000000000000000, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 2.1175425069176302E-005, + dmin1: 2.9944624525135358E-002, + dmin2: 2.9944624525135358E-002, + dn: 2.1175425069176302E-005, + dn1: 7.2928780948497918E-002, + dn2: 0.16065460645225654, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + tauOut: 2.1175313795360271E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 1.1127325659669794E-010, + dmin1: 3.1433071595911154E-002, + dmin2: 3.1433071595911154E-002, + dn: 1.1127325659669794E-010, + dn1: 3.5896964560873705E-002, + dn2: 0.25842281720128102, + tau: 2.1175313795360271E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + tauOut: 2.1175313795360271E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 0.0000000000000000, + dmin1: 2.9139336744737766E-002, + dmin2: 4.9426557292086552E-002, + dn: -2.0808762284537102E-024, + dn1: 2.9139336744737766E-002, + dn2: 0.15959234211062134, + tau: 1.1127325659669789E-010, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 21, + dmin: 0.0000000000000000, + dmin1: 2.7016889331018056E-002, + dmin2: 5.3061698118516694E-002, + dn: 0.0000000000000000, + dn1: 2.7016889331018056E-002, + dn2: 8.6018658784156071E-002, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 2.5763383633962696E-002, + dmin1: 4.3622798915905092E-002, + dmin2: 7.4536672467372611E-002, + dn: 2.5763383633962696E-002, + dn1: 4.3622798915905092E-002, + dn2: 9.8141518071882677E-002, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + tauOut: 2.0080554394878082E-002, + ttypeOut: -3, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 1.8576185384092288E-002, + dmin1: 1.8576185384092288E-002, + dmin2: 5.2365600435162571E-002, + dn: 1.9114649409197451E-002, + dn1: 1.8576185384092288E-002, + dn2: 5.2365600435162571E-002, + tau: 5.0201385987195205E-003, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + tauOut: 5.4769133315280185E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 9.5622848228283271E-003, + dmin1: 9.5622848228283271E-003, + dmin2: 6.9533978479808370E-002, + dn: 1.0856003705186750E-002, + dn1: 9.5622848228283271E-003, + dn2: 6.9533978479808370E-002, + tau: 5.4769133315280185E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + tauOut: 5.1216063611655054E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 2.0601312480394186E-003, + dmin1: 5.4371870398960158E-003, + dmin2: 8.0023511442426670E-002, + dn: 2.0601312480394186E-003, + dn1: 5.4371870398960158E-003, + dn2: 8.0023511442426670E-002, + tau: 5.1216063611655054E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + tauOut: 1.2817878169164906E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 6.0731361153288982E-005, + dmin1: 6.8738708636769136E-003, + dmin2: 8.1489512892123819E-002, + dn: 6.0731361153288982E-005, + dn1: 6.8738708636769136E-003, + dn2: 8.1489512892123819E-002, + tau: 1.2817878169164906E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + tauOut: 5.6837241251038845E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 3.1568086081919418E-009, + dmin1: 1.0483100129151506E-002, + dmin2: 8.1316774559040517E-002, + dn: 3.1568086081919418E-009, + dn1: 1.0483100129151506E-002, + dn2: 8.1316774559040517E-002, + tau: 5.6837241251038845E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + tauOut: 3.1557121791797713E-009, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 6.9684975813366743E-017, + dmin1: 1.1199576261102989E-002, + dmin2: 8.1067607231828140E-002, + dn: 6.9684975813366743E-017, + dn1: 1.1199576261102989E-002, + dn2: 8.1067607231828140E-002, + tau: 3.1557121791797713E-009, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + tauOut: 6.9684975806547287E-017, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 6.1629758220391547E-032, + dmin1: 1.1203310405167735E-002, + dmin2: 8.0927116373146771E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203310405167735E-002, + dn2: 8.0927116373146771E-002, + tau: 6.9684975806547287E-017, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + tauOut: 6.1629758220391547E-032, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + i0: 1, + n0: 19, + pp: 0, + n0in: 20, + dmin: 6.1629758220391547E-032, + dmin1: 1.1203288675083998E-002, + dmin2: 8.0846453894262649E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203288675083998E-002, + dn2: 8.0846453894262649E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + tauOut: 1.1203284285913290E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 8.9043085058082561E-010, + dmin1: 6.9585227169791292E-002, + dmin2: 0.11373841371027797, + dn: 8.9043085058082561E-010, + dn1: 6.9585227169791292E-002, + dn2: 0.11373841371027797, + tau: 1.1203284285913290E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + tauOut: 8.9043080564395014E-010, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.3962105636374437E-019, + dmin1: 6.9544122471813200E-002, + dmin2: 9.8247027562672340E-002, + dn: 1.3962105636374437E-019, + dn1: 6.9544122471813200E-002, + dn2: 9.8247027562672340E-002, + tau: 8.9043080564395014E-010, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + tauOut: 1.3962105636374427E-019, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 19, + dmin: 1.3962105636374430E-019, + dmin1: 6.9512134440652351E-002, + dmin2: 8.9358776708560295E-002, + dn: 1.3962105636374430E-019, + dn1: 6.9512134440652351E-002, + dn2: 8.9358776708560295E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + tauOut: 6.8088572105595116E-002, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 1.2643548659038301E-003, + dmin1: 1.3935943135754067E-002, + dmin2: 9.9495800084882416E-002, + dn: 1.2643548659038301E-003, + dn1: 1.3935943135754067E-002, + dn2: 9.9495800084882416E-002, + tau: 6.8088572105595116E-002, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + tauOut: 1.2463174543591322E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 1.2236274461701734E-006, + dmin1: 1.1812799375517376E-002, + dmin2: 0.10597947881780349, + dn: 1.2236274461701734E-006, + dn1: 1.1812799375517376E-002, + dn2: 0.10597947881780349, + tau: 1.2463174543591322E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + tauOut: 1.2218877946904154E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 9.5986727915820745E-012, + dmin1: 1.1875197612370336E-002, + dmin2: 0.11291768719739126, + dn: 9.5986727915820745E-012, + dn1: 1.1875197612370336E-002, + dn2: 0.11291768719739126, + tau: 1.2218877946904154E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + tauOut: 9.5986713933289272E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 6.6174125886815435E-022, + dmin1: 1.1882019541390456E-002, + dmin2: 0.11366976186212303, + dn: 6.6174125886815435E-022, + dn1: 1.1882019541390456E-002, + dn2: 0.11366976186212303, + tau: 9.5986713933289272E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + tauOut: 6.6174125886815426E-022, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + i0: 1, + n0: 17, + pp: 0, + n0in: 18, + dmin: 6.6174125886815426E-022, + dmin1: 1.1880977265773463E-002, + dmin2: 0.11370904624558997, + dn: 6.6174125886815426E-022, + dn1: 1.1880977265773463E-002, + dn2: 0.11370904624558997, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + tauOut: 1.1880832155707781E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + i0: 1, + n0: 17, + pp: 1, + n0in: 17, + dmin: 2.3287035572430725E-008, + dmin1: 0.10181720511285566, + dmin2: 0.30482311636216664, + dn: 2.3287035572430725E-008, + dn1: 0.10181720511285566, + dn2: 0.30482311636216664, + tau: 1.1880832155707781E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + tauOut: 2.3287007705477136E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + i0: 1, + n0: 17, + pp: 0, + n0in: 17, + dmin: 2.6961654281145418E-018, + dmin1: 0.10181121275944585, + dmin2: 0.30487633314418217, + dn: 2.6961654281145418E-018, + dn1: 0.10181121275944585, + dn2: 0.30487633314418217, + tau: 2.3287007705477136E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + tauOut: 2.6961654281138038E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + n0in: 17, + dmin: 2.6961654281138038E-018, + dmin1: 0.10180899282350273, + dmin2: 0.30489636738914000, + dn: 2.6961654281138038E-018, + dn1: 0.10180899282350273, + dn2: 0.30489636738914000, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + tauOut: 0.10180650470263587, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + i0: 1, + n0: 16, + pp: 0, + n0in: 16, + dmin: 1.3142485785350155E-006, + dmin1: 0.20309651253108729, + dmin2: 0.57610166617362735, + dn: 1.3142485785350155E-006, + dn1: 0.20309651253108729, + dn2: 0.81137144083676127, + tau: 0.10180650470263587, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + tauOut: 1.3142409824136984E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + n0in: 16, + dmin: 8.4118841991824567E-018, + dmin1: 0.20309744276965425, + dmin2: 0.50018599148866161, + dn: 8.4118841991824567E-018, + dn1: 0.20309744276965425, + dn2: 0.75834178007645303, + tau: 1.3142409824136984E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + tauOut: 8.4118841988678429E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + i0: 1, + n0: 16, + pp: 0, + n0in: 16, + dmin: 8.4118841988678429E-018, + dmin1: 0.20309858884628909, + dmin2: 0.53283137411117854, + dn: 8.4118841988678429E-018, + dn1: 0.20309858884628909, + dn2: 0.71080515929391042, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + tauOut: 8.4118841988678429E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 16, + dmin: 8.4118841988678429E-018, + dmin1: 0.20309858045029386, + dmin2: 0.51860540644834729, + dn: 8.4118841988678429E-018, + dn1: 0.20309858045029386, + dn2: 0.67176795876146822, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + tauOut: 0.10154929022514693, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + i0: 1, + n0: 15, + pp: 0, + n0in: 15, + dmin: 0.10154928703201281, + dmin1: 0.32391205918605420, + dmin2: 0.32391205918605420, + dn: 0.10154928703201281, + dn1: 0.53450854002684800, + dn2: 0.69531980574199759, + tau: 0.10154929022514693, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + tauOut: 0.10154100618138810, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 15, + dmin: 8.2800215414347011E-006, + dmin1: 0.16866357962181588, + dmin2: 0.16866357962181588, + dn: 8.2800215414347011E-006, + dn1: 0.39110725789187228, + dn2: 0.42026820370851276, + tau: 0.10154100618138810, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + tauOut: 8.2795951083136037E-006, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + i0: 1, + n0: 15, + pp: 0, + n0in: 15, + dmin: 4.2641220534843968E-010, + dmin1: 0.19554701532405336, + dmin2: 0.19554701532405336, + dn: 4.2641220534843968E-010, + dn1: 0.32821333105682254, + dn2: 0.21848306981706411, + tau: 8.2795951083136037E-006, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + tauOut: 4.2641207498271701E-010, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 15, + dmin: 1.3036568472020817E-016, + dmin1: 0.15841174212052453, + dmin2: 0.15841174212052453, + dn: 1.3036568472020817E-016, + dn1: 0.23494558610432464, + dn2: 0.15841174212052453, + tau: 4.2641207498271701E-010, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + tauOut: 1.3036568471812905E-016, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + i0: 1, + n0: 14, + pp: 0, + n0in: 15, + dmin: 2.0791168714198411E-027, + dmin1: 0.15670572686712736, + dmin2: 0.18680490956440032, + dn: 2.0791168714198411E-027, + dn1: 0.15670572686712736, + dn2: 0.18680490956440032, + tau: 1.3036568471812905E-016, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + tauOut: 5.2226904068357879E-002, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 6.1979733096699005E-002, + dmin1: 0.21025182606004778, + dmin2: 0.35454858327394784, + dn: 6.1979733096699005E-002, + dn1: 0.21025182606004778, + dn2: 0.51458348500658069, + tau: 5.2226904068357879E-002, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + tauOut: 4.3992746597899146E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + i0: 1, + n0: 14, + pp: 0, + n0in: 14, + dmin: 8.3978432207528000E-003, + dmin1: 0.23219513064786862, + dmin2: 0.34734604130905122, + dn: 8.3978432207528000E-003, + dn1: 0.23219513064786862, + dn2: 0.39493697562207530, + tau: 4.3992746597899146E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + tauOut: 8.0121275381568099E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 8.3015533671799979E-005, + dmin1: 0.25644350373773794, + dmin2: 0.31779880038403513, + dn: 8.3015533671799979E-005, + dn1: 0.25644350373773794, + dn2: 0.31779880038403513, + tau: 8.0121275381568099E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + tauOut: 8.2898056486573887E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + i0: 1, + n0: 14, + pp: 0, + n0in: 14, + dmin: 1.9676836973621424E-008, + dmin1: 0.25663722751477031, + dmin2: 0.28224921557690585, + dn: 1.9676836973621424E-008, + dn1: 0.25663722751477031, + dn2: 0.28224921557690585, + tau: 8.2898056486573887E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + tauOut: 1.9676827722764296E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 1.5032959860012969E-015, + dmin1: 0.24838793989138258, + dmin2: 0.27047787997045275, + dn: 1.5032959860012969E-015, + dn1: 0.24838793989138258, + dn2: 0.27047787997045275, + tau: 1.9676827722764296E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + tauOut: 1.5032959860012393E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + i0: 1, + n0: 13, + pp: 0, + n0in: 14, + dmin: 9.2691156363468887E-030, + dmin1: 0.24076768543540897, + dmin2: 0.27020241256687788, + dn: 9.2691156363468887E-030, + dn1: 0.24076768543540897, + dn2: 0.27020241256687788, + tau: 1.5032959860012393E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + tauOut: 0.19361025134591583, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 2.5949209826162500E-002, + dmin1: 7.8890170839591350E-002, + dmin2: 0.28791033268116917, + dn: 2.5949209826162500E-002, + dn1: 7.8890170839591350E-002, + dn2: 0.41777236268627749, + tau: 0.19361025134591583, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + tauOut: 1.8780556192507153E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + i0: 1, + n0: 13, + pp: 0, + n0in: 13, + dmin: 8.7653100724300811E-004, + dmin1: 6.6256164803006098E-002, + dmin2: 0.24571773655185866, + dn: 8.7653100724300811E-004, + dn1: 6.6256164803006098E-002, + dn2: 0.36084635920253871, + tau: 1.8780556192507153E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + tauOut: 8.1622622999092049E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 6.9556311345050133E-007, + dmin1: 8.6231166987816729E-002, + dmin2: 0.25114202935985525, + dn: 6.9556311345050133E-007, + dn1: 8.6231166987816729E-002, + dn2: 0.30765445605457048, + tau: 8.1622622999092049E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + tauOut: 6.9511331676175615E-007, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + i0: 1, + n0: 13, + pp: 0, + n0in: 13, + dmin: 1.2278907249223888E-012, + dmin1: 9.2372077429255559E-002, + dmin2: 0.25591158693238830, + dn: 1.2278907249223888E-012, + dn1: 9.2372077429255559E-002, + dn2: 0.25591158693238830, + tau: 6.9511331676175615E-007, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + tauOut: 1.2278907189544363E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 4.9598525010503808E-024, + dmin1: 9.2368632133320736E-002, + dmin2: 0.22049265431403467, + dn: 4.9598525010503808E-024, + dn1: 9.2368632133320736E-002, + dn2: 0.22049265431403467, + tau: 1.2278907189544363E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + tauOut: 4.9598525010503808E-024, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + i0: 1, + n0: 12, + pp: 0, + n0in: 13, + dmin: 4.9598525010503808E-024, + dmin1: 9.2339683204333278E-002, + dmin2: 0.20112464802017624, + dn: 4.9598525010503808E-024, + dn1: 9.2339683204333278E-002, + dn2: 0.20112464802017624, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + tauOut: 9.2159326345418235E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + n0in: 12, + dmin: 1.5272797578758102E-004, + dmin1: 9.6724015270930774E-002, + dmin2: 0.29962742013672317, + dn: 1.5272797578758102E-004, + dn1: 9.6724015270930774E-002, + dn2: 0.29962742013672317, + tau: 9.2159326345418235E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + tauOut: 1.5267965277267402E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + i0: 1, + n0: 12, + pp: 0, + n0in: 12, + dmin: 2.8998364833248812E-009, + dmin1: 9.2869952038417761E-002, + dmin2: 0.30683160095299705, + dn: 2.8998364833248812E-009, + dn1: 9.2869952038417761E-002, + dn2: 0.30683160095299705, + tau: 1.5267965277267402E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + tauOut: 2.8998350258011044E-009, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + n0in: 12, + dmin: 2.2456987483859239E-017, + dmin1: 9.1786476970678488E-002, + dmin2: 0.30815750788579249, + dn: 2.2456987483859239E-017, + dn1: 9.1786476970678488E-002, + dn2: 0.30815750788579249, + tau: 2.8998350258011044E-009, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + tauOut: 2.2456987483858885E-017, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + i0: 1, + n0: 11, + pp: 0, + n0in: 12, + dmin: 2.2456987483858888E-017, + dmin1: 9.1450429866798411E-002, + dmin2: 0.30232944966555197, + dn: 2.2456987483858888E-017, + dn1: 9.1450429866798411E-002, + dn2: 0.30232944966555197, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + tauOut: 9.1173077708044642E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + n0in: 11, + dmin: 1.2510327751137640E-004, + dmin1: 0.20154260650453434, + dmin2: 0.26087886618071221, + dn: 1.2510327751137640E-004, + dn1: 0.20154260650453434, + dn2: 0.26087886618071221, + tau: 9.1173077708044642E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + tauOut: 1.2498058228587147E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + i0: 1, + n0: 11, + pp: 0, + n0in: 11, + dmin: 2.4554386425680716E-008, + dmin1: 0.19392428663386141, + dmin2: 0.26581143244488259, + dn: 2.4554386425680716E-008, + dn1: 0.19392428663386141, + dn2: 0.26581143244488259, + tau: 1.2498058228587147E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + tauOut: 2.4554370888251911E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + n0in: 11, + dmin: 2.7649302792337775E-015, + dmin1: 0.18866996369915248, + dmin2: 0.27322036360404983, + dn: 2.7649302792337775E-015, + dn1: 0.18866996369915248, + dn2: 0.27322036360404983, + tau: 2.4554370888251911E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + tauOut: 2.7649302792335523E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + i0: 1, + n0: 10, + pp: 0, + n0in: 11, + dmin: 3.4709879829724519E-029, + dmin1: 0.18507826404867261, + dmin2: 0.27717487004787600, + dn: 3.4709879829724519E-029, + dn1: 0.18507826404867261, + dn2: 0.27858872904535659, + tau: 2.7649302792335523E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + tauOut: 9.2539132024336307E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 8.9088074504151571E-002, + dmin1: 0.17705256406949207, + dmin2: 0.17705256406949207, + dn: 8.9088074504151571E-002, + dn1: 0.18903428744201686, + dn2: 0.28613205491191551, + tau: 9.2539132024336307E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + tauOut: 7.5387921832037685E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 1.1106216559126303E-002, + dmin1: 0.10021441433509834, + dmin2: 0.10021441433509834, + dn: 1.1106216559126303E-002, + dn1: 0.11507463320059727, + dn2: 0.21320388392650824, + tau: 7.5387921832037685E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + tauOut: 9.2006637361187298E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 1.6452860548183366E-003, + dmin1: 9.0837695870445614E-002, + dmin2: 9.0837695870445614E-002, + dn: 1.6452860548183366E-003, + dn1: 0.10809563217808144, + dn2: 0.20642195434625446, + tau: 9.2006637361187298E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + tauOut: 1.5594219393746818E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 8.1926049685687600E-005, + dmin1: 8.9258234858565516E-002, + dmin2: 8.9258234858565516E-002, + dn: 8.1926049685687600E-005, + dn1: 0.10847668953277810, + dn2: 0.20701876553386761, + tau: 1.5594219393746818E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + tauOut: 8.1416944590412474E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 5.0612658152462498E-007, + dmin1: 8.9177229293753768E-002, + dmin2: 8.9177229293753768E-002, + dn: 5.0612658152462498E-007, + dn1: 0.10831524323681536, + dn2: 0.20814970454128662, + tau: 8.1416944590412474E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + tauOut: 5.0604049633765406E-007, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 8.6071246971392626E-011, + dmin1: 8.9183660885577137E-002, + dmin2: 8.9183660885577137E-002, + dn: 8.6071246971392626E-011, + dn1: 0.10814239569959758, + dn2: 0.20876277035564564, + tau: 5.0604049633765406E-007, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + tauOut: 8.6071215292546838E-011, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 3.1678834699165494E-017, + dmin1: 8.9200650586607991E-002, + dmin2: 8.9200650586607991E-002, + dn: 3.1678834699165494E-017, + dn1: 0.10805126770967630, + dn2: 0.20900961033533805, + tau: 8.6071215292546838E-011, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + tauOut: 3.1678834698836348E-017, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + i0: 1, + n0: 9, + pp: 0, + n0in: 10, + dmin: 3.1678834699165494E-017, + dmin1: 8.9240528714785800E-002, + dmin2: 8.9240528714785800E-002, + dn: 3.1678834699165494E-017, + dn1: 0.10800416691102718, + dn2: 0.20896705170504334, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + tauOut: 2.2310132178696450E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 6.7023851586769906E-002, + dmin1: 6.7023851586769906E-002, + dmin2: 6.7023851586769906E-002, + dn: 8.5666701693601133E-002, + dn1: 0.18606768031923254, + dn2: 6.7023851586769906E-002, + tau: 2.2310132178696450E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + tauOut: 6.4730147312741043E-002, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.5125423409859404E-003, + dmin1: 2.5125423409859404E-003, + dmin2: 2.5125423409859404E-003, + dn: 2.0907912921905053E-002, + dn1: 8.1725879285544201E-002, + dn2: 2.5125423409859404E-003, + tau: 6.4730147312741043E-002, + ttype: -5, + g: 0.0000000000000000, + zOut: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + tauOut: 2.3478378904869292E-003, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.6059529570832572E-003, + dmin1: 2.6059529570832572E-003, + dmin2: 2.6059529570832572E-003, + dn: 2.0187357299561493E-002, + dn1: 4.4537716273149721E-003, + dn2: 2.6059529570832572E-003, + tau: 5.8695947262173229E-004, + ttype: -17, + g: 0.0000000000000000, + zOut: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + tauOut: 4.9324499328963489E-004, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.0870277779300500E-003, + dmin1: 1.0870277779300500E-003, + dmin2: 4.1771462483342674E-002, + dn: 1.7484624889890960E-002, + dn1: 1.0870277779300500E-003, + dn2: 4.1771462483342674E-002, + tau: 4.9324499328963489E-004, + ttype: -5, + g: 0.0000000000000000, + zOut: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + tauOut: 8.6238530354903250E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 3.2884671240747138E-004, + dmin1: 3.2884671240747138E-004, + dmin2: 0.11762155840411674, + dn: 1.4027859154437344E-003, + dn1: 3.2884671240747138E-004, + dn2: 0.11762155840411674, + tau: 8.6238530354903250E-004, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + tauOut: 1.8442717265434725E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 3.4295817345512611E-006, + dmin1: 2.3532871395603098E-003, + dmin2: 0.12033927154650945, + dn: 3.4295817345512611E-006, + dn1: 2.3532871395603098E-003, + dn2: 0.12033927154650945, + tau: 1.8442717265434725E-004, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + tauOut: 3.2077610710809750E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 3.3505760549073344E-012, + dmin1: 1.7569442559804263E-002, + dmin2: 0.12036545569713296, + dn: 3.3505760549073344E-012, + dn1: 1.7569442559804263E-002, + dn2: 0.12036545569713296, + tau: 3.2077610710809750E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + tauOut: 3.3505364896797715E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.0335799151090034E-023, + dmin1: 1.8784357595683275E-002, + dmin2: 0.12036607551035594, + dn: 2.0335799151090034E-023, + dn1: 1.8784357595683275E-002, + dn2: 0.12036607551035594, + tau: 3.3505364896797715E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + tauOut: 2.0335799151089990E-023, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + n0in: 9, + dmin: 2.0335799151089993E-023, + dmin1: 1.8784577209116738E-002, + dmin2: 0.12036616599993906, + dn: 2.0335799151089993E-023, + dn1: 1.8784577209116738E-002, + dn2: 0.12036616599993906, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + tauOut: 1.8784576682472597E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + i0: 1, + n0: 8, + pp: 0, + n0in: 8, + dmin: 1.1910047947871760E-010, + dmin1: 0.10158160343929173, + dmin2: 0.48640978493259379, + dn: 1.1910047947871760E-010, + dn1: 0.10158160343929173, + dn2: 0.48640978493259379, + tau: 1.8784576682472597E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + tauOut: 1.1910047900088848E-010, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + n0in: 8, + dmin: 0.0000000000000000, + dmin1: 0.10158160552407068, + dmin2: 0.48500827096381138, + dn: 0.0000000000000000, + dn1: 0.10158160552407068, + dn2: 0.48500827096381138, + tau: 1.1910047900088848E-010, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + i0: 1, + n0: 7, + pp: 0, + n0in: 8, + dmin: 0.0000000000000000, + dmin1: 0.10158160593161437, + dmin2: 0.48388184445926297, + dn: 0.0000000000000000, + dn1: 0.10158160593161437, + dn2: 0.48388184445926297, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + i0: 1, + n0: 7, + pp: 1, + n0in: 7, + dmin: 0.10158160593161437, + dmin1: 0.48298010023310722, + dmin2: 0.60332139679048247, + dn: 0.10158160593161437, + dn1: 0.48298010023310722, + dn2: 0.60332139679048247, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + tauOut: 0.10158160593161437, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + i0: 1, + n0: 7, + pp: 0, + n0in: 7, + dmin: 0.0000000000000000, + dmin1: 0.38053382595775820, + dmin2: 0.50278793042091730, + dn: 0.0000000000000000, + dn1: 0.38053382595775820, + dn2: 0.50278793042091730, + tau: 0.10158160593161437, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 7, + dmin: 0.0000000000000000, + dmin1: 0.37988164443454930, + dmin2: 0.50365062581387521, + dn: 0.0000000000000000, + dn1: 0.37988164443454930, + dn2: 0.50365062581387521, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + i0: 1, + n0: 6, + pp: 0, + n0in: 6, + dmin: 0.37939119035907048, + dmin1: 0.50449560273072791, + dmin2: 0.93712213699945368, + dn: 0.37939119035907048, + dn1: 0.50449560273072791, + dn2: 1.0004335774214996, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + tauOut: 0.37791671367087804, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 6, + dmin: 1.7417124602014944E-005, + dmin1: 0.12721465844156904, + dmin2: 0.55997778901175921, + dn: 1.7417124602014944E-005, + dn1: 0.12721465844156904, + dn2: 0.60606091447901145, + tau: 0.37791671367087804, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + tauOut: 1.7220607103034587E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + i0: 1, + n0: 6, + pp: 0, + n0in: 6, + dmin: 5.8496704963934779E-012, + dmin1: 0.12768433261716639, + dmin2: 0.56397303984076830, + dn: 5.8496704963934779E-012, + dn1: 0.12768433261716639, + dn2: 0.58884056200405466, + tau: 1.7220607103034587E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + tauOut: 5.8496615949827599E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 6, + dmin: 5.2413685591311719E-023, + dmin1: 0.12914058828956335, + dmin2: 0.57178448001987381, + dn: 5.2413685591311719E-023, + dn1: 0.12914058828956335, + dn2: 0.57178448001987381, + tau: 5.8496615949827599E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + tauOut: 5.2413685591311714E-023, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + i0: 1, + n0: 5, + pp: 0, + n0in: 6, + dmin: 5.2413685591311719E-023, + dmin1: 0.12914059800027977, + dmin2: 0.55574794205624078, + dn: 5.2413685591311719E-023, + dn1: 0.12914059800027977, + dn2: 0.55574794205624078, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + tauOut: 0.12914051019182277, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 2.8760335918365243E-008, + dmin1: 0.40854091047624980, + dmin2: 0.47735135942481804, + dn: 2.8760335918365243E-008, + dn1: 0.40854091047624980, + dn2: 0.47735135942481804, + tau: 0.12914051019182277, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + tauOut: 2.8760330654564486E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 9.5429721930147733E-016, + dmin1: 0.39406941605409296, + dmin2: 0.49198119275848701, + dn: 9.5429721930147733E-016, + dn1: 0.39406941605409296, + dn2: 0.49198119275848701, + tau: 2.8760330654564486E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + tauOut: 9.5429721930146451E-016, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 5, + dmin: 1.9721522630525295E-030, + dmin1: 0.38317668529976806, + dmin2: 0.50907067170667131, + dn: 1.9721522630525295E-030, + dn1: 0.38317668529976806, + dn2: 0.50907067170667131, + tau: 9.5429721930146451E-016, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + tauOut: 0.31895966905528556, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 4.4735699115826311E-002, + dmin1: 0.20335674284478694, + dmin2: 0.35119999573453003, + dn: 4.4735699115826311E-002, + dn1: 0.20335674284478694, + dn2: 0.41662457975226058, + tau: 0.31895966905528556, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + tauOut: 3.9897804510299034E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 3.2556800493375310E-004, + dmin1: 0.17365859019389857, + dmin2: 0.31130219122423097, + dn: 3.2556800493375310E-004, + dn1: 0.17365859019389857, + dn2: 0.37770462156728835, + tau: 3.9897804510299034E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + tauOut: 3.1797943619548145E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.3065740500455263E-007, + dmin1: 0.19246898670783216, + dmin2: 0.31098421178803548, + dn: 1.3065740500455263E-007, + dn1: 0.19246898670783216, + dn2: 0.37861255440045072, + tau: 3.1797943619548145E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + tauOut: 1.3065240973281283E-007, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 4.4031878668096113E-014, + dmin1: 0.19679806330970273, + dmin2: 0.31098408113562576, + dn: 4.4031878668096113E-014, + dn1: 0.19679806330970273, + dn2: 0.37930556169107532, + tau: 1.3065240973281283E-007, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + tauOut: 4.4031878666982759E-014, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 5.0676424551397798E-027, + dmin1: 0.19671064247077341, + dmin2: 0.31098408113558174, + dn: 5.0676424551397798E-027, + dn1: 0.19671064247077341, + dn2: 0.37965850286956282, + tau: 4.4031878666982759E-014, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + tauOut: 5.0676424551397798E-027, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 4, + dmin: 5.0676424551397798E-027, + dmin1: 0.19666151937261311, + dmin2: 0.31098408113558174, + dn: 5.0676424551397798E-027, + dn1: 0.19666151937261311, + dn2: 0.37984162221587608, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + tauOut: 9.8330759686306557E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 9.8296460175394978E-002, + dmin1: 0.21265332144927518, + dmin2: 0.21265332144927518, + dn: 9.8296460175394978E-002, + dn1: 0.28160574127978810, + dn2: 0.21265332144927518, + tau: 9.8330759686306557E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + tauOut: 9.7172513485343004E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 1.1056745151512559E-003, + dmin1: 0.11548080796393217, + dmin2: 0.11548080796393217, + dn: 1.1056745151512559E-003, + dn1: 0.18448235089755655, + dn2: 0.11548080796393217, + tau: 9.7172513485343004E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + tauOut: 1.0942861809085330E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 1.1278200095129901E-005, + dmin1: 0.11438652178302365, + dmin2: 0.11438652178302365, + dn: 1.1278200095129901E-005, + dn1: 0.18342236422755959, + dn2: 0.11438652178302365, + tau: 1.0942861809085330E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + tauOut: 1.1269238360546607E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 8.9549629620034135E-009, + dmin1: 0.11437525254466312, + dmin2: 0.11437525254466312, + dn: 8.9549629620034135E-009, + dn1: 0.18342936716409974, + dn2: 0.11437525254466312, + tau: 1.1269238360546607E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + tauOut: 8.9549072084035346E-009, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 5.5753269291151117E-014, + dmin1: 0.11437524358975594, + dmin2: 0.11437524358975594, + dn: 5.5753269291151117E-014, + dn1: 0.18342946834334006, + dn2: 0.11437524358975594, + tau: 8.9549072084035346E-009, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + tauOut: 5.5753269214454873E-014, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: -0.0000000000000000, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + tau: 0.0000000000000000, + ttype: 0, + g: 0.0000000000000000, + zOut: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + tauOut: 0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 7.8766827084626452E-005, + dmin1: 1.2363512593342330E-003, + dmin2: 1.2363512593342330E-003, + dn: 7.8766827084626452E-005, + dn1: 4.3867054272813191E-003, + dn2: 3.7622286348031123E-003, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02, 0.1037537856266618 - 321}, + tauOut: 0.0000000000000000, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 7.8192294615504193E-005, + dmin1: 7.2365102959979382E-004, + dmin2: 1.7075768415239889E-002, + dn: 7.8192294615504193E-005, + dn1: 7.2365102959979382E-004, + dn2: 1.7075768415239889E-002, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + tauOut: 7.8083356181667918E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 3.6610242528964756E-008, + dmin1: 6.2053891278358614E-004, + dmin2: 2.9611625055501498E-002, + dn: 3.6610242528964756E-008, + dn1: 6.2053891278358614E-004, + dn2: 9.1148025223602810E-002, + tau: 7.8083356181667918E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.1037537856266618 - 321}, + tauOut: 3.6605973538398975E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 4.0593516462113082E-015, + dmin1: 6.2079410376128833E-004, + dmin2: 4.5102919754957636E-002, + dn: 4.0593516462113082E-015, + dn1: 6.2079410376128833E-004, + dn2: 6.6633580933131861E-002, + tau: 3.6605973538398975E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + tauOut: 4.0593516183260787E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 3.7865323450608567E-029, + dmin1: 6.2086198711654151E-004, + dmin2: 3.9492996735707858E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086198711654151E-004, + dn2: 3.9492996735707858E-002, + tau: 4.0593516183260787E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1037537856266618 - 321}, + tauOut: 3.7865323450608567E-029, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22}, + i0: 1, + n0: 20, + pp: 0, + n0in: 21, + dmin: 3.7865323450608567E-029, + dmin1: 6.2086189351765679E-004, + dmin2: 2.8198643003083550E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086189351765679E-004, + dn2: 2.8198643003083550E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22}, + tauOut: 0.0000000000000000, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 6.2086189110482101E-004, + dmin1: 2.5181951038433764E-002, + dmin2: 8.7297525620826724E-002, + dn: 6.2086189110482101E-004, + dn1: 2.5181951038433764E-002, + dn2: 9.4282269055547374E-002, + tau: 0.0000000000000000, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04}, + tauOut: 6.2086189103875732E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 3.2573770070154495E-015, + dmin1: 2.3851725145806461E-002, + dmin2: 8.6019261441467765E-002, + dn: 3.2573770070154495E-015, + dn1: 2.3851725145806461E-002, + dn2: 0.10407400868154487, + tau: 6.2086189103875732E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03}, + tauOut: 3.2573770070067200E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 9.4663308626521417E-029, + dmin1: 2.3692824533332088E-002, + dmin2: 7.0611780886194908E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3692824533332088E-002, + dn2: 0.10576950347767239, + tau: 3.2573770070067200E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04}, + tauOut: 9.4663308626521417E-029, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26}, + i0: 1, + n0: 19, + pp: 0, + n0in: 20, + dmin: 9.4663308626521417E-029, + dmin1: 2.3656857476986041E-002, + dmin2: 7.0305173122617720E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3656857476986041E-002, + dn2: 0.10451478588027406, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26}, + tauOut: 1.1828428738493020E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 1.1818926896585069E-002, + dmin1: 5.9707584261797009E-002, + dmin2: 5.9707584261797009E-002, + dn: 1.1818926896585069E-002, + dn1: 8.9511673871889130E-002, + dn2: 5.9707584261797009E-002, + tau: 1.1828428738493020E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03}, + tauOut: 1.1689473904977585E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.2789903011516807E-004, + dmin1: 4.9975042235645591E-002, + dmin2: 4.9975042235645591E-002, + dn: 1.2789903011516807E-004, + dn1: 7.2258424646843816E-002, + dn2: 4.9975042235645591E-002, + tau: 1.1689473904977585E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04}, + tauOut: 1.1689473904977585E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 7.7577072096399712E-010, + dmin1: 5.3179116896294863E-002, + dmin2: 5.3179116896294863E-002, + dn: 7.7577072096399712E-010, + dn1: 6.5255212904451090E-002, + dn2: 5.3179116896294863E-002, + tau: 1.2789520868072135E-004, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03}, + tauOut: 1.2789520868072135E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.0135599141977102E-019, + dmin1: 5.8414457514939733E-002, + dmin2: 5.8777374831867304E-002, + dn: 1.0135599141977102E-019, + dn1: 5.8414457514939733E-002, + dn2: 5.8777374831867304E-002, + tau: 7.7577068041483555E-010, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05}, + tauOut: 1.0135599141977091E-019, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.2434478048112329E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 19, + dmin: 1.0135599141977093E-019, + dmin1: 5.1614639267802333E-002, + dmin2: 5.1614639267802333E-002, + dn: 1.0135599141977093E-019, + dn1: 5.2901697084955956E-002, + dn2: 6.5660305799035965E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.2434478048112329E-01}, + tauOut: 1.2903659816950583E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2605878684924073E+01, 0.2615950460208911E+01, 0.1945503997226627E-02, 0.2831884532112553E-02, 0.1792287311167312E+01, 0.1790238034184775E+01, 0.1831165540887852E-01, 0.1689844079671380E-01, 0.1912064812489923E+01, 0.1942176087759744E+01, 0.5350346462390188E-03, 0.1104039956008399E-02, 0.9149979242236238E+00, 0.9266158484293474E+00, 0.2199691768758329E-02, 0.1820770257466081E-02, 0.1425451464914127E+01, 0.1105418651305687E+01, 0.2857477273065492E+00, 0.3351361651941490E+00, 0.9167409543554429E+00, 0.1215385144271246E+01, 0.7843816205451699E-05, 0.7197207696703830E-05, 0.1003973806896052E+01, 0.9991024098509327E+00, 0.9418498631040351E-02, 0.1778290067827487E-01, 0.5121827465172590E+00, 0.5317426047035739E+00, 0.2263732461064059E-02, 0.2762300261676148E-02, 0.4201365406709412E+00, 0.4197388406228219E+00, 0.3107071375346623E-01, 0.1556509232613395E-01, 0.1196803030427524E+01, 0.8386678292065533E+00, 0.3403588894097180E+00, 0.4021095747913879E+00, 0.1359492109368225E+01, 0.1013013804731768E+01, 0.2411467892724848E+00, 0.6997408538631263E+00, 0.3392875246772514E+00, 0.4685122433619579E+00, 0.1652848117124708E+00, 0.1248257304047288E+00, 0.4228949559754990E+00, 0.4492589344427766E+00, 0.1708424320817961E+00, 0.1518244930621437E+00, 0.3159848280636428E+00, 0.4758679007372426E+00, 0.6745243660763246E-01, 0.2386301922514691E-01, 0.8251512110211983E+00, 0.8931789553886716E+00, 0.7711819686391232E-03, 0.1232835205710967E-01, 0.3794316855579739E-01, 0.5161612293293578E-01, 0.3606500256058598E-05, 0.1887408451311279E-05, 0.6510811153270980E-01, 0.7250261437426894E-01, 0.4479235177066975E-02, 0.5512763475647510E-02, 0.3551880209093845E-01, 0.5290169708495600E-01, 0.7843816205451699E-05, 0.7197207696703830E-05}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 3.5518802090938446E-002, + dmin1: 3.7941281147346073E-002, + dmin2: 3.7941281147346073E-002, + dn: 3.5518802090938446E-002, + dn1: 5.9595348057062299E-002, + dn2: 3.7941281147346073E-002, + tau: 1.2903659816950583E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2605878684924073E+01, 0.2615950460208911E+01, 0.1945503997226627E-02, 0.2831884532112553E-02, 0.1792287311167312E+01, 0.1790238034184775E+01, 0.1831165540887852E-01, 0.1689844079671380E-01, 0.1912064812489923E+01, 0.1942176087759744E+01, 0.5350346462390188E-03, 0.1104039956008399E-02, 0.9149979242236238E+00, 0.9266158484293474E+00, 0.2199691768758329E-02, 0.1820770257466081E-02, 0.1425451464914127E+01, 0.1105418651305687E+01, 0.2857477273065492E+00, 0.3351361651941490E+00, 0.9167409543554429E+00, 0.1215385144271246E+01, 0.7843816205451699E-05, 0.7197207696703830E-05, 0.1003973806896052E+01, 0.9991024098509327E+00, 0.9418498631040351E-02, 0.1778290067827487E-01, 0.5121827465172590E+00, 0.5317426047035739E+00, 0.2263732461064059E-02, 0.2762300261676148E-02, 0.4201365406709412E+00, 0.4197388406228219E+00, 0.3107071375346623E-01, 0.1556509232613395E-01, 0.1196803030427524E+01, 0.8386678292065533E+00, 0.3403588894097180E+00, 0.4021095747913879E+00, 0.1359492109368225E+01, 0.1013013804731768E+01, 0.2411467892724848E+00, 0.6997408538631263E+00, 0.3392875246772514E+00, 0.4685122433619579E+00, 0.1652848117124708E+00, 0.1248257304047288E+00, 0.4228949559754990E+00, 0.4492589344427766E+00, 0.1708424320817961E+00, 0.1518244930621437E+00, 0.3159848280636428E+00, 0.4758679007372426E+00, 0.6745243660763246E-01, 0.2386301922514691E-01, 0.8251512110211983E+00, 0.8931789553886716E+00, 0.7711819686391232E-03, 0.1232835205710967E-01, 0.3794316855579739E-01, 0.5161612293293578E-01, 0.3606500256058598E-05, 0.1887408451311279E-05, 0.6510811153270980E-01, 0.7250261437426894E-01, 0.4479235177066975E-02, 0.5512763475647510E-02, 0.3551880209093845E-01, 0.5290169708495600E-01, 0.7843816205451699E-05, 0.7197207696703830E-05}, + tauOut: 2.4222106054237202E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2605878684924073E+01, 0.2583602082867062E+01, 0.1945503997226627E-02, 0.1349628161076996E-02, 0.1792287311167312E+01, 0.1785027232360876E+01, 0.1831165540887852E-01, 0.1961486711855321E-01, 0.1912064812489923E+01, 0.1868762873963372E+01, 0.5350346462390188E-03, 0.2619677421449130E-03, 0.9149979242236238E+00, 0.8927135421960001E+00, 0.2199691768758329E-02, 0.3512385223173503E-02, 0.1425451464914127E+01, 0.1683464700943265E+01, 0.2857477273065492E+00, 0.1556056649653108E+00, 0.9167409543554429E+00, 0.7369210271521004E+00, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.1003973806896052E+01, 0.9891595131364276E+00, 0.9418498631040351E-02, 0.4876860034049891E-02, 0.5121827465172590E+00, 0.4853475128900360E+00, 0.2263732461064059E-02, 0.1959578858316830E-02, 0.4201365406709412E+00, 0.4250255695118534E+00, 0.3107071375346623E-01, 0.8749008776201990E-01, 0.1196803030427524E+01, 0.1425449726020986E+01, 0.3403588894097180E+00, 0.3246099922425689E+00, 0.1359492109368225E+01, 0.1251806800343904E+01, 0.2411467892724848E+00, 0.6536000379104072E-01, 0.3392875246772514E+00, 0.4149902265444443E+00, 0.1652848117124708E+00, 0.1684331550518530E+00, 0.4228949559754990E+00, 0.4010821269512049E+00, 0.1708424320817961E+00, 0.1345949193440586E+00, 0.3159848280636428E+00, 0.2246202392729794E+00, 0.6745243660763246E-01, 0.2477891570824889E+00, 0.8251512110211983E+00, 0.5539111298531113E+00, 0.7711819686391232E-03, 0.5282632149136541E-04, 0.3794316855579739E-01, 0.1367184268032488E-01, 0.3606500256058598E-05, 0.1717489195894037E-04, 0.6510811153270980E-01, 0.4534806576358064E-01, 0.4479235177066975E-02, 0.3508353996892708E-02, 0.3551880209093845E-01, 0.7788342039808532E-02, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.2434478048112329E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 7.7883420398085317E-003, + dmin1: 1.3668236180068825E-002, + dmin2: 1.3668236180068825E-002, + dn: 7.7883420398085317E-003, + dn1: 4.0868830586513666E-002, + dn2: 1.3668236180068825E-002, + tau: 2.4222106054237202E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2605878684924073E+01, 0.2583602082867062E+01, 0.1945503997226627E-02, 0.1349628161076996E-02, 0.1792287311167312E+01, 0.1785027232360876E+01, 0.1831165540887852E-01, 0.1961486711855321E-01, 0.1912064812489923E+01, 0.1868762873963372E+01, 0.5350346462390188E-03, 0.2619677421449130E-03, 0.9149979242236238E+00, 0.8927135421960001E+00, 0.2199691768758329E-02, 0.3512385223173503E-02, 0.1425451464914127E+01, 0.1683464700943265E+01, 0.2857477273065492E+00, 0.1556056649653108E+00, 0.9167409543554429E+00, 0.7369210271521004E+00, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.1003973806896052E+01, 0.9891595131364276E+00, 0.9418498631040351E-02, 0.4876860034049891E-02, 0.5121827465172590E+00, 0.4853475128900360E+00, 0.2263732461064059E-02, 0.1959578858316830E-02, 0.4201365406709412E+00, 0.4250255695118534E+00, 0.3107071375346623E-01, 0.8749008776201990E-01, 0.1196803030427524E+01, 0.1425449726020986E+01, 0.3403588894097180E+00, 0.3246099922425689E+00, 0.1359492109368225E+01, 0.1251806800343904E+01, 0.2411467892724848E+00, 0.6536000379104072E-01, 0.3392875246772514E+00, 0.4149902265444443E+00, 0.1652848117124708E+00, 0.1684331550518530E+00, 0.4228949559754990E+00, 0.4010821269512049E+00, 0.1708424320817961E+00, 0.1345949193440586E+00, 0.3159848280636428E+00, 0.2246202392729794E+00, 0.6745243660763246E-01, 0.2477891570824889E+00, 0.8251512110211983E+00, 0.5539111298531113E+00, 0.7711819686391232E-03, 0.5282632149136541E-04, 0.3794316855579739E-01, 0.1367184268032488E-01, 0.3606500256058598E-05, 0.1717489195894037E-04, 0.6510811153270980E-01, 0.4534806576358064E-01, 0.4479235177066975E-02, 0.3508353996892708E-02, 0.3551880209093845E-01, 0.7788342039808532E-02, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.2434478048112329E-01}, + tauOut: 5.1484099711571517E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + + { + z: []float64{0.1845045664413523E+01, 0.1845045673681623E+01, 0.9284324334305927E-09, 0.1331924177594376E-08, 0.1286110617891388E+01, 0.1286109423357647E+01, 0.8600075793510468E-06, 0.1206062196852843E-05, 0.9228692597002398E+00, 0.9170877606119078E+00, 0.7344017075309068E-02, 0.5782369695935185E-02, 0.1164764979181097E+01, 0.1172109006845551E+01, 0.1416795225784663E-10, 0.1087898982148097E-10, 0.1516899526939413E+01, 0.1516899536394917E+01, 0.1175479719901021E-09, 0.1158688024893155E-08, 0.1569402316257081E+00, 0.1538882419371820E+00, 0.4821181617659422E-02, 0.3052000406097992E-02, 0.2431018491557045E+00, 0.2479152225121892E+00, 0.8755391955186837E-05, 0.7818861198543554E-05, 0.2722314297289909E+00, 0.2722202019375114E+00, 0.1357252989661879E-04, 0.1999378345859679E-04, 0.1847873189363651E+00, 0.1848009020627515E+00, 0.2027258571663375E-18, 0.3534048617228375E-11, 0.4750110334503861E-13, 0.1060007138617788E-07, 0.1416795225784663E-10, 0.1087898982148097E-10}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 4.7501103345038606E-014, + dmin1: 0.15388823121961009, + dmin2: 0.15388823121961009, + dn: 4.7501103345038606E-014, + dn1: 0.18478731893283101, + dn2: 0.27221143594553232, + tau: 1.0600023884871808E-008, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1845045664413523E+01, 0.1845045673681623E+01, 0.9284324334305927E-09, 0.1331924177594376E-08, 0.1286110617891388E+01, 0.1286109423357647E+01, 0.8600075793510468E-06, 0.1206062196852843E-05, 0.9228692597002398E+00, 0.9170877606119078E+00, 0.7344017075309068E-02, 0.5782369695935185E-02, 0.1164764979181097E+01, 0.1172109006845551E+01, 0.1416795225784663E-10, 0.1087898982148097E-10, 0.1516899526939413E+01, 0.1516899536394917E+01, 0.1175479719901021E-09, 0.1158688024893155E-08, 0.1569402316257081E+00, 0.1538882419371820E+00, 0.4821181617659422E-02, 0.3052000406097992E-02, 0.2431018491557045E+00, 0.2479152225121892E+00, 0.8755391955186837E-05, 0.7818861198543554E-05, 0.2722314297289909E+00, 0.2722202019375114E+00, 0.1357252989661879E-04, 0.1999378345859679E-04, 0.1847873189363651E+00, 0.1848009020627515E+00, 0.2027258571663375E-18, 0.3534048617228375E-11, 0.4750110334503861E-13, 0.1060007138617788E-07, 0.1416795225784663E-10, 0.1087898982148097E-10}, + tauOut: 4.7501103294055340E-014, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1845045664413523E+01, 0.1845045665341908E+01, 0.9284324334305927E-09, 0.6471746651368383E-09, 0.1286110617891388E+01, 0.1286111477251745E+01, 0.8600075793510468E-06, 0.6171117917307419E-06, 0.9228692597002398E+00, 0.9302126596637096E+00, 0.7344017075309068E-02, 0.9195804644198721E-02, 0.1164764979181097E+01, 0.1155569174551018E+01, 0.1416795225784663E-10, 0.1859807318413278E-10, 0.1516899526939413E+01, 0.1516899527038316E+01, 0.1175479719901021E-09, 0.1216165317638265E-10, 0.1569402316257081E+00, 0.1617614132311584E+00, 0.4821181617659422E-02, 0.7245474325163344E-02, 0.2431018491557045E+00, 0.2358651302224488E+00, 0.8755391955186837E-05, 0.1010532106865606E-04, 0.2722314297289909E+00, 0.2722348969377714E+00, 0.1357252989661879E-04, 0.9212747663842461E-05, 0.1847873189363651E+00, 0.1847781061886537E+00, 0.2027258571663375E-18, 0.5211495068651724E-31, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 10, + dmin: 5.0983266199979805E-023, + dmin1: 0.15694023161349893, + dmin2: 0.15694023161349893, + dn: 5.0983266199979805E-023, + dn1: 0.18477810618865373, + dn2: 0.27222132440787472, + tau: 4.7501103294055340E-014, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1845045664413523E+01, 0.1845045665341908E+01, 0.9284324334305927E-09, 0.6471746651368383E-09, 0.1286110617891388E+01, 0.1286111477251745E+01, 0.8600075793510468E-06, 0.6171117917307419E-06, 0.9228692597002398E+00, 0.9302126596637096E+00, 0.7344017075309068E-02, 0.9195804644198721E-02, 0.1164764979181097E+01, 0.1155569174551018E+01, 0.1416795225784663E-10, 0.1859807318413278E-10, 0.1516899526939413E+01, 0.1516899527038316E+01, 0.1175479719901021E-09, 0.1216165317638265E-10, 0.1569402316257081E+00, 0.1617614132311584E+00, 0.4821181617659422E-02, 0.7245474325163344E-02, 0.2431018491557045E+00, 0.2358651302224488E+00, 0.8755391955186837E-05, 0.1010532106865606E-04, 0.2722314297289909E+00, 0.2722348969377714E+00, 0.1357252989661879E-04, 0.9212747663842461E-05, 0.1847873189363651E+00, 0.1847781061886537E+00, 0.2027258571663375E-18, 0.5211495068651724E-31, 0.8046649468928653E+00}, + tauOut: 3.9235057903374733E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1805810608085708E+01, 0.1845045665341908E+01, 0.4609225136302542E-09, 0.6471746651368383E-09, 0.1246877035999240E+01, 0.1286111477251745E+01, 0.4603863769418564E-06, 0.6171117917307419E-06, 0.9001729460181566E+00, 0.9302126596637096E+00, 0.1180482975969687E-01, 0.9195804644198721E-02, 0.1104529286906545E+01, 0.1155569174551018E+01, 0.2554156666668993E-10, 0.1859807318413278E-10, 0.1477664469121561E+01, 0.1516899527038316E+01, 0.1331348385339719E-11, 0.1216165317638265E-10, 0.1297718296516156E+00, 0.1617614132311584E+00, 0.1316891924708087E-01, 0.7245474325163344E-02, 0.1834712583930619E+00, 0.2358651302224488E+00, 0.1499428882618218E-04, 0.1010532106865606E-04, 0.2329940574932343E+00, 0.2722348969377714E+00, 0.7306255294378852E-05, 0.9212747663842461E-05, 0.1455357420299846E+00, 0.1847781061886537E+00, 0.1331348385339719E-11, 0.1216165317638265E-10}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 0.12252635532645229, + dmin1: 0.12252635532645229, + dmin2: 0.12252635532645229, + dn: 0.14553574202998462, + dn1: 0.23298484474557046, + dn2: 0.18346115307199323, + tau: 3.9235057903374733E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1805810608085708E+01, 0.1845045665341908E+01, 0.4609225136302542E-09, 0.6471746651368383E-09, 0.1246877035999240E+01, 0.1286111477251745E+01, 0.4603863769418564E-06, 0.6171117917307419E-06, 0.9001729460181566E+00, 0.9302126596637096E+00, 0.1180482975969687E-01, 0.9195804644198721E-02, 0.1104529286906545E+01, 0.1155569174551018E+01, 0.2554156666668993E-10, 0.1859807318413278E-10, 0.1477664469121561E+01, 0.1516899527038316E+01, 0.1331348385339719E-11, 0.1216165317638265E-10, 0.1297718296516156E+00, 0.1617614132311584E+00, 0.1316891924708087E-01, 0.7245474325163344E-02, 0.1834712583930619E+00, 0.2358651302224488E+00, 0.1499428882618218E-04, 0.1010532106865606E-04, 0.2329940574932343E+00, 0.2722348969377714E+00, 0.7306255294378852E-05, 0.9212747663842461E-05, 0.1455357420299846E+00, 0.1847781061886537E+00, 0.1331348385339719E-11, 0.1216165317638265E-10}, + tauOut: 3.0631588831613071E-002, + ttypeOut: -6, + gOut: 0.25000000000000000, + }, + { + z: []float64{0.1805810608085708E+01, 0.1775179019715018E+01, 0.4609225136302542E-09, 0.3237497126982006E-09, 0.1246877035999240E+01, 0.1216245907230254E+01, 0.4603863769418564E-06, 0.3407430674789675E-06, 0.9001729460181566E+00, 0.8813458462031728E+00, 0.1180482975969687E-01, 0.1479416990810367E-01, 0.1104529286906545E+01, 0.1059103528192370E+01, 0.2554156666668993E-10, 0.3563567162644001E-10, 0.1477664469121561E+01, 0.1447032880255644E+01, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.1297718296516156E+00, 0.1123091600669640E+00, 0.1316891924708087E-01, 0.2151309995104528E-01, 0.1834712583930619E+00, 0.1313415638992297E+00, 0.1499428882618218E-04, 0.2659919745982362E-04, 0.2329940574932343E+00, 0.2023431757194558E+00, 0.7306255294378852E-05, 0.5255039029347846E-05, 0.1455357420299846E+00, 0.1148988981593422E+00, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 9.9140240819883152E-002, + dmin1: 9.9140240819883152E-002, + dmin2: 9.9140240819883152E-002, + dn: 0.11489889815934221, + dn1: 0.20233586946416143, + dn2: 0.13132656961040354, + tau: 3.0631588831613071E-002, + ttype: -6, + g: 0.25000000000000000, + zOut: []float64{0.1805810608085708E+01, 0.1775179019715018E+01, 0.4609225136302542E-09, 0.3237497126982006E-09, 0.1246877035999240E+01, 0.1216245907230254E+01, 0.4603863769418564E-06, 0.3407430674789675E-06, 0.9001729460181566E+00, 0.8813458462031728E+00, 0.1180482975969687E-01, 0.1479416990810367E-01, 0.1104529286906545E+01, 0.1059103528192370E+01, 0.2554156666668993E-10, 0.3563567162644001E-10, 0.1477664469121561E+01, 0.1447032880255644E+01, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.1297718296516156E+00, 0.1123091600669640E+00, 0.1316891924708087E-01, 0.2151309995104528E-01, 0.1834712583930619E+00, 0.1313415638992297E+00, 0.1499428882618218E-04, 0.2659919745982362E-04, 0.2329940574932343E+00, 0.2023431757194558E+00, 0.7306255294378852E-05, 0.5255039029347846E-05, 0.1455357420299846E+00, 0.1148988981593422E+00, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.8046649468928653E+00}, + tauOut: 4.9545335349736611E-002, + ttypeOut: -6, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1725633684689031E+01, 0.1775179019715018E+01, 0.2281824158451768E-09, 0.3237497126982006E-09, 0.1166700912395402E+01, 0.1216245907230254E+01, 0.2574031475886406E-06, 0.3407430674789675E-06, 0.8465944233583922E+00, 0.8813458462031728E+00, 0.1850774953630535E-01, 0.1479416990810367E-01, 0.9910504433419636E+00, 0.1059103528192370E+01, 0.5203164874187830E-10, 0.3563567162644001E-10, 0.1397487544853995E+01, 0.1447032880255644E+01, 0.9595353465813834E-14, 0.1193970905752580E-12, 0.8427692466826309E-01, 0.1123091600669640E+00, 0.3352713928531350E-01, 0.2151309995104528E-01, 0.4829568846163943E-01, 0.1313415638992297E+00, 0.1114419580100731E-03, 0.2659919745982362E-04, 0.1526916534507385E+00, 0.2023431757194558E+00, 0.3954362799871079E-05, 0.5255039029347846E-05, 0.6534960844680572E-01, 0.1148988981593422E+00, 0.9595353465813834E-14, 0.1193970905752580E-12}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 4.8269089264179610E-002, + dmin1: 4.8269089264179610E-002, + dmin2: 4.8269089264179610E-002, + dn: 6.5349608446805721E-002, + dn1: 0.15268639841170917, + dn2: 4.8269089264179610E-002, + tau: 4.9545335349736611E-002, + ttype: -6, + g: 0.49975000000000003, + zOut: []float64{0.1725633684689031E+01, 0.1775179019715018E+01, 0.2281824158451768E-09, 0.3237497126982006E-09, 0.1166700912395402E+01, 0.1216245907230254E+01, 0.2574031475886406E-06, 0.3407430674789675E-06, 0.8465944233583922E+00, 0.8813458462031728E+00, 0.1850774953630535E-01, 0.1479416990810367E-01, 0.9910504433419636E+00, 0.1059103528192370E+01, 0.5203164874187830E-10, 0.3563567162644001E-10, 0.1397487544853995E+01, 0.1447032880255644E+01, 0.9595353465813834E-14, 0.1193970905752580E-12, 0.8427692466826309E-01, 0.1123091600669640E+00, 0.3352713928531350E-01, 0.2151309995104528E-01, 0.4829568846163943E-01, 0.1313415638992297E+00, 0.1114419580100731E-03, 0.2659919745982362E-04, 0.1526916534507385E+00, 0.2023431757194558E+00, 0.3954362799871079E-05, 0.5255039029347846E-05, 0.6534960844680572E-01, 0.1148988981593422E+00, 0.9595353465813834E-14, 0.1193970905752580E-12}, + tauOut: 1.2037453975339630E-002, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1725633684689031E+01, 0.1713596230941874E+01, 0.2281824158451768E-09, 0.1553578538234923E-09, 0.1166700912395402E+01, 0.1154663715667853E+01, 0.2574031475886406E-06, 0.1887268702969492E-06, 0.8465944233583922E+00, 0.8530645301924875E+00, 0.1850774953630535E-01, 0.2150143715280096E-01, 0.9910504433419636E+00, 0.9575115522658546E+00, 0.5203164874187830E-10, 0.7594016059954953E-10, 0.1397487544853995E+01, 0.1385450090802725E+01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8427692466826309E-01, 0.1057666099782364E+00, 0.3352713928531350E-01, 0.1530933320323569E-01, 0.4829568846163943E-01, 0.2106034324107419E-01, 0.1114419580100731E-03, 0.8079762346493418E-03, 0.1526916534507385E+00, 0.1398501776035494E+00, 0.3954362799871079E-05, 0.1847806452993955E-05, 0.6534960844680572E-01, 0.5331030666501309E-01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.0948901283064113E-002, + dmin1: 2.0948901283064113E-002, + dmin2: 2.0948901283064113E-002, + dn: 5.3310306665013088E-002, + dn1: 0.13984622324074955, + dn2: 2.0948901283064113E-002, + tau: 1.2037453975339630E-002, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1725633684689031E+01, 0.1713596230941874E+01, 0.2281824158451768E-09, 0.1553578538234923E-09, 0.1166700912395402E+01, 0.1154663715667853E+01, 0.2574031475886406E-06, 0.1887268702969492E-06, 0.8465944233583922E+00, 0.8530645301924875E+00, 0.1850774953630535E-01, 0.2150143715280096E-01, 0.9910504433419636E+00, 0.9575115522658546E+00, 0.5203164874187830E-10, 0.7594016059954953E-10, 0.1397487544853995E+01, 0.1385450090802725E+01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8427692466826309E-01, 0.1057666099782364E+00, 0.3352713928531350E-01, 0.1530933320323569E-01, 0.4829568846163943E-01, 0.2106034324107419E-01, 0.1114419580100731E-03, 0.8079762346493418E-03, 0.1526916534507385E+00, 0.1398501776035494E+00, 0.3954362799871079E-05, 0.1847806452993955E-05, 0.6534960844680572E-01, 0.5331030666501309E-01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8046649468928653E+00}, + tauOut: 1.1070386405955311E-002, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1702525844691276E+01, 0.1713596230941874E+01, 0.1053646717395619E-09, 0.1553578538234923E-09, 0.1143593517883403E+01, 0.1154663715667853E+01, 0.1407809649380857E-06, 0.1887268702969492E-06, 0.8634954401583683E+00, 0.8530645301924875E+00, 0.2384248197112572E-01, 0.2150143715280096E-01, 0.9225986839647138E+00, 0.9575115522658546E+00, 0.1140379931457212E-09, 0.7594016059954953E-10, 0.1374379704282732E+01, 0.1385450090802725E+01, 0.4491802194179927E-16, 0.5836853211617396E-15, 0.1100055567755167E+00, 0.1057666099782364E+00, 0.2930941140637693E-02, 0.1530933320323569E-01, 0.7866991929130526E-02, 0.2106034324107419E-01, 0.1436325611276508E-01, 0.8079762346493418E-03, 0.1144183828912820E+00, 0.1398501776035494E+00, 0.8609379557504958E-06, 0.1847806452993955E-05, 0.4223905932110202E-01, 0.5331030666501309E-01, 0.4491802194179927E-16, 0.5836853211617396E-15}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 7.0590156944811844E-003, + dmin1: 7.0590156944811844E-003, + dmin2: 7.0590156944811844E-003, + dn: 4.2239059321102022E-002, + dn1: 0.11441653508482905, + dn2: 7.0590156944811844E-003, + tau: 1.1070386405955311E-002, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1702525844691276E+01, 0.1713596230941874E+01, 0.1053646717395619E-09, 0.1553578538234923E-09, 0.1143593517883403E+01, 0.1154663715667853E+01, 0.1407809649380857E-06, 0.1887268702969492E-06, 0.8634954401583683E+00, 0.8530645301924875E+00, 0.2384248197112572E-01, 0.2150143715280096E-01, 0.9225986839647138E+00, 0.9575115522658546E+00, 0.1140379931457212E-09, 0.7594016059954953E-10, 0.1374379704282732E+01, 0.1385450090802725E+01, 0.4491802194179927E-16, 0.5836853211617396E-15, 0.1100055567755167E+00, 0.1057666099782364E+00, 0.2930941140637693E-02, 0.1530933320323569E-01, 0.7866991929130526E-02, 0.2106034324107419E-01, 0.1436325611276508E-01, 0.8079762346493418E-03, 0.1144183828912820E+00, 0.1398501776035494E+00, 0.8609379557504958E-06, 0.1847806452993955E-05, 0.4223905932110202E-01, 0.5331030666501309E-01, 0.4491802194179927E-16, 0.5836853211617396E-15}, + tauOut: 5.5670727120955849E-003, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1702525844691276E+01, 0.1696958772084545E+01, 0.1053646717395619E-09, 0.7100605954454643E-10, 0.1143593517883403E+01, 0.1138026585881266E+01, 0.1407809649380857E-06, 0.1068197551738174E-06, 0.8634954401583683E+00, 0.8817707425976433E+00, 0.2384248197112572E-01, 0.2494644177488929E-01, 0.9225986839647138E+00, 0.8920851695917670E+00, 0.1140379931457212E-09, 0.1756911880603681E-09, 0.1374379704282732E+01, 0.1368812631394945E+01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.1100055567755167E+00, 0.1073694252040588E+00, 0.2930941140637693E-02, 0.2147509894397918E-03, 0.7866991929130526E-02, 0.1644842434036023E-01, 0.1436325611276508E-01, 0.9991355423895336E-01, 0.1144183828912820E+00, 0.8938616878188867E-02, 0.8609379557504958E-06, 0.4068326216494222E-05, 0.4223905932110202E-01, 0.3666791828278994E-01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.0851682275951503E-003, + dmin1: 2.0851682275951503E-003, + dmin2: 2.0851682275951503E-003, + dn: 3.6667918282789938E-002, + dn1: 8.9377559402331157E-003, + dn2: 2.0851682275951503E-003, + tau: 5.5670727120955849E-003, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1702525844691276E+01, 0.1696958772084545E+01, 0.1053646717395619E-09, 0.7100605954454643E-10, 0.1143593517883403E+01, 0.1138026585881266E+01, 0.1407809649380857E-06, 0.1068197551738174E-06, 0.8634954401583683E+00, 0.8817707425976433E+00, 0.2384248197112572E-01, 0.2494644177488929E-01, 0.9225986839647138E+00, 0.8920851695917670E+00, 0.1140379931457212E-09, 0.1756911880603681E-09, 0.1374379704282732E+01, 0.1368812631394945E+01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.1100055567755167E+00, 0.1073694252040588E+00, 0.2930941140637693E-02, 0.2147509894397918E-03, 0.7866991929130526E-02, 0.1644842434036023E-01, 0.1436325611276508E-01, 0.9991355423895336E-01, 0.1144183828912820E+00, 0.8938616878188867E-02, 0.8609379557504958E-06, 0.4068326216494222E-05, 0.4223905932110202E-01, 0.3666791828278994E-01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.8046649468928653E+00}, + tauOut: 1.1659821590613959E-003, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695792789996490E+01, 0.1696958772084545E+01, 0.4765133098633433E-10, 0.7100605954454643E-10, 0.1136860710494309E+01, 0.1138026585881266E+01, 0.8285142935651389E-07, 0.1068197551738174E-06, 0.9055511193620417E+00, 0.8817707425976433E+00, 0.2457547703893446E-01, 0.2494644177488929E-01, 0.8663437105694624E+00, 0.8920851695917670E+00, 0.2775899617066991E-09, 0.1756911880603681E-09, 0.1367646648958294E+01, 0.1368812631394945E+01, 0.2833987723936393E-18, 0.3609867340226789E-17, 0.1064181940344372E+00, 0.1073694252040588E+00, 0.3319277717374952E-04, 0.2147509894397918E-03, 0.1151628036430784E+00, 0.1644842434036023E-01, 0.7755012504281143E-02, 0.9991355423895336E-01, 0.2169054106282214E-04, 0.8938616878188867E-02, 0.6877516463147774E-02, 0.4068326216494222E-05, 0.2862441966058077E-01, 0.3666791828278994E-01, 0.2833987723936393E-18, 0.3609867340226789E-17}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.7622214846327918E-005, + dmin1: 1.7622214846327918E-005, + dmin2: 1.5249249404125084E-002, + dn: 2.8624419660580765E-002, + dn1: 1.7622214846327918E-005, + dn2: 1.5249249404125084E-002, + tau: 1.1659821590613959E-003, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1695792789996490E+01, 0.1696958772084545E+01, 0.4765133098633433E-10, 0.7100605954454643E-10, 0.1136860710494309E+01, 0.1138026585881266E+01, 0.8285142935651389E-07, 0.1068197551738174E-06, 0.9055511193620417E+00, 0.8817707425976433E+00, 0.2457547703893446E-01, 0.2494644177488929E-01, 0.8663437105694624E+00, 0.8920851695917670E+00, 0.2775899617066991E-09, 0.1756911880603681E-09, 0.1367646648958294E+01, 0.1368812631394945E+01, 0.2833987723936393E-18, 0.3609867340226789E-17, 0.1064181940344372E+00, 0.1073694252040588E+00, 0.3319277717374952E-04, 0.2147509894397918E-03, 0.1151628036430784E+00, 0.1644842434036023E-01, 0.7755012504281143E-02, 0.9991355423895336E-01, 0.2169054106282214E-04, 0.8938616878188867E-02, 0.6877516463147774E-02, 0.4068326216494222E-05, 0.2862441966058077E-01, 0.3666791828278994E-01, 0.2833987723936393E-18, 0.3609867340226789E-17}, + tauOut: 1.2076215031173109E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695792789996490E+01, 0.1695780713829110E+01, 0.4765133098633433E-10, 0.3194571418305606E-10, 0.1136860710494309E+01, 0.1136848717098761E+01, 0.8285142935651389E-07, 0.6599488873594650E-07, 0.9055511193620417E+00, 0.9301144541910563E+00, 0.2457547703893446E-01, 0.2289052693567938E-01, 0.8663437105694624E+00, 0.8434411076963417E+00, 0.2775899617066991E-09, 0.4501143914475995E-09, 0.1367646648958294E+01, 0.1367634572293148E+01, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.1064181940344372E+00, 0.1064393105965798E+00, 0.3319277717374952E-04, 0.3591317210346347E-04, 0.1151628036430784E+00, 0.1228698267602250E+00, 0.7755012504281143E-02, 0.1369013219942635E-05, 0.2169054106282214E-04, 0.6885761775959480E-02, 0.6877516463147774E-02, 0.2859014352646020E-01, 0.2862441966058077E-01, 0.2219991908939190E-04, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 8.2453128117063980E-006, + dmin1: 8.2453128117063980E-006, + dmin2: 0.10640611781940604, + dn: 2.2199919089391903E-005, + dn1: 8.2453128117063980E-006, + dn2: 0.11511481425594380, + tau: 1.2076215031173109E-005, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1695792789996490E+01, 0.1695780713829110E+01, 0.4765133098633433E-10, 0.3194571418305606E-10, 0.1136860710494309E+01, 0.1136848717098761E+01, 0.8285142935651389E-07, 0.6599488873594650E-07, 0.9055511193620417E+00, 0.9301144541910563E+00, 0.2457547703893446E-01, 0.2289052693567938E-01, 0.8663437105694624E+00, 0.8434411076963417E+00, 0.2775899617066991E-09, 0.4501143914475995E-09, 0.1367646648958294E+01, 0.1367634572293148E+01, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.1064181940344372E+00, 0.1064393105965798E+00, 0.3319277717374952E-04, 0.3591317210346347E-04, 0.1151628036430784E+00, 0.1228698267602250E+00, 0.7755012504281143E-02, 0.1369013219942635E-05, 0.2169054106282214E-04, 0.6885761775959480E-02, 0.6877516463147774E-02, 0.2859014352646020E-01, 0.2862441966058077E-01, 0.2219991908939190E-04, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.8046649468928653E+00}, + tauOut: 3.2770273787704380E-006, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695777436833677E+01, 0.1695780713829110E+01, 0.2141639781080129E-10, 0.3194571418305606E-10, 0.1136845506044855E+01, 0.1136848717098761E+01, 0.5399396803668456E-07, 0.6599488873594650E-07, 0.9530016501053890E+00, 0.9301144541910563E+00, 0.2025894854667596E-01, 0.2289052693567938E-01, 0.8231788825724013E+00, 0.8434411076963417E+00, 0.7478228806194929E-09, 0.4501143914475995E-09, 0.1367631294517947E+01, 0.1367634572293148E+01, 0.1716235185693175E-20, 0.2205178646452290E-19, 0.1064719467413045E+00, 0.1064393105965798E+00, 0.4144420544393849E-04, 0.3591317210346347E-04, 0.1228264745406222E+00, 0.1228698267602250E+00, 0.7674810284932935E-07, 0.1369013219942635E-05, 0.3547255152693805E-01, 0.6885761775959480E-02, 0.1789267604726782E-04, 0.2859014352646020E-01, 0.1030215663353646E-05, 0.2219991908939190E-04, 0.1716235185693175E-20, 0.2205178646452290E-19}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.0302156633536465E-006, + dmin1: 6.8824080004778604E-003, + dmin2: 0.10643603356920101, + dn: 1.0302156633536465E-006, + dn1: 6.8824080004778604E-003, + dn2: 0.12282510552740224, + tau: 3.2770273787704380E-006, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1695777436833677E+01, 0.1695780713829110E+01, 0.2141639781080129E-10, 0.3194571418305606E-10, 0.1136845506044855E+01, 0.1136848717098761E+01, 0.5399396803668456E-07, 0.6599488873594650E-07, 0.9530016501053890E+00, 0.9301144541910563E+00, 0.2025894854667596E-01, 0.2289052693567938E-01, 0.8231788825724013E+00, 0.8434411076963417E+00, 0.7478228806194929E-09, 0.4501143914475995E-09, 0.1367631294517947E+01, 0.1367634572293148E+01, 0.1716235185693175E-20, 0.2205178646452290E-19, 0.1064719467413045E+00, 0.1064393105965798E+00, 0.4144420544393849E-04, 0.3591317210346347E-04, 0.1228264745406222E+00, 0.1228698267602250E+00, 0.7674810284932935E-07, 0.1369013219942635E-05, 0.3547255152693805E-01, 0.6885761775959480E-02, 0.1789267604726782E-04, 0.2859014352646020E-01, 0.1030215663353646E-05, 0.2219991908939190E-04, 0.1716235185693175E-20, 0.2205178646452290E-19}, + tauOut: 1.0296962592568820E-006, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695777436833677E+01, 0.1695776407158834E+01, 0.2141639781080129E-10, 0.1435751523850387E-10, 0.1136845506044855E+01, 0.1136844530328206E+01, 0.5399396803668456E-07, 0.4526242530264241E-07, 0.9530016501053890E+00, 0.9732595236933804E+00, 0.2025894854667596E-01, 0.1713493494875720E-01, 0.8231788825724013E+00, 0.8060429186752077E+00, 0.7478228806194929E-09, 0.1268848035998799E-08, 0.1367631294517947E+01, 0.1367630263552839E+01, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.1064719467413045E+00, 0.1065123612504892E+00, 0.4144420544393849E-04, 0.4779206455525695E-04, 0.1228264745406222E+00, 0.1227777295279105E+00, 0.7674810284932935E-07, 0.2217381803186623E-07, 0.3547255152693805E-01, 0.3548939233290803E-01, 0.1789267604726782E-04, 0.5194035150079302E-09, 0.1030215663353646E-05, 0.5817566277343568E-15, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 5.8175662773435680E-016, + dmin1: 3.5471499656860764E-002, + dmin2: 0.10647091704504522, + dn: 5.8175662773435680E-016, + dn1: 3.5471499656860764E-002, + dn2: 0.12277765277980766, + tau: 1.0296962592568820E-006, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695777436833677E+01, 0.1695776407158834E+01, 0.2141639781080129E-10, 0.1435751523850387E-10, 0.1136845506044855E+01, 0.1136844530328206E+01, 0.5399396803668456E-07, 0.4526242530264241E-07, 0.9530016501053890E+00, 0.9732595236933804E+00, 0.2025894854667596E-01, 0.1713493494875720E-01, 0.8231788825724013E+00, 0.8060429186752077E+00, 0.7478228806194929E-09, 0.1268848035998799E-08, 0.1367631294517947E+01, 0.1367630263552839E+01, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.1064719467413045E+00, 0.1065123612504892E+00, 0.4144420544393849E-04, 0.4779206455525695E-04, 0.1228264745406222E+00, 0.1227777295279105E+00, 0.7674810284932935E-07, 0.2217381803186623E-07, 0.3547255152693805E-01, 0.3548939233290803E-01, 0.1789267604726782E-04, 0.5194035150079302E-09, 0.1030215663353646E-05, 0.5817566277343568E-15, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.8046649468928653E+00}, + tauOut: 5.8175661922007790E-016, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695776407173191E+01, 0.1695776407158834E+01, 0.9625244577618415E-11, 0.1435751523850387E-10, 0.1136844575581005E+01, 0.1136844530328206E+01, 0.3874943632355666E-07, 0.4526242530264241E-07, 0.9903944198927007E+00, 0.9732595236933804E+00, 0.1394544708652782E-01, 0.1713493494875720E-01, 0.7920974728575274E+00, 0.8060429186752077E+00, 0.2190784636165185E-08, 0.1268848035998799E-08, 0.1367630261362054E+01, 0.1367630263552839E+01, 0.1040577915698430E-22, 0.1336113320657127E-21, 0.1065601533150438E+00, 0.1065123612504892E+00, 0.5506562249584694E-04, 0.4779206455525695E-04, 0.1227226860792321E+00, 0.1227777295279105E+00, 0.6412305277798032E-08, 0.2217381803186623E-07, 0.3548938644000568E-01, 0.3548939233290803E-01, 0.8514276171981532E-23, 0.5194035150079302E-09, 0.2761013168273541E-29, 0.5817566277343568E-15, 0.1040577915698430E-22, 0.1336113320657127E-21}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.7610131682735413E-030, + dmin1: 3.5489385920602169E-002, + dmin2: 0.10651236125048857, + dn: 2.7610131682735413E-030, + dn1: 3.5489385920602169E-002, + dn2: 0.12272266390541409, + tau: 5.8175661922007790E-016, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695776407173191E+01, 0.1695776407158834E+01, 0.9625244577618415E-11, 0.1435751523850387E-10, 0.1136844575581005E+01, 0.1136844530328206E+01, 0.3874943632355666E-07, 0.4526242530264241E-07, 0.9903944198927007E+00, 0.9732595236933804E+00, 0.1394544708652782E-01, 0.1713493494875720E-01, 0.7920974728575274E+00, 0.8060429186752077E+00, 0.2190784636165185E-08, 0.1268848035998799E-08, 0.1367630261362054E+01, 0.1367630263552839E+01, 0.1040577915698430E-22, 0.1336113320657127E-21, 0.1065601533150438E+00, 0.1065123612504892E+00, 0.5506562249584694E-04, 0.4779206455525695E-04, 0.1227226860792321E+00, 0.1227777295279105E+00, 0.6412305277798032E-08, 0.2217381803186623E-07, 0.3548938644000568E-01, 0.3548939233290803E-01, 0.8514276171981532E-23, 0.5194035150079302E-09, 0.2761013168273541E-29, 0.5817566277343568E-15, 0.1040577915698430E-22, 0.1336113320657127E-21}, + tauOut: 2.7610131682735413E-030, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695776407173191E+01, 0.1695776407182817E+01, 0.9625244577618415E-11, 0.6452741670633652E-11, 0.1136844575581005E+01, 0.1136844614323989E+01, 0.3874943632355666E-07, 0.3375767015588020E-07, 0.9903944198927007E+00, 0.1004339833221559E+01, 0.1394544708652782E-01, 0.1099842207759001E-01, 0.7920974728575274E+00, 0.7810990529707220E+00, 0.2190784636165185E-08, 0.3835855840755795E-08, 0.1367630261362054E+01, 0.1367630257526198E+01, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.1065601533150438E+00, 0.1066152189375397E+00, 0.5506562249584694E-04, 0.6338495733216447E-04, 0.1227226860792321E+00, 0.1226593075342052E+00, 0.6412305277798032E-08, 0.1855291575909163E-08, 0.3548938644000568E-01, 0.3548938458471410E-01, 0.8514276171981532E-23, 0.6623960630549781E-51, 0.9539342071687115E+00}, + i0: 1, + n0: 8, + pp: 1, + n0in: 9, + dmin: 2.7610131682735413E-030, + dmin1: 3.5489384584714102E-002, + dmin2: 0.10656015331504384, + dn: 2.7610131682735413E-030, + dn1: 3.5489384584714102E-002, + dn2: 0.12265930112189996, + tau: 0.0000000000000000, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695776407173191E+01, 0.1695776407182817E+01, 0.9625244577618415E-11, 0.6452741670633652E-11, 0.1136844575581005E+01, 0.1136844614323989E+01, 0.3874943632355666E-07, 0.3375767015588020E-07, 0.9903944198927007E+00, 0.1004339833221559E+01, 0.1394544708652782E-01, 0.1099842207759001E-01, 0.7920974728575274E+00, 0.7810990529707220E+00, 0.2190784636165185E-08, 0.3835855840755795E-08, 0.1367630261362054E+01, 0.1367630257526198E+01, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.1065601533150438E+00, 0.1066152189375397E+00, 0.5506562249584694E-04, 0.6338495733216447E-04, 0.1227226860792321E+00, 0.1226593075342052E+00, 0.6412305277798032E-08, 0.1855291575909163E-08, 0.3548938644000568E-01, 0.3548938458471410E-01, 0.8514276171981532E-23, 0.6623960630549781E-51, 0.9539342071687115E+00}, + tauOut: 1.7744692292357051E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1678031714896912E+01, 0.1695776407182817E+01, 0.4371648372768990E-11, 0.6452741670633652E-11, 0.1119099955784930E+01, 0.1136844614323989E+01, 0.3029592900888367E-07, 0.3375767015588020E-07, 0.9975935327108624E+00, 0.1004339833221559E+01, 0.8611580555893368E-02, 0.1099842207759001E-01, 0.7547427839583274E+00, 0.7810990529707220E+00, 0.6950755439903452E-08, 0.3835855840755795E-08, 0.1349885558283086E+01, 0.1367630257526198E+01, 0.6403582257922030E-25, 0.8107757314001177E-24, 0.8893391160251481E-01, 0.1066152189375397E+00, 0.8742171388117141E-04, 0.6338495733216447E-04, 0.1048271953832586E+00, 0.1226593075342052E+00, 0.6281113981299557E-09, 0.1855291575909163E-08, 0.1774469166424565E-01, 0.3548938458471410E-01, 0.6403582257922030E-25, 0.8107757314001177E-24}, + i0: 1, + n0: 8, + pp: 0, + n0in: 8, + dmin: 1.7744691664245655E-002, + dmin1: 8.8870526645182649E-002, + dmin2: 8.8870526645182649E-002, + dn: 1.7744691664245655E-002, + dn1: 0.10482719352796703, + dn2: 8.8870526645182649E-002, + tau: 1.7744692292357051E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.1678031714896912E+01, 0.1695776407182817E+01, 0.4371648372768990E-11, 0.6452741670633652E-11, 0.1119099955784930E+01, 0.1136844614323989E+01, 0.3029592900888367E-07, 0.3375767015588020E-07, 0.9975935327108624E+00, 0.1004339833221559E+01, 0.8611580555893368E-02, 0.1099842207759001E-01, 0.7547427839583274E+00, 0.7810990529707220E+00, 0.6950755439903452E-08, 0.3835855840755795E-08, 0.1349885558283086E+01, 0.1367630257526198E+01, 0.6403582257922030E-25, 0.8107757314001177E-24, 0.8893391160251481E-01, 0.1066152189375397E+00, 0.8742171388117141E-04, 0.6338495733216447E-04, 0.1048271953832586E+00, 0.1226593075342052E+00, 0.6281113981299557E-09, 0.1855291575909163E-08, 0.1774469166424565E-01, 0.3548938458471410E-01, 0.6403582257922030E-25, 0.8107757314001177E-24}, + tauOut: 1.7743283373674822E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1678031714896912E+01, 0.1660288431527609E+01, 0.4371648372768990E-11, 0.2946663608425970E-11, 0.1119099955784930E+01, 0.1101356702704238E+01, 0.3029592900888367E-07, 0.2744162973950316E-07, 0.9975935327108624E+00, 0.9884618024514511E+00, 0.8611580555893368E-02, 0.6575396506892930E-02, 0.7547427839583274E+00, 0.7304241110285150E+00, 0.6950755439903452E-08, 0.1284558415558242E-07, 0.1349885558283086E+01, 0.1332142262063827E+01, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.8893391160251481E-01, 0.7127804994272115E-01, 0.8742171388117141E-04, 0.1285693574547170E-03, 0.1048271953832586E+00, 0.8695534328024046E-01, 0.6281113981299557E-09, 0.1281766326273249E-09, 0.1774469166424565E-01, 0.1408162394200135E-05, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.9539342071687115E+00}, + i0: 1, + n0: 8, + pp: 1, + n0in: 8, + dmin: 1.4081623942001353E-006, + dmin1: 7.1190628228839981E-002, + dmin2: 7.1190628228839981E-002, + dn: 1.4081623942001353E-006, + dn1: 8.6955342652129064E-002, + dn2: 7.1190628228839981E-002, + tau: 1.7743283373674822E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1678031714896912E+01, 0.1660288431527609E+01, 0.4371648372768990E-11, 0.2946663608425970E-11, 0.1119099955784930E+01, 0.1101356702704238E+01, 0.3029592900888367E-07, 0.2744162973950316E-07, 0.9975935327108624E+00, 0.9884618024514511E+00, 0.8611580555893368E-02, 0.6575396506892930E-02, 0.7547427839583274E+00, 0.7304241110285150E+00, 0.6950755439903452E-08, 0.1284558415558242E-07, 0.1349885558283086E+01, 0.1332142262063827E+01, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.8893391160251481E-01, 0.7127804994272115E-01, 0.8742171388117141E-04, 0.1285693574547170E-03, 0.1048271953832586E+00, 0.8695534328024046E-01, 0.6281113981299557E-09, 0.1281766326273249E-09, 0.1774469166424565E-01, 0.1408162394200135E-05, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.9539342071687115E+00}, + tauOut: 1.4081069428512511E-006, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7127804994272115E-01, 0.1565683011922014E-03, 0.1285693574547170E-03, 0.8679736700028205E-01, 0.8695534328024046E-01, 0.2079481441878513E-14, 0.1281766326273249E-09, 0.5544926940271698E-10, 0.1408162394200135E-05, 0.1565683011922014E-03, 0.1285693574547170E-03}, + i0: 6, + n0: 8, + pp: 0, + n0in: 8, + dmin: 5.5449269402716976E-011, + dmin1: 7.1276641835778295E-002, + dmin2: 7.1276641835778295E-002, + dn: 5.5449269402716976E-011, + dn1: 8.6797366872105416E-002, + dn2: 7.1276641835778295E-002, + tau: 1.4081069428512511E-006, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7127804994272115E-01, 0.1565683011922014E-03, 0.1285693574547170E-03, 0.8679736700028205E-01, 0.8695534328024046E-01, 0.2079481441878513E-14, 0.1281766326273249E-09, 0.5544926940271698E-10, 0.1408162394200135E-05, 0.1565683011922014E-03, 0.1285693574547170E-03}, + tauOut: 5.5449260598506680E-011, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7156177943897596E-01, 0.1565683011922014E-03, 0.1899018778701386E-03, 0.8679736700028205E-01, 0.8660746506696473E-01, 0.2079481441878513E-14, 0.1331360138522907E-23, 0.5544926940271698E-10, 0.8804208964992894E-17, 0.1565683011922014E-03, 0.8679736700028205E-01, 0.9539342071687115E+00}, + i0: 6, + n0: 8, + pp: 1, + n0in: 8, + dmin: 8.8042089649928937E-018, + dmin1: 7.1405211137783753E-002, + dmin2: 7.1405211137783753E-002, + dn: 8.8042089649928937E-018, + dn1: 8.6607465066962652E-002, + dn2: 7.1405211137783753E-002, + tau: 5.5449260598506680E-011, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7156177943897596E-01, 0.1565683011922014E-03, 0.1899018778701386E-03, 0.8679736700028205E-01, 0.8660746506696473E-01, 0.2079481441878513E-14, 0.1331360138522907E-23, 0.5544926940271698E-10, 0.8804208964992894E-17, 0.1565683011922014E-03, 0.8679736700028205E-01, 0.9539342071687115E+00}, + tauOut: 8.8042089649574750E-018, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: -0.60723548073666500, + dmin1: 7.1561779438975959E-002, + dmin2: 7.1561779438975959E-002, + dn: 8.8042089649928937E-018, + dn1: 8.6378245068883266E-002, + dn2: 7.1561779438975959E-002, + tau: 0.0000000000000000, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26}, + tauOut: 0.60723548073666500, + ttypeOut: -1, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1053051542688903E+01, 0.1954678721190348E-11, 0.2044340400431280E-11, 0.1101355322036970E+01, 0.4941198659270088E+00, 0.2462874809952034E-07, 0.4959623550114665E-07, 0.9950357662226532E+00, 0.3926270253492309E+00, 0.4826789459478154E-02, 0.8920167341580701E-02, 0.7255959263076781E+00, 0.1094403018130068E+00, 0.2358357443050565E-07, 0.2870664819501689E-06, 0.1332140830373310E+01, 0.7249050625701626E+00, -0.9894235909416862E+00, 0.2044340400431280E-11, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 0.10944027822943236, + dmin1: 0.10944027822943236, + dmin2: 0.38780023588975276, + dn: 0.72490506257016263, + dn1: 0.10944027822943236, + dn2: 0.38780023588975276, + tau: 0.60723548073666500, + ttype: -1, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1053051542688903E+01, 0.1954678721190348E-11, 0.2044340400431280E-11, 0.1101355322036970E+01, 0.4941198659270088E+00, 0.2462874809952034E-07, 0.4959623550114665E-07, 0.9950357662226532E+00, 0.3926270253492309E+00, 0.4826789459478154E-02, 0.8920167341580701E-02, 0.7255959263076781E+00, 0.1094403018130068E+00, 0.2358357443050565E-07, 0.2870664819501689E-06, 0.1332140830373310E+01, 0.7249050625701626E+00, -0.9894235909416862E+00, 0.2044340400431280E-11, 0.1077066053646038E+01}, + tauOut: 9.0381042476589277E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9626705002143580E+00, 0.1053051542688903E+01, 0.1049319787347115E-11, 0.2044340400431280E-11, 0.4037388730456057E+00, 0.4941198659270088E+00, 0.4823122991958101E-07, 0.4959623550114665E-07, 0.3111661019829924E+00, 0.3926270253492309E+00, 0.3137314122148422E-02, 0.8920167341580701E-02, 0.1592223228075105E-01, 0.1094403018130068E+00, 0.1306952080528672E-04, 0.2870664819501689E-06, 0.6345109505727681E+00, 0.7249050625701626E+00, 0.1049319787347115E-11, 0.2044340400431280E-11}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 1.5921945214269095E-002, + dmin1: 1.5921945214269095E-002, + dmin2: 0.30224593464141175, + dn: 0.63451095057276807, + dn1: 1.5921945214269095E-002, + dn2: 0.30224593464141175, + tau: 9.0381042476589277E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9626705002143580E+00, 0.1053051542688903E+01, 0.1049319787347115E-11, 0.2044340400431280E-11, 0.4037388730456057E+00, 0.4941198659270088E+00, 0.4823122991958101E-07, 0.4959623550114665E-07, 0.3111661019829924E+00, 0.3926270253492309E+00, 0.3137314122148422E-02, 0.8920167341580701E-02, 0.1592223228075105E-01, 0.1094403018130068E+00, 0.1306952080528672E-04, 0.2870664819501689E-06, 0.6345109505727681E+00, 0.7249050625701626E+00, 0.1049319787347115E-11, 0.2044340400431280E-11}, + tauOut: 1.4134050686447828E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9626705002143580E+00, 0.9485364495289594E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.4037388730456057E+00, 0.3896048705899411E+00, 0.4823122991958101E-07, 0.3852088344069326E-07, 0.3111661019829924E+00, 0.3001693268978096E+00, 0.3137314122148422E-02, 0.1664162181618706E-03, 0.1592223228075105E-01, 0.1634834896946635E-02, 0.1306952080528672E-04, 0.5072533064458891E-02, 0.6345109505727681E+00, 0.6153043668218613E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 1.6217653761413479E-003, + dmin1: 1.6217653761413479E-003, + dmin2: 0.29703201277566116, + dn: 0.61530436682186129, + dn1: 1.6217653761413479E-003, + dn2: 0.29703201277566116, + tau: 1.4134050686447828E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9626705002143580E+00, 0.9485364495289594E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.4037388730456057E+00, 0.3896048705899411E+00, 0.4823122991958101E-07, 0.3852088344069326E-07, 0.3111661019829924E+00, 0.3001693268978096E+00, 0.3137314122148422E-02, 0.1664162181618706E-03, 0.1592223228075105E-01, 0.1634834896946635E-02, 0.1306952080528672E-04, 0.5072533064458891E-02, 0.6345109505727681E+00, 0.6153043668218613E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.1077066053646038E+01}, + tauOut: 1.5809617416939919E-003, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469554877877121E+00, 0.9485364495289594E+00, 0.1837592531426069E-12, 0.4466366986934060E-12, 0.3880239473689468E+00, 0.3896048705899411E+00, 0.2979915990315817E-07, 0.3852088344069326E-07, 0.2987547515751175E+00, 0.3001693268978096E+00, 0.9106567826436868E-06, 0.1664162181618706E-03, 0.5125495562928890E-02, 0.1634834896946635E-02, 0.6089463364253304E+00, 0.5072533064458891E-02, 0.4777068654836977E-02, 0.6153043668218613E+00, 0.1837592531426069E-12, 0.4466366986934060E-12}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 5.2962498469998932E-005, + dmin1: 5.2962498469998932E-005, + dmin2: 0.29858833535695567, + dn: 4.7770686548369769E-003, + dn1: 5.2962498469998932E-005, + dn2: 0.29858833535695567, + tau: 1.5809617416939919E-003, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469554877877121E+00, 0.9485364495289594E+00, 0.1837592531426069E-12, 0.4466366986934060E-12, 0.3880239473689468E+00, 0.3896048705899411E+00, 0.2979915990315817E-07, 0.3852088344069326E-07, 0.2987547515751175E+00, 0.3001693268978096E+00, 0.9106567826436868E-06, 0.1664162181618706E-03, 0.5125495562928890E-02, 0.1634834896946635E-02, 0.6089463364253304E+00, 0.5072533064458891E-02, 0.4777068654836977E-02, 0.6153043668218613E+00, 0.1837592531426069E-12, 0.4466366986934060E-12}, + tauOut: 4.7621670852039755E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469554877877121E+00, 0.9469159823779022E+00, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.3880239473689468E+00, 0.3879844717580378E+00, 0.2979915990315817E-07, 0.2294586835827609E-07, 0.2987547515751175E+00, 0.2987161338760382E+00, 0.9106567826436868E-06, 0.1562542751952015E-07, 0.5125495562928890E-02, 0.6140323109528382E+00, 0.6089463364253304E+00, 0.4737500623869755E-02, 0.4777068654836977E-02, 0.6262097360996939E-07, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 6.2620973609969386E-008, + dmin1: 5.0859745275077589E-003, + dmin2: 0.29871522321925559, + dn: 6.2620973609969386E-008, + dn1: 5.0859745275077589E-003, + dn2: 0.29871522321925559, + tau: 3.9505409993611756E-005, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.9469554877877121E+00, 0.9469159823779022E+00, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.3880239473689468E+00, 0.3879844717580378E+00, 0.2979915990315817E-07, 0.2294586835827609E-07, 0.2987547515751175E+00, 0.2987161338760382E+00, 0.9106567826436868E-06, 0.1562542751952015E-07, 0.5125495562928890E-02, 0.6140323109528382E+00, 0.6089463364253304E+00, 0.4737500623869755E-02, 0.4777068654836977E-02, 0.6262097360996939E-07, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.1077066053646038E+01}, + tauOut: 6.2141437994562936E-008, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202365395E+00, 0.9469159823779022E+00, 0.3085312975855001E-13, 0.7530022947855128E-13, 0.3879844325624373E+00, 0.3879844717580378E+00, 0.1766643326162244E-07, 0.2294586835827609E-07, 0.2987160696935945E+00, 0.2987161338760382E+00, 0.3211918722443868E-07, 0.1562542751952015E-07, 0.6187697173160828E+00, 0.6140323109528382E+00, 0.4794463808464251E-09, 0.4737500623869755E-02, 0.8923456002485611E-13, 0.6262097360996939E-07, 0.3085312975855001E-13, 0.7530022947855128E-13}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 8.9234560024856112E-014, + dmin1: 0.29871605406816698, + dmin2: 0.29871605406816698, + dn: 8.9234560024856112E-014, + dn1: 0.61403221669221297, + dn2: 0.29871605406816698, + tau: 6.2141437994562936E-008, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.9469159202365395E+00, 0.9469159823779022E+00, 0.3085312975855001E-13, 0.7530022947855128E-13, 0.3879844325624373E+00, 0.3879844717580378E+00, 0.1766643326162244E-07, 0.2294586835827609E-07, 0.2987160696935945E+00, 0.2987161338760382E+00, 0.3211918722443868E-07, 0.1562542751952015E-07, 0.6187697173160828E+00, 0.6140323109528382E+00, 0.4794463808464251E-09, 0.4737500623869755E-02, 0.8923456002485611E-13, 0.6262097360996939E-07, 0.3085312975855001E-13, 0.7530022947855128E-13}, + tauOut: 8.9232014685788963E-014, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202365395E+00, 0.9469159202364811E+00, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.3879844325624373E+00, 0.3879844502287687E+00, 0.1766643326162244E-07, 0.1360169848638109E-07, 0.2987160696935945E+00, 0.2987160882109940E+00, 0.3211918722443868E-07, 0.6653267495003571E-07, 0.6187697173160828E+00, 0.6187696512627651E+00, 0.4794463808464251E-09, 0.6914234847011291E-22, 0.8923456002485611E-13, 0.2545269924803487E-17, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 2.5452699248034865E-018, + dmin1: 0.29871605609180679, + dmin2: 0.29871605609180679, + dn: 2.5452699248034865E-018, + dn1: 0.61876965078331869, + dn2: 0.29871605609180679, + tau: 8.9232014685788963E-014, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469159202365395E+00, 0.9469159202364811E+00, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.3879844325624373E+00, 0.3879844502287687E+00, 0.1766643326162244E-07, 0.1360169848638109E-07, 0.2987160696935945E+00, 0.2987160882109940E+00, 0.3211918722443868E-07, 0.6653267495003571E-07, 0.6187697173160828E+00, 0.6187696512627651E+00, 0.4794463808464251E-09, 0.6914234847011291E-22, 0.8923456002485611E-13, 0.2545269924803487E-17, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.1077066053646038E+01}, + tauOut: 2.5452699247759164E-018, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202364937E+00, 0.9469159202364811E+00, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.3879844638304620E+00, 0.3879844502287687E+00, 0.1047218779010850E-07, 0.1360169848638109E-07, 0.2987161442714811E+00, 0.2987160882109940E+00, 0.1378177941363543E-06, 0.6653267495003571E-07, 0.6187695134449710E+00, 0.6187696512627651E+00, 0.2844127518685707E-39, 0.6914234847011291E-22}, + i0: 1, + n0: 4, + pp: 0, + n0in: 5, + dmin: 2.5452699248034865E-018, + dmin1: 0.29871607773880621, + dmin2: 0.29871607773880621, + dn: 2.5452699248034865E-018, + dn1: 0.61876951344497100, + dn2: 0.29871607773880621, + tau: 0.0000000000000000, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469159202364937E+00, 0.9469159202364811E+00, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.3879844638304620E+00, 0.3879844502287687E+00, 0.1047218779010850E-07, 0.1360169848638109E-07, 0.2987161442714811E+00, 0.2987160882109940E+00, 0.1378177941363543E-06, 0.6653267495003571E-07, 0.6187695134449710E+00, 0.6187696512627651E+00, 0.2844127518685707E-39, 0.6914234847011291E-22}, + tauOut: 7.4679019434701552E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202364937E+00, 0.8722369008017974E+00, 0.5179704803914515E-14, 0.2304012808102351E-14, 0.3879844638304620E+00, 0.3133054548679459E+00, 0.1047218779010850E-07, 0.9984542273822185E-08, 0.2987161442714811E+00, 0.2240372526700314E+00, 0.1378177941363543E-06, 0.3806395963416417E-06, 0.6187695134449710E+00, 0.5440901133706730E+00, 0.2844127518685707E-39, 0.2304012808102351E-14, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 0.22403711485223726, + dmin1: 0.22403711485223726, + dmin2: 0.31330544439575814, + dn: 0.54409011337067303, + dn1: 0.22403711485223726, + dn2: 0.31330544439575814, + tau: 7.4679019434701552E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.9469159202364937E+00, 0.8722369008017974E+00, 0.5179704803914515E-14, 0.2304012808102351E-14, 0.3879844638304620E+00, 0.3133054548679459E+00, 0.1047218779010850E-07, 0.9984542273822185E-08, 0.2987161442714811E+00, 0.2240372526700314E+00, 0.1378177941363543E-06, 0.3806395963416417E-06, 0.6187695134449710E+00, 0.5440901133706730E+00, 0.2844127518685707E-39, 0.2304012808102351E-14, 0.1702794694134603E+01}, + tauOut: 0.22392121955733330, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6483156812444665E+00, 0.8722369008017974E+00, 0.1113438717814820E-14, 0.2304012808102351E-14, 0.8938424529515379E-01, 0.3133054548679459E+00, 0.2502576838690600E-07, 0.9984542273822185E-08, 0.1163887265260836E-03, 0.2240372526700314E+00, 0.1779401212715201E-02, 0.3806395963416417E-06, 0.3183894926006245E+00, 0.5440901133706730E+00, 0.1113438717814820E-14, 0.2304012808102351E-14}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.1600808692974196E-004, + dmin1: 1.1600808692974196E-004, + dmin2: 8.9384235310611515E-002, + dn: 0.31838949260062449, + dn1: 1.1600808692974196E-004, + dn2: 8.9384235310611515E-002, + tau: 0.22392121955733330, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6483156812444665E+00, 0.8722369008017974E+00, 0.1113438717814820E-14, 0.2304012808102351E-14, 0.8938424529515379E-01, 0.3133054548679459E+00, 0.2502576838690600E-07, 0.9984542273822185E-08, 0.1163887265260836E-03, 0.2240372526700314E+00, 0.1779401212715201E-02, 0.3806395963416417E-06, 0.3183894926006245E+00, 0.5440901133706730E+00, 0.1113438717814820E-14, 0.2304012808102351E-14}, + tauOut: 1.1589031543524988E-004, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6483156812444665E+00, 0.6482265310101248E+00, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.8938424529515379E-01, 0.8929512008657929E-01, 0.2502576838690600E-07, 0.3261899765703413E-10, 0.1163887265260836E-03, 0.1806639672279546E-02, 0.1779401212715201E-02, 0.3135891777105103E+00, 0.3183894926006245E+00, 0.4711164655771408E-02, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 2.7238459564345061E-005, + dmin1: 2.7238459564345061E-005, + dmin2: 8.9295095060810903E-002, + dn: 4.7111646557714080E-003, + dn1: 2.7238459564345061E-005, + dn2: 8.9295095060810903E-002, + tau: 8.9150234342740890E-005, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.6483156812444665E+00, 0.6482265310101248E+00, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.8938424529515379E-01, 0.8929512008657929E-01, 0.2502576838690600E-07, 0.3261899765703413E-10, 0.1163887265260836E-03, 0.1806639672279546E-02, 0.1779401212715201E-02, 0.3135891777105103E+00, 0.3183894926006245E+00, 0.4711164655771408E-02, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.1702794694134603E+01}, + tauOut: 2.5005145741075717E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6482015258643838E+00, 0.6482265310101248E+00, 0.2115037983241246E-16, 0.1535325610927932E-15, 0.8927011497345719E-01, 0.8929512008657929E-01, 0.6601400172354812E-12, 0.3261899765703413E-10, 0.3153708122363886E+00, 0.1806639672279546E-02, 0.4684549720964035E-02, 0.3135891777105103E+00, 0.1609789066298190E-05, 0.4711164655771408E-02, 0.2115037983241246E-16, 0.1535325610927932E-15}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.6097890662981897E-006, + dmin1: 1.7816345258783307E-003, + dmin2: 8.9270114940838197E-002, + dn: 1.6097890662981897E-006, + dn1: 1.7816345258783307E-003, + dn2: 8.9270114940838197E-002, + tau: 2.5005145741075717E-005, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6482015258643838E+00, 0.6482265310101248E+00, 0.2115037983241246E-16, 0.1535325610927932E-15, 0.8927011497345719E-01, 0.8929512008657929E-01, 0.6601400172354812E-12, 0.3261899765703413E-10, 0.3153708122363886E+00, 0.1806639672279546E-02, 0.4684549720964035E-02, 0.3135891777105103E+00, 0.1609789066298190E-05, 0.4711164655771408E-02, 0.2115037983241246E-16, 0.1535325610927932E-15}, + tauOut: 1.5862205428611591E-006, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 6.4301480751548441E-012, + dmin1: 8.9268528752914328E-002, + dmin2: 8.9268528752914328E-002, + dn: 6.4301480751548441E-012, + dn1: 0.31536922601351364, + dn2: 8.9268528752914328E-002, + tau: 1.5862205428611591E-006, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01}, + tauOut: 6.4283598105616478E-012, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.7877912110675335E-015, + dmin1: 8.9268528747146109E-002, + dmin2: 8.9268528747146109E-002, + dn: 1.7877912110675335E-015, + dn1: 0.32005377571968785, + dn2: 8.9268528747146109E-002, + tau: 6.4283598105616478E-012, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17}, + tauOut: 1.7877912088395813E-015, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.2001510674733695E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 4, + dmin: 2.2279522444840209E-024, + dmin1: 8.9268528749476481E-002, + dmin2: 8.9268528749476481E-002, + dn: 2.2279522444840209E-024, + dn1: 0.32005379925180094, + dn2: 8.9268528749476481E-002, + tau: 1.7877912088395813E-015, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.2001510674733695E+01}, + tauOut: 2.2317132187369120E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 6.6951396570468849E-002, + dmin1: 6.6951396570468849E-002, + dmin2: 0.62588280745004166, + dn: 0.29773666692112338, + dn1: 6.6951396570468849E-002, + dn2: 0.62588280745004166, + tau: 2.2317132187369120E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32}, + tauOut: 6.6950732596142107E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 6.6400430513702258E-007, + dmin1: 6.6400430513702258E-007, + dmin2: 0.55893207485389951, + dn: 0.23072168931229292, + dn1: 6.6400430513702258E-007, + dn2: 0.55893207485389951, + tau: 6.6950732596142107E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01}, + tauOut: 6.6398937736467640E-007, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 9.5878878222950548E-008, + dmin1: 9.5878878222950548E-008, + dmin2: 0.55893150658516422, + dn: 3.4324631347444829E-004, + dn1: 9.5878878222950548E-008, + dn2: 0.55893150658516422, + tau: 5.6826873533591094E-007, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01}, + tauOut: 9.4211902206835373E-008, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + + // Print for fortran input + //printDlasq4FortranInput(test) + + i0 := test.i0 - 1 // zero index + n0 := test.n0 - 1 // zero index + n0in := test.n0in - 1 + + tauOut, ttypeOut, gOut := impl.Dlasq4(i0, n0, z, test.pp, n0in, test.dmin, test.dmin1, test.dmin2, test.dn, test.dn1, test.dn2, test.tau, test.ttype, test.g) + + if !floats.EqualApprox(z, test.zOut, dTol) { + t.Errorf("Z mismatch") + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("Case %d, wrong tau. Want %v, got %v", cas, test.tauOut, tauOut) + } + if ttypeOut != test.ttypeOut { + t.Errorf("Wrong ttype. Want %v, got %v", test.ttypeOut, ttypeOut) + } + if !floats.EqualWithinAbsOrRel(gOut, test.gOut, dTol, dTol) { + t.Errorf("Wrong g. Want %v, got %v", test.gOut, gOut) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq5.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq5.go new file mode 100644 index 00000000..235b9b9e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasq5.go @@ -0,0 +1,1992 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasq5er interface { + Dlasq5(i0, n0 int, z []float64, pp int, tau, sigma float64) (i0Out, n0Out, ppOut int, tauOut, sigmaOut, dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) +} + +func Dlasq5Test(t *testing.T, impl Dlasq5er) { + dTol := 1e-14 + for _, test := range []struct { + z []float64 + i0, n0, pp int + tau, sigma float64 + + i0Out, n0Out, ppOut int + tauOut, sigmaOut float64 + dminOut, dmin1Out, dmin2Out float64 + dnOut, dnm1Out, dnm2Out float64 + }{ + { + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 2.1175426017541180E-005, + dmin1Out: 4.4311601260836921E-002, + dmin2Out: 4.4311601260836921E-002, + dnOut: 2.1175426017541180E-005, + dnm1Out: 0.33915960483100382, + dnm2Out: 0.16428924199195991, + }, + { + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 2.1175425069176302E-005, + dmin1Out: 2.9944624525135358E-002, + dmin2Out: 2.9944624525135358E-002, + dnOut: 2.1175425069176302E-005, + dnm1Out: 7.2928780948497918E-002, + dnm2Out: 0.16065460645225654, + }, + { + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0: 1, + n0: 21, + pp: 0, + tau: 2.1175313795360271E-005, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 2.1175313795360271E-005, + sigmaOut: 0.0000000000000000, + dminOut: 1.1127325659669794E-010, + dmin1Out: 3.1433071595911154E-002, + dmin2Out: 3.1433071595911154E-002, + dnOut: 1.1127325659669794E-010, + dnm1Out: 3.5896964560873705E-002, + dnm2Out: 0.25842281720128102, + }, + { + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 2.1175313795360271E-005, + sigma: 2.1175313795360271E-005, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 2.1175313795360271E-005, + sigmaOut: 2.1175313795360271E-005, + dminOut: -2.1175202522103674E-005, + dmin1Out: 2.9116497146097618E-002, + dmin2Out: 4.9396687496051764E-002, + dnOut: -2.1175202522103674E-005, + dnm1Out: 2.9116497146097618E-002, + dnm2Out: 0.15954393093937583, + }, + { + z: []float64{0.2440423833090186E+01, 0.2398080345610006E+01, 0.2094994698033050E-01, 0.4236466279397526E-01, 0.1195377978069578E+01, 0.1206825371451915E+01, 0.4200624064314086E-02, 0.9523728911788614E-02, 0.5236479130172386E+00, 0.5272444803016919E+00, 0.9895730475750664E-03, 0.6252320936560726E-03, 0.8561493851923613E+00, 0.8287928057414093E+00, 0.3940527300515336E-01, 0.2836732781232222E-01, 0.1391213380351470E+01, 0.1189283688611819E+01, 0.1042588274099539E+00, 0.2413561400585997E+00, 0.8502714936537001E+00, 0.6009636865971842E+00, 0.9053470847599347E-01, 0.3535878097802652E+00, 0.2082745543764428E+00, 0.2177085286147829E+00, 0.5124445590385125E+00, 0.8112190955144877E-01, 0.9742631623318954E+00, 0.1315663829494665E+01, 0.1544732645319877E+00, 0.1710650671895379E+00, 0.1146377683139938E+01, 0.8797682289623537E+00, 0.6964776521238716E-01, 0.4211038940233675E+00, 0.1311831861373520E+01, 0.1896031949674164E+00, 0.4911110065859084E+00, 0.1191897606932286E+01, 0.5147826357647675E+00, 0.5405288693957555E+00, 0.5388939477127089E+00, 0.4653859482687157E+00, 0.1688462397843937E+00, 0.5960928726645816E+00, 0.2380205454936569E+00, 0.1116684901463164E+00, 0.6803588803422466E+00, 0.3598944880993349E+00, 0.8083375797812383E+00, 0.5585061130503639E+00, 0.6439457065812542E+00, 0.9846976386969850E+00, 0.8958050967125053E+00, 0.4676068229793028E+00, 0.5200424313866183E+00, 0.1233621533334973E+01, 0.1331299890548604E+00, 0.1822471700779458E+00, 0.9512006336257413E+00, 0.3798865198782122E+00, 0.9904762202705547E+00, 0.7044652781161848E+00, 0.7143741900128092E+00, 0.1337385443370563E+01, 0.2263121215682984E+00, 0.3674861422265960E+00, 0.7024108348076278E+00, 0.4399391431629689E+00, 0.3651408483866702E+00, 0.4888049885267526E+00, 0.1965545752794010E+00, 0.5247059546398414E+00, 0.6759292101929097E-02, 0.3701064434002514E-01, 0.2911649714609818E-01, 0.3589696456182207E-01, 0.2137969692662087E-23, 0.5594353069081231E-15, -0.2117520252210367E-04, 0.1112732565966979E-09, 0.9895730475750664E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 1.1127325659669789E-010, + sigma: 2.1175313795360271E-005, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 1.1127325659669789E-010, + sigmaOut: 2.1175313795360271E-005, + dminOut: -2.0808762284537102E-024, + dmin1Out: 2.9139336744737766E-002, + dmin2Out: 4.9426557292086552E-002, + dnOut: -2.0808762284537102E-024, + dnm1Out: 2.9139336744737766E-002, + dnm2Out: 0.15959234211062134, + }, + { + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0: 1, + n0: 21, + pp: 0, + tau: -0.0000000000000000, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.1175425068616867E-005, + dminOut: 0.0000000000000000, + dmin1Out: 2.7016889331018056E-002, + dmin2Out: 5.3061698118516694E-002, + dnOut: 0.0000000000000000, + dnm1Out: 2.7016889331018056E-002, + dnm2Out: 8.6018658784156071E-002, + }, + { + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: -0.0000000000000000, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 2.1175425068616867E-005, + dminOut: 2.5763383633962696E-002, + dmin1Out: 4.3622798915905092E-002, + dmin2Out: 7.4536672467372611E-002, + dnOut: 2.5763383633962696E-002, + dnm1Out: 4.3622798915905092E-002, + dnm2Out: 9.8141518071882677E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + i0: 1, + n0: 20, + pp: 0, + tau: 2.0080554394878082E-002, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 2.0080554394878082E-002, + sigmaOut: 2.1175425068616867E-005, + dminOut: -2.1187919252575148E-003, + dmin1Out: -2.1187919252575148E-003, + dmin2Out: 3.1777270007152948E-002, + dnOut: 4.3005217031728403E-002, + dnm1Out: -2.1187919252575148E-003, + dnm2Out: 3.1777270007152948E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2456385050537078E+01, 0.4896382518051712E-02, 0.2364842030515144E-02, 0.1186378431264915E+01, 0.1164748012891115E+01, 0.8149780515932184E-03, 0.3663750368606913E-03, 0.5236148327211592E+00, 0.5059345305621403E+00, 0.2766627272719901E-02, 0.5208666879309463E-02, 0.9525115502267366E+00, 0.1019555750555114E+01, 0.9233342160256496E-01, 0.1271177219084926E+00, 0.1403647802928048E+01, 0.1295158592310706E+01, 0.3870906568602875E-01, 0.2575581550365553E-01, 0.8617584837127339E+00, 0.8333292886837029E+00, 0.1740717486950262E-01, 0.2915663048658400E-01, 0.1395808011693333E+01, 0.1558759230767007E+01, 0.2121884039551361E+00, 0.8569226352498945E-01, 0.6295047433559955E+00, 0.1058885473974269E+01, 0.5351535485381410E+00, 0.1868951540728986E+00, 0.3698014604305115E+00, 0.6910236107191923E+00, 0.5281978587564573E+00, 0.1000437033056103E+01, 0.1308838344228090E+01, 0.3918007450464985E+00, 0.1034799882693896E+00, 0.2379777816619179E+00, 0.9010425466701916E+00, 0.6771983450302391E+00, 0.3421413441684364E-01, 0.4045895778871807E-01, 0.8008017657953598E+00, 0.1374143583674083E+01, 0.6338813300623194E+00, 0.4005339232303680E+00, 0.8682873190108105E+00, 0.1070641461682245E+01, 0.6229686202966810E+00, 0.4896740201485869E+00, 0.8415597376799326E+00, 0.4351392095057171E+00, 0.1033340463692495E+00, 0.1811694274708021E+00, 0.7629036530181579E+00, 0.1686298765095183E+01, 0.1124645093942705E+01, 0.4654019842229331E+00, 0.6978261813392677E+00, 0.5176639768935063E+00, 0.3053203341720497E+00, 0.2907699806261721E+00, 0.4929941693545132E+00, 0.7331214635495586E+00, 0.5509778292160957E+00, 0.1568680213363420E+00, 0.2087258457383731E+00, 0.8093075758121498E-01, 0.4915348757406203E-01, 0.2778348386000479E-01, 0.4574524632962537E-01, -0.8652862282021575E-03, 0.1253505697055357E-02, -0.3732238779264379E-01, 0.2576338363396270E-01, 0.4300521703172840E-01, 0.8149780515932184E-03, 0.3663750368606913E-03}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.0201385987195205E-003, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.0201385987195205E-003, + sigmaOut: 2.1175425068616867E-005, + dminOut: 1.8576185384092288E-002, + dmin1Out: 1.8576185384092288E-002, + dmin2Out: 5.2365600435162571E-002, + dnOut: 1.9114649409197451E-002, + dnm1Out: 1.8576185384092288E-002, + dnm2Out: 5.2365600435162571E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 5.4769133315280185E-003, + sigma: 5.0413140237881371E-003, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 5.4769133315280185E-003, + sigmaOut: 5.0413140237881371E-003, + dminOut: 9.5622848228283271E-003, + dmin1Out: 9.5622848228283271E-003, + dmin2Out: 6.9533978479808370E-002, + dnOut: 1.0856003705186750E-002, + dnm1Out: 9.5622848228283271E-003, + dnm2Out: 6.9533978479808370E-002, + }, + { + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.1216063611655054E-003, + sigma: 1.0518227355316156E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.1216063611655054E-003, + sigmaOut: 1.0518227355316156E-002, + dminOut: 2.0601312480394186E-003, + dmin1Out: 5.4371870398960158E-003, + dmin2Out: 8.0023511442426670E-002, + dnOut: 2.0601312480394186E-003, + dnm1Out: 5.4371870398960158E-003, + dnm2Out: 8.0023511442426670E-002, + }, + { + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 1.2817878169164906E-003, + sigma: 1.5639833716481661E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 1.2817878169164906E-003, + sigmaOut: 1.5639833716481661E-002, + dminOut: 6.0731361153288982E-005, + dmin1Out: 6.8738708636769136E-003, + dmin2Out: 8.1489512892123819E-002, + dnOut: 6.0731361153288982E-005, + dnm1Out: 6.8738708636769136E-003, + dnm2Out: 8.1489512892123819E-002, + }, + { + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.6837241251038845E-005, + sigma: 1.6921621533398150E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.6837241251038845E-005, + sigmaOut: 1.6921621533398150E-002, + dminOut: 3.1568086081919418E-009, + dmin1Out: 1.0483100129151506E-002, + dmin2Out: 8.1316774559040517E-002, + dnOut: 3.1568086081919418E-009, + dnm1Out: 1.0483100129151506E-002, + dnm2Out: 8.1316774559040517E-002, + }, + { + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 3.1557121791797713E-009, + sigma: 1.6978458774649190E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 3.1557121791797713E-009, + sigmaOut: 1.6978458774649190E-002, + dminOut: 6.9684975813366743E-017, + dmin1Out: 1.1199576261102989E-002, + dmin2Out: 8.1067607231828140E-002, + dnOut: 6.9684975813366743E-017, + dnm1Out: 1.1199576261102989E-002, + dnm2Out: 8.1067607231828140E-002, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + i0: 1, + n0: 20, + pp: 0, + tau: 6.9684975806547287E-017, + sigma: 1.6978461930361368E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 6.9684975806547287E-017, + sigmaOut: 1.6978461930361368E-002, + dminOut: 6.1629758220391547E-032, + dmin1Out: 1.1203310405167735E-002, + dmin2Out: 8.0927116373146771E-002, + dnOut: 6.1629758220391547E-032, + dnm1Out: 1.1203310405167735E-002, + dnm2Out: 8.0927116373146771E-002, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 6.1629758220391547E-032, + sigma: 1.6978461930361441E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.6978461930361441E-002, + dminOut: 6.1629758220391547E-032, + dmin1Out: 1.1203288675083998E-002, + dmin2Out: 8.0846453894262649E-002, + dnOut: 6.1629758220391547E-032, + dnm1Out: 1.1203288675083998E-002, + dnm2Out: 8.0846453894262649E-002, + }, + { + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + i0: 1, + n0: 19, + pp: 0, + tau: 1.1203284285913290E-002, + sigma: 1.6978461930361441E-002, + i0Out: 1, + n0Out: 19, + ppOut: 0, + tauOut: 1.1203284285913290E-002, + sigmaOut: 1.6978461930361441E-002, + dminOut: 8.9043085058082561E-010, + dmin1Out: 6.9585227169791292E-002, + dmin2Out: 0.11373841371027797, + dnOut: 8.9043085058082561E-010, + dnm1Out: 6.9585227169791292E-002, + dnm2Out: 0.11373841371027797, + }, + { + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + i0: 1, + n0: 19, + pp: 1, + tau: 8.9043080564395014E-010, + sigma: 2.8181746216274728E-002, + i0Out: 1, + n0Out: 19, + ppOut: 1, + tauOut: 8.9043080564395014E-010, + sigmaOut: 2.8181746216274728E-002, + dminOut: 1.3962105636374437E-019, + dmin1Out: 6.9544122471813200E-002, + dmin2Out: 9.8247027562672340E-002, + dnOut: 1.3962105636374437E-019, + dnm1Out: 6.9544122471813200E-002, + dnm2Out: 9.8247027562672340E-002, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + i0: 1, + n0: 19, + pp: 0, + tau: 1.3962105636374427E-019, + sigma: 2.8181747106705537E-002, + i0Out: 1, + n0Out: 19, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.8181747106705537E-002, + dminOut: 1.3962105636374430E-019, + dmin1Out: 6.9512134440652351E-002, + dmin2Out: 8.9358776708560295E-002, + dnOut: 1.3962105636374430E-019, + dnm1Out: 6.9512134440652351E-002, + dnm2Out: 8.9358776708560295E-002, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 6.8088572105595116E-002, + sigma: 2.8181747106705537E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 6.8088572105595116E-002, + sigmaOut: 2.8181747106705537E-002, + dminOut: 1.2643548659038301E-003, + dmin1Out: 1.3935943135754067E-002, + dmin2Out: 9.9495800084882416E-002, + dnOut: 1.2643548659038301E-003, + dnm1Out: 1.3935943135754067E-002, + dnm2Out: 9.9495800084882416E-002, + }, + { + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + i0: 1, + n0: 18, + pp: 0, + tau: 1.2463174543591322E-003, + sigma: 9.6270319212300656E-002, + i0Out: 1, + n0Out: 18, + ppOut: 0, + tauOut: 1.2463174543591322E-003, + sigmaOut: 9.6270319212300656E-002, + dminOut: 1.2236274461701734E-006, + dmin1Out: 1.1812799375517376E-002, + dmin2Out: 0.10597947881780349, + dnOut: 1.2236274461701734E-006, + dnm1Out: 1.1812799375517376E-002, + dnm2Out: 0.10597947881780349, + }, + { + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 1.2218877946904154E-006, + sigma: 9.7516636666659787E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 1.2218877946904154E-006, + sigmaOut: 9.7516636666659787E-002, + dminOut: 9.5986727915820745E-012, + dmin1Out: 1.1875197612370336E-002, + dmin2Out: 0.11291768719739126, + dnOut: 9.5986727915820745E-012, + dnm1Out: 1.1875197612370336E-002, + dnm2Out: 0.11291768719739126, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + i0: 1, + n0: 18, + pp: 0, + tau: 9.5986713933289272E-012, + sigma: 9.7517858554454467E-002, + i0Out: 1, + n0Out: 18, + ppOut: 0, + tauOut: 9.5986713933289272E-012, + sigmaOut: 9.7517858554454467E-002, + dminOut: 6.6174125886815435E-022, + dmin1Out: 1.1882019541390456E-002, + dmin2Out: 0.11366976186212303, + dnOut: 6.6174125886815435E-022, + dnm1Out: 1.1882019541390456E-002, + dnm2Out: 0.11366976186212303, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 6.6174125886815426E-022, + sigma: 9.7517858564053150E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 9.7517858564053150E-002, + dminOut: 6.6174125886815426E-022, + dmin1Out: 1.1880977265773463E-002, + dmin2Out: 0.11370904624558997, + dnOut: 6.6174125886815426E-022, + dnm1Out: 1.1880977265773463E-002, + dnm2Out: 0.11370904624558997, + }, + { + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + i0: 1, + n0: 17, + pp: 0, + tau: 1.1880832155707781E-002, + sigma: 9.7517858564053150E-002, + i0Out: 1, + n0Out: 17, + ppOut: 0, + tauOut: 1.1880832155707781E-002, + sigmaOut: 9.7517858564053150E-002, + dminOut: 2.3287035572430725E-008, + dmin1Out: 0.10181720511285566, + dmin2Out: 0.30482311636216664, + dnOut: 2.3287035572430725E-008, + dnm1Out: 0.10181720511285566, + dnm2Out: 0.30482311636216664, + }, + { + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + i0: 1, + n0: 17, + pp: 1, + tau: 2.3287007705477136E-008, + sigma: 0.10939869071976092, + i0Out: 1, + n0Out: 17, + ppOut: 1, + tauOut: 2.3287007705477136E-008, + sigmaOut: 0.10939869071976092, + dminOut: 2.6961654281145418E-018, + dmin1Out: 0.10181121275944585, + dmin2Out: 0.30487633314418217, + dnOut: 2.6961654281145418E-018, + dnm1Out: 0.10181121275944585, + dnm2Out: 0.30487633314418217, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + i0: 1, + n0: 17, + pp: 0, + tau: 2.6961654281138038E-018, + sigma: 0.10939871400676864, + i0Out: 1, + n0Out: 17, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.10939871400676864, + dminOut: 2.6961654281138038E-018, + dmin1Out: 0.10180899282350273, + dmin2Out: 0.30489636738914000, + dnOut: 2.6961654281138038E-018, + dnm1Out: 0.10180899282350273, + dnm2Out: 0.30489636738914000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + tau: 0.10180650470263587, + sigma: 0.10939871400676864, + i0Out: 1, + n0Out: 16, + ppOut: 1, + tauOut: 0.10180650470263587, + sigmaOut: 0.10939871400676864, + dminOut: 1.3142485785350155E-006, + dmin1Out: 0.20309651253108729, + dmin2Out: 0.57610166617362735, + dnOut: 1.3142485785350155E-006, + dnm1Out: 0.20309651253108729, + dnm2Out: 0.81137144083676127, + }, + { + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + i0: 1, + n0: 16, + pp: 0, + tau: 1.3142409824136984E-006, + sigma: 0.21120521870940451, + i0Out: 1, + n0Out: 16, + ppOut: 0, + tauOut: 1.3142409824136984E-006, + sigmaOut: 0.21120521870940451, + dminOut: 8.4118841991824567E-018, + dmin1Out: 0.20309744276965425, + dmin2Out: 0.50018599148866161, + dnOut: 8.4118841991824567E-018, + dnm1Out: 0.20309744276965425, + dnm2Out: 0.75834178007645303, + }, + { + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + tau: 8.4118841988678429E-018, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 16, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.21120653295038691, + dminOut: 8.4118841988678429E-018, + dmin1Out: 0.20309858884628909, + dmin2Out: 0.53283137411117854, + dnOut: 8.4118841988678429E-018, + dnm1Out: 0.20309858884628909, + dnm2Out: 0.71080515929391042, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + i0: 1, + n0: 16, + pp: 0, + tau: 8.4118841988678429E-018, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 16, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.21120653295038691, + dminOut: 8.4118841988678429E-018, + dmin1Out: 0.20309858045029386, + dmin2Out: 0.51860540644834729, + dnOut: 8.4118841988678429E-018, + dnm1Out: 0.20309858045029386, + dnm2Out: 0.67176795876146822, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 0.10154929022514693, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 0.10154929022514693, + sigmaOut: 0.21120653295038691, + dminOut: 0.10154928703201281, + dmin1Out: 0.32391205918605420, + dmin2Out: 0.32391205918605420, + dnOut: 0.10154928703201281, + dnm1Out: 0.53450854002684800, + dnm2Out: 0.69531980574199759, + }, + { + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + i0: 1, + n0: 15, + pp: 0, + tau: 0.10154100618138810, + sigma: 0.31275582317553385, + i0Out: 1, + n0Out: 15, + ppOut: 0, + tauOut: 0.10154100618138810, + sigmaOut: 0.31275582317553385, + dminOut: 8.2800215414347011E-006, + dmin1Out: 0.16866357962181588, + dmin2Out: 0.16866357962181588, + dnOut: 8.2800215414347011E-006, + dnm1Out: 0.39110725789187228, + dnm2Out: 0.42026820370851276, + }, + { + z: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 8.2795951083136037E-006, + sigma: 0.41429682935692197, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 8.2795951083136037E-006, + sigmaOut: 0.41429682935692197, + dminOut: 4.2641220534843968E-010, + dmin1Out: 0.19554701532405336, + dmin2Out: 0.19554701532405336, + dnOut: 4.2641220534843968E-010, + dnm1Out: 0.32821333105682254, + dnm2Out: 0.21848306981706411, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + i0: 1, + n0: 15, + pp: 0, + tau: 4.2641207498271701E-010, + sigma: 0.41430510895203027, + i0Out: 1, + n0Out: 15, + ppOut: 0, + tauOut: 4.2641207498271701E-010, + sigmaOut: 0.41430510895203027, + dminOut: 1.3036568472020817E-016, + dmin1Out: 0.15841174212052453, + dmin2Out: 0.15841174212052453, + dnOut: 1.3036568472020817E-016, + dnm1Out: 0.23494558610432464, + dnm2Out: 0.15841174212052453, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 1.3036568471812905E-016, + sigma: 0.41430510937844234, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 1.3036568471812905E-016, + sigmaOut: 0.41430510937844234, + dminOut: 2.0791168714198411E-027, + dmin1Out: 0.15670572686712736, + dmin2Out: 0.18680490956440032, + dnOut: 2.0791168714198411E-027, + dnm1Out: 0.15670572686712736, + dnm2Out: 0.18680490956440032, + }, + { + z: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + i0: 1, + n0: 14, + pp: 0, + tau: 5.2226904068357879E-002, + sigma: 0.41430510937844245, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 5.2226904068357879E-002, + sigmaOut: 0.41430510937844245, + dminOut: 6.1979733096699005E-002, + dmin1Out: 0.21025182606004778, + dmin2Out: 0.35454858327394784, + dnOut: 6.1979733096699005E-002, + dnm1Out: 0.21025182606004778, + dnm2Out: 0.51458348500658069, + }, + { + z: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 4.3992746597899146E-002, + sigma: 0.46653201344680034, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 4.3992746597899146E-002, + sigmaOut: 0.46653201344680034, + dminOut: 8.3978432207528000E-003, + dmin1Out: 0.23219513064786862, + dmin2Out: 0.34734604130905122, + dnOut: 8.3978432207528000E-003, + dnm1Out: 0.23219513064786862, + dnm2Out: 0.39493697562207530, + }, + { + z: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + i0: 1, + n0: 14, + pp: 0, + tau: 8.0121275381568099E-003, + sigma: 0.51052476004469949, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 8.0121275381568099E-003, + sigmaOut: 0.51052476004469949, + dminOut: 8.3015533671799979E-005, + dmin1Out: 0.25644350373773794, + dmin2Out: 0.31779880038403513, + dnOut: 8.3015533671799979E-005, + dnm1Out: 0.25644350373773794, + dnm2Out: 0.31779880038403513, + }, + { + z: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 8.2898056486573887E-005, + sigma: 0.51853688758285632, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 8.2898056486573887E-005, + sigmaOut: 0.51853688758285632, + dminOut: 1.9676836973621424E-008, + dmin1Out: 0.25663722751477031, + dmin2Out: 0.28224921557690585, + dnOut: 1.9676836973621424E-008, + dnm1Out: 0.25663722751477031, + dnm2Out: 0.28224921557690585, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + i0: 1, + n0: 14, + pp: 0, + tau: 1.9676827722764296E-008, + sigma: 0.51861978563934286, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 1.9676827722764296E-008, + sigmaOut: 0.51861978563934286, + dminOut: 1.5032959860012969E-015, + dmin1Out: 0.24838793989138258, + dmin2Out: 0.27047787997045275, + dnOut: 1.5032959860012969E-015, + dnm1Out: 0.24838793989138258, + dnm2Out: 0.27047787997045275, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 1.5032959860012393E-015, + sigma: 0.51861980531617058, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 1.5032959860012393E-015, + sigmaOut: 0.51861980531617058, + dminOut: 9.2691156363468887E-030, + dmin1Out: 0.24076768543540897, + dmin2Out: 0.27020241256687788, + dnOut: 9.2691156363468887E-030, + dnm1Out: 0.24076768543540897, + dnm2Out: 0.27020241256687788, + }, + { + z: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + i0: 1, + n0: 13, + pp: 0, + tau: 0.19361025134591583, + sigma: 0.51861980531617213, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 0.19361025134591583, + sigmaOut: 0.51861980531617213, + dminOut: 2.5949209826162500E-002, + dmin1Out: 7.8890170839591350E-002, + dmin2Out: 0.28791033268116917, + dnOut: 2.5949209826162500E-002, + dnm1Out: 7.8890170839591350E-002, + dnm2Out: 0.41777236268627749, + }, + { + z: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 1.8780556192507153E-002, + sigma: 0.71223005666208794, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 1.8780556192507153E-002, + sigmaOut: 0.71223005666208794, + dminOut: 8.7653100724300811E-004, + dmin1Out: 6.6256164803006098E-002, + dmin2Out: 0.24571773655185866, + dnOut: 8.7653100724300811E-004, + dnm1Out: 6.6256164803006098E-002, + dnm2Out: 0.36084635920253871, + }, + { + z: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + i0: 1, + n0: 13, + pp: 0, + tau: 8.1622622999092049E-004, + sigma: 0.73101061285459512, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 8.1622622999092049E-004, + sigmaOut: 0.73101061285459512, + dminOut: 6.9556311345050133E-007, + dmin1Out: 8.6231166987816729E-002, + dmin2Out: 0.25114202935985525, + dnOut: 6.9556311345050133E-007, + dnm1Out: 8.6231166987816729E-002, + dnm2Out: 0.30765445605457048, + }, + { + z: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 6.9511331676175615E-007, + sigma: 0.73182683908458601, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 6.9511331676175615E-007, + sigmaOut: 0.73182683908458601, + dminOut: 1.2278907249223888E-012, + dmin1Out: 9.2372077429255559E-002, + dmin2Out: 0.25591158693238830, + dnOut: 1.2278907249223888E-012, + dnm1Out: 9.2372077429255559E-002, + dnm2Out: 0.25591158693238830, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + i0: 1, + n0: 13, + pp: 0, + tau: 1.2278907189544363E-012, + sigma: 0.73182753419790281, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 1.2278907189544363E-012, + sigmaOut: 0.73182753419790281, + dminOut: 4.9598525010503808E-024, + dmin1Out: 9.2368632133320736E-002, + dmin2Out: 0.22049265431403467, + dnOut: 4.9598525010503808E-024, + dnm1Out: 9.2368632133320736E-002, + dnm2Out: 0.22049265431403467, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 4.9598525010503808E-024, + sigma: 0.73182753419913071, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.73182753419913071, + dminOut: 4.9598525010503808E-024, + dmin1Out: 9.2339683204333278E-002, + dmin2Out: 0.20112464802017624, + dnOut: 4.9598525010503808E-024, + dnm1Out: 9.2339683204333278E-002, + dnm2Out: 0.20112464802017624, + }, + { + z: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + i0: 1, + n0: 12, + pp: 0, + tau: 9.2159326345418235E-002, + sigma: 0.73182753419913071, + i0Out: 1, + n0Out: 12, + ppOut: 0, + tauOut: 9.2159326345418235E-002, + sigmaOut: 0.73182753419913071, + dminOut: 1.5272797578758102E-004, + dmin1Out: 9.6724015270930774E-002, + dmin2Out: 0.29962742013672317, + dnOut: 1.5272797578758102E-004, + dnm1Out: 9.6724015270930774E-002, + dnm2Out: 0.29962742013672317, + }, + { + z: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + tau: 1.5267965277267402E-004, + sigma: 0.82398686054454895, + i0Out: 1, + n0Out: 12, + ppOut: 1, + tauOut: 1.5267965277267402E-004, + sigmaOut: 0.82398686054454895, + dminOut: 2.8998364833248812E-009, + dmin1Out: 9.2869952038417761E-002, + dmin2Out: 0.30683160095299705, + dnOut: 2.8998364833248812E-009, + dnm1Out: 9.2869952038417761E-002, + dnm2Out: 0.30683160095299705, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + i0: 1, + n0: 12, + pp: 0, + tau: 2.8998350258011044E-009, + sigma: 0.82413954019732161, + i0Out: 1, + n0Out: 12, + ppOut: 0, + tauOut: 2.8998350258011044E-009, + sigmaOut: 0.82413954019732161, + dminOut: 2.2456987483859239E-017, + dmin1Out: 9.1786476970678488E-002, + dmin2Out: 0.30815750788579249, + dnOut: 2.2456987483859239E-017, + dnm1Out: 9.1786476970678488E-002, + dnm2Out: 0.30815750788579249, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + tau: 2.2456987483858885E-017, + sigma: 0.82413954309715665, + i0Out: 1, + n0Out: 12, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.82413954309715665, + dminOut: 2.2456987483858888E-017, + dmin1Out: 9.1450429866798411E-002, + dmin2Out: 0.30232944966555197, + dnOut: 2.2456987483858888E-017, + dnm1Out: 9.1450429866798411E-002, + dnm2Out: 0.30232944966555197, + }, + { + z: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + i0: 1, + n0: 11, + pp: 0, + tau: 9.1173077708044642E-002, + sigma: 0.82413954309715665, + i0Out: 1, + n0Out: 11, + ppOut: 0, + tauOut: 9.1173077708044642E-002, + sigmaOut: 0.82413954309715665, + dminOut: 1.2510327751137640E-004, + dmin1Out: 0.20154260650453434, + dmin2Out: 0.26087886618071221, + dnOut: 1.2510327751137640E-004, + dnm1Out: 0.20154260650453434, + dnm2Out: 0.26087886618071221, + }, + { + z: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + tau: 1.2498058228587147E-004, + sigma: 0.91531262080520126, + i0Out: 1, + n0Out: 11, + ppOut: 1, + tauOut: 1.2498058228587147E-004, + sigmaOut: 0.91531262080520126, + dminOut: 2.4554386425680716E-008, + dmin1Out: 0.19392428663386141, + dmin2Out: 0.26581143244488259, + dnOut: 2.4554386425680716E-008, + dnm1Out: 0.19392428663386141, + dnm2Out: 0.26581143244488259, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + i0: 1, + n0: 11, + pp: 0, + tau: 2.4554370888251911E-008, + sigma: 0.91543760138748709, + i0Out: 1, + n0Out: 11, + ppOut: 0, + tauOut: 2.4554370888251911E-008, + sigmaOut: 0.91543760138748709, + dminOut: 2.7649302792337775E-015, + dmin1Out: 0.18866996369915248, + dmin2Out: 0.27322036360404983, + dnOut: 2.7649302792337775E-015, + dnm1Out: 0.18866996369915248, + dnm2Out: 0.27322036360404983, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + tau: 2.7649302792335523E-015, + sigma: 0.91543762594185796, + i0Out: 1, + n0Out: 11, + ppOut: 1, + tauOut: 2.7649302792335523E-015, + sigmaOut: 0.91543762594185796, + dminOut: 3.4709879829724519E-029, + dmin1Out: 0.18507826404867261, + dmin2Out: 0.27717487004787600, + dnOut: 3.4709879829724519E-029, + dnm1Out: 0.18507826404867261, + dnm2Out: 0.27858872904535659, + }, + { + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + i0: 1, + n0: 10, + pp: 0, + tau: 9.2539132024336307E-002, + sigma: 0.91543762594186073, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 9.2539132024336307E-002, + sigmaOut: 0.91543762594186073, + dminOut: 8.9088074504151571E-002, + dmin1Out: 0.17705256406949207, + dmin2Out: 0.17705256406949207, + dnOut: 8.9088074504151571E-002, + dnm1Out: 0.18903428744201686, + dnm2Out: 0.28613205491191551, + }, + { + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 7.5387921832037685E-002, + sigma: 1.0079767579661971, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 7.5387921832037685E-002, + sigmaOut: 1.0079767579661971, + dminOut: 1.1106216559126303E-002, + dmin1Out: 0.10021441433509834, + dmin2Out: 0.10021441433509834, + dnOut: 1.1106216559126303E-002, + dnm1Out: 0.11507463320059727, + dnm2Out: 0.21320388392650824, + }, + { + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 9.2006637361187298E-003, + sigma: 1.0833646797982348, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 9.2006637361187298E-003, + sigmaOut: 1.0833646797982348, + dminOut: 1.6452860548183366E-003, + dmin1Out: 9.0837695870445614E-002, + dmin2Out: 9.0837695870445614E-002, + dnOut: 1.6452860548183366E-003, + dnm1Out: 0.10809563217808144, + dnm2Out: 0.20642195434625446, + }, + { + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 1.5594219393746818E-003, + sigma: 1.0925653435343534, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 1.5594219393746818E-003, + sigmaOut: 1.0925653435343534, + dminOut: 8.1926049685687600E-005, + dmin1Out: 8.9258234858565516E-002, + dmin2Out: 8.9258234858565516E-002, + dnOut: 8.1926049685687600E-005, + dnm1Out: 0.10847668953277810, + dnm2Out: 0.20701876553386761, + }, + { + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 8.1416944590412474E-005, + sigma: 1.0941247654737283, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 8.1416944590412474E-005, + sigmaOut: 1.0941247654737283, + dminOut: 5.0612658152462498E-007, + dmin1Out: 8.9177229293753768E-002, + dmin2Out: 8.9177229293753768E-002, + dnOut: 5.0612658152462498E-007, + dnm1Out: 0.10831524323681536, + dnm2Out: 0.20814970454128662, + }, + { + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 5.0604049633765406E-007, + sigma: 1.0942061824183187, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 5.0604049633765406E-007, + sigmaOut: 1.0942061824183187, + dminOut: 8.6071246971392626E-011, + dmin1Out: 8.9183660885577137E-002, + dmin2Out: 8.9183660885577137E-002, + dnOut: 8.6071246971392626E-011, + dnm1Out: 0.10814239569959758, + dnm2Out: 0.20876277035564564, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 8.6071215292546838E-011, + sigma: 1.0942066884588149, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 8.6071215292546838E-011, + sigmaOut: 1.0942066884588149, + dminOut: 3.1678834699165494E-017, + dmin1Out: 8.9200650586607991E-002, + dmin2Out: 8.9200650586607991E-002, + dnOut: 3.1678834699165494E-017, + dnm1Out: 0.10805126770967630, + dnm2Out: 0.20900961033533805, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 3.1678834698836348E-017, + sigma: 1.0942066885448862, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.0942066885448862, + dminOut: 3.1678834699165494E-017, + dmin1Out: 8.9240528714785800E-002, + dmin2Out: 8.9240528714785800E-002, + dnOut: 3.1678834699165494E-017, + dnm1Out: 0.10800416691102718, + dnm2Out: 0.20896705170504334, + }, + { + z: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.2310132178696450E-002, + sigma: 1.0942066885448862, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 2.2310132178696450E-002, + sigmaOut: 1.0942066885448862, + dminOut: 6.7023851586769906E-002, + dmin1Out: 6.7023851586769906E-002, + dmin2Out: 6.7023851586769906E-002, + dnOut: 8.5666701693601133E-002, + dnm1Out: 0.18606768031923254, + dnm2Out: 6.7023851586769906E-002, + }, + { + z: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 6.4730147312741043E-002, + sigma: 1.1165168207235825, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 6.4730147312741043E-002, + sigmaOut: 1.1165168207235825, + dminOut: 2.5125423409859404E-003, + dmin1Out: 2.5125423409859404E-003, + dmin2Out: 2.5125423409859404E-003, + dnOut: 2.0907912921905053E-002, + dnm1Out: 8.1725879285544201E-002, + dnm2Out: 2.5125423409859404E-003, + }, + { + z: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.3478378904869292E-003, + sigma: 1.1812469680363236, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 2.3478378904869292E-003, + sigmaOut: 1.1812469680363236, + dminOut: -6.4213352031532861E-004, + dmin1Out: -6.4213352031532861E-004, + dmin2Out: 8.4507453921550072E-004, + dnOut: 1.9536180783236046E-002, + dnm1Out: -6.4213352031532861E-004, + dnm2Out: 8.4507453921550072E-004, + }, + { + z: []float64{0.1299730545465525E+01, 0.1297382707575038E+01, 0.6869337119490330E-18, 0.5602483738451179E-18, 0.1058117456648598E+01, 0.1072935957047634E+01, 0.1716633828952343E-01, 0.2001409424891253E-01, 0.1250927309320471E+01, 0.1236091950773070E+01, 0.7526573591998700E-02, 0.5966648869520194E-02, 0.9799049395522637E+00, 0.1059928950127001E+01, 0.8833849733474472E-01, 0.6057909540261972E-01, 0.7268579263515238E+00, 0.6718652894389281E+00, 0.7934296380510910E-02, 0.6331166051893822E-02, 0.5361144212346215E+00, 0.5274354174180577E+00, 0.1258170079408221E-09, 0.7616528495272331E-12, 0.3192912430464083E-02, 0.4050382905882583E-01, 0.3965875451961033E-01, 0.8004750795410222E-01, 0.8175321232427381E-01, -0.6134920613602832E-03, 0.2864145895504550E-04, -0.9761057518179271E-03, 0.2090791292190505E-01, 0.1953618078323605E-01, 0.6869337119490330E-18, 0.5602483738451179E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 5.8695947262173229E-004, + sigma: 1.1812469680363236, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 5.8695947262173229E-004, + sigmaOut: 1.1812469680363236, + dminOut: 2.6059529570832572E-003, + dmin1Out: 2.6059529570832572E-003, + dmin2Out: 2.6059529570832572E-003, + dnOut: 2.0187357299561493E-002, + dnm1Out: 4.4537716273149721E-003, + dnm2Out: 2.6059529570832572E-003, + }, + { + z: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 4.9324499328963489E-004, + sigma: 1.1818339275089453, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 4.9324499328963489E-004, + sigmaOut: 1.1818339275089453, + dminOut: 1.0870277779300500E-003, + dmin1Out: 1.0870277779300500E-003, + dmin2Out: 4.1771462483342674E-002, + dnOut: 1.7484624889890960E-002, + dnm1Out: 1.0870277779300500E-003, + dnm2Out: 4.1771462483342674E-002, + }, + { + z: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 8.6238530354903250E-004, + sigma: 1.1823271725022351, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 8.6238530354903250E-004, + sigmaOut: 1.1823271725022351, + dminOut: 3.2884671240747138E-004, + dmin1Out: 3.2884671240747138E-004, + dmin2Out: 0.11762155840411674, + dnOut: 1.4027859154437344E-003, + dnm1Out: 3.2884671240747138E-004, + dnm2Out: 0.11762155840411674, + }, + { + z: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 1.8442717265434725E-004, + sigma: 1.1831895578057841, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 1.8442717265434725E-004, + sigmaOut: 1.1831895578057841, + dminOut: 3.4295817345512611E-006, + dmin1Out: 2.3532871395603098E-003, + dmin2Out: 0.12033927154650945, + dnOut: 3.4295817345512611E-006, + dnm1Out: 2.3532871395603098E-003, + dnm2Out: 0.12033927154650945, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 3.2077610710809750E-006, + sigma: 1.1833739849784384, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 3.2077610710809750E-006, + sigmaOut: 1.1833739849784384, + dminOut: 3.3505760549073344E-012, + dmin1Out: 1.7569442559804263E-002, + dmin2Out: 0.12036545569713296, + dnOut: 3.3505760549073344E-012, + dnm1Out: 1.7569442559804263E-002, + dnm2Out: 0.12036545569713296, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 3.3505364896797715E-012, + sigma: 1.1833771927395094, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 3.3505364896797715E-012, + sigmaOut: 1.1833771927395094, + dminOut: 2.0335799151090034E-023, + dmin1Out: 1.8784357595683275E-002, + dmin2Out: 0.12036607551035594, + dnOut: 2.0335799151090034E-023, + dnm1Out: 1.8784357595683275E-002, + dnm2Out: 0.12036607551035594, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.0335799151089990E-023, + sigma: 1.1833771927428600, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.1833771927428600, + dminOut: 2.0335799151089993E-023, + dmin1Out: 1.8784577209116738E-002, + dmin2Out: 0.12036616599993906, + dnOut: 2.0335799151089993E-023, + dnm1Out: 1.8784577209116738E-002, + dnm2Out: 0.12036616599993906, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + tau: 1.8784576682472597E-002, + sigma: 1.1833771927428600, + i0Out: 1, + n0Out: 8, + ppOut: 1, + tauOut: 1.8784576682472597E-002, + sigmaOut: 1.1833771927428600, + dminOut: 1.1910047947871760E-010, + dmin1Out: 0.10158160343929173, + dmin2Out: 0.48640978493259379, + dnOut: 1.1910047947871760E-010, + dnm1Out: 0.10158160343929173, + dnm2Out: 0.48640978493259379, + }, + { + z: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + i0: 1, + n0: 8, + pp: 0, + tau: 1.1910047900088848E-010, + sigma: 1.2021617694253326, + i0Out: 1, + n0Out: 8, + ppOut: 0, + tauOut: 1.1910047900088848E-010, + sigmaOut: 1.2021617694253326, + dminOut: 0.0000000000000000, + dmin1Out: 0.10158160552407068, + dmin2Out: 0.48500827096381138, + dnOut: 0.0000000000000000, + dnm1Out: 0.10158160552407068, + dnm2Out: 0.48500827096381138, + }, + { + z: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + tau: -0.0000000000000000, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 8, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.2021617695444331, + dminOut: 0.0000000000000000, + dmin1Out: 0.10158160593161437, + dmin2Out: 0.48388184445926297, + dnOut: 0.0000000000000000, + dnm1Out: 0.10158160593161437, + dnm2Out: 0.48388184445926297, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + i0: 1, + n0: 7, + pp: 0, + tau: -0.0000000000000000, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 7, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.2021617695444331, + dminOut: 0.10158160593161437, + dmin1Out: 0.48298010023310722, + dmin2Out: 0.60332139679048247, + dnOut: 0.10158160593161437, + dnm1Out: 0.48298010023310722, + dnm2Out: 0.60332139679048247, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + i0: 1, + n0: 7, + pp: 1, + tau: 0.10158160593161437, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 7, + ppOut: 1, + tauOut: 0.10158160593161437, + sigmaOut: 1.2021617695444331, + dminOut: 0.0000000000000000, + dmin1Out: 0.38053382595775820, + dmin2Out: 0.50278793042091730, + dnOut: 0.0000000000000000, + dnm1Out: 0.38053382595775820, + dnm2Out: 0.50278793042091730, + }, + { + z: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + i0: 1, + n0: 7, + pp: 0, + tau: -0.0000000000000000, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 7, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.3037433754760475, + dminOut: 0.0000000000000000, + dmin1Out: 0.37988164443454930, + dmin2Out: 0.50365062581387521, + dnOut: 0.0000000000000000, + dnm1Out: 0.37988164443454930, + dnm2Out: 0.50365062581387521, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: -0.0000000000000000, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.3037433754760475, + dminOut: 0.37939119035907048, + dmin1Out: 0.50449560273072791, + dmin2Out: 0.93712213699945368, + dnOut: 0.37939119035907048, + dnm1Out: 0.50449560273072791, + dnm2Out: 1.0004335774214996, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + i0: 1, + n0: 6, + pp: 0, + tau: 0.37791671367087804, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 6, + ppOut: 0, + tauOut: 0.37791671367087804, + sigmaOut: 1.3037433754760475, + dminOut: 1.7417124602014944E-005, + dmin1Out: 0.12721465844156904, + dmin2Out: 0.55997778901175921, + dnOut: 1.7417124602014944E-005, + dnm1Out: 0.12721465844156904, + dnm2Out: 0.60606091447901145, + }, + { + z: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: 1.7220607103034587E-005, + sigma: 1.6816600891469256, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 1.7220607103034587E-005, + sigmaOut: 1.6816600891469256, + dminOut: 5.8496704963934779E-012, + dmin1Out: 0.12768433261716639, + dmin2Out: 0.56397303984076830, + dnOut: 5.8496704963934779E-012, + dnm1Out: 0.12768433261716639, + dnm2Out: 0.58884056200405466, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + i0: 1, + n0: 6, + pp: 0, + tau: 5.8496615949827599E-012, + sigma: 1.6816773097540285, + i0Out: 1, + n0Out: 6, + ppOut: 0, + tauOut: 5.8496615949827599E-012, + sigmaOut: 1.6816773097540285, + dminOut: 5.2413685591311719E-023, + dmin1Out: 0.12914058828956335, + dmin2Out: 0.57178448001987381, + dnOut: 5.2413685591311719E-023, + dnm1Out: 0.12914058828956335, + dnm2Out: 0.57178448001987381, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: 5.2413685591311714E-023, + sigma: 1.6816773097598783, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.6816773097598783, + dminOut: 5.2413685591311719E-023, + dmin1Out: 0.12914059800027977, + dmin2Out: 0.55574794205624078, + dnOut: 5.2413685591311719E-023, + dnm1Out: 0.12914059800027977, + dnm2Out: 0.55574794205624078, + }, + { + z: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + i0: 1, + n0: 5, + pp: 0, + tau: 0.12914051019182277, + sigma: 1.6816773097598783, + i0Out: 1, + n0Out: 5, + ppOut: 0, + tauOut: 0.12914051019182277, + sigmaOut: 1.6816773097598783, + dminOut: 2.8760335918365243E-008, + dmin1Out: 0.40854091047624980, + dmin2Out: 0.47735135942481804, + dnOut: 2.8760335918365243E-008, + dnm1Out: 0.40854091047624980, + dnm2Out: 0.47735135942481804, + }, + { + z: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + i0: 1, + n0: 5, + pp: 1, + tau: 2.8760330654564486E-008, + sigma: 1.8108178199517009, + i0Out: 1, + n0Out: 5, + ppOut: 1, + tauOut: 2.8760330654564486E-008, + sigmaOut: 1.8108178199517009, + dminOut: 9.5429721930147733E-016, + dmin1Out: 0.39406941605409296, + dmin2Out: 0.49198119275848701, + dnOut: 9.5429721930147733E-016, + dnm1Out: 0.39406941605409296, + dnm2Out: 0.49198119275848701, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + i0: 1, + n0: 5, + pp: 0, + tau: 9.5429721930146451E-016, + sigma: 1.8108178487120317, + i0Out: 1, + n0Out: 5, + ppOut: 0, + tauOut: 9.5429721930146451E-016, + sigmaOut: 1.8108178487120317, + dminOut: 1.9721522630525295E-030, + dmin1Out: 0.38317668529976806, + dmin2Out: 0.50907067170667131, + dnOut: 1.9721522630525295E-030, + dnm1Out: 0.38317668529976806, + dnm2Out: 0.50907067170667131, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 0.31895966905528556, + sigma: 1.8108178487120326, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 0.31895966905528556, + sigmaOut: 1.8108178487120326, + dminOut: 4.4735699115826311E-002, + dmin1Out: 0.20335674284478694, + dmin2Out: 0.35119999573453003, + dnOut: 4.4735699115826311E-002, + dnm1Out: 0.20335674284478694, + dnm2Out: 0.41662457975226058, + }, + { + z: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + i0: 1, + n0: 4, + pp: 0, + tau: 3.9897804510299034E-002, + sigma: 2.1297775177673182, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 3.9897804510299034E-002, + sigmaOut: 2.1297775177673182, + dminOut: 3.2556800493375310E-004, + dmin1Out: 0.17365859019389857, + dmin2Out: 0.31130219122423097, + dnOut: 3.2556800493375310E-004, + dnm1Out: 0.17365859019389857, + dnm2Out: 0.37770462156728835, + }, + { + z: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 3.1797943619548145E-004, + sigma: 2.1696753222776173, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 3.1797943619548145E-004, + sigmaOut: 2.1696753222776173, + dminOut: 1.3065740500455263E-007, + dmin1Out: 0.19246898670783216, + dmin2Out: 0.31098421178803548, + dnOut: 1.3065740500455263E-007, + dnm1Out: 0.19246898670783216, + dnm2Out: 0.37861255440045072, + }, + { + z: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + i0: 1, + n0: 4, + pp: 0, + tau: 1.3065240973281283E-007, + sigma: 2.1699933017138124, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 1.3065240973281283E-007, + sigmaOut: 2.1699933017138124, + dminOut: 4.4031878668096113E-014, + dmin1Out: 0.19679806330970273, + dmin2Out: 0.31098408113562576, + dnOut: 4.4031878668096113E-014, + dnm1Out: 0.19679806330970273, + dnm2Out: 0.37930556169107532, + }, + { + z: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 4.4031878666982759E-014, + sigma: 2.1699934323662222, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 4.4031878666982759E-014, + sigmaOut: 2.1699934323662222, + dminOut: 5.0676424551397798E-027, + dmin1Out: 0.19671064247077341, + dmin2Out: 0.31098408113558174, + dnOut: 5.0676424551397798E-027, + dnm1Out: 0.19671064247077341, + dnm2Out: 0.37965850286956282, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + i0: 1, + n0: 4, + pp: 0, + tau: 5.0676424551397798E-027, + sigma: 2.1699934323662662, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.1699934323662662, + dminOut: 5.0676424551397798E-027, + dmin1Out: 0.19666151937261311, + dmin2Out: 0.31098408113558174, + dnOut: 5.0676424551397798E-027, + dnm1Out: 0.19666151937261311, + dnm2Out: 0.37984162221587608, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 9.8330759686306557E-002, + sigma: 2.1699934323662662, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 9.8330759686306557E-002, + sigmaOut: 2.1699934323662662, + dminOut: 9.8296460175394978E-002, + dmin1Out: 0.21265332144927518, + dmin2Out: 0.21265332144927518, + dnOut: 9.8296460175394978E-002, + dnm1Out: 0.28160574127978810, + dnm2Out: 0.21265332144927518, + }, + { + z: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + i0: 1, + n0: 3, + pp: 0, + tau: 9.7172513485343004E-002, + sigma: 2.2683241920525727, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 9.7172513485343004E-002, + sigmaOut: 2.2683241920525727, + dminOut: 1.1056745151512559E-003, + dmin1Out: 0.11548080796393217, + dmin2Out: 0.11548080796393217, + dnOut: 1.1056745151512559E-003, + dnm1Out: 0.18448235089755655, + dnm2Out: 0.11548080796393217, + }, + { + z: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 1.0942861809085330E-003, + sigma: 2.3654967055379159, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 1.0942861809085330E-003, + sigmaOut: 2.3654967055379159, + dminOut: 1.1278200095129901E-005, + dmin1Out: 0.11438652178302365, + dmin2Out: 0.11438652178302365, + dnOut: 1.1278200095129901E-005, + dnm1Out: 0.18342236422755959, + dnm2Out: 0.11438652178302365, + }, + { + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + i0: 1, + n0: 3, + pp: 0, + tau: 1.1269238360546607E-005, + sigma: 2.3665909917188244, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 1.1269238360546607E-005, + sigmaOut: 2.3665909917188244, + dminOut: 8.9549629620034135E-009, + dmin1Out: 0.11437525254466312, + dmin2Out: 0.11437525254466312, + dnOut: 8.9549629620034135E-009, + dnm1Out: 0.18342936716409974, + dnm2Out: 0.11437525254466312, + }, + { + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 8.9549072084035346E-009, + sigma: 2.3666022609571851, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 8.9549072084035346E-009, + sigmaOut: 2.3666022609571851, + dminOut: 5.5753269291151117E-014, + dmin1Out: 0.11437524358975594, + dmin2Out: 0.11437524358975594, + dnOut: 5.5753269291151117E-014, + dnm1Out: 0.18342946834334006, + dnm2Out: 0.11437524358975594, + }, + { + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + i0: 1, + n0: 3, + pp: 0, + tau: 5.5753269214454873E-014, + sigma: 2.3666022699120921, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 5.5753269214454873E-014, + sigmaOut: 2.3666022699120921, + dminOut: 7.6696244203643861E-023, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dnm1Out: 0.18342946835005580, + dnm2Out: 0.11437524358970023, + }, + { + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 7.8766827084626452E-005, + dmin1Out: 1.2363512593342330E-003, + dmin2Out: 1.2363512593342330E-003, + dnOut: 7.8766827084626452E-005, + dnm1Out: 4.3867054272813191E-003, + dnm2Out: 3.7622286348031123E-003, + }, + } { + // TODO(btracey): Check other outputs + i0 := test.i0 - 1 + n0 := test.n0 - 1 + z := make([]float64, len(test.z)) + copy(z, test.z) + + i0Out, n0Out, ppOut, tauOut, sigmaOut, dminOut, dmin1Out, dmin2Out, dnOut, dnm1Out, dnm2Out := impl.Dlasq5(i0, n0, z, test.pp, test.tau, test.sigma) + + if i0Out != test.i0Out-1 { + t.Errorf("Wrong i0. Want %v, got %v", test.n0Out, n0Out) + } + if n0Out != test.n0Out-1 { + t.Errorf("Wrong n0. Want %v, got %v", test.n0Out, n0Out) + } + if ppOut != test.ppOut { + t.Errorf("Wrong pp. Want %v, got %v", test.ppOut, ppOut) + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("Wrong tau. Want %v, got %v", test.tauOut, tauOut) + } + if !floats.EqualWithinAbsOrRel(sigmaOut, test.sigmaOut, dTol, dTol) { + t.Errorf("Wrong tau. Want %v, got %v", test.sigmaOut, sigmaOut) + } + + if !floats.EqualWithinAbsOrRel(dminOut, test.dminOut, dTol, dTol) { + t.Errorf("Wrong dmin. Want %v, got %v", test.dminOut, dminOut) + } + if !floats.EqualWithinAbsOrRel(dmin1Out, test.dmin1Out, dTol, dTol) { + t.Errorf("Wrong dmin1. Want %v, got %v", test.dmin1Out, dmin1Out) + } + if !floats.EqualWithinAbsOrRel(dmin2Out, test.dmin2Out, dTol, dTol) { + t.Errorf("Wrong dmin2. Want %v, got %v", test.dmin2Out, dmin2Out) + } + if !floats.EqualWithinAbsOrRel(dnOut, test.dnOut, dTol, dTol) { + t.Errorf("Wrong dn. Want %v, got %v", test.dnOut, dnOut) + } + if !floats.EqualWithinAbsOrRel(dnm1Out, test.dnm1Out, dTol, dTol) { + t.Errorf("Wrong dnm1. Want %v, got %v", test.dnm1Out, dnm1Out) + } + if !floats.EqualWithinAbsOrRel(dnm2Out, test.dnm2Out, dTol, dTol) { + t.Errorf("Wrong dnm2. Want %v, got %v", test.dnm2Out, dnm2Out) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasr.go new file mode 100644 index 00000000..87a26059 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasr.go @@ -0,0 +1,148 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlasrer interface { + Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) +} + +func DlasrTest(t *testing.T, impl Dlasrer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, pivot := range []lapack.Pivot{lapack.Variable, lapack.Top, lapack.Bottom} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, test := range []struct { + m, n, lda int + }{ + {5, 5, 0}, + {5, 10, 0}, + {10, 5, 0}, + + {5, 5, 20}, + {5, 10, 20}, + {10, 5, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + var s, c []float64 + if side == blas.Left { + s = make([]float64, m-1) + c = make([]float64, m-1) + } else { + s = make([]float64, n-1) + c = make([]float64, n-1) + } + for k := range s { + theta := rnd.Float64() * 2 * math.Pi + s[k] = math.Sin(theta) + c[k] = math.Cos(theta) + } + aCopy := make([]float64, len(a)) + copy(a, aCopy) + impl.Dlasr(side, pivot, direct, m, n, c, s, a, lda) + + pSize := m + if side == blas.Right { + pSize = n + } + p := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + pk := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + ptmp := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + for i := 0; i < pSize; i++ { + p.Data[i*p.Stride+i] = 1 + ptmp.Data[i*p.Stride+i] = 1 + } + // Compare to direct computation. + for k := range s { + for i := range p.Data { + pk.Data[i] = 0 + } + for i := 0; i < pSize; i++ { + pk.Data[i*p.Stride+i] = 1 + } + if pivot == lapack.Variable { + pk.Data[k*p.Stride+k] = c[k] + pk.Data[k*p.Stride+k+1] = s[k] + pk.Data[(k+1)*p.Stride+k] = -s[k] + pk.Data[(k+1)*p.Stride+k+1] = c[k] + } else if pivot == lapack.Top { + pk.Data[0] = c[k] + pk.Data[k+1] = s[k] + pk.Data[(k+1)*p.Stride] = -s[k] + pk.Data[(k+1)*p.Stride+k+1] = c[k] + } else { + pk.Data[(pSize-1-k)*p.Stride+pSize-k-1] = c[k] + pk.Data[(pSize-1-k)*p.Stride+pSize-1] = s[k] + pk.Data[(pSize-1)*p.Stride+pSize-1-k] = -s[k] + pk.Data[(pSize-1)*p.Stride+pSize-1] = c[k] + } + if direct == lapack.Forward { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, pk, ptmp, 0, p) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, ptmp, pk, 0, p) + } + copy(ptmp.Data, p.Data) + } + + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(a, aCopy) + newA := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + if side == blas.Left { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, p, aMat, 0, newA) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, p, 0, newA) + } + if !floats.EqualApprox(newA.Data, a, 1e-12) { + t.Errorf("A update mismatch") + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasrt.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasrt.go new file mode 100644 index 00000000..80b1404b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasrt.go @@ -0,0 +1,80 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlasrter interface { + Dlasrt(s lapack.Sort, n int, d []float64) +} + +func DlasrtTest(t *testing.T, impl Dlasrter) { + for ti, test := range []struct { + data []float64 + wantInc []float64 + wantDec []float64 + }{ + { + data: nil, + wantInc: nil, + wantDec: nil, + }, + { + data: []float64{}, + wantInc: []float64{}, + wantDec: []float64{}, + }, + { + data: []float64{1}, + wantInc: []float64{1}, + wantDec: []float64{1}, + }, + { + data: []float64{1, 2}, + wantInc: []float64{1, 2}, + wantDec: []float64{2, 1}, + }, + { + data: []float64{1, 2, -3}, + wantInc: []float64{-3, 1, 2}, + wantDec: []float64{2, 1, -3}, + }, + { + data: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + { + data: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + { + data: []float64{-2, 4, -1, 2, -4, 0, 3, 5, -5, 1, -3}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + } { + n := len(test.data) + ds := make([]float64, n) + + copy(ds, test.data) + impl.Dlasrt(lapack.SortIncreasing, n, ds) + if !floats.Equal(ds, test.wantInc) { + t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) + } + + copy(ds, test.data) + impl.Dlasrt(lapack.SortDecreasing, n, ds) + if !floats.Equal(ds, test.wantDec) { + t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasv2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasv2.go new file mode 100644 index 00000000..85184e62 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasv2.go @@ -0,0 +1,48 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasv2er interface { + Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) +} + +func Dlasv2Test(t *testing.T, impl Dlasv2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 100; i++ { + f := rnd.NormFloat64() + g := rnd.NormFloat64() + h := rnd.NormFloat64() + + ssmin, ssmax, snr, csr, snl, csl := impl.Dlasv2(f, g, h) + + // tmp = + // [ csl snl] [f g] + // [-snl csl] [0 h] + tmp11 := csl * f + tmp12 := csl*g + snl*h + tmp21 := -snl * f + tmp22 := -snl*g + csl*h + // lhs = + // [tmp11 tmp12] [csr -snr] + // [tmp21 tmp22] [snr csr] + ans11 := tmp11*csr + tmp12*snr + ans12 := tmp11*-snr + tmp12*csr + ans21 := tmp21*csr + tmp22*snr + ans22 := tmp21*-snr + tmp22*csr + + lhs := []float64{ans11, ans12, ans21, ans22} + rhs := []float64{ssmax, 0, 0, ssmin} + if !floats.EqualApprox(rhs, lhs, 1e-12) { + t.Errorf("SVD mismatch. f = %v, g = %v, h = %v.\nLHS: %v\nRHS: %v", f, g, h, lhs, rhs) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaswp.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaswp.go new file mode 100644 index 00000000..9d8e08d7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlaswp.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaswper interface { + Dlaswp(n int, a []float64, lda, k1, k2 int, ipiv []int, incX int) +} + +func DlaswpTest(t *testing.T, impl Dlaswper) { + for ti, test := range []struct { + k1, k2 int + ipiv []int + incX int + + want blas64.General + }{ + { + k1: 0, + k2: 2, + ipiv: []int{0, 1, 2}, + incX: 1, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{0, 1, 2}, + incX: -1, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{1, 2, 3}, + incX: 1, + want: blas64.General{ + Rows: 5, + Cols: 3, + Stride: 3, + Data: []float64{ + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 1, 2, 3, + 13, 14, 15, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{1, 2, 3}, + incX: -1, + want: blas64.General{ + Rows: 5, + Cols: 3, + Stride: 3, + Data: []float64{ + 10, 11, 12, + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 13, 14, 15, + }, + }, + }, + } { + m := test.want.Rows + n := test.want.Cols + k1 := test.k1 + k2 := test.k2 + if len(test.ipiv) != k2+1 { + panic("bad length of ipiv") + } + incX := test.incX + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + + ipiv := make([]int, len(test.ipiv)) + copy(ipiv, test.ipiv) + + impl.Dlaswp(n, a.Data, a.Stride, k1, k2, ipiv, incX) + + prefix := fmt.Sprintf("Case %v (m=%v,n=%v,k1=%v,k2=%v,extra=%v)", ti, m, n, k1, k2, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if !equalApproxGeneral(a, test.want, 0) { + t.Errorf("%v: unexpected A\n%v\n%v", prefix, a, test.want) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasy2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasy2.go new file mode 100644 index 00000000..7ed5ed8c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlasy2.go @@ -0,0 +1,104 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlasy2er interface { + Dlasy2(tranl, tranr bool, isgn, n1, n2 int, tl []float64, ldtl int, tr []float64, ldtr int, b []float64, ldb int, x []float64, ldx int) (scale, xnorm float64, ok bool) +} + +func Dlasy2Test(t *testing.T, impl Dlasy2er) { + rnd := rand.New(rand.NewSource(1)) + for _, tranl := range []bool{true, false} { + for _, tranr := range []bool{true, false} { + for _, isgn := range []int{1, -1} { + for _, n1 := range []int{0, 1, 2} { + for _, n2 := range []int{0, 1, 2} { + for _, extra := range []int{0, 1, 2, 13} { + for cas := 0; cas < 1000; cas++ { + testDlasy2(t, impl, tranl, tranr, isgn, n1, n2, extra, rnd) + } + } + } + } + } + } + } +} + +func testDlasy2(t *testing.T, impl Dlasy2er, tranl, tranr bool, isgn, n1, n2, extra int, rnd *rand.Rand) { + const tol = 1e-11 + + tl := randomGeneral(n1, n1, n1+extra, rnd) + tr := randomGeneral(n2, n2, n2+extra, rnd) + b := randomGeneral(n1, n2, n2+extra, rnd) + x := randomGeneral(n1, n2, n2+extra, rnd) + + scale, xnorm, ok := impl.Dlasy2(tranl, tranr, isgn, n1, n2, tl.Data, tl.Stride, tr.Data, tr.Stride, b.Data, b.Stride, x.Data, x.Stride) + if scale > 1 { + t.Errorf("invalid value of scale, want <= 1, got %v", scale) + } + if n1 == 0 || n2 == 0 { + return + } + + prefix := fmt.Sprintf("Case n1=%v, n2=%v, isgn=%v", n1, n2, isgn) + + // Check any invalid modifications of x. + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to x\n%v", prefix, x.Data) + } + + var xnormWant float64 + for i := 0; i < n1; i++ { + var rowsum float64 + for j := 0; j < n2; j++ { + rowsum += math.Abs(x.Data[i*x.Stride+j]) + } + if rowsum > xnormWant { + xnormWant = rowsum + } + } + if xnormWant != xnorm { + t.Errorf("%v: unexpected xnorm: want %v, got %v", prefix, xnormWant, xnorm) + } + + // Multiply b by scale to get the wanted right-hand side. + for i := 0; i < n1; i++ { + for j := 0; j < n2; j++ { + b.Data[i*b.Stride+j] *= scale + } + } + // Compute the wanted left-hand side. + lhsWant := randomGeneral(n1, n2, n2, rnd) + if tranl { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, tl, x, 0, lhsWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tl, x, 0, lhsWant) + } + if tranr { + blas64.Gemm(blas.NoTrans, blas.Trans, float64(isgn), x, tr, 1, lhsWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, float64(isgn), x, tr, 1, lhsWant) + } + // Compare them. + for i := 0; i < n1; i++ { + for j := 0; j < n2; j++ { + diff := lhsWant.Data[i*lhsWant.Stride+j] - b.Data[i*b.Stride+j] + if math.Abs(diff) > tol && ok { + t.Errorf("%v: unexpected result, diff[%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrd.go new file mode 100644 index 00000000..f4d3cddc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrd.go @@ -0,0 +1,245 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlatrder interface { + Dlatrd(uplo blas.Uplo, n, nb int, a []float64, lda int, e, tau, w []float64, ldw int) +} + +func DlatrdTest(t *testing.T, impl Dlatrder) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, nb, lda, ldw int + }{ + {5, 2, 0, 0}, + {5, 5, 0, 0}, + + {5, 3, 10, 11}, + {5, 5, 10, 11}, + } { + n := test.n + nb := test.nb + lda := test.lda + if lda == 0 { + lda = n + } + ldw := test.ldw + if ldw == 0 { + ldw = nb + } + + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + e := make([]float64, n-1) + for i := range e { + e[i] = math.NaN() + } + tau := make([]float64, n-1) + for i := range tau { + tau[i] = math.NaN() + } + w := make([]float64, n*ldw) + for i := range w { + w[i] = math.NaN() + } + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + impl.Dlatrd(uplo, n, nb, a, lda, e, tau, w, ldw) + + // Construct Q. + ldq := n + q := blas64.General{ + Rows: n, + Cols: n, + Stride: ldq, + Data: make([]float64, n*ldq), + } + for i := 0; i < n; i++ { + q.Data[i*ldq+i] = 1 + } + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + if i == 0 { + continue + } + h := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + for j := 0; j < n; j++ { + h.Data[j*n+j] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + for j := 0; j < i-1; j++ { + v.Data[j] = a[j*lda+i] + } + v.Data[i-1] = 1 + + blas64.Ger(-tau[i-1], v, v, h) + + qTmp := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qTmp, h, 0, q) + } + } else { + for i := 0; i < nb; i++ { + if i == n-1 { + continue + } + h := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + for j := 0; j < n; j++ { + h.Data[j*n+j] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[i+1] = 1 + for j := i + 2; j < n; j++ { + v.Data[j] = a[j*lda+i] + } + blas64.Ger(-tau[i], v, v, h) + + qTmp := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qTmp, h, 0, q) + } + } + errStr := fmt.Sprintf("isUpper = %v, n = %v, nb = %v", uplo == blas.Upper, n, nb) + if !isOrthonormal(q) { + t.Errorf("Q not orthonormal. %s", errStr) + } + aGen := genFromSym(blas64.Symmetric{N: n, Stride: lda, Uplo: uplo, Data: aCopy}) + if !dlatrdCheckDecomposition(t, uplo, n, nb, e, tau, a, lda, aGen, q) { + t.Errorf("Decomposition mismatch. %s", errStr) + } + } + } +} + +// dlatrdCheckDecomposition checks that the first nb rows have been successfully +// reduced. +func dlatrdCheckDecomposition(t *testing.T, uplo blas.Uplo, n, nb int, e, tau, a []float64, lda int, aGen, q blas64.General) bool { + // Compute Q^T * A * Q. + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + ans := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aGen, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, ans) + + // Compare with T. + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + for j := 0; j < n; j++ { + v := ans.Data[i*ans.Stride+j] + switch { + case i == j: + if math.Abs(v-a[i*lda+j]) > 1e-10 { + return false + } + case i == j-1: + if math.Abs(a[i*lda+j]-1) > 1e-10 { + return false + } + if math.Abs(v-e[i]) > 1e-10 { + return false + } + case i == j+1: + default: + if math.Abs(v) > 1e-10 { + return false + } + } + } + } + } else { + for i := 0; i < nb; i++ { + for j := 0; j < n; j++ { + v := ans.Data[i*ans.Stride+j] + switch { + case i == j: + if math.Abs(v-a[i*lda+j]) > 1e-10 { + return false + } + case i == j-1: + case i == j+1: + if math.Abs(a[i*lda+j]-1) > 1e-10 { + return false + } + if math.Abs(v-e[i-1]) > 1e-10 { + return false + } + default: + if math.Abs(v) > 1e-10 { + return false + } + } + } + } + } + return true +} + +// genFromSym constructs a (symmetric) general matrix from the data in the +// symmetric. +// TODO(btracey): Replace other constructions of this with a call to this function. +func genFromSym(a blas64.Symmetric) blas64.General { + n := a.N + lda := a.Stride + uplo := a.Uplo + b := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a.Data[i*lda+j] + if uplo == blas.Lower { + v = a.Data[j*lda+i] + } + b.Data[i*n+j] = v + b.Data[j*n+i] = v + } + } + return b +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrs.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrs.go new file mode 100644 index 00000000..d2d77897 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dlatrs.go @@ -0,0 +1,141 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlatrser interface { + Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n int, a []float64, lda int, x []float64, cnorm []float64) (scale float64) +} + +func DlatrsTest(t *testing.T, impl Dlatrser) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, trans := range []blas.Transpose{blas.Trans, blas.NoTrans} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 7, 10, 20, 50, 100} { + for _, lda := range []int{n, 2*n + 1} { + lda = max(1, lda) + imats := []int{7, 11, 12, 13, 14, 15, 16, 17, 18} + if n < 6 { + imats = append(imats, 19) + } + for _, imat := range imats { + testDlatrs(t, impl, imat, uplo, trans, n, lda, rnd) + } + } + } + } + } +} + +func testDlatrs(t *testing.T, impl Dlatrser, imat int, uplo blas.Uplo, trans blas.Transpose, n, lda int, rnd *rand.Rand) { + const tol = 1e-14 + + a := nanSlice(n * lda) + b := nanSlice(n) + work := make([]float64, 3*n) + + // Generate triangular test matrix and right hand side. + diag := dlattr(imat, uplo, trans, n, a, lda, b, work, rnd) + if imat <= 10 { + // b has not been generated. + dlarnv(b, 3, rnd) + } + + cnorm := nanSlice(n) + x := make([]float64, n) + + // Call Dlatrs with normin=false. + copy(x, b) + scale := impl.Dlatrs(uplo, trans, diag, false, n, a, lda, x, cnorm) + prefix := fmt.Sprintf("Case imat=%v (n=%v,lda=%v,trans=%v,uplo=%v,diag=%v", imat, n, lda, trans, uplo, diag) + for i, v := range cnorm { + if math.IsNaN(v) { + t.Errorf("%v: cnorm[%v] not computed (scale=%v,normin=false)", prefix, i, scale) + } + } + resid, hasNaN := dlatrsResidual(uplo, trans, diag, n, a, lda, scale, cnorm, x, b, work[:n]) + if hasNaN { + t.Errorf("%v: unexpected NaN (scale=%v,normin=false)", prefix, scale) + } else if resid > tol { + t.Errorf("%v: residual %v too large (scale=%v,normin=false)", prefix, resid, scale) + } + + // Call Dlatrs with normin=true because cnorm has been filled. + copy(x, b) + scale = impl.Dlatrs(uplo, trans, diag, true, n, a, lda, x, cnorm) + resid, hasNaN = dlatrsResidual(uplo, trans, diag, n, a, lda, scale, cnorm, x, b, work[:n]) + if hasNaN { + t.Errorf("%v: unexpected NaN (scale=%v,normin=true)", prefix, scale) + } else if resid > tol { + t.Errorf("%v: residual %v too large (scale=%v,normin=true)", prefix, resid, scale) + } +} + +// dlatrsResidual returns norm(trans(A)*x-scale*b) / (norm(trans(A))*norm(x)*eps) +// and whether NaN has been encountered in the process. +func dlatrsResidual(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []float64, lda int, scale float64, cnorm []float64, x, b, work []float64) (resid float64, hasNaN bool) { + if n == 0 { + return 0, false + } + + // Compute the norm of the triangular matrix A using the column norms + // already computed by Dlatrs. + var tnorm float64 + if diag == blas.NonUnit { + for j := 0; j < n; j++ { + tnorm = math.Max(tnorm, math.Abs(a[j*lda+j])+cnorm[j]) + } + } else { + for j := 0; j < n; j++ { + tnorm = math.Max(tnorm, 1+cnorm[j]) + } + } + + eps := dlamchE + smlnum := dlamchS + bi := blas64.Implementation() + + // Compute norm(trans(A)*x-scale*b) / (norm(trans(A))*norm(x)*eps) + copy(work, x) + ix := bi.Idamax(n, work, 1) + xnorm := math.Max(1, math.Abs(work[ix])) + xscal := 1 / xnorm / float64(n) + bi.Dscal(n, xscal, work, 1) + bi.Dtrmv(uplo, trans, diag, n, a, lda, work, 1) + bi.Daxpy(n, -scale*xscal, b, 1, work, 1) + for _, v := range work { + if math.IsNaN(v) { + return 1 / eps, true + } + } + ix = bi.Idamax(n, work, 1) + resid = math.Abs(work[ix]) + ix = bi.Idamax(n, x, 1) + xnorm = math.Abs(x[ix]) + if resid*smlnum <= xnorm { + if xnorm > 0 { + resid /= xnorm + } + } else if resid > 0 { + resid = 1 / eps + } + if resid*smlnum <= tnorm { + if tnorm > 0 { + resid /= tnorm + } + } else if resid > 0 { + resid = 1 / eps + } + return resid, false +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/doc.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/doc.go new file mode 100644 index 00000000..76da5d18 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 testlapack implements a set of testing routines for Lapack functions. +package testlapack // import "gonum.org/v1/gonum/lapack/testlapack" diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2l.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2l.go new file mode 100644 index 00000000..e1f2f155 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2l.go @@ -0,0 +1,75 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorg2ler interface { + Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) + Dgeql2er +} + +func Dorg2lTest(t *testing.T, impl Dorg2ler) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, k, lda int + }{ + {5, 4, 3, 0}, + {5, 4, 4, 0}, + {3, 3, 2, 0}, + {5, 5, 5, 0}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + tau := nanSlice(max(m, n)) + work := make([]float64, n) + impl.Dgeql2(m, n, a, lda, tau, work) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dorg2l(m, n, k, a, lda, tau[n-k:], work) + if !hasOrthonormalColumns(m, n, a, lda) { + t.Errorf("Q is not orthonormal. m = %v, n = %v, k = %v", m, n, k) + } + } +} + +// hasOrthornormalColumns checks that the columns of a are orthonormal. +func hasOrthonormalColumns(m, n int, a []float64, lda int) bool { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(m, + blas64.Vector{Inc: lda, Data: a[i:]}, + blas64.Vector{Inc: lda, Data: a[j:]}, + ) + if i == j { + if math.Abs(dot-1) > 1e-10 { + return false + } + } else { + if math.Abs(dot) > 1e-10 { + return false + } + } + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2r.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2r.go new file mode 100644 index 00000000..beeca34d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorg2r.go @@ -0,0 +1,79 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorg2rer interface { + Dgeqrfer + Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) +} + +func Dorg2rTest(t *testing.T, impl Dorg2rer) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, k, lda int + }{ + {3, 3, 0, 0}, + {4, 3, 0, 0}, + {3, 3, 2, 0}, + {4, 3, 2, 0}, + + {5, 5, 0, 20}, + {5, 5, 3, 20}, + {10, 5, 0, 20}, + {10, 5, 2, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + k := min(m, n) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + + k = test.k + if k == 0 { + k = n + } + q := constructQK("QR", m, n, k, a, lda, tau) + + impl.Dorg2r(m, n, k, a, lda, tau, work) + + // Check that the first n columns match. + same := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { + same = false + break + } + } + } + if !same { + fmt.Println() + fmt.Println("a =") + printRowise(a, m, n, lda, false) + fmt.Println("q =") + printRowise(q.Data, q.Rows, q.Cols, q.Stride, false) + t.Errorf("Q mismatch") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgbr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgbr.go new file mode 100644 index 00000000..3f43fb94 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgbr.go @@ -0,0 +1,156 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dorgbrer interface { + Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + Dgebrder +} + +func DorgbrTest(t *testing.T, impl Dorgbrer) { + rnd := rand.New(rand.NewSource(1)) + for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} { + for _, test := range []struct { + m, n, k, lda int + }{ + {5, 5, 5, 0}, + {5, 5, 3, 0}, + {5, 3, 5, 0}, + {3, 5, 5, 0}, + {3, 4, 5, 0}, + {3, 5, 4, 0}, + {4, 3, 5, 0}, + {4, 5, 3, 0}, + {5, 3, 4, 0}, + {5, 4, 3, 0}, + + {5, 5, 5, 10}, + {5, 5, 3, 10}, + {5, 3, 5, 10}, + {3, 5, 5, 10}, + {3, 4, 5, 10}, + {3, 5, 4, 10}, + {4, 3, 5, 10}, + {4, 5, 3, 10}, + {5, 3, 4, 10}, + {5, 4, 3, 10}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + // Filter out bad tests + if vect == lapack.ApplyQ { + if m < n || n < min(m, k) || m < min(m, k) { + continue + } + } else { + if n < m || m < min(n, k) || n < min(n, k) { + continue + } + } + // Sizes for Dorgbr. + var ma, na int + if vect == lapack.ApplyQ { + if m >= k { + ma = m + na = k + } else { + ma = m + na = m + } + } else { + if n >= k { + ma = k + na = n + } else { + ma = n + na = n + } + } + // a eventually needs to store either P or Q, so it must be + // sufficiently big. + var a []float64 + if vect == lapack.ApplyQ { + lda = max(m, lda) + a = make([]float64, m*lda) + } else { + lda = max(n, lda) + a = make([]float64, n*lda) + } + for i := range a { + a[i] = rnd.NormFloat64() + } + + nTau := min(ma, na) + tauP := make([]float64, nTau) + tauQ := make([]float64, nTau) + d := make([]float64, nTau) + e := make([]float64, nTau) + lwork := -1 + work := make([]float64, 1) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) + work = make([]float64, int(work[0])) + lwork = len(work) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + var tau []float64 + if vect == lapack.ApplyQ { + tau = tauQ + } else { + tau = tauP + } + + impl.Dorgbr(vect, m, n, k, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + impl.Dorgbr(vect, m, n, k, a, lda, tau, work, lwork) + + var ans blas64.General + var nRows, nCols int + equal := true + if vect == lapack.ApplyQ { + nRows = m + nCols = m + if m >= k { + nCols = n + } + ans = constructQPBidiagonal(vect, ma, na, min(m, k), aCopy, lda, tau) + } else { + nRows = n + if k < n { + nRows = m + } + nCols = n + ansTmp := constructQPBidiagonal(vect, ma, na, min(k, n), aCopy, lda, tau) + // Dorgbr actually computes P^T + ans = transposeGeneral(ansTmp) + } + for i := 0; i < nRows; i++ { + for j := 0; j < nCols; j++ { + if !floats.EqualWithinAbsOrRel(a[i*lda+j], ans.Data[i*ans.Stride+j], 1e-8, 1e-8) { + equal = false + } + } + } + if !equal { + applyQ := vect == lapack.ApplyQ + t.Errorf("Extracted matrix mismatch. applyQ: %v, m = %v, n = %v, k = %v", applyQ, m, n, k) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorghr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorghr.go new file mode 100644 index 00000000..7311d015 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorghr.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorghrer interface { + Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) + + Dgehrder +} + +func DorghrTest(t *testing.T, impl Dorghrer) { + rnd := rand.New(rand.NewSource(1)) + + for _, n := range []int{1, 2, 3, 4, 5, 6, 7, 8, 23, 34} { + for _, extra := range []int{0, 1, 13} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 100; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDorghr(t, impl, n, ilo, ihi, extra, optwork, rnd) + } + } + } + } + testDorghr(t, impl, 0, 0, -1, 0, false, rnd) + testDorghr(t, impl, 0, 0, -1, 0, true, rnd) +} + +func testDorghr(t *testing.T, impl Dorghrer, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + // Construct the matrix A with elementary reflectors and scalar factors tau. + a := randomGeneral(n, n, n+extra, rnd) + var tau []float64 + if n > 1 { + tau = nanSlice(n - 1) + } + work := nanSlice(max(1, n)) // Minimum work for Dgehrd. + impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + // Extract Q for later comparison. + q := eye(n, n) + qCopy := cloneGeneral(q) + for j := ilo; j < ihi; j++ { + h := eye(n, n) + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + + if optwork { + work = nanSlice(1) + impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, ihi-ilo)) + } + impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", n, ilo, ihi, extra, optwork) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !isOrthonormal(a) { + t.Errorf("%v: A is not orthogonal\n%v", prefix, a.Data) + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + aij := a.Data[i*a.Stride+j] + qij := q.Data[i*q.Stride+j] + if math.Abs(aij-qij) > tol { + t.Errorf("%v: unexpected value of A[%v,%v]. want %v, got %v", prefix, i, j, qij, aij) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgl2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgl2.go new file mode 100644 index 00000000..5ae3fcb1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgl2.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorgl2er interface { + Dgelqfer + Dorgl2(m, n, k int, a []float64, lda int, tau []float64, work []float64) +} + +func Dorgl2Test(t *testing.T, impl Dorgl2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {3, 3, 0}, + {3, 4, 0}, + + {5, 5, 20}, + {5, 10, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + k := min(m, n) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + + q := constructQ("LQ", m, n, a, lda, tau) + + impl.Dorgl2(m, n, k, a, lda, tau, work) + + // Check that the first m rows match. + same := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { + same = false + break + } + } + } + if !same { + t.Errorf("Q mismatch") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorglq.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorglq.go new file mode 100644 index 00000000..3d8bb105 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorglq.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorglqer interface { + Dorgl2er + Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DorglqTest(t *testing.T, impl Dorglqer) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Base tests off of nb and nx. + for _, test := range []struct{ m, n, k, lda int }{ + {10, 10, 10, 0}, + {10, 10, 10, 20}, + {10, 30, 10, 0}, + {20, 30, 10, 0}, + + {100, 100, 100, 0}, + {100, 100, 50, 0}, + {100, 130, 100, 0}, + {100, 130, 50, 0}, + {100, 100, 100, 150}, + {100, 100, 50, 150}, + {100, 130, 100, 150}, + {100, 130, 50, 150}, + + {200, 200, 200, 0}, + {200, 200, 150, 0}, + {200, 230, 200, 0}, + {200, 230, 150, 0}, + {200, 200, 200, 250}, + {200, 200, 150, 250}, + {200, 230, 200, 250}, + {200, 230, 150, 250}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + work := make([]float64, 1) + tau := make([]float64, m) + for i := range tau { + tau[i] = math.NaN() + } + // Compute LQ factorization. + impl.Dgelqf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + + aUnblocked := make([]float64, len(a)) + copy(aUnblocked, a) + for i := range work { + work[i] = math.NaN() + } + impl.Dorgl2(m, n, k, aUnblocked, lda, tau, work) + // make sure work isn't used before initialized + for i := range work { + work[i] = math.NaN() + } + impl.Dorglq(m, n, k, a, lda, tau, work, len(work)) + if !floats.EqualApprox(a, aUnblocked, 1e-10) { + t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgql.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgql.go new file mode 100644 index 00000000..4cf9b22a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgql.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorgqler interface { + Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + + Dlarfger +} + +func DorgqlTest(t *testing.T, impl Dorgqler) { + const tol = 1e-14 + + type Dorg2ler interface { + Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) + } + dorg2ler, hasDorg2l := impl.(Dorg2ler) + + rnd := rand.New(rand.NewSource(1)) + for _, m := range []int{0, 1, 2, 3, 4, 5, 7, 10, 15, 30, 50, 150} { + for _, extra := range []int{0, 11} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + var k int + if m >= 129 { + // For large matrices make sure that k + // is large enough to trigger blocked + // path. + k = 129 + rnd.Intn(m-129+1) + } else { + k = rnd.Intn(m + 1) + } + n := k + rnd.Intn(m-k+1) + if m == 0 || n == 0 { + m = 0 + n = 0 + k = 0 + } + + // Generate k elementary reflectors in the last + // k columns of A. + a := nanGeneral(m, n, n+extra) + tau := make([]float64, k) + for l := 0; l < k; l++ { + jj := m - k + l + v := randomSlice(jj, rnd) + _, tau[l] = impl.Dlarfg(len(v)+1, rnd.NormFloat64(), v, 1) + j := n - k + l + for i := 0; i < jj; i++ { + a.Data[i*a.Stride+j] = v[i] + } + } + aCopy := cloneGeneral(a) + + // Compute the full matrix Q by forming the + // Householder reflectors explicitly. + q := eye(m, m) + qCopy := eye(m, m) + for l := 0; l < k; l++ { + h := eye(m, m) + jj := m - k + l + j := n - k + l + v := blas64.Vector{1, make([]float64, m)} + for i := 0; i < jj; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + v.Data[jj] = 1 + blas64.Ger(-tau[l], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qCopy, 0, q) + } + // View the last n columns of Q as 'want'. + want := blas64.General{ + Rows: m, + Cols: n, + Stride: q.Stride, + Data: q.Data[m-n:], + } + + var lwork int + switch wl { + case minimumWork: + lwork = max(1, n) + case mediumWork: + work := make([]float64, 1) + impl.Dorgql(m, n, k, nil, a.Stride, nil, work, -1) + lwork = (int(work[0]) + n) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dorgql(m, n, k, nil, a.Stride, nil, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + // Compute the last n columns of Q by a call to + // Dorgql. + impl.Dorgql(m, n, k, a.Data, a.Stride, tau, work, len(work)) + + prefix := fmt.Sprintf("Case m=%v,n=%v,k=%v,wl=%v", m, n, k, wl) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + if !equalApproxGeneral(want, a, tol) { + t.Errorf("%v: unexpected Q", prefix) + } + + // Compute the last n columns of Q by a call to + // Dorg2l and check that we get the same result. + if !hasDorg2l { + continue + } + dorg2ler.Dorg2l(m, n, k, aCopy.Data, aCopy.Stride, tau, work) + if !equalApproxGeneral(aCopy, a, tol) { + t.Errorf("%v: mismatch between Dorgql and Dorg2l", prefix) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgqr.go new file mode 100644 index 00000000..57306c05 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgqr.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorgqrer interface { + Dorg2rer + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DorgqrTest(t *testing.T, impl Dorgqrer) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Base tests off of nb and nx. + for _, test := range []struct{ m, n, k, lda int }{ + {10, 10, 10, 0}, + {10, 10, 10, 20}, + {30, 10, 10, 0}, + {30, 20, 10, 20}, + + {100, 100, 100, 0}, + {100, 100, 50, 0}, + {130, 100, 100, 0}, + {130, 100, 50, 0}, + {100, 100, 100, 150}, + {100, 100, 50, 150}, + {130, 100, 100, 150}, + {130, 100, 50, 150}, + + {200, 200, 200, 0}, + {200, 200, 150, 0}, + {230, 200, 200, 0}, + {230, 200, 150, 0}, + {200, 200, 200, 250}, + {200, 200, 150, 250}, + {230, 200, 200, 250}, + {230, 200, 150, 250}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + work := make([]float64, 1) + tau := make([]float64, n) + for i := range tau { + tau[i] = math.NaN() + } + // Compute QR factorization. + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + + aUnblocked := make([]float64, len(a)) + copy(aUnblocked, a) + for i := range work { + work[i] = math.NaN() + } + impl.Dorg2r(m, n, k, aUnblocked, lda, tau, work) + // make sure work isn't used before initialized + for i := range work { + work[i] = math.NaN() + } + impl.Dorgqr(m, n, k, a, lda, tau, work, len(work)) + if !floats.EqualApprox(a, aUnblocked, 1e-10) { + t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgtr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgtr.go new file mode 100644 index 00000000..4f49d1a4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorgtr.go @@ -0,0 +1,136 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorgtrer interface { + Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) + Dsytrder +} + +func DorgtrTest(t *testing.T, impl Dorgtrer) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {6, 0}, + {33, 0}, + {100, 0}, + + {1, 3}, + {2, 5}, + {3, 7}, + {6, 10}, + {33, 50}, + {100, 120}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + d := make([]float64, n) + e := make([]float64, n-1) + tau := make([]float64, n-1) + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, len(work)) + + var lwork int + switch wl { + case minimumWork: + lwork = max(1, n-1) + case mediumWork: + work := make([]float64, 1) + impl.Dorgtr(uplo, n, a, lda, tau, work, -1) + lwork = (int(work[0]) + n - 1) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dorgtr(uplo, n, a, lda, tau, work, -1) + lwork = int(work[0]) + } + work = nanSlice(lwork) + + impl.Dorgtr(uplo, n, a, lda, tau, work, len(work)) + + q := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + tri := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + tri.Data[i*tri.Stride+i] = d[i] + if i != n-1 { + tri.Data[i*tri.Stride+i+1] = e[i] + tri.Data[(i+1)*tri.Stride+i] = e[i] + } + } + + aMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := aCopy[i*lda+j] + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + } + + tmp := blas64.General{Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n)} + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, q, 0, tmp) + + ans := blas64.General{Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n)} + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tmp, 0, ans) + + if !floats.EqualApprox(ans.Data, tri.Data, 1e-13) { + t.Errorf("Recombination mismatch. n = %v, isUpper = %v", n, uplo == blas.Upper) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorm2r.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorm2r.go new file mode 100644 index 00000000..5e23415d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorm2r.go @@ -0,0 +1,139 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorm2rer interface { + Dgeqrfer + Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dorm2rTest(t *testing.T, impl Dorm2rer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.common + na = test.adim + mc = test.common + nc = test.cdim + } else { + ma = test.common + na = test.adim + mc = test.cdim + nc = test.common + } + + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute QR + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("QR", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + t.Errorf("Multiplication mismatch.\n Want %v \n got %v.", cMat.Data, c) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dormbr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormbr.go new file mode 100644 index 00000000..0a44faf5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormbr.go @@ -0,0 +1,164 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dormbrer interface { + Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dgebrder +} + +func DormbrTest(t *testing.T, impl Dormbrer) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} { + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + m, n, k, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + + {3, 4, 5, 10, 12}, + {3, 5, 4, 10, 12}, + {4, 3, 5, 10, 12}, + {4, 5, 3, 10, 12}, + {5, 3, 4, 10, 12}, + {5, 4, 3, 10, 12}, + + {150, 140, 130, 0, 0}, + } { + m := test.m + n := test.n + k := test.k + ldc := test.ldc + if ldc == 0 { + ldc = n + } + nq := n + nw := m + if side == blas.Left { + nq = m + nw = n + } + + // Compute a decomposition. + var ma, na int + var a []float64 + if vect == lapack.ApplyQ { + ma = nq + na = k + } else { + ma = k + na = nq + } + lda := test.lda + if lda == 0 { + lda = na + } + a = make([]float64, ma*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + nTau := min(nq, k) + tauP := make([]float64, nTau) + tauQ := make([]float64, nTau) + d := make([]float64, nTau) + e := make([]float64, nTau) + + work := make([]float64, 1) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, -1) + work = make([]float64, int(work[0])) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, len(work)) + + // Apply and compare update. + c := make([]float64, m*ldc) + for i := range c { + c[i] = rnd.NormFloat64() + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + var lwork int + switch wl { + case minimumWork: + lwork = nw + case optimumWork: + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1) + lwork = int(work[0]) + case mediumWork: + work := make([]float64, 1) + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1) + lwork = (int(work[0]) + nw) / 2 + } + lwork = max(1, lwork) + work = make([]float64, lwork) + + if vect == lapack.ApplyQ { + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, lwork) + } else { + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauP, c, ldc, work, lwork) + } + + // Check that the multiplication was correct. + cOrig := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, len(cCopy)), + } + copy(cOrig.Data, cCopy) + cAns := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, len(cCopy)), + } + copy(cAns.Data, cCopy) + nb := min(ma, na) + var mulMat blas64.General + if vect == lapack.ApplyQ { + mulMat = constructQPBidiagonal(lapack.ApplyQ, ma, na, nb, a, lda, tauQ) + } else { + mulMat = constructQPBidiagonal(lapack.ApplyP, ma, na, nb, a, lda, tauP) + } + + mulTrans := trans + + if side == blas.Left { + bi.Dgemm(mulTrans, blas.NoTrans, m, n, m, 1, mulMat.Data, mulMat.Stride, cOrig.Data, cOrig.Stride, 0, cAns.Data, cAns.Stride) + } else { + bi.Dgemm(blas.NoTrans, mulTrans, m, n, n, 1, cOrig.Data, cOrig.Stride, mulMat.Data, mulMat.Stride, 0, cAns.Data, cAns.Stride) + } + + if !floats.EqualApprox(cAns.Data, c, 1e-13) { + isApplyQ := vect == lapack.ApplyQ + isLeft := side == blas.Left + isTrans := trans == blas.Trans + + t.Errorf("C mismatch. isApplyQ: %v, isLeft: %v, isTrans: %v, m = %v, n = %v, k = %v, lda = %v, ldc = %v", + isApplyQ, isLeft, isTrans, m, n, k, lda, ldc) + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dormhr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormhr.go new file mode 100644 index 00000000..7b908aa1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormhr.go @@ -0,0 +1,132 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dormhrer interface { + Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + + Dgehrder +} + +func DormhrTest(t *testing.T, impl Dormhrer) { + rnd := rand.New(rand.NewSource(1)) + + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, m := range []int{1, 2, 3, 4, 5, 8, 9, 10, 23} { + for _, n := range []int{1, 2, 3, 4, 5, 8, 9, 10, 23} { + for _, extra := range []int{0, 1, 13} { + for cas := 0; cas < 10; cas++ { + nq := m + if side == blas.Right { + nq = n + } + ilo := rnd.Intn(nq) + ihi := rnd.Intn(nq) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDormhr(t, impl, side, trans, m, n, ilo, ihi, extra, true, rnd) + testDormhr(t, impl, side, trans, m, n, ilo, ihi, extra, false, rnd) + } + } + } + } + } + } + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + testDormhr(t, impl, side, trans, 0, 0, 0, -1, 0, true, rnd) + testDormhr(t, impl, side, trans, 0, 0, 0, -1, 0, false, rnd) + } + } +} + +func testDormhr(t *testing.T, impl Dormhrer, side blas.Side, trans blas.Transpose, m, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + var nq, nw int + switch side { + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + } + + // Compute the elementary reflectors and tau. + a := randomGeneral(nq, nq, nq+extra, rnd) + var tau []float64 + if nq > 1 { + tau = nanSlice(nq - 1) + } + work := nanSlice(max(1, nq)) // Minimum work for Dgehrd. + impl.Dgehrd(nq, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + // Construct Q from the elementary reflectors in a and from tau. + q := eye(nq, nq) + qCopy := eye(nq, nq) + for j := ilo; j < ihi; j++ { + h := eye(nq, nq) + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, nq), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + + c := randomGeneral(m, n, n+extra, rnd) + + // Compute the product of Q and C explicitly. + qc := randomGeneral(m, n, n+extra, rnd) + if side == blas.Left { + blas64.Gemm(trans, blas.NoTrans, 1, q, c, 0, qc) + } else { + blas64.Gemm(blas.NoTrans, trans, 1, c, q, 0, qc) + } + + // Compute the product of Q and C using Dormhr. + if optwork { + work = nanSlice(1) + impl.Dormhr(side, trans, m, n, ilo, ihi, nil, a.Stride, nil, nil, c.Stride, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, nw)) + } + impl.Dormhr(side, trans, m, n, ilo, ihi, a.Data, a.Stride, tau, c.Data, c.Stride, work, len(work)) + + // Compare the two answers. + prefix := fmt.Sprintf("Case side=%v, trans=%v, m=%v, n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", + side, trans, m, n, ilo, ihi, extra, optwork) + if !generalOutsideAllNaN(c) { + t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + cij := c.Data[i*c.Stride+j] + qcij := qc.Data[i*qc.Stride+j] + if math.Abs(cij-qcij) > tol { + t.Errorf("%v: unexpected value of the QC product at [%v,%v]: want %v, got %v", prefix, i, j, qcij, cij) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dorml2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorml2.go new file mode 100644 index 00000000..909c56e4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dorml2.go @@ -0,0 +1,144 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorml2er interface { + Dgelqfer + Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dorml2Test(t *testing.T, impl Dorml2er) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): This test is not complete, because it + // doesn't test individual values of m, n, and k, instead only testing + // a specific subset of possible k values. + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.adim + na = test.common + mc = test.common + nc = test.cdim + } else { + ma = test.adim + na = test.common + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute LQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("LQ", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dorml2(side, trans, mc, nc, k, a, lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + isLeft := side == blas.Left + isTrans := trans == blas.Trans + t.Errorf("Multiplication mismatch. IsLeft = %v. IsTrans = %v", isLeft, isTrans) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dormlq.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormlq.go new file mode 100644 index 00000000..19302e21 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormlq.go @@ -0,0 +1,130 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dormlqer interface { + Dorml2er + Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) +} + +func DormlqTest(t *testing.T, impl Dormlqer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {0, 0, 0, 0, 0}, + {6, 7, 8, 0, 0}, + {6, 8, 7, 0, 0}, + {7, 6, 8, 0, 0}, + {7, 8, 6, 0, 0}, + {8, 6, 7, 0, 0}, + {8, 7, 6, 0, 0}, + {100, 200, 300, 0, 0}, + {100, 300, 200, 0, 0}, + {200, 100, 300, 0, 0}, + {200, 300, 100, 0, 0}, + {300, 100, 200, 0, 0}, + {300, 200, 100, 0, 0}, + {100, 200, 300, 400, 500}, + {100, 300, 200, 400, 500}, + {200, 100, 300, 400, 500}, + {200, 300, 100, 400, 500}, + {300, 100, 200, 400, 500}, + {300, 200, 100, 400, 500}, + {100, 200, 300, 500, 400}, + {100, 300, 200, 500, 400}, + {200, 100, 300, 500, 400}, + {200, 300, 100, 500, 400}, + {300, 100, 200, 500, 400}, + {300, 200, 100, 500, 400}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.adim + na = test.common + mc = test.common + nc = test.cdim + } else { + ma = test.adim + na = test.common + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + // Compute random C matrix + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute LQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(ma, na, a, lda, tau, work, len(work)) + + cCopy := make([]float64, len(c)) + copy(cCopy, c) + ans := make([]float64, len(c)) + copy(ans, cCopy) + + var nw int + if side == blas.Left { + nw = nc + } else { + nw = mc + } + work = make([]float64, max(1, nw)) + impl.Dorml2(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work) + + var lwork int + switch wl { + case minimumWork: + lwork = nw + case optimumWork: + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, -1) + lwork = int(work[0]) + case mediumWork: + work := make([]float64, 1) + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, -1) + lwork = (int(work[0]) + nw) / 2 + } + lwork = max(1, lwork) + work = make([]float64, lwork) + + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, lwork) + if !floats.EqualApprox(c, ans, 1e-13) { + t.Errorf("Dormqr and Dorm2r results mismatch") + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dormqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormqr.go new file mode 100644 index 00000000..cfacd81b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormqr.go @@ -0,0 +1,154 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dormqrer interface { + Dorm2rer + Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) +} + +func DormqrTest(t *testing.T, impl Dormqrer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {6, 7, 8, 0, 0}, + {6, 8, 7, 0, 0}, + {7, 6, 8, 0, 0}, + {7, 8, 6, 0, 0}, + {8, 6, 7, 0, 0}, + {8, 7, 6, 0, 0}, + {100, 200, 300, 0, 0}, + {100, 300, 200, 0, 0}, + {200, 100, 300, 0, 0}, + {200, 300, 100, 0, 0}, + {300, 100, 200, 0, 0}, + {300, 200, 100, 0, 0}, + {100, 200, 300, 400, 500}, + {100, 300, 200, 400, 500}, + {200, 100, 300, 400, 500}, + {200, 300, 100, 400, 500}, + {300, 100, 200, 400, 500}, + {300, 200, 100, 400, 500}, + {100, 200, 300, 500, 400}, + {100, 300, 200, 500, 400}, + {200, 100, 300, 500, 400}, + {200, 300, 100, 500, 400}, + {300, 100, 200, 500, 400}, + {300, 200, 100, 500, 400}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.common + na = test.adim + mc = test.common + nc = test.cdim + } else { + ma = test.common + na = test.adim + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + // Compute random C matrix + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute QR + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(ma, na, a, lda, tau, work, len(work)) + + cCopy := make([]float64, len(c)) + copy(cCopy, c) + ans := make([]float64, len(c)) + copy(ans, cCopy) + + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work) + + // Make sure Dorm2r and Dormqr match with small work + for i := range work { + work[i] = rnd.Float64() + } + copy(c, cCopy) + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for small work") + } + + // Try with the optimum amount of work + copy(c, cCopy) + impl.Dormqr(side, trans, mc, nc, k, nil, lda, nil, nil, ldc, work, -1) + work = make([]float64, int(work[0])) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for full work") + fmt.Println("ccopy") + for i := 0; i < mc; i++ { + fmt.Println(cCopy[i*ldc : (i+1)*ldc]) + } + fmt.Println("ans =") + for i := 0; i < mc; i++ { + fmt.Println(ans[i*ldc : (i+1)*ldc]) + } + fmt.Println("c =") + for i := 0; i < mc; i++ { + fmt.Println(c[i*ldc : (i+1)*ldc]) + } + } + + // Try with amount of work that is less than + // optimal but still long enough to use the + // blocked code. + copy(c, cCopy) + if side == blas.Left { + work = make([]float64, 3*nc) + } else { + work = make([]float64, 3*mc) + } + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for medium work") + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dormr2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormr2.go new file mode 100644 index 00000000..94a13488 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dormr2.go @@ -0,0 +1,137 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dormr2er interface { + Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dormr2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dormr2Test(t *testing.T, impl Dormr2er) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + ma := test.adim + na := test.common + var mc, nc int + if side == blas.Left { + mc = test.common + nc = test.cdim + } else { + mc = test.cdim + nc = test.common + } + + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute RQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgerqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgerqf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("RQ", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dormr2(side, trans, mc, nc, k, a[(ma-k)*lda:], lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + t.Errorf("Multiplication mismatch.\n Want %v \n got %v.", cMat.Data, c) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dpbtf2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpbtf2.go new file mode 100644 index 00000000..7f5498b8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpbtf2.go @@ -0,0 +1,47 @@ +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dpbtf2er interface { + Dpbtf2(ul blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) + Dpotrfer +} + +func Dpbtf2Test(t *testing.T, impl Dpbtf2er) { + // Test random symmetric banded matrices against the full version. + rnd := rand.New(rand.NewSource(1)) + + for _, n := range []int{5, 10, 20} { + for _, kb := range []int{0, 1, 3, n - 1} { + for _, ldoff := range []int{0, 4} { + for _, ul := range []blas.Uplo{blas.Upper, blas.Lower} { + ldab := kb + 1 + ldoff + sym, band := randSymBand(ul, n, ldab, kb, rnd) + + // Compute the Cholesky decomposition of the symmetric matrix. + ok := impl.Dpotrf(ul, sym.N, sym.Data, sym.Stride) + if !ok { + panic("bad test: symmetric cholesky decomp failed") + } + + // Compute the Cholesky decomposition of the banded matrix. + ok = impl.Dpbtf2(band.Uplo, band.N, band.K, band.Data, band.Stride) + if !ok { + t.Errorf("SymBand cholesky decomp failed") + } + + // Compare the result to the Symmetric decomposition. + sb := symBandToSym(ul, band.Data, n, kb, ldab) + if !equalApproxSymmetric(sym, sb, 1e-10) { + t.Errorf("chol mismatch banded and sym. n = %v, kb = %v, ldoff = %v", n, kb, ldoff) + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dpocon.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpocon.go new file mode 100644 index 00000000..87b6cca0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpocon.go @@ -0,0 +1,157 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "log" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dpoconer interface { + Dpotrfer + Dgeconer + Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 + Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 +} + +func DpoconTest(t *testing.T, impl Dpoconer) { + for _, test := range []struct { + a []float64 + n int + cond float64 + uplo blas.Uplo + }{ + { + a: []float64{ + 89, 59, 77, + 0, 107, 59, + 0, 0, 89, + }, + uplo: blas.Upper, + n: 3, + cond: 0.050052137643379, + }, + { + a: []float64{ + 89, 0, 0, + 59, 107, 0, + 77, 59, 89, + }, + uplo: blas.Lower, + n: 3, + cond: 0.050052137643379, + }, + // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. + { + a: []float64{ + 2.9995576045549965, -2.0898894566158663, 3.965560740124006, + 0, 1.9634729526261008, -2.8681002706874104, + 0, 0, 5.502416670471008, + }, + uplo: blas.Upper, + n: 3, + cond: 0.024054837369015203, + }, + } { + n := test.n + a := make([]float64, len(test.a)) + copy(a, test.a) + lda := n + uplo := test.uplo + work := make([]float64, 3*n) + anorm := impl.Dlansy(lapack.MaxColumnSum, uplo, n, a, lda, work) + // Compute cholesky decomposition + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Bad test, matrix not positive definite") + continue + } + iwork := make([]int, n) + cond := impl.Dpocon(uplo, n, a, lda, anorm, work, iwork) + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(cond, test.cond, 1e0, 1e0) { + t.Errorf("Cond mismatch. Want %v, got %v.", test.cond, cond) + } else if !floats.EqualWithinAbsOrRel(cond, test.cond, 1e-14, 1e-14) { + log.Printf("Dpocon cond mismatch. Want %v, got %v.", test.cond, cond) + } + } + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + // Randomized tests compared against Dgecon. + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {3, 5}, + } { + for trial := 0; trial < 100; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + // Multiply a by itself to make it symmetric positive definite. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, aCopy, lda, aCopy, lda, 0, a, lda) + + aDat := make([]float64, len(aCopy)) + copy(aDat, a) + + aDense := make([]float64, len(a)) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a[i*lda+j] + aDense[i*lda+j] = v + aDense[j*lda+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := a[i*lda+j] + aDense[i*lda+j] = v + aDense[j*lda+i] = v + } + } + } + work := make([]float64, 4*n) + iwork := make([]int, n) + + anorm := impl.Dlansy(lapack.MaxColumnSum, uplo, n, a, lda, work) + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Bad test, matrix not positive definite") + continue + } + got := impl.Dpocon(uplo, n, a, lda, anorm, work, iwork) + + denseNorm := impl.Dlange(lapack.MaxColumnSum, n, n, aDense, lda, work) + ipiv := make([]int, n) + impl.Dgetrf(n, n, aDense, lda, ipiv) + want := impl.Dgecon(lapack.MaxColumnSum, n, aDense, lda, denseNorm, work, iwork) + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(want, got, 1e0, 1e0) { + t.Errorf("Dpocon and Dgecon mismatch. Dpocon %v, Dgecon %v.", got, want) + } else if !floats.EqualWithinAbsOrRel(want, got, 1e-14, 1e-14) { + log.Printf("Dpocon and Dgecon mismatch. Dpocon %v, Dgecon %v.", got, want) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotf2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotf2.go new file mode 100644 index 00000000..d6e1691c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotf2.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dpotf2er interface { + Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) +} + +func Dpotf2Test(t *testing.T, impl Dpotf2er) { + for _, test := range []struct { + a [][]float64 + pos bool + U [][]float64 + }{ + { + a: [][]float64{ + {23, 37, 34, 32}, + {108, 71, 48, 48}, + {109, 109, 67, 58}, + {106, 107, 106, 63}, + }, + pos: true, + U: [][]float64{ + {4.795831523312719, 7.715033320111766, 7.089490077940543, 6.672461249826393}, + {0, 3.387958215439679, -1.976308959006481, -1.026654004678691}, + {0, 0, 3.582364210034111, 2.419258947036024}, + {0, 0, 0, 3.401680257083044}, + }, + }, + { + a: [][]float64{ + {8, 2}, + {2, 4}, + }, + pos: true, + U: [][]float64{ + {2.82842712474619, 0.707106781186547}, + {0, 1.870828693386971}, + }, + }, + } { + testDpotf2(t, impl, test.pos, test.a, test.U, len(test.a[0]), blas.Upper) + testDpotf2(t, impl, test.pos, test.a, test.U, len(test.a[0])+5, blas.Upper) + aT := transpose(test.a) + L := transpose(test.U) + testDpotf2(t, impl, test.pos, aT, L, len(test.a[0]), blas.Lower) + testDpotf2(t, impl, test.pos, aT, L, len(test.a[0])+5, blas.Lower) + } +} + +func testDpotf2(t *testing.T, impl Dpotf2er, testPos bool, a, ans [][]float64, stride int, ul blas.Uplo) { + aFlat := flattenTri(a, stride, ul) + ansFlat := flattenTri(ans, stride, ul) + pos := impl.Dpotf2(ul, len(a[0]), aFlat, stride) + if pos != testPos { + t.Errorf("Positive definite mismatch: Want %v, Got %v", testPos, pos) + return + } + if testPos && !floats.EqualApprox(ansFlat, aFlat, 1e-14) { + t.Errorf("Result mismatch: Want %v, Got %v", ansFlat, aFlat) + } +} + +// flattenTri with a certain stride. stride must be >= dimension. Puts repeatable +// nonce values in non-accessed places +func flattenTri(a [][]float64, stride int, ul blas.Uplo) []float64 { + m := len(a) + n := len(a[0]) + if stride < n { + panic("bad stride") + } + upper := ul == blas.Upper + v := make([]float64, m*stride) + count := 1000.0 + for i := 0; i < m; i++ { + for j := 0; j < stride; j++ { + if j >= n || (upper && j < i) || (!upper && j > i) { + // not accessed, so give a unique crazy number + v[i*stride+j] = count + count++ + continue + } + v[i*stride+j] = a[i][j] + } + } + return v +} + +func transpose(a [][]float64) [][]float64 { + m := len(a) + n := len(a[0]) + if m != n { + panic("not square") + } + aNew := make([][]float64, m) + for i := 0; i < m; i++ { + aNew[i] = make([]float64, n) + } + for i := 0; i < m; i++ { + if len(a[i]) != n { + panic("bad n size") + } + for j := 0; j < n; j++ { + aNew[j][i] = a[i][j] + } + } + return aNew +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotrf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotrf.go new file mode 100644 index 00000000..d4318228 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dpotrf.go @@ -0,0 +1,135 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dpotrfer interface { + Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) +} + +func DpotrfTest(t *testing.T, impl Dpotrfer) { + const tol = 1e-13 + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for tc, test := range []struct { + n int + lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {10, 0}, + {30, 0}, + {63, 0}, + {65, 0}, + {127, 0}, + {129, 0}, + {500, 0}, + {1, 10}, + {2, 10}, + {3, 10}, + {10, 20}, + {30, 50}, + {63, 100}, + {65, 100}, + {127, 200}, + {129, 200}, + {500, 600}, + } { + n := test.n + + // Random diagonal matrix D with positive entries. + d := make([]float64, n) + Dlatm1(d, 4, 10000, false, 1, rnd) + + // Construct a positive definite matrix A as + // A = U * D * U^T + // where U is a random orthogonal matrix. + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + Dlagsy(n, 0, d, a, lda, rnd, make([]float64, 2*n)) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Case %v: unexpected failure for positive definite matrix", tc) + continue + } + + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + } + default: + panic("bad uplo") + } + + ans := make([]float64, len(a)) + switch uplo { + case blas.Upper: + // Multiply U^T * U. + bi.Dsyrk(uplo, blas.Trans, n, n, 1, a, lda, 0, ans, lda) + case blas.Lower: + // Multiply L * L^T. + bi.Dsyrk(uplo, blas.NoTrans, n, n, 1, a, lda, 0, ans, lda) + } + + match := true + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(ans[i*lda+j], aCopy[i*lda+j], tol, tol) { + match = false + } + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + if !floats.EqualWithinAbsOrRel(ans[i*lda+j], aCopy[i*lda+j], tol, tol) { + match = false + } + } + } + } + if !match { + t.Errorf("Case %v (uplo=%v,n=%v,lda=%v): unexpected result", tc, uplo, n, lda) + } + + // Make one element of D negative so that A is not + // positive definite, and check that Dpotrf fails. + d[0] *= -1 + Dlagsy(n, 0, d, a, lda, rnd, make([]float64, 2*n)) + ok = impl.Dpotrf(uplo, n, a, lda) + if ok { + t.Errorf("Case %v: unexpected success for not positive definite matrix", tc) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/drscl.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/drscl.go new file mode 100644 index 00000000..df87db40 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/drscl.go @@ -0,0 +1,52 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Drscler interface { + Drscl(n int, a float64, x []float64, incX int) +} + +func DrsclTest(t *testing.T, impl Drscler) { + for _, test := range []struct { + x []float64 + a float64 + }{ + { + x: []float64{1, 2, 3, 4, 5}, + a: 4, + }, + { + x: []float64{1, 2, 3, 4, 5}, + a: math.MaxFloat64, + }, + { + x: []float64{1, 2, 3, 4, 5}, + a: 1e-307, + }, + } { + xcopy := make([]float64, len(test.x)) + copy(xcopy, test.x) + + // Cannot test the scaling directly because of floating point scaling issues + // (the purpose of Drscl). Instead, check that scaling and scaling back + // yeilds approximately x. If overflow or underflow occurs then the scaling + // won't match. + impl.Drscl(len(test.x), test.a, xcopy, 1) + if floats.Equal(xcopy, test.x) { + t.Errorf("x unchanged during call to drscl. a = %v, x = %v.", test.a, test.x) + } + impl.Drscl(len(test.x), 1/test.a, xcopy, 1) + if !floats.EqualApprox(xcopy, test.x, 1e-14) { + t.Errorf("x not equal after scaling and unscaling. a = %v, x = %v.", test.a, test.x) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dsteqr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsteqr.go new file mode 100644 index 00000000..1fffdb1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsteqr.go @@ -0,0 +1,171 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dsteqrer interface { + Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) + Dorgtrer +} + +func DsteqrTest(t *testing.T, impl Dsteqrer) { + rnd := rand.New(rand.NewSource(1)) + for _, compz := range []lapack.EVComp{lapack.OriginalEV, lapack.TridiagEV} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {4, 0}, + {8, 0}, + {10, 0}, + + {2, 10}, + {8, 10}, + {10, 20}, + } { + for cas := 0; cas < 100; cas++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + d := make([]float64, n) + for i := range d { + d[i] = rnd.Float64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.Float64() + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + eCopy := make([]float64, len(e)) + copy(eCopy, e) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + if compz == lapack.OriginalEV { + // Compute triangular decomposition and orthonormal matrix. + uplo := blas.Upper + tau := make([]float64, n) + work := make([]float64, 1) + impl.Dsytrd(blas.Upper, n, a, lda, d, e, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, len(work)) + impl.Dorgtr(uplo, n, a, lda, tau, work, len(work)) + } else { + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + if i == j { + a[i*lda+j] = 1 + } + } + } + } + work := make([]float64, 2*n) + + aDecomp := make([]float64, len(a)) + copy(aDecomp, a) + dDecomp := make([]float64, len(d)) + copy(dDecomp, d) + eDecomp := make([]float64, len(e)) + copy(eDecomp, e) + impl.Dsteqr(compz, n, d, e, a, lda, work) + dAns := make([]float64, len(d)) + copy(dAns, d) + + var truth blas64.General + if compz == lapack.OriginalEV { + truth = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + truth.Data[i*truth.Stride+j] = v + truth.Data[j*truth.Stride+i] = v + } + } + } else { + truth = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + truth.Data[i*truth.Stride+i] = dCopy[i] + if i != n-1 { + truth.Data[(i+1)*truth.Stride+i] = eCopy[i] + truth.Data[i*truth.Stride+i+1] = eCopy[i] + } + } + } + + V := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + if !eigenDecompCorrect(d, truth, V) { + t.Errorf("Eigen reconstruction mismatch. fromFull = %v, n = %v", + compz == lapack.OriginalEV, n) + } + + // Compare eigenvalues when not computing eigenvectors. + for i := range work { + work[i] = rnd.Float64() + } + impl.Dsteqr(lapack.None, n, dDecomp, eDecomp, aDecomp, lda, work) + if !floats.EqualApprox(d, dAns, 1e-8) { + t.Errorf("Eigenvalue mismatch when eigenvectors not computed") + } + } + } + } +} + +// eigenDecompCorrect returns whether the eigen decomposition is correct. +// It checks if +// A * v ≈ λ * v +// where the eigenvalues λ are stored in values, and the eigenvectors are stored +// in the columns of v. +func eigenDecompCorrect(values []float64, A, V blas64.General) bool { + n := A.Rows + for i := 0; i < n; i++ { + lambda := values[i] + vector := make([]float64, n) + ans2 := make([]float64, n) + for j := range vector { + v := V.Data[j*V.Stride+i] + vector[j] = v + ans2[j] = lambda * v + } + v := blas64.Vector{Inc: 1, Data: vector} + ans1 := blas64.Vector{Inc: 1, Data: make([]float64, n)} + blas64.Gemv(blas.NoTrans, 1, A, v, 0, ans1) + if !floats.EqualApprox(ans1.Data, ans2, 1e-8) { + return false + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dsterf.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsterf.go new file mode 100644 index 00000000..66b4a9e1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsterf.go @@ -0,0 +1,126 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dsterfer interface { + Dgetrfer + Dsterf(n int, d, e []float64) (ok bool) +} + +func DsterfTest(t *testing.T, impl Dsterfer) { + // Hand coded tests. + for cas, test := range []struct { + d []float64 + e []float64 + n int + + ans []float64 + }{ + // Computed from Fortran code. + { + d: []float64{1, 3, 4, 6}, + e: []float64{2, 4, 5}, + n: 4, + ans: []float64{11.046227528488854, 4.795922173417400, -2.546379458290125, 0.704229756383872}, + }, + } { + n := test.n + d := make([]float64, len(test.d)) + copy(d, test.d) + e := make([]float64, len(test.e)) + copy(e, test.e) + ok := impl.Dsterf(n, d, e) + if !ok { + t.Errorf("Case %d, Eigenvalue decomposition failed", cas) + continue + } + ans := make([]float64, len(test.ans)) + copy(ans, test.ans) + sort.Float64s(ans) + if !floats.EqualApprox(ans, d, 1e-10) { + t.Errorf("eigenvalue mismatch") + } + } + + rnd := rand.New(rand.NewSource(1)) + // Probabilistic tests. + for _, n := range []int{4, 6, 10} { + for cas := 0; cas < 10; cas++ { + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + eCopy := make([]float64, len(e)) + copy(eCopy, e) + + ok := impl.Dsterf(n, d, e) + if !ok { + t.Errorf("Eigenvalue decomposition failed") + continue + } + + // Test that the eigenvalues are sorted. + if !sort.Float64sAreSorted(d) { + t.Errorf("Values are not sorted") + } + + // Construct original tridagional matrix. + lda := n + a := make([]float64, n*lda) + for i := 0; i < n; i++ { + a[i*lda+i] = dCopy[i] + if i != n-1 { + a[i*lda+i+1] = eCopy[i] + a[(i+1)*lda+i] = eCopy[i] + } + } + + asub := make([]float64, len(a)) + ipiv := make([]int, n) + + // Test that they are actually eigenvalues by computing the + // determinant of A - λI. + // TODO(btracey): Replace this test with a more numerically stable + // test. + for _, lambda := range d { + copy(asub, a) + for i := 0; i < n; i++ { + asub[i*lda+i] -= lambda + } + + // Compute LU. + ok := impl.Dgetrf(n, n, asub, lda, ipiv) + if !ok { + // Definitely singular. + continue + } + // Compute determinant. + var logdet float64 + for i := 0; i < n; i++ { + v := asub[i*lda+i] + logdet += math.Log(math.Abs(v)) + } + if math.Exp(logdet) > 2 { + t.Errorf("Incorrect singular value. n = %d, cas = %d, det = %v", n, cas, math.Exp(logdet)) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dsyev.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsyev.go new file mode 100644 index 00000000..e70088c9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsyev.go @@ -0,0 +1,115 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dsyever interface { + Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) +} + +func DsyevTest(t *testing.T, impl Dsyever) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {5, 0}, + {10, 0}, + {100, 0}, + + {1, 5}, + {2, 5}, + {5, 10}, + {10, 20}, + {100, 110}, + } { + for cas := 0; cas < 10; cas++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + w := make([]float64, n) + for i := range w { + w[i] = rnd.NormFloat64() + } + + work := make([]float64, 1) + impl.Dsyev(lapack.ComputeEV, uplo, n, a, lda, w, work, -1) + work = make([]float64, int(work[0])) + impl.Dsyev(lapack.ComputeEV, uplo, n, a, lda, w, work, len(work)) + + // Check that the decomposition is correct + orig := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + orig.Data[i*orig.Stride+j] = v + orig.Data[j*orig.Stride+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := aCopy[i*lda+j] + orig.Data[i*orig.Stride+j] = v + orig.Data[j*orig.Stride+i] = v + } + } + } + + V := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + + if !eigenDecompCorrect(w, orig, V) { + t.Errorf("Decomposition mismatch") + } + + // Check that the decomposition is correct when the eigenvectors + // are not computed. + wAns := make([]float64, len(w)) + copy(wAns, w) + copy(a, aCopy) + for i := range w { + w[i] = rnd.Float64() + } + for i := range work { + work[i] = rnd.Float64() + } + impl.Dsyev(lapack.None, uplo, n, a, lda, w, work, len(work)) + if !floats.EqualApprox(w, wAns, 1e-8) { + t.Errorf("Eigenvalue mismatch when vectors not computed") + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytd2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytd2.go new file mode 100644 index 00000000..af71cf1f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytd2.go @@ -0,0 +1,205 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dsytd2er interface { + Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) +} + +func Dsytd2Test(t *testing.T, impl Dsytd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {4, 0}, + {5, 0}, + + {3, 10}, + {4, 10}, + {5, 10}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + d := make([]float64, n) + for i := range d { + d[i] = math.NaN() + } + e := make([]float64, n-1) + for i := range e { + e[i] = math.NaN() + } + tau := make([]float64, n-1) + for i := range tau { + tau[i] = math.NaN() + } + + impl.Dsytd2(uplo, n, a, lda, d, e, tau) + + // Construct Q + qMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + qCopy := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, len(qMat.Data)), + } + // Set Q to I. + for i := 0; i < n; i++ { + qMat.Data[i*qMat.Stride+i] = 1 + } + for i := 0; i < n-1; i++ { + hMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + // Set H to I. + for i := 0; i < n; i++ { + hMat.Data[i*hMat.Stride+i] = 1 + } + var vi blas64.Vector + if uplo == blas.Upper { + vi = blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + for j := 0; j < i; j++ { + vi.Data[j] = a[j*lda+i+1] + } + vi.Data[i] = 1 + } else { + vi = blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + vi.Data[i+1] = 1 + for j := i + 2; j < n; j++ { + vi.Data[j] = a[j*lda+i] + } + } + blas64.Ger(-tau[i], vi, vi, hMat) + copy(qCopy.Data, qMat.Data) + + // Multiply q by the new h. + if uplo == blas.Upper { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hMat, qCopy, 0, qMat) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, hMat, 0, qMat) + } + } + // Check that Q is orthonormal + othonormal := true + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(n, + blas64.Vector{Inc: 1, Data: qMat.Data[i*qMat.Stride:]}, + blas64.Vector{Inc: 1, Data: qMat.Data[j*qMat.Stride:]}, + ) + if i == j { + if math.Abs(dot-1) > 1e-10 { + othonormal = false + } + } else { + if math.Abs(dot) > 1e-10 { + othonormal = false + } + } + } + } + if !othonormal { + t.Errorf("Q not orthonormal") + } + + // Compute Q^T * A * Q. + aMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, len(a)), + } + + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + if uplo == blas.Lower { + v = aCopy[j*lda+i] + } + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + ans := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + blas64.Gemm(blas.Trans, blas.NoTrans, 1, qMat, aMat, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, qMat, 0, ans) + + // Compare with T. + tMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n-1; i++ { + tMat.Data[i*tMat.Stride+i] = d[i] + tMat.Data[i*tMat.Stride+i+1] = e[i] + tMat.Data[(i+1)*tMat.Stride+i] = e[i] + } + tMat.Data[(n-1)*tMat.Stride+n-1] = d[n-1] + + same := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if math.Abs(ans.Data[i*ans.Stride+j]-tMat.Data[i*tMat.Stride+j]) > 1e-10 { + same = false + } + } + } + if !same { + t.Errorf("Matrix answer mismatch") + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytrd.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytrd.go new file mode 100644 index 00000000..74e2beba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dsytrd.go @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dsytrder interface { + Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) + + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DsytrdTest(t *testing.T, impl Dsytrder) { + const tol = 1e-13 + rnd := rand.New(rand.NewSource(1)) + for tc, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {4, 0}, + {10, 0}, + {50, 0}, + {100, 0}, + {150, 0}, + {300, 0}, + + {1, 3}, + {2, 3}, + {3, 7}, + {4, 9}, + {10, 20}, + {50, 70}, + {100, 120}, + {150, 170}, + {300, 320}, + } { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := randomGeneral(n, n, lda, rnd) + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a.Data[i*a.Stride+j] = a.Data[j*a.Stride+i] + } + } + aCopy := cloneGeneral(a) + + d := nanSlice(n) + e := nanSlice(n - 1) + tau := nanSlice(n - 1) + + var lwork int + switch wl { + case minimumWork: + lwork = 1 + case mediumWork: + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, -1) + lwork = (int(work[0]) + 1) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, lwork) + + prefix := fmt.Sprintf("Case #%v: uplo=%v,n=%v,lda=%v,work=%v", + tc, uplo, n, lda, wl) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + // Extract Q by doing what Dorgtr does. + q := cloneGeneral(a) + if uplo == blas.Upper { + for j := 0; j < n-1; j++ { + for i := 0; i < j; i++ { + q.Data[i*q.Stride+j] = q.Data[i*q.Stride+j+1] + } + q.Data[(n-1)*q.Stride+j] = 0 + } + for i := 0; i < n-1; i++ { + q.Data[i*q.Stride+n-1] = 0 + } + q.Data[(n-1)*q.Stride+n-1] = 1 + if n > 1 { + work = make([]float64, n-1) + impl.Dorgql(n-1, n-1, n-1, q.Data, q.Stride, tau, work, len(work)) + } + } else { + for j := n - 1; j > 0; j-- { + q.Data[j] = 0 + for i := j + 1; i < n; i++ { + q.Data[i*q.Stride+j] = q.Data[i*q.Stride+j-1] + } + } + q.Data[0] = 1 + for i := 1; i < n; i++ { + q.Data[i*q.Stride] = 0 + } + if n > 1 { + work = make([]float64, n-1) + impl.Dorgqr(n-1, n-1, n-1, q.Data[q.Stride+1:], q.Stride, tau, work, len(work)) + } + } + if !isOrthonormal(q) { + t.Errorf("%v: Q not orthogonal", prefix) + } + + // Contruct symmetric tridiagonal T from d and e. + tMat := zeros(n, n, n) + for i := 0; i < n; i++ { + tMat.Data[i*tMat.Stride+i] = d[i] + } + if uplo == blas.Upper { + for j := 1; j < n; j++ { + tMat.Data[(j-1)*tMat.Stride+j] = e[j-1] + tMat.Data[j*tMat.Stride+j-1] = e[j-1] + } + } else { + for j := 0; j < n-1; j++ { + tMat.Data[(j+1)*tMat.Stride+j] = e[j] + tMat.Data[j*tMat.Stride+j+1] = e[j] + } + } + + // Compute Q^T * A * Q. + tmp := zeros(n, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aCopy, 0, tmp) + got := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, got) + + // Compare with T. + if !equalApproxGeneral(got, tMat, tol) { + t.Errorf("%v: Q^T*A*Q != T", prefix) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtgsja.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtgsja.go new file mode 100644 index 00000000..af4cec80 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtgsja.go @@ -0,0 +1,165 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtgsjaer interface { + Dlanger + Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) +} + +func DtgsjaTest(t *testing.T, impl Dtgsjaer) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, k, l, lda, ldb, ldu, ldv, ldq int + + ok bool + }{ + {m: 5, p: 5, n: 5, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, k: 5, l: 3, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, k: 6, l: 4, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, k: 2, l: 2, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 5, k: 4, l: 1, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 10, k: 2, l: 2, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 1, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 2, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 10, p: 5, n: 5, k: 2, l: 2, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 5, n: 5, k: 4, l: 1, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 10, n: 10, k: 5, l: 3, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + {m: 10, p: 10, n: 10, k: 6, l: 4, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + } { + m := test.m + p := test.p + n := test.n + k := test.k + l := test.l + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := blockedUpperTriGeneral(m, n, k, l, lda, true, rnd) + aCopy := cloneGeneral(a) + b := blockedUpperTriGeneral(p, n, k, l, ldb, false, rnd) + bCopy := cloneGeneral(b) + + tola := float64(max(m, n)) * impl.Dlange(lapack.NormFrob, m, n, a.Data, a.Stride, nil) * dlamchE + tolb := float64(max(p, n)) * impl.Dlange(lapack.NormFrob, p, n, b.Data, b.Stride, nil) * dlamchE + + alpha := make([]float64, n) + beta := make([]float64, n) + + work := make([]float64, 2*n) + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + _, ok := impl.Dtgsja(lapack.GSVDUnit, lapack.GSVDUnit, lapack.GSVDUnit, + m, p, n, k, l, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work) + + if !ok { + if test.ok { + t.Errorf("test %d unexpectedly did not converge", cas) + } + continue + } + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + // Check C^2 + S^2 = I. + var elements []float64 + if m-k-l >= 0 { + elements = alpha[k : k+l] + } else { + elements = alpha[k:m] + } + for i := range elements { + i += k + d := alpha[i]*alpha[i] + beta[i]*beta[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("test %d: alpha_%d^2 + beta_%d^2 != 1: got: %v", cas, i, i, d) + } + } + + zeroR, d1, d2 := constructGSVDresults(n, p, m, k, l, a, b, alpha, beta) + + // Check U^T*A*Q = D1*[ 0 R ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + d10r := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d1, zeroR, 0, d10r) + + if !equalApproxGeneral(uAns, d10r, 1e-14) { + t.Errorf("test %d: U^T*A*Q != D1*[ 0 R ]\nU^T*A*Q:\n%+v\nD1*[ 0 R ]:\n%+v", + cas, uAns, d10r) + } + + // Check V^T*B*Q = D2*[ 0 R ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + d20r := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d2, zeroR, 0, d20r) + + if !equalApproxGeneral(vAns, d20r, 1e-14) { + t.Errorf("test %d: V^T*B*Q != D2*[ 0 R ]\nV^T*B*Q:\n%+v\nD2*[ 0 R ]:\n%+v", + cas, vAns, d20r) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrcon.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrcon.go new file mode 100644 index 00000000..1e490ca9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrcon.go @@ -0,0 +1,184 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtrconer interface { + Dgeconer + Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 +} + +func DtrconTest(t *testing.T, impl Dtrconer) { + rnd := rand.New(rand.NewSource(1)) + // Hand crafted tests. + for _, test := range []struct { + a []float64 + n int + uplo blas.Uplo + diag blas.Diag + condOne float64 + condInf float64 + }{ + { + a: []float64{ + 8, 5, 6, + 0, 7, 8, + 0, 0, 6, + }, + n: 3, + uplo: blas.Upper, + diag: blas.Unit, + condOne: 1.0 / 645, + condInf: 1.0 / 480, + }, + { + a: []float64{ + 8, 5, 6, + 0, 7, 8, + 0, 0, 6, + }, + n: 3, + uplo: blas.Upper, + diag: blas.NonUnit, + condOne: 0.137704918032787, + condInf: 0.157894736842105, + }, + { + a: []float64{ + 8, 0, 0, + 5, 7, 0, + 6, 8, 6, + }, + n: 3, + uplo: blas.Lower, + diag: blas.Unit, + condOne: 1.0 / 480, + condInf: 1.0 / 645, + }, + { + a: []float64{ + 8, 0, 0, + 5, 7, 0, + 6, 8, 6, + }, + n: 3, + uplo: blas.Lower, + diag: blas.NonUnit, + condOne: 0.157894736842105, + condInf: 0.137704918032787, + }, + } { + lda := test.n + work := make([]float64, 3*test.n) + for i := range work { + work[i] = rnd.Float64() + } + iwork := make([]int, test.n) + for i := range iwork { + iwork[i] = int(rnd.Int31()) + } + aCopy := make([]float64, len(test.a)) + copy(aCopy, test.a) + condOne := impl.Dtrcon(lapack.MaxColumnSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork) + if math.Abs(condOne-test.condOne) > 1e-14 { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) + } + if !floats.Equal(aCopy, test.a) { + t.Errorf("a modified during call") + } + condInf := impl.Dtrcon(lapack.MaxRowSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork) + if math.Abs(condInf-test.condInf) > 1e-14 { + t.Errorf("Inf norm mismatch. Want %v, got %v.", test.condInf, condInf) + } + if !floats.Equal(aCopy, test.a) { + t.Errorf("a modified during call") + } + } + + // Dtrcon does not match the Dgecon output in many cases. See + // https://github.com/xianyi/OpenBLAS/issues/636 + // TODO(btracey): Uncomment this when the mismatch between Dgecon and Dtrcon + // is understood. + /* + // Randomized tests against Dgecon. + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {4, 9}, + } { + for trial := 0; trial < 1; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + if trial == 0 { + for i := range a { + a[i] = float64(i + 2) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + + aDense := make([]float64, len(a)) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + aDense[i*lda+i] = 1 + } + } + + ipiv := make([]int, n) + work := make([]float64, 4*n) + denseOne := impl.Dlange(lapack.MaxColumnSum, n, n, aDense, lda, work) + denseInf := impl.Dlange(lapack.MaxRowSum, n, n, aDense, lda, work) + + aDenseLU := make([]float64, len(aDense)) + copy(aDenseLU, aDense) + impl.Dgetrf(n, n, aDenseLU, lda, ipiv) + iwork := make([]int, n) + want := impl.Dgecon(lapack.MaxColumnSum, n, aDenseLU, lda, denseOne, work, iwork) + got := impl.Dtrcon(lapack.MaxColumnSum, uplo, diag, n, a, lda, work, iwork) + if math.Abs(want-got) > 1e-14 { + t.Errorf("One norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got) + } + want = impl.Dgecon(lapack.MaxRowSum, n, aDenseLU, lda, denseInf, work, iwork) + got = impl.Dtrcon(lapack.MaxRowSum, uplo, diag, n, a, lda, work, iwork) + if math.Abs(want-got) > 1e-14 { + t.Errorf("Inf norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got) + } + } + } + } + } + */ +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrevc3.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrevc3.go new file mode 100644 index 00000000..60c51241 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrevc3.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtrevc3er interface { + Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) int +} + +func Dtrevc3Test(t *testing.T, impl Dtrevc3er) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []lapack.EVSide{lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV} { + for _, howmny := range []lapack.HowMany{lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 34, 100} { + for _, extra := range []int{0, 11} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 10; cas++ { + tmat := randomSchurCanonical(n, n+extra, rnd) + testDtrevc3(t, impl, side, howmny, tmat, optwork, rnd) + } + } + } + } + } + } +} + +func testDtrevc3(t *testing.T, impl Dtrevc3er, side lapack.EVSide, howmny lapack.HowMany, tmat blas64.General, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + n := tmat.Rows + extra := tmat.Stride - tmat.Cols + right := side != lapack.LeftEV + left := side != lapack.RightEV + + var selected, selectedWant []bool + var mWant int // How many columns will the eigenvectors occupy. + if howmny == lapack.SelectedEV { + selected = make([]bool, n) + selectedWant = make([]bool, n) + // Dtrevc3 will compute only selected eigenvectors. Pick them + // randomly disregarding whether they are real or complex. + for i := range selected { + if rnd.Float64() < 0.5 { + selected[i] = true + } + } + // Dtrevc3 will modify (standardize) the slice selected based on + // whether the corresponding eigenvalues are real or complex. Do + // the same process here to fill selectedWant. + for i := 0; i < n; { + if i == n-1 || tmat.Data[(i+1)*tmat.Stride+i] == 0 { + // Real eigenvalue. + if selected[i] { + selectedWant[i] = true + mWant++ // Real eigenvectors occupy one column. + } + i++ + } else { + // Complex eigenvalue. + if selected[i] || selected[i+1] { + // Dtrevc3 will modify selected so that + // only the first element of the pair is + // true. + selectedWant[i] = true + mWant += 2 // Complex eigenvectors occupy two columns. + } + i += 2 + } + } + } else { + // All eigenvectors occupy n columns. + mWant = n + } + + var vr blas64.General + if right { + if howmny == lapack.AllEVMulQ { + vr = eye(n, n+extra) + } else { + // VR will be overwritten. + vr = nanGeneral(n, mWant, n+extra) + } + } + + var vl blas64.General + if left { + if howmny == lapack.AllEVMulQ { + vl = eye(n, n+extra) + } else { + // VL will be overwritten. + vl = nanGeneral(n, mWant, n+extra) + } + } + + work := make([]float64, max(1, 3*n)) + if optwork { + impl.Dtrevc3(side, howmny, nil, n, nil, 1, nil, 1, nil, 1, mWant, work, -1) + work = make([]float64, int(work[0])) + } + + m := impl.Dtrevc3(side, howmny, selected, n, tmat.Data, tmat.Stride, + vl.Data, vl.Stride, vr.Data, vr.Stride, mWant, work, len(work)) + + prefix := fmt.Sprintf("Case side=%v, howmny=%v, n=%v, extra=%v, optwk=%v", + side, howmny, n, extra, optwork) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if !generalOutsideAllNaN(vl) { + t.Errorf("%v: out-of-range write to VL", prefix) + } + if !generalOutsideAllNaN(vr) { + t.Errorf("%v: out-of-range write to VR", prefix) + } + + if m != mWant { + t.Errorf("%v: unexpected value of m. Want %v, got %v", prefix, mWant, m) + } + + if howmny == lapack.SelectedEV { + for i := range selected { + if selected[i] != selectedWant[i] { + t.Errorf("%v: unexpected selected[%v]", prefix, i) + } + } + } + + // Check that the columns of VR and VL are actually eigenvectors and + // that the magnitude of their largest element is 1. + var k int + for j := 0; j < n; { + re := tmat.Data[j*tmat.Stride+j] + if j == n-1 || tmat.Data[(j+1)*tmat.Stride+j] == 0 { + if howmny == lapack.SelectedEV && !selected[j] { + j++ + continue + } + if right { + ev := columnOf(vr, k) + norm := floats.Norm(ev, math.Inf(1)) + if math.Abs(norm-1) > tol { + t.Errorf("%v: magnitude of largest element of VR[:,%v] not 1", prefix, k) + } + if !isRightEigenvectorOf(tmat, ev, nil, complex(re, 0), tol) { + t.Errorf("%v: VR[:,%v] is not real right eigenvector", prefix, k) + } + } + if left { + ev := columnOf(vl, k) + norm := floats.Norm(ev, math.Inf(1)) + if math.Abs(norm-1) > tol { + t.Errorf("%v: magnitude of largest element of VL[:,%v] not 1", prefix, k) + } + if !isLeftEigenvectorOf(tmat, ev, nil, complex(re, 0), tol) { + t.Errorf("%v: VL[:,%v] is not real left eigenvector", prefix, k) + } + } + k++ + j++ + continue + } + if howmny == lapack.SelectedEV && !selected[j] { + j += 2 + continue + } + im := math.Sqrt(math.Abs(tmat.Data[(j+1)*tmat.Stride+j])) * + math.Sqrt(math.Abs(tmat.Data[j*tmat.Stride+j+1])) + if right { + evre := columnOf(vr, k) + evim := columnOf(vr, k+1) + var evmax float64 + for i, v := range evre { + evmax = math.Max(evmax, math.Abs(v)+math.Abs(evim[i])) + } + if math.Abs(evmax-1) > tol { + t.Errorf("%v: magnitude of largest element of VR[:,%v] not 1", prefix, k) + } + if !isRightEigenvectorOf(tmat, evre, evim, complex(re, im), tol) { + t.Errorf("%v: VR[:,%v:%v] is not complex right eigenvector", prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isRightEigenvectorOf(tmat, evre, evim, complex(re, -im), tol) { + t.Errorf("%v: VR[:,%v:%v] is not complex right eigenvector", prefix, k, k+1) + } + } + if left { + evre := columnOf(vl, k) + evim := columnOf(vl, k+1) + var evmax float64 + for i, v := range evre { + evmax = math.Max(evmax, math.Abs(v)+math.Abs(evim[i])) + } + if math.Abs(evmax-1) > tol { + t.Errorf("%v: magnitude of largest element of VL[:,%v] not 1", prefix, k) + } + if !isLeftEigenvectorOf(tmat, evre, evim, complex(re, im), tol) { + t.Errorf("%v: VL[:,%v:%v] is not complex left eigenvector", prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isLeftEigenvectorOf(tmat, evre, evim, complex(re, -im), tol) { + t.Errorf("%v: VL[:,%v:%v] is not complex left eigenvector", prefix, k, k+1) + } + } + k += 2 + j += 2 + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrexc.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrexc.go new file mode 100644 index 00000000..855805fb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrexc.go @@ -0,0 +1,219 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "fmt" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dtrexcer interface { + Dtrexc(compq lapack.EVComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) +} + +func DtrexcTest(t *testing.T, impl Dtrexcer) { + rnd := rand.New(rand.NewSource(1)) + + for _, compq := range []lapack.EVComp{lapack.None, lapack.UpdateSchur} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + tmat := randomSchurCanonical(n, n+extra, rnd) + ifst := rnd.Intn(n) + ilst := rnd.Intn(n) + testDtrexc(t, impl, compq, tmat, ifst, ilst, extra, rnd) + } + } + } + } + + for _, compq := range []lapack.EVComp{lapack.None, lapack.UpdateSchur} { + for _, extra := range []int{0, 1, 11} { + tmat := randomSchurCanonical(0, extra, rnd) + testDtrexc(t, impl, compq, tmat, 0, 0, extra, rnd) + } + } +} + +func testDtrexc(t *testing.T, impl Dtrexcer, compq lapack.EVComp, tmat blas64.General, ifst, ilst, extra int, rnd *rand.Rand) { + const tol = 1e-13 + + n := tmat.Rows + fstSize, fstFirst := schurBlockSize(tmat, ifst) + lstSize, lstFirst := schurBlockSize(tmat, ilst) + + tmatCopy := cloneGeneral(tmat) + + var wantq bool + var q, qCopy blas64.General + if compq == lapack.UpdateSchur { + wantq = true + q = eye(n, n+extra) + qCopy = cloneGeneral(q) + } + + work := nanSlice(n) + + ifstGot, ilstGot, ok := impl.Dtrexc(compq, n, tmat.Data, tmat.Stride, q.Data, q.Stride, ifst, ilst, work) + + prefix := fmt.Sprintf("Case compq=%v, n=%v, ifst=%v, nbf=%v, ilst=%v, nbl=%v, extra=%v", + compq, n, ifst, fstSize, ilst, lstSize, extra) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if wantq && !generalOutsideAllNaN(q) { + t.Errorf("%v: out-of-range write to Q", prefix) + } + + if !ok { + t.Logf("%v: Dtrexc returned ok=false", prefix) + } + + // Check that the index of the first block was correctly updated (if + // necessary). + ifstWant := ifst + if !fstFirst { + ifstWant = ifst - 1 + } + if ifstWant != ifstGot { + t.Errorf("%v: unexpected ifst index. Want %v, got %v ", prefix, ifstWant, ifstGot) + } + + // Check that the index of the last block is as expected when ok=true. + // When ok=false, we don't know at which block the algorithm failed, so + // we don't check. + ilstWant := ilst + if !lstFirst { + ilstWant-- + } + if ok { + if ifstWant < ilstWant { + // If the blocks are swapped backwards, these + // adjustments are not necessary, the first row of the + // last block will end up at ifst. + switch { + case fstSize == 2 && lstSize == 1: + ilstWant-- + case fstSize == 1 && lstSize == 2: + ilstWant++ + } + } + if ilstWant != ilstGot { + t.Errorf("%v: unexpected ilst index. Want %v, got %v", prefix, ilstWant, ilstGot) + } + } + + if n <= 1 || ifstGot == ilstGot { + // Too small matrix or no swapping. + // Check that T was not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if tmat.Data[i*tmat.Stride+j] != tmatCopy.Data[i*tmatCopy.Stride+j] { + t.Errorf("%v: unexpected modification at T[%v,%v]", prefix, i, j) + } + } + } + if !wantq { + return + } + // Check that Q was not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if q.Data[i*q.Stride+j] != qCopy.Data[i*qCopy.Stride+j] { + t.Errorf("%v: unexpected modification at Q[%v,%v]", prefix, i, j) + } + } + } + return + } + + if !isSchurCanonicalGeneral(tmat) { + t.Errorf("%v: T is not in Schur canonical form", prefix) + } + + // Check that T was not modified except above the second subdiagonal in + // rows and columns [modMin,modMax]. + modMin := min(ifstGot, ilstGot) + modMax := max(ifstGot, ilstGot) + fstSize + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if modMin <= i && i < modMax && j+1 >= i { + continue + } + if modMin <= j && j < modMax && j+1 >= i { + continue + } + diff := tmat.Data[i*tmat.Stride+j] - tmatCopy.Data[i*tmatCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification at T[%v,%v]", prefix, i, j) + } + } + } + + // Check that the block at ifstGot was delivered to ilstGot correctly. + if fstSize == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[ilstGot*tmat.Stride+ilstGot] + want := tmatCopy.Data[ifstGot*tmatCopy.Stride+ifstGot] + if want != got { + t.Errorf("%v: unexpected 1×1 block at T[%v,%v]. Want %v, got %v", + prefix, want, got, ilstGot, ilstGot) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + a, b, c, d := extract2x2Block(tmat.Data[ilstGot*tmat.Stride+ilstGot:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, ilstGot, ilstGot) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The block was originally located at T[ifstGot,ifstGot]. + a, b, c, d = extract2x2Block(tmatCopy.Data[ifstGot*tmatCopy.Stride+ifstGot:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, ilstGot, ilstGot, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, ilstGot, ilstGot, ev2Want, ev2Got) + } + } + + if !wantq { + return + } + + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Check that Q is unchanged outside of columns [modMin,modMax]. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if modMin <= j && j < modMax { + continue + } + if q.Data[i*q.Stride+j]-qCopy.Data[i*qCopy.Stride+j] != 0 { + t.Errorf("%v: unexpected modification of Q[%v,%v]", prefix, i, j) + } + } + } + // Check that Q^T TOrig Q == T. + tq := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmatCopy, q, 0, tq) + qtq := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tq, 0, qtq) + if !equalApproxGeneral(qtq, tmat, tol) { + t.Errorf("%v: Q^T (initial T) Q and (final T) are not equal", prefix) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrti2.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrti2.go new file mode 100644 index 00000000..acb8b5e9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrti2.go @@ -0,0 +1,163 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dtrti2er interface { + Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) +} + +func Dtrti2Test(t *testing.T, impl Dtrti2er) { + const tol = 1e-14 + for _, test := range []struct { + a []float64 + n int + uplo blas.Uplo + diag blas.Diag + ans []float64 + }{ + { + a: []float64{ + 2, 3, 4, + 0, 5, 6, + 8, 0, 8}, + n: 3, + uplo: blas.Upper, + diag: blas.NonUnit, + ans: []float64{ + 0.5, -0.3, -0.025, + 0, 0.2, -0.15, + 8, 0, 0.125, + }, + }, + { + a: []float64{ + 5, 3, 4, + 0, 7, 6, + 10, 0, 8}, + n: 3, + uplo: blas.Upper, + diag: blas.Unit, + ans: []float64{ + 5, -3, 14, + 0, 7, -6, + 10, 0, 8, + }, + }, + { + a: []float64{ + 2, 0, 0, + 3, 5, 0, + 4, 6, 8}, + n: 3, + uplo: blas.Lower, + diag: blas.NonUnit, + ans: []float64{ + 0.5, 0, 0, + -0.3, 0.2, 0, + -0.025, -0.15, 0.125, + }, + }, + { + a: []float64{ + 1, 0, 0, + 3, 1, 0, + 4, 6, 1}, + n: 3, + uplo: blas.Lower, + diag: blas.Unit, + ans: []float64{ + 1, 0, 0, + -3, 1, 0, + 14, -6, 1, + }, + }, + } { + impl.Dtrti2(test.uplo, test.diag, test.n, test.a, test.n) + if !floats.EqualApprox(test.ans, test.a, tol) { + t.Errorf("Matrix inverse mismatch. Want %v, got %v.", test.ans, test.a) + } + } + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {1, 5}, + {2, 5}, + {3, 5}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dtrti2(uplo, diag, n, a, lda) + if uplo == blas.Upper { + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + a[i*lda+i] = 1 + aCopy[i*lda+i] = 1 + } + } + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, a, lda, aCopy, lda, 0, ans, lda) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(ans[i*lda+i]-1) > tol { + iseye = false + break + } + } else { + if math.Abs(ans[i*lda+j]) > tol { + iseye = false + break + } + } + } + } + if !iseye { + t.Errorf("inv(A) * A != I. Upper = %v, unit = %v, ans = %v", uplo == blas.Upper, diag == blas.Unit, ans) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrtri.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrtri.go new file mode 100644 index 00000000..1224b7b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/dtrtri.go @@ -0,0 +1,95 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dtrtrier interface { + Dtrconer + Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) bool +} + +func DtrtriTest(t *testing.T, impl Dtrtrier) { + const tol = 1e-6 + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {70, 0}, + {200, 0}, + {3, 5}, + {70, 92}, + {200, 205}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + 1 // This keeps the matrices well conditioned. + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dtrtri(uplo, diag, n, a, lda) + if uplo == blas.Upper { + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + a[i*lda+i] = 1 + aCopy[i*lda+i] = 1 + } + } + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, a, lda, aCopy, lda, 0, ans, lda) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(ans[i*lda+i]-1) > tol { + iseye = false + break + } + } else { + if math.Abs(ans[i*lda+j]) > tol { + iseye = false + break + } + } + } + } + if !iseye { + t.Errorf("inv(A) * A != I. Upper = %v, unit = %v, n = %v, lda = %v", + uplo == blas.Upper, diag == blas.Unit, n, lda) + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/fortran.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/fortran.go new file mode 100644 index 00000000..45ea6d07 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/fortran.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "strings" +) + +// This file implements types for helping to convert to Fortran testing capabilities. + +// fortran64 is a float64 type that prints as a double precision constant in +// Fortran format. +type fortran64 float64 + +func (f fortran64) String() string { + // Replace exponent with D + s := fmt.Sprintf("%0.16E", f) + s = strings.Replace(s, "E", "D", 1) + return s +} + +// printFortranArray prints a Go slice as an array that can be copied into a +// fortran script. +func printFortranArray(z []float64, name string) { + fmt.Printf("%s(1:%d) = (/%v, &\n", name, len(z), fortran64(z[0])) + for i := 1; i < len(z)-1; i++ { + fmt.Printf("%v, &\n", fortran64(z[i])) + } + fmt.Printf("%s/)\n", fortran64(z[len(z)-1])) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/general.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/general.go new file mode 100644 index 00000000..f2376a7d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/general.go @@ -0,0 +1,1516 @@ +// Copyright ©2015 The gonum 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 testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +const ( + // dlamchE is the machine epsilon. For IEEE this is 2^{-53}. + dlamchE = 1.0 / (1 << 53) + dlamchB = 2 + dlamchP = dlamchB * dlamchE + // dlamchS is the smallest normal number. For IEEE this is 2^{-1022}. + dlamchS = 1.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) +) + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// worklen describes how much workspace a test should use. +type worklen int + +const ( + minimumWork worklen = iota + mediumWork + optimumWork +) + +// nanSlice allocates a new slice of length n filled with NaN. +func nanSlice(n int) []float64 { + s := make([]float64, n) + for i := range s { + s[i] = math.NaN() + } + return s +} + +// randomSlice allocates a new slice of length n filled with random values. +func randomSlice(n int, rnd *rand.Rand) []float64 { + s := make([]float64, n) + for i := range s { + s[i] = rnd.NormFloat64() + } + return s +} + +// nanGeneral allocates a new r×c general matrix filled with NaN values. +func nanGeneral(r, c, stride int) blas64.General { + if r < 0 || c < 0 { + panic("bad matrix size") + } + if r == 0 || c == 0 { + return blas64.General{Stride: max(1, stride)} + } + if stride < c { + panic("bad stride") + } + return blas64.General{ + Rows: r, + Cols: c, + Stride: stride, + Data: nanSlice((r-1)*stride + c), + } +} + +// randomGeneral allocates a new r×c general matrix filled with random +// numbers. Out-of-range elements are filled with NaN values. +func randomGeneral(r, c, stride int, rnd *rand.Rand) blas64.General { + ans := nanGeneral(r, c, stride) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// randomHessenberg allocates a new n×n Hessenberg matrix filled with zeros +// under the first subdiagonal and with random numbers elsewhere. Out-of-range +// elements are filled with NaN values. +func randomHessenberg(n, stride int, rnd *rand.Rand) blas64.General { + ans := nanGeneral(n, n, stride) + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + ans.Data[i*ans.Stride+j] = 0 + } + for j := max(0, i-1); j < n; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// randomSchurCanonical returns a random, general matrix in Schur canonical +// form, that is, block upper triangular with 1×1 and 2×2 diagonal blocks where +// each 2×2 diagonal block has its diagonal elements equal and its off-diagonal +// elements of opposite sign. +func randomSchurCanonical(n, stride int, rnd *rand.Rand) blas64.General { + t := randomGeneral(n, n, stride, rnd) + // Zero out the lower triangle. + for i := 0; i < t.Rows; i++ { + for j := 0; j < i; j++ { + t.Data[i*t.Stride+j] = 0 + } + } + // Randomly create 2×2 diagonal blocks. + for i := 0; i < t.Rows; { + if i == t.Rows-1 || rnd.Float64() < 0.5 { + // 1×1 block. + i++ + continue + } + // 2×2 block. + // Diagonal elements equal. + t.Data[(i+1)*t.Stride+i+1] = t.Data[i*t.Stride+i] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(t.Data[i*t.Stride+i+1]) { + c *= -1 + } + t.Data[(i+1)*t.Stride+i] = c + i += 2 + } + return t +} + +// blockedUpperTriGeneral returns a normal random, general matrix in the form +// +// c-k-l k l +// A = k [ 0 A12 A13 ] if r-k-l >= 0; +// l [ 0 0 A23 ] +// r-k-l [ 0 0 0 ] +// +// c-k-l k l +// A = k [ 0 A12 A13 ] if r-k-l < 0; +// r-k [ 0 0 A23 ] +// +// where the k×k matrix A12 and l×l matrix is non-singular +// upper triangular. A23 is l×l upper triangular if r-k-l >= 0, +// otherwise A23 is (r-k)×l upper trapezoidal. +func blockedUpperTriGeneral(r, c, k, l, stride int, kblock bool, rnd *rand.Rand) blas64.General { + t := l + if kblock { + t += k + } + ans := zeros(r, c, stride) + for i := 0; i < min(r, t); i++ { + var v float64 + for v == 0 { + v = rnd.NormFloat64() + } + ans.Data[i*ans.Stride+i+(c-t)] = v + } + for i := 0; i < min(r, t); i++ { + for j := i + (c - t) + 1; j < c; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// nanTriangular allocates a new r×c triangular matrix filled with NaN values. +func nanTriangular(uplo blas.Uplo, n, stride int) blas64.Triangular { + if n < 0 { + panic("bad matrix size") + } + if n == 0 { + return blas64.Triangular{ + Stride: max(1, stride), + Uplo: uplo, + Diag: blas.NonUnit, + } + } + if stride < n { + panic("bad stride") + } + return blas64.Triangular{ + N: n, + Stride: stride, + Data: nanSlice((n-1)*stride + n), + Uplo: uplo, + Diag: blas.NonUnit, + } +} + +// generalOutsideAllNaN returns whether all out-of-range elements have NaN +// values. +func generalOutsideAllNaN(a blas64.General) bool { + // Check after last column. + for i := 0; i < a.Rows-1; i++ { + for _, v := range a.Data[i*a.Stride+a.Cols : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + // Check after last element. + last := (a.Rows-1)*a.Stride + a.Cols + if a.Rows == 0 || a.Cols == 0 { + last = 0 + } + for _, v := range a.Data[last:] { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// triangularOutsideAllNaN returns whether all out-of-triangle elements have NaN +// values. +func triangularOutsideAllNaN(a blas64.Triangular) bool { + if a.Uplo == blas.Upper { + // Check below diagonal. + for i := 0; i < a.N; i++ { + for _, v := range a.Data[i*a.Stride : i*a.Stride+i] { + if !math.IsNaN(v) { + return false + } + } + } + // Check after last column. + for i := 0; i < a.N-1; i++ { + for _, v := range a.Data[i*a.Stride+a.N : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + } else { + // Check above diagonal. + for i := 0; i < a.N-1; i++ { + for _, v := range a.Data[i*a.Stride+i+1 : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + } + // Check after last element. + for _, v := range a.Data[max(0, a.N-1)*a.Stride+a.N:] { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// transposeGeneral returns a new general matrix that is the transpose of the +// input. Nothing is done with data outside the {rows, cols} limit of the general. +func transposeGeneral(a blas64.General) blas64.General { + ans := blas64.General{ + Rows: a.Cols, + Cols: a.Rows, + Stride: a.Rows, + Data: make([]float64, a.Cols*a.Rows), + } + for i := 0; i < a.Rows; i++ { + for j := 0; j < a.Cols; j++ { + ans.Data[j*ans.Stride+i] = a.Data[i*a.Stride+j] + } + } + return ans +} + +// columnNorms returns the column norms of a. +func columnNorms(m, n int, a []float64, lda int) []float64 { + bi := blas64.Implementation() + norms := make([]float64, n) + for j := 0; j < n; j++ { + norms[j] = bi.Dnrm2(m, a[j:], lda) + } + return norms +} + +// extractVMat collects the single reflectors from a into a matrix. +func extractVMat(m, n int, a []float64, lda int, direct lapack.Direct, store lapack.StoreV) blas64.General { + k := min(m, n) + switch { + default: + panic("not implemented") + case direct == lapack.Forward && store == lapack.ColumnWise: + v := blas64.General{ + Rows: m, + Cols: k, + Stride: k, + Data: make([]float64, m*k), + } + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + v.Data[j*v.Stride+i] = 0 + } + v.Data[i*v.Stride+i] = 1 + for j := i + 1; j < m; j++ { + v.Data[j*v.Stride+i] = a[j*lda+i] + } + } + return v + case direct == lapack.Forward && store == lapack.RowWise: + v := blas64.General{ + Rows: k, + Cols: n, + Stride: n, + Data: make([]float64, k*n), + } + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + v.Data[i*v.Stride+j] = 0 + } + v.Data[i*v.Stride+i] = 1 + for j := i + 1; j < n; j++ { + v.Data[i*v.Stride+j] = a[i*lda+j] + } + } + return v + } +} + +// constructBidiagonal constructs a bidiagonal matrix with the given diagonal +// and off-diagonal elements. +func constructBidiagonal(uplo blas.Uplo, n int, d, e []float64) blas64.General { + bMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + for i := 0; i < n-1; i++ { + bMat.Data[i*bMat.Stride+i] = d[i] + if uplo == blas.Upper { + bMat.Data[i*bMat.Stride+i+1] = e[i] + } else { + bMat.Data[(i+1)*bMat.Stride+i] = e[i] + } + } + bMat.Data[(n-1)*bMat.Stride+n-1] = d[n-1] + return bMat +} + +// constructVMat transforms the v matrix based on the storage. +func constructVMat(vMat blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General { + m := vMat.Rows + k := vMat.Cols + switch { + default: + panic("not implemented") + case store == lapack.ColumnWise && direct == lapack.Forward: + ldv := k + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + if j > i { + v[i*ldv+j] = 0 + } else if j == i { + v[i*ldv+i] = 1 + } else { + v[i*ldv+j] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: m, + Cols: k, + Stride: k, + Data: v, + } + case store == lapack.RowWise && direct == lapack.Forward: + ldv := m + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + if j > i { + v[j*ldv+i] = 0 + } else if j == i { + v[j*ldv+i] = 1 + } else { + v[j*ldv+i] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: k, + Cols: m, + Stride: m, + Data: v, + } + case store == lapack.ColumnWise && direct == lapack.Backward: + rowsv := m + ldv := k + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + vrow := rowsv - i - 1 + vcol := k - j - 1 + if j > i { + v[vrow*ldv+vcol] = 0 + } else if j == i { + v[vrow*ldv+vcol] = 1 + } else { + v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: rowsv, + Cols: ldv, + Stride: ldv, + Data: v, + } + case store == lapack.RowWise && direct == lapack.Backward: + rowsv := k + ldv := m + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + vcol := ldv - i - 1 + vrow := k - j - 1 + if j > i { + v[vrow*ldv+vcol] = 0 + } else if j == i { + v[vrow*ldv+vcol] = 1 + } else { + v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: rowsv, + Cols: ldv, + Stride: ldv, + Data: v, + } + } +} + +func constructH(tau []float64, v blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General { + m := v.Rows + k := v.Cols + if store == lapack.RowWise { + m, k = k, m + } + h := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + h.Data[i*m+i] = 1 + } + for i := 0; i < k; i++ { + vecData := make([]float64, m) + if store == lapack.ColumnWise { + for j := 0; j < m; j++ { + vecData[j] = v.Data[j*v.Cols+i] + } + } else { + for j := 0; j < m; j++ { + vecData[j] = v.Data[i*v.Cols+j] + } + } + vec := blas64.Vector{ + Inc: 1, + Data: vecData, + } + + hi := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + hi.Data[i*m+i] = 1 + } + // hi = I - tau * v * v^T + blas64.Ger(-tau[i], vec, vec, hi) + + hcopy := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + copy(hcopy.Data, h.Data) + if direct == lapack.Forward { + // H = H * H_I in forward mode + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hcopy, hi, 0, h) + } else { + // H = H_I * H in backward mode + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hi, hcopy, 0, h) + } + } + return h +} + +// constructQ constructs the Q matrix from the result of dgeqrf and dgeqr2. +func constructQ(kind string, m, n int, a []float64, lda int, tau []float64) blas64.General { + k := min(m, n) + return constructQK(kind, m, n, k, a, lda, tau) +} + +// constructQK constructs the Q matrix from the result of dgeqrf and dgeqr2 using +// the first k reflectors. +func constructQK(kind string, m, n, k int, a []float64, lda int, tau []float64) blas64.General { + var sz int + switch kind { + case "QR": + sz = m + case "LQ", "RQ": + sz = n + } + + q := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + for i := 0; i < sz; i++ { + q.Data[i*sz+i] = 1 + } + qCopy := blas64.General{ + Rows: q.Rows, + Cols: q.Cols, + Stride: q.Stride, + Data: make([]float64, len(q.Data)), + } + for i := 0; i < k; i++ { + h := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + for j := 0; j < sz; j++ { + h.Data[j*sz+j] = 1 + } + vVec := blas64.Vector{ + Inc: 1, + Data: make([]float64, sz), + } + switch kind { + case "QR": + vVec.Data[i] = 1 + for j := i + 1; j < sz; j++ { + vVec.Data[j] = a[lda*j+i] + } + case "LQ": + vVec.Data[i] = 1 + for j := i + 1; j < sz; j++ { + vVec.Data[j] = a[i*lda+j] + } + case "RQ": + for j := 0; j < n-k+i; j++ { + vVec.Data[j] = a[(m-k+i)*lda+j] + } + vVec.Data[n-k+i] = 1 + } + blas64.Ger(-tau[i], vVec, vVec, h) + copy(qCopy.Data, q.Data) + // Multiply q by the new h. + switch kind { + case "QR", "RQ": + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + case "LQ": + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qCopy, 0, q) + } + } + return q +} + +// checkBidiagonal checks the bidiagonal decomposition from dlabrd and dgebd2. +// The input to this function is the answer returned from the routines, stored +// in a, d, e, tauP, and tauQ. The data of original A matrix (before +// decomposition) is input in aCopy. +// +// checkBidiagonal constructs the V and U matrices, and from them constructs Q +// and P. Using these constructions, it checks that Q^T * A * P and checks that +// the result is bidiagonal. +func checkBidiagonal(t *testing.T, m, n, nb int, a []float64, lda int, d, e, tauP, tauQ, aCopy []float64) { + // Check the answer. + // Construct V and U. + qMat := constructQPBidiagonal(lapack.ApplyQ, m, n, nb, a, lda, tauQ) + pMat := constructQPBidiagonal(lapack.ApplyP, m, n, nb, a, lda, tauP) + + // Compute Q^T * A * P. + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, len(aCopy)), + } + copy(aMat.Data, aCopy) + + tmp1 := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, qMat, aMat, 0, tmp1) + tmp2 := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp1, pMat, 0, tmp2) + + // Check that the first nb rows and cols of tm2 are upper bidiagonal + // if m >= n, and lower bidiagonal otherwise. + correctDiag := true + matchD := true + matchE := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if i >= nb && j >= nb { + continue + } + v := tmp2.Data[i*tmp2.Stride+j] + if i == j { + if math.Abs(d[i]-v) > 1e-12 { + matchD = false + } + continue + } + if m >= n && i == j-1 { + if math.Abs(e[j-1]-v) > 1e-12 { + matchE = false + } + continue + } + if m < n && i-1 == j { + if math.Abs(e[i-1]-v) > 1e-12 { + matchE = false + } + continue + } + if math.Abs(v) > 1e-12 { + correctDiag = false + } + } + } + if !correctDiag { + t.Errorf("Updated A not bi-diagonal") + } + if !matchD { + fmt.Println("d = ", d) + t.Errorf("D Mismatch") + } + if !matchE { + t.Errorf("E mismatch") + } +} + +// constructQPBidiagonal constructs Q or P from the Bidiagonal decomposition +// computed by dlabrd and bgebd2. +func constructQPBidiagonal(vect lapack.DecompUpdate, m, n, nb int, a []float64, lda int, tau []float64) blas64.General { + sz := n + if vect == lapack.ApplyQ { + sz = m + } + + var ldv int + var v blas64.General + if vect == lapack.ApplyQ { + ldv = nb + v = blas64.General{ + Rows: m, + Cols: nb, + Stride: ldv, + Data: make([]float64, m*ldv), + } + } else { + ldv = n + v = blas64.General{ + Rows: nb, + Cols: n, + Stride: ldv, + Data: make([]float64, m*ldv), + } + } + + if vect == lapack.ApplyQ { + if m >= n { + for i := 0; i < m; i++ { + for j := 0; j <= min(nb-1, i); j++ { + if i == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j <= min(nb-1, i-1); j++ { + if i-1 == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } + } else { + if m < n { + for i := 0; i < nb; i++ { + for j := i; j < n; j++ { + if i == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < nb; i++ { + for j := i + 1; j < n; j++ { + if j-1 == i { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } + } + + // The variable name is a computation of Q, but the algorithm is mostly the + // same for computing P (just with different data). + qMat := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + hMat := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + // set Q to I + for i := 0; i < sz; i++ { + qMat.Data[i*qMat.Stride+i] = 1 + } + for i := 0; i < nb; i++ { + qCopy := blas64.General{Rows: qMat.Rows, Cols: qMat.Cols, Stride: qMat.Stride, Data: make([]float64, len(qMat.Data))} + copy(qCopy.Data, qMat.Data) + + // Set g and h to I + for i := 0; i < sz; i++ { + for j := 0; j < sz; j++ { + if i == j { + hMat.Data[i*sz+j] = 1 + } else { + hMat.Data[i*sz+j] = 0 + } + } + } + var vi blas64.Vector + // H -= tauQ[i] * v[i] * v[i]^t + if vect == lapack.ApplyQ { + vi = blas64.Vector{ + Inc: v.Stride, + Data: v.Data[i:], + } + } else { + vi = blas64.Vector{ + Inc: 1, + Data: v.Data[i*v.Stride:], + } + } + blas64.Ger(-tau[i], vi, vi, hMat) + // Q = Q * G[1] + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, hMat, 0, qMat) + } + return qMat +} + +// printRowise prints the matrix with one row per line. This is useful for debugging. +// If beyond is true, it prints beyond the final column to lda. If false, only +// the columns are printed. +func printRowise(a []float64, m, n, lda int, beyond bool) { + for i := 0; i < m; i++ { + end := n + if beyond { + end = lda + } + fmt.Println(a[i*lda : i*lda+end]) + } +} + +// isOrthonormal checks that a general matrix is orthonormal. +func isOrthonormal(q blas64.General) bool { + n := q.Rows + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(n, + blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, + blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}, + ) + if math.IsNaN(dot) { + return false + } + if i == j { + if math.Abs(dot-1) > 1e-10 { + return false + } + } else { + if math.Abs(dot) > 1e-10 { + return false + } + } + } + } + return true +} + +// copyMatrix copies an m×n matrix src of stride n into an m×n matrix dst of stride ld. +func copyMatrix(m, n int, dst []float64, ld int, src []float64) { + for i := 0; i < m; i++ { + copy(dst[i*ld:i*ld+n], src[i*n:i*n+n]) + } +} + +func copyGeneral(dst, src blas64.General) { + r := min(dst.Rows, src.Rows) + c := min(dst.Cols, src.Cols) + for i := 0; i < r; i++ { + copy(dst.Data[i*dst.Stride:i*dst.Stride+c], src.Data[i*src.Stride:i*src.Stride+c]) + } +} + +// cloneGeneral allocates and returns an exact copy of the given general matrix. +func cloneGeneral(a blas64.General) blas64.General { + c := a + c.Data = make([]float64, len(a.Data)) + copy(c.Data, a.Data) + return c +} + +// equalApprox returns whether the matrices A and B of order n are approximately +// equal within given tolerance. +func equalApprox(m, n int, a []float64, lda int, b []float64, tol float64) bool { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +// equalApproxGeneral returns whether the general matrices a and b are +// approximately equal within given tolerance. +func equalApproxGeneral(a, b blas64.General, tol float64) bool { + if a.Rows != b.Rows || a.Cols != b.Cols { + panic("bad input") + } + for i := 0; i < a.Rows; i++ { + for j := 0; j < a.Cols; j++ { + diff := a.Data[i*a.Stride+j] - b.Data[i*b.Stride+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +// equalApproxTriangular returns whether the triangular matrices A and B of +// order n are approximately equal within given tolerance. +func equalApproxTriangular(upper bool, n int, a []float64, lda int, b []float64, tol float64) bool { + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +func equalApproxSymmetric(a, b blas64.Symmetric, tol float64) bool { + if a.Uplo != b.Uplo { + return false + } + if a.N != b.N { + return false + } + if a.Uplo == blas.Upper { + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + if !floats.EqualWithinAbsOrRel(a.Data[i*a.Stride+j], b.Data[i*b.Stride+j], tol, tol) { + return false + } + } + } + return true + } + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + if !floats.EqualWithinAbsOrRel(a.Data[i*a.Stride+j], b.Data[i*b.Stride+j], tol, tol) { + return false + } + } + } + return true +} + +// randSymBand creates a random symmetric banded matrix, and returns both the +// random matrix and the equivalent Symmetric matrix for testing. rnder +// specifies the random number +func randSymBand(ul blas.Uplo, n, ldab, kb int, rnd *rand.Rand) (blas64.Symmetric, blas64.SymmetricBand) { + // A matrix is positive definite if and only if it has a Cholesky + // decomposition. Generate a random banded lower triangular matrix + // to construct the random symmetric matrix. + a := make([]float64, n*n) + for i := 0; i < n; i++ { + for j := max(0, i-kb); j <= i; j++ { + a[i*n+j] = rnd.NormFloat64() + } + a[i*n+i] = math.Abs(a[i*n+i]) + // Add an extra amound to the diagonal in order to improve the condition number. + a[i*n+i] += 1.5 * rnd.Float64() + } + agen := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: a, + } + + // Construct the SymDense from a*a^T + c := make([]float64, n*n) + cgen := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: c, + } + blas64.Gemm(blas.NoTrans, blas.Trans, 1, agen, agen, 0, cgen) + sym := blas64.Symmetric{ + N: n, + Stride: n, + Data: c, + Uplo: ul, + } + + b := symToSymBand(ul, c, n, n, kb, ldab) + band := blas64.SymmetricBand{ + N: n, + K: kb, + Stride: ldab, + Data: b, + Uplo: ul, + } + + return sym, band +} + +// symToSymBand takes the data in a Symmetric matrix and returns a +// SymmetricBanded matrix. +func symToSymBand(ul blas.Uplo, a []float64, n, lda, kb, ldab int) []float64 { + if ul == blas.Upper { + band := make([]float64, (n-1)*ldab+kb+1) + for i := 0; i < n; i++ { + for j := i; j < min(i+kb+1, n); j++ { + band[i*ldab+j-i] = a[i*lda+j] + } + } + return band + } + band := make([]float64, (n-1)*ldab+kb+1) + for i := 0; i < n; i++ { + for j := max(0, i-kb); j <= i; j++ { + band[i*ldab+j-i+kb] = a[i*lda+j] + } + } + return band +} + +// symBandToSym takes a banded symmetric matrix and returns the same data as +// a Symmetric matrix. +func symBandToSym(ul blas.Uplo, band []float64, n, kb, ldab int) blas64.Symmetric { + sym := make([]float64, n*n) + if ul == blas.Upper { + for i := 0; i < n; i++ { + for j := 0; j < min(kb+1+i, n)-i; j++ { + sym[i*n+i+j] = band[i*ldab+j] + } + } + } else { + for i := 0; i < n; i++ { + for j := kb - min(i, kb); j < kb+1; j++ { + sym[i*n+i-kb+j] = band[i*ldab+j] + } + } + } + return blas64.Symmetric{ + N: n, + Stride: n, + Data: sym, + Uplo: ul, + } +} + +// eye returns an identity matrix of given order and stride. +func eye(n, stride int) blas64.General { + ans := nanGeneral(n, n, stride) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + ans.Data[i*ans.Stride+j] = 0 + } + ans.Data[i*ans.Stride+i] = 1 + } + return ans +} + +// zeros returns an m×n matrix with given stride filled with zeros. +func zeros(m, n, stride int) blas64.General { + a := nanGeneral(m, n, stride) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = 0 + } + } + return a +} + +// extract2x2Block returns the elements of T at [0,0], [0,1], [1,0], and [1,1]. +func extract2x2Block(t []float64, ldt int) (a, b, c, d float64) { + return t[0], t[1], t[ldt], t[ldt+1] +} + +// isSchurCanonical returns whether the 2×2 matrix [a b; c d] is in Schur +// canonical form. +func isSchurCanonical(a, b, c, d float64) bool { + return c == 0 || (a == d && math.Signbit(b) != math.Signbit(c)) +} + +// isSchurCanonicalGeneral returns whether T is block upper triangular with 1×1 +// and 2×2 diagonal blocks, each 2×2 block in Schur canonical form. The function +// checks only along the diagonal and the first subdiagonal, otherwise the lower +// triangle is not accessed. +func isSchurCanonicalGeneral(t blas64.General) bool { + if t.Rows != t.Cols { + panic("invalid matrix") + } + for i := 0; i < t.Rows-1; { + if t.Data[(i+1)*t.Stride+i] == 0 { + // 1×1 block. + i++ + continue + } + // 2×2 block. + a, b, c, d := extract2x2Block(t.Data[i*t.Stride+i:], t.Stride) + if !isSchurCanonical(a, b, c, d) { + return false + } + i += 2 + } + return true +} + +// schurBlockEigenvalues returns the two eigenvalues of the 2×2 matrix [a b; c d] +// that must be in Schur canonical form. +func schurBlockEigenvalues(a, b, c, d float64) (ev1, ev2 complex128) { + if !isSchurCanonical(a, b, c, d) { + panic("block not in Schur canonical form") + } + if c == 0 { + return complex(a, 0), complex(d, 0) + } + im := math.Sqrt(-b * c) + return complex(a, im), complex(a, -im) +} + +// schurBlockSize returns the size of the diagonal block at i-th row in the +// upper quasi-triangular matrix t in Schur canonical form, and whether i points +// to the first row of the block. For zero-sized matrices the function returns 0 +// and true. +func schurBlockSize(t blas64.General, i int) (size int, first bool) { + if t.Rows != t.Cols { + panic("matrix not square") + } + if t.Rows == 0 { + return 0, true + } + if i < 0 || t.Rows <= i { + panic("index out of range") + } + + first = true + if i > 0 && t.Data[i*t.Stride+i-1] != 0 { + // There is a non-zero element to the left, therefore i must + // point to the second row in a 2×2 diagonal block. + first = false + i-- + } + size = 1 + if i+1 < t.Rows && t.Data[(i+1)*t.Stride+i] != 0 { + // There is a non-zero element below, this must be a 2×2 + // diagonal block. + size = 2 + } + return size, first +} + +// containsComplex returns whether z is approximately equal to one of the complex +// numbers in v. If z is found, its index in v will be also returned. +func containsComplex(v []complex128, z complex128, tol float64) (found bool, index int) { + for i := range v { + if cmplx.Abs(v[i]-z) < tol { + return true, i + } + } + return false, -1 +} + +// isAllNaN returns whether x contains only NaN values. +func isAllNaN(x []float64) bool { + for _, v := range x { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// isUpperHessenberg returns whether h contains only zeros below the +// subdiagonal. +func isUpperHessenberg(h blas64.General) bool { + if h.Rows != h.Cols { + panic("matrix not square") + } + n := h.Rows + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i > j+1 && h.Data[i*h.Stride+j] != 0 { + return false + } + } + } + return true +} + +// isUpperTriangular returns whether a contains only zeros below the diagonal. +func isUpperTriangular(a blas64.General) bool { + n := a.Rows + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + if a.Data[i*a.Stride+j] != 0 { + return false + } + } + } + return true +} + +// unbalancedSparseGeneral returns an m×n dense matrix with a random sparse +// structure consisting of nz nonzero elements. The matrix will be unbalanced by +// multiplying each element randomly by its row or column index. +func unbalancedSparseGeneral(m, n, stride int, nonzeros int, rnd *rand.Rand) blas64.General { + a := zeros(m, n, stride) + for k := 0; k < nonzeros; k++ { + i := rnd.Intn(n) + j := rnd.Intn(n) + if rnd.Float64() < 0.5 { + a.Data[i*stride+j] = float64(i+1) * rnd.NormFloat64() + } else { + a.Data[i*stride+j] = float64(j+1) * rnd.NormFloat64() + } + } + return a +} + +// columnOf returns a copy of the j-th column of a. +func columnOf(a blas64.General, j int) []float64 { + if j < 0 || a.Cols <= j { + panic("bad column index") + } + col := make([]float64, a.Rows) + for i := range col { + col[i] = a.Data[i*a.Stride+j] + } + return col +} + +// isRightEigenvectorOf returns whether the vector xRe+i*xIm, where i is the +// imaginary unit, is the right eigenvector of A corresponding to the eigenvalue +// lambda. +// +// A right eigenvector corresponding to a complex eigenvalue λ is a complex +// non-zero vector x such that +// A x = λ x. +func isRightEigenvectorOf(a blas64.General, xRe, xIm []float64, lambda complex128, tol float64) bool { + if a.Rows != a.Cols { + panic("matrix not square") + } + + if imag(lambda) != 0 && xIm == nil { + // Complex eigenvalue of a real matrix cannot have a real + // eigenvector. + return false + } + + n := a.Rows + + // Compute A real(x) and store the result into xReAns. + xReAns := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xRe}, 0, blas64.Vector{1, xReAns}) + + if imag(lambda) == 0 && xIm == nil { + // Real eigenvalue and eigenvector. + + // Compute λx and store the result into lambdax. + lambdax := make([]float64, n) + floats.AddScaled(lambdax, real(lambda), xRe) + + // This is expressed as the inverse to catch the case + // xReAns_i = Inf and lambdax_i = Inf of the same sign. + return !(floats.Distance(xReAns, lambdax, math.Inf(1)) > tol) + } + + // Complex eigenvector, and real or complex eigenvalue. + + // Compute A imag(x) and store the result into xImAns. + xImAns := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xIm}, 0, blas64.Vector{1, xImAns}) + + // Compute λx and store the result into lambdax. + lambdax := make([]complex128, n) + for i := range lambdax { + lambdax[i] = lambda * complex(xRe[i], xIm[i]) + } + + for i, v := range lambdax { + ax := complex(xReAns[i], xImAns[i]) + if cmplx.Abs(v-ax) > tol { + return false + } + } + return true +} + +// isLeftEigenvectorOf returns whether the vector yRe+i*yIm, where i is the +// imaginary unit, is the left eigenvector of A corresponding to the eigenvalue +// lambda. +// +// A left eigenvector corresponding to a complex eigenvalue λ is a complex +// non-zero vector y such that +// y^H A = λ y^H, +// which is equivalent for real A to +// A^T y = conj(λ) y, +func isLeftEigenvectorOf(a blas64.General, yRe, yIm []float64, lambda complex128, tol float64) bool { + if a.Rows != a.Cols { + panic("matrix not square") + } + + if imag(lambda) != 0 && yIm == nil { + // Complex eigenvalue of a real matrix cannot have a real + // eigenvector. + return false + } + + n := a.Rows + + // Compute A^T real(y) and store the result into yReAns. + yReAns := make([]float64, n) + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yRe}, 0, blas64.Vector{1, yReAns}) + + if imag(lambda) == 0 && yIm == nil { + // Real eigenvalue and eigenvector. + + // Compute λy and store the result into lambday. + lambday := make([]float64, n) + floats.AddScaled(lambday, real(lambda), yRe) + + // This is expressed as the inverse to catch the case + // yReAns_i = Inf and lambday_i = Inf of the same sign. + return !(floats.Distance(yReAns, lambday, math.Inf(1)) > tol) + } + + // Complex eigenvector, and real or complex eigenvalue. + + // Compute A^T imag(y) and store the result into yImAns. + yImAns := make([]float64, n) + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yIm}, 0, blas64.Vector{1, yImAns}) + + // Compute conj(λ)y and store the result into lambday. + lambda = cmplx.Conj(lambda) + lambday := make([]complex128, n) + for i := range lambday { + lambday[i] = lambda * complex(yRe[i], yIm[i]) + } + + for i, v := range lambday { + ay := complex(yReAns[i], yImAns[i]) + if cmplx.Abs(v-ay) > tol { + return false + } + } + return true +} + +// rootsOfUnity returns the n complex numbers whose n-th power is equal to 1. +func rootsOfUnity(n int) []complex128 { + w := make([]complex128, n) + for i := 0; i < n; i++ { + angle := math.Pi * float64(2*i) / float64(n) + w[i] = complex(math.Cos(angle), math.Sin(angle)) + } + return w +} + +// randomOrthogonal returns an n×n random orthogonal matrix. +func randomOrthogonal(n int, rnd *rand.Rand) blas64.General { + q := eye(n, n) + x := make([]float64, n) + v := make([]float64, n) + for j := 0; j < n-1; j++ { + // x represents the j-th column of a random matrix. + for i := 0; i < j; i++ { + x[i] = 0 + } + for i := j; i < n; i++ { + x[i] = rnd.NormFloat64() + } + // Compute v that represents the elementary reflector that + // annihilates the subdiagonal elements of x. + reflector(v, x, j) + // Compute Q * H_j and store the result into Q. + applyReflector(q, q, v) + } + if !isOrthonormal(q) { + panic("Q not orthogonal") + } + return q +} + +// reflector generates a Householder reflector v that zeros out subdiagonal +// entries in the j-th column of a matrix. +func reflector(v, col []float64, j int) { + n := len(col) + if len(v) != n { + panic("slice length mismatch") + } + if j < 0 || n <= j { + panic("invalid column index") + } + + for i := range v { + v[i] = 0 + } + if j == n-1 { + return + } + s := floats.Norm(col[j:], 2) + if s == 0 { + return + } + v[j] = col[j] + math.Copysign(s, col[j]) + copy(v[j+1:], col[j+1:]) + s = floats.Norm(v[j:], 2) + floats.Scale(1/s, v[j:]) +} + +// applyReflector computes Q*H where H is a Householder matrix represented by +// the Householder reflector v. +func applyReflector(qh blas64.General, q blas64.General, v []float64) { + n := len(v) + if qh.Rows != n || qh.Cols != n { + panic("bad size of qh") + } + if q.Rows != n || q.Cols != n { + panic("bad size of q") + } + qv := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, q, blas64.Vector{1, v}, 0, blas64.Vector{1, qv}) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] = q.Data[i*q.Stride+j] + } + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] -= 2 * qv[i] * v[j] + } + } + var norm2 float64 + for _, vi := range v { + norm2 += vi * vi + } + norm2inv := 1 / norm2 + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] *= norm2inv + } + } +} + +// constructGSVDresults returns the matrices [ 0 R ], D1 and D2 described +// in the documentation of Dtgsja and Dggsvd3, and the result matrix in +// the documentation for Dggsvp3. +func constructGSVDresults(n, p, m, k, l int, a, b blas64.General, alpha, beta []float64) (zeroR, d1, d2 blas64.General) { + // [ 0 R ] + zeroR = zeros(k+l, n, n) + dst := zeroR + dst.Rows = min(m, k+l) + dst.Cols = k + l + dst.Data = zeroR.Data[n-k-l:] + src := a + src.Rows = min(m, k+l) + src.Cols = k + l + src.Data = a.Data[n-k-l:] + copyGeneral(dst, src) + if m < k+l { + // [ 0 R ] + dst.Rows = k + l - m + dst.Cols = k + l - m + dst.Data = zeroR.Data[m*zeroR.Stride+n-(k+l-m):] + src = b + src.Rows = k + l - m + src.Cols = k + l - m + src.Data = b.Data[(m-k)*b.Stride+n+m-k-l:] + copyGeneral(dst, src) + } + + // D1 + d1 = zeros(m, k+l, k+l) + for i := 0; i < k; i++ { + d1.Data[i*d1.Stride+i] = 1 + } + for i := k; i < min(m, k+l); i++ { + d1.Data[i*d1.Stride+i] = alpha[i] + } + + // D2 + d2 = zeros(p, k+l, k+l) + for i := 0; i < min(l, m-k); i++ { + d2.Data[i*d2.Stride+i+k] = beta[k+i] + } + for i := m - k; i < l; i++ { + d2.Data[i*d2.Stride+i+k] = 1 + } + + return zeroR, d1, d2 +} + +func constructGSVPresults(n, p, m, k, l int, a, b blas64.General) (zeroA, zeroB blas64.General) { + zeroA = zeros(m, n, n) + dst := zeroA + dst.Rows = min(m, k+l) + dst.Cols = k + l + dst.Data = zeroA.Data[n-k-l:] + src := a + dst.Rows = min(m, k+l) + src.Cols = k + l + src.Data = a.Data[n-k-l:] + copyGeneral(dst, src) + + zeroB = zeros(p, n, n) + dst = zeroB + dst.Rows = l + dst.Cols = l + dst.Data = zeroB.Data[n-l:] + src = b + dst.Rows = l + src.Cols = l + src.Data = b.Data[n-l:] + copyGeneral(dst, src) + + return zeroA, zeroB +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlc.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlc.go new file mode 100644 index 00000000..b8a5b2b3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlc.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 testlapack + +import "testing" + +type Iladlcer interface { + Iladlc(m, n int, a []float64, lda int) int +} + +func IladlcTest(t *testing.T, impl Iladlcer) { + for i, test := range []struct { + a []float64 + m, n, lda int + ans int + }{ + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 1, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 2, + n: 2, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 4, + n: 1, + lda: 1, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 4, + lda: 4, + ans: -1, + }, + { + a: []float64{ + 1, 2, 3, 4, + 5, 6, 7, 8, + }, + m: 2, + n: 4, + lda: 4, + ans: 3, + }, + { + a: []float64{ + 1, 2, 3, 0, + 0, 0, 0, 0, + }, + m: 2, + n: 4, + lda: 4, + ans: 2, + }, + { + a: []float64{ + 0, 0, 3, 4, + 0, 0, 0, 0, + }, + m: 2, + n: 2, + lda: 4, + ans: -1, + }, + } { + ans := impl.Iladlc(test.m, test.n, test.a, test.lda) + if ans != test.ans { + t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlr.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlr.go new file mode 100644 index 00000000..bd74d28c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/iladlr.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum 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 testlapack + +import "testing" + +type Iladlrer interface { + Iladlr(m, n int, a []float64, lda int) int +} + +func IladlrTest(t *testing.T, impl Iladlrer) { + for i, test := range []struct { + a []float64 + m, n, lda int + ans int + }{ + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 1, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 2, + n: 2, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 4, + n: 1, + lda: 1, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 4, + lda: 4, + ans: -1, + }, + { + a: []float64{ + 1, 2, 3, 4, + 5, 6, 7, 8, + }, + m: 2, + n: 4, + lda: 4, + ans: 1, + }, + { + a: []float64{ + 1, 2, 3, 0, + 0, 0, 0, 0, + }, + m: 2, + n: 4, + lda: 4, + ans: 0, + }, + { + a: []float64{ + 0, 0, 3, 4, + 0, 0, 0, 0, + }, + m: 2, + n: 2, + lda: 4, + ans: -1, + }, + } { + ans := impl.Iladlr(test.m, test.n, test.a, test.lda) + if ans != test.ans { + t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen.go new file mode 100644 index 00000000..b47d9270 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen.go @@ -0,0 +1,655 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatm1 computes the entries of dst as specified by mode, cond and rsign. +// +// mode describes how dst will be computed: +// |mode| == 1: dst[0] = 1 and dst[1:n] = 1/cond +// |mode| == 2: dst[:n-1] = 1/cond and dst[n-1] = 1 +// |mode| == 3: dst[i] = cond^{-i/(n-1)}, i=0,...,n-1 +// |mode| == 4: dst[i] = 1 - i*(1-1/cond)/(n-1) +// |mode| == 5: dst[i] = random number in the range (1/cond, 1) such that +// their logarithms are uniformly distributed +// |mode| == 6: dst[i] = random number from the distribution given by dist +// If mode is negative, the order of the elements of dst will be reversed. +// For other values of mode Dlatm1 will panic. +// +// If rsign is true and mode is not ±6, each entry of dst will be multiplied by 1 +// or -1 with probability 0.5 +// +// dist specifies the type of distribution to be used when mode == ±6: +// dist == 1: Uniform[0,1) +// dist == 2: Uniform[-1,1) +// dist == 3: Normal(0,1) +// For other values of dist Dlatm1 will panic. +// +// rnd is used as a source of random numbers. +func Dlatm1(dst []float64, mode int, cond float64, rsign bool, dist int, rnd *rand.Rand) { + amode := mode + if amode < 0 { + amode = -amode + } + if amode < 1 || 6 < amode { + panic("testlapack: invalid mode") + } + if cond < 1 { + panic("testlapack: cond < 1") + } + if amode == 6 && (dist < 1 || 3 < dist) { + panic("testlapack: invalid dist") + } + + n := len(dst) + if n == 0 { + return + } + + switch amode { + case 1: + dst[0] = 1 + for i := 1; i < n; i++ { + dst[i] = 1 / cond + } + case 2: + for i := 0; i < n-1; i++ { + dst[i] = 1 + } + dst[n-1] = 1 / cond + case 3: + dst[0] = 1 + if n > 1 { + alpha := math.Pow(cond, -1/float64(n-1)) + for i := 1; i < n; i++ { + dst[i] = math.Pow(alpha, float64(i)) + } + } + case 4: + dst[0] = 1 + if n > 1 { + condInv := 1 / cond + alpha := (1 - condInv) / float64(n-1) + for i := 1; i < n; i++ { + dst[i] = float64(n-i-1)*alpha + condInv + } + } + case 5: + alpha := math.Log(1 / cond) + for i := range dst { + dst[i] = math.Exp(alpha * rnd.Float64()) + } + case 6: + switch dist { + case 1: + for i := range dst { + dst[i] = rnd.Float64() + } + case 2: + for i := range dst { + dst[i] = 2*rnd.Float64() - 1 + } + case 3: + for i := range dst { + dst[i] = rnd.NormFloat64() + } + } + } + + if rsign && amode != 6 { + for i, v := range dst { + if rnd.Float64() < 0.5 { + dst[i] = -v + } + } + } + + if mode < 0 { + for i := 0; i < n/2; i++ { + dst[i], dst[n-i-1] = dst[n-i-1], dst[i] + } + } +} + +// Dlagsy generates an n×n symmetric matrix A, by pre- and post- multiplying a +// real diagonal matrix D with a random orthogonal matrix: +// A = U * D * U^T. +// +// work must have length at least 2*n, otherwise Dlagsy will panic. +// +// The parameter k is unused but it must satisfy +// 0 <= k <= n-1. +func Dlagsy(n, k int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) { + checkMatrix(n, n, a, lda) + if k < 0 || max(0, n-1) < k { + panic("testlapack: invalid value of k") + } + if len(d) != n { + panic("testlapack: bad length of d") + } + if len(work) < 2*n { + panic("testlapack: insufficient work length") + } + + // Initialize lower triangle of A to diagonal matrix. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + } + for i := 0; i < n; i++ { + a[i*lda+i] = d[i] + } + + bi := blas64.Implementation() + + // Generate lower triangle of symmetric matrix. + for i := n - 2; i >= 0; i-- { + for j := 0; j < n-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(n-i, work[:n-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Apply random reflection to A[i:n,i:n] from the left and the + // right. + // + // Compute y := tau * A * u. + bi.Dsymv(blas.Lower, n-i, tau, a[i*lda+i:], lda, work[:n-i], 1, 0, work[n:2*n-i], 1) + + // Compute v := y - 1/2 * tau * ( y, u ) * u. + alpha := -0.5 * tau * bi.Ddot(n-i, work[n:2*n-i], 1, work[:n-i], 1) + bi.Daxpy(n-i, alpha, work[:n-i], 1, work[n:2*n-i], 1) + + // Apply the transformation as a rank-2 update to A[i:n,i:n]. + bi.Dsyr2(blas.Lower, n-i, -1, work[:n-i], 1, work[n:2*n-i], 1, a[i*lda+i:], lda) + } + + // Store full symmetric matrix. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a[j*lda+i] = a[i*lda+j] + } + } +} + +// Dlagge generates a real general m×n matrix A, by pre- and post-multiplying +// a real diagonal matrix D with random orthogonal matrices: +// A = U*D*V. +// +// d must have length min(m,n), and work must have length m+n, otherwise Dlagge +// will panic. +// +// The parameters ku and kl are unused but they must satisfy +// 0 <= kl <= m-1, +// 0 <= ku <= n-1. +func Dlagge(m, n, kl, ku int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) { + checkMatrix(m, n, a, lda) + if kl < 0 || max(0, m-1) < kl { + panic("testlapack: invalid value of kl") + } + if ku < 0 || max(0, n-1) < ku { + panic("testlapack: invalid value of ku") + } + if len(d) != min(m, n) { + panic("testlapack: bad length of d") + } + if len(work) < m+n { + panic("testlapack: insufficient work length") + } + + // Initialize A to diagonal matrix. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + } + for i := 0; i < min(m, n); i++ { + a[i*lda+i] = d[i] + } + + // Quick exit if the user wants a diagonal matrix. + // if kl == 0 && ku == 0 { + // return + // } + + bi := blas64.Implementation() + + // Pre- and post-multiply A by random orthogonal matrices. + for i := min(m, n) - 1; i >= 0; i-- { + if i < m-1 { + for j := 0; j < m-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(m-i, work[:m-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(m-i-1, 1/wb, work[1:m-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Multiply A[i:m,i:n] by random reflection from the left. + bi.Dgemv(blas.Trans, m-i, n-i, + 1, a[i*lda+i:], lda, work[:m-i], 1, + 0, work[m:m+n-i], 1) + bi.Dger(m-i, n-i, + -tau, work[:m-i], 1, work[m:m+n-i], 1, + a[i*lda+i:], lda) + } + if i < n-1 { + for j := 0; j < n-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(n-i, work[:n-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Multiply A[i:m,i:n] by random reflection from the right. + bi.Dgemv(blas.NoTrans, m-i, n-i, + 1, a[i*lda+i:], lda, work[:n-i], 1, + 0, work[n:n+m-i], 1) + bi.Dger(m-i, n-i, + -tau, work[n:n+m-i], 1, work[:n-i], 1, + a[i*lda+i:], lda) + } + } + + // TODO(vladimir-ch): Reduce number of subdiagonals to kl and number of + // superdiagonals to ku. +} + +// dlarnv fills dst with random numbers from a uniform or normal distribution +// specified by dist: +// dist=1: uniform(0,1), +// dist=2: uniform(-1,1), +// dist=3: normal(0,1). +// For other values of dist dlarnv will panic. +func dlarnv(dst []float64, dist int, rnd *rand.Rand) { + switch dist { + default: + panic("testlapack: invalid dist") + case 1: + for i := range dst { + dst[i] = rnd.Float64() + } + case 2: + for i := range dst { + dst[i] = 2*rnd.Float64() - 1 + } + case 3: + for i := range dst { + dst[i] = rnd.NormFloat64() + } + } +} + +// dlattr generates an n×n triangular test matrix A with its properties uniquely +// determined by imat and uplo, and returns whether A has unit diagonal. If diag +// is blas.Unit, the diagonal elements are set so that A[k,k]=k. +// +// trans specifies whether the matrix A or its transpose will be used. +// +// If imat is greater than 10, dlattr also generates the right hand side of the +// linear system A*x=b, or A^T*x=b. Valid values of imat are 7, and all between 11 +// and 19, inclusive. +// +// b mush have length n, and work must have length 3*n, and dlattr will panic +// otherwise. +func dlattr(imat int, uplo blas.Uplo, trans blas.Transpose, n int, a []float64, lda int, b, work []float64, rnd *rand.Rand) (diag blas.Diag) { + checkMatrix(n, n, a, lda) + if len(b) != n { + panic("testlapack: bad length of b") + } + if len(work) < 3*n { + panic("testlapack: insufficient length of work") + } + if uplo != blas.Upper && uplo != blas.Lower { + panic("testlapack: bad uplo") + } + if trans != blas.Trans && trans != blas.NoTrans { + panic("testlapack: bad trans") + } + + if n == 0 { + return blas.NonUnit + } + + ulp := dlamchE * dlamchB + smlnum := dlamchS + bignum := (1 - ulp) / smlnum + + bi := blas64.Implementation() + + switch imat { + default: + // TODO(vladimir-ch): Implement the remaining cases. + panic("testlapack: invalid or unimplemented imat") + case 7: + // Identity matrix. The diagonal is set to NaN. + diag = blas.Unit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = math.NaN() + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = math.NaN() + } + } + case 11: + // Generate a triangular matrix with elements between -1 and 1, + // give the diagonal norm 2 to make it well-conditioned, and + // make the right hand side large so that it requires scaling. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n-1; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + } + case blas.Lower: + for i := 1; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + } + } + for i := 0; i < n; i++ { + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + // Set the right hand side so that the largest value is bignum. + dlarnv(b, 2, rnd) + imax := bi.Idamax(n, b, 1) + bscal := bignum / math.Max(1, b[imax]) + bi.Dscal(n, bscal, b, 1) + case 12: + // Make the first diagonal element in the solve small to cause + // immediate overflow when dividing by T[j,j]. The off-diagonal + // elements are small (cnorm[j] < 1). + diag = blas.NonUnit + tscal := 1 / math.Max(1, float64(n-1)) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + bi.Dscal(n-i-1, tscal, a[i*lda+i+1:], 1) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[(n-1)*lda+n-1] *= smlnum + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + bi.Dscal(i, tscal, a[i*lda:], 1) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[0] *= smlnum + } + dlarnv(b, 2, rnd) + case 13: + // Make the first diagonal element in the solve small to cause + // immediate overflow when dividing by T[j,j]. The off-diagonal + // elements are O(1) (cnorm[j] > 1). + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[(n-1)*lda+n-1] *= smlnum + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[0] *= smlnum + } + dlarnv(b, 2, rnd) + case 14: + // T is diagonal with small numbers on the diagonal to + // make the growth factor underflow, but a small right hand side + // chosen so that the solution does not overflow. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + if (n-1-i)&0x2 == 0 { + a[i*lda+i] = smlnum + } else { + a[i*lda+i] = 1 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + if i&0x2 == 0 { + a[i*lda+i] = smlnum + } else { + a[i*lda+i] = 1 + } + } + } + // Set the right hand side alternately zero and small. + switch uplo { + case blas.Upper: + b[0] = 0 + for i := n - 1; i > 0; i -= 2 { + b[i] = 0 + b[i-1] = smlnum + } + case blas.Lower: + for i := 0; i < n-1; i += 2 { + b[i] = 0 + b[i+1] = smlnum + } + b[n-1] = 0 + } + case 15: + // Make the diagonal elements small to cause gradual overflow + // when dividing by T[j,j]. To control the amount of scaling + // needed, the matrix is bidiagonal. + diag = blas.NonUnit + texp := 1 / math.Max(1, float64(n-1)) + tscal := math.Pow(smlnum, texp) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = tscal + if i < n-1 { + a[i*lda+i+1] = -1 + } + for j := i + 2; j < n; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + a[i*lda+j] = 0 + } + if i > 0 { + a[i*lda+i-1] = -1 + } + a[i*lda+i] = tscal + } + } + dlarnv(b, 2, rnd) + case 16: + // One zero diagonal element. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + } + iy := n / 2 + a[iy*lda+iy] = 0 + dlarnv(b, 2, rnd) + bi.Dscal(n, 2, b, 1) + case 17: + // Make the offdiagonal elements large to cause overflow when + // adding a column of T. In the non-transposed case, the matrix + // is constructed to cause overflow when adding a column in + // every other step. + diag = blas.NonUnit + tscal := (1 - ulp) / (dlamchS / ulp) + texp := 1.0 + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + a[i*lda+j] = 0 + } + } + for j := n - 1; j >= 1; j -= 2 { + a[j] = -tscal / float64(n+1) + a[j*lda+j] = 1 + b[j] = texp * (1 - ulp) + a[j-1] = -tscal / float64(n+1) / float64(n+2) + a[(j-1)*lda+j-1] = 1 + b[j-1] = texp * float64(n*n+n-1) + texp *= 2 + } + b[0] = float64(n+1) / float64(n+2) * tscal + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + a[i*lda+j] = 0 + } + } + for j := 0; j < n-1; j += 2 { + a[(n-1)*lda+j] = -tscal / float64(n+1) + a[j*lda+j] = 1 + b[j] = texp * (1 - ulp) + a[(n-1)*lda+j+1] = -tscal / float64(n+1) / float64(n+2) + a[(j+1)*lda+j+1] = 1 + b[j+1] = texp * float64(n*n+n-1) + texp *= 2 + } + b[n-1] = float64(n+1) / float64(n+2) * tscal + } + case 18: + // Generate a unit triangular matrix with elements between -1 + // and 1, and make the right hand side large so that it requires + // scaling. The diagonal is set to NaN. + diag = blas.Unit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = math.NaN() + dlarnv(a[i*lda+i+1:i*lda+n], 2, rnd) + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i], 2, rnd) + a[i*lda+i] = math.NaN() + } + } + // Set the right hand side so that the largest value is bignum. + dlarnv(b, 2, rnd) + iy := bi.Idamax(n, b, 1) + bnorm := math.Abs(b[iy]) + bscal := bignum / math.Max(1, bnorm) + bi.Dscal(n, bscal, b, 1) + case 19: + // Generate a triangular matrix with elements between + // bignum/(n-1) and bignum so that at least one of the column + // norms will exceed bignum. + // Dlatrs cannot handle this case for (typically) n>5. + diag = blas.NonUnit + tleft := bignum / math.Max(1, float64(n-1)) + tscal := bignum * (float64(n-1) / math.Max(1, float64(n))) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + for j := i; j < n; j++ { + aij := a[i*lda+j] + a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij + } + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + for j := 0; j <= i; j++ { + aij := a[i*lda+j] + a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij + } + } + } + dlarnv(b, 2, rnd) + bi.Dscal(n, 2, b, 1) + } + + // Flip the matrix if the transpose will be used. + if trans == blas.Trans { + switch uplo { + case blas.Upper: + for j := 0; j < n/2; j++ { + bi.Dswap(n-2*j-1, a[j*lda+j:], 1, a[(j+1)*lda+n-j-1:], -lda) + } + case blas.Lower: + for j := 0; j < n/2; j++ { + bi.Dswap(n-2*j-1, a[j*lda+j:], lda, a[(n-j-1)*lda+j+1:], -1) + } + } + } + + return diag +} + +func checkMatrix(m, n int, a []float64, lda int) { + if m < 0 { + panic("testlapack: m < 0") + } + if n < 0 { + panic("testlapack: n < 0") + } + if lda < max(1, n) { + panic("testlapack: lda < max(1, n)") + } + if len(a) < (m-1)*lda+n { + panic("testlapack: insufficient matrix slice length") + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen_test.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen_test.go new file mode 100644 index 00000000..1bb86d3c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/matgen_test.go @@ -0,0 +1,90 @@ +// Copyright ©2017 The gonum 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 testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestDlagsy(t *testing.T) { + const tol = 1e-14 + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { + for _, lda := range []int{0, 2*n + 1} { + if lda == 0 { + lda = max(1, n) + } + d := make([]float64, n) + for i := range d { + d[i] = 1 + } + a := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: nanSlice(n * lda), + } + work := make([]float64, a.Rows+a.Cols) + + Dlagsy(a.Rows, 0, d, a.Data, a.Stride, rnd, work) + + isIdentity := true + identityLoop: + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + aij := a.Data[i*a.Stride+j] + if math.IsNaN(aij) { + isIdentity = false + } + if i == j && math.Abs(aij-1) > tol { + isIdentity = false + } + if i != j && math.Abs(aij) > tol { + isIdentity = false + } + if !isIdentity { + break identityLoop + } + } + } + if !isIdentity { + t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) + } + } + } +} + +func TestDlagge(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { + for _, lda := range []int{0, 2*n + 1} { + if lda == 0 { + lda = max(1, n) + } + d := make([]float64, n) + for i := range d { + d[i] = 1 + } + a := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: nanSlice(n * lda), + } + work := make([]float64, a.Rows+a.Cols) + + Dlagge(a.Rows, a.Cols, 0, 0, d, a.Data, a.Stride, rnd, work) + + if !isOrthonormal(a) { + t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) + } + } + } + +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/test_matrices.go b/vendor/gonum.org/v1/gonum/lapack/testlapack/test_matrices.go new file mode 100644 index 00000000..6be490b2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/testlapack/test_matrices.go @@ -0,0 +1,615 @@ +// Copyright ©2016 The gonum 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 testlapack + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/blas/blas64" +) + +// A123 is the non-symmetric singular matrix +// [ 1 2 3 ] +// A = [ 4 5 6 ] +// [ 7 8 9 ] +// It has three distinct real eigenvalues. +type A123 struct{} + +func (A123) Matrix() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + } +} + +func (A123) Eigenvalues() []complex128 { + return []complex128{16.116843969807043, -1.116843969807043, 0} +} + +func (A123) LeftEV() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + -0.464547273387671, -0.570795531228578, -0.677043789069485, + -0.882905959653586, -0.239520420054206, 0.403865119545174, + 0.408248290463862, -0.816496580927726, 0.408248290463863, + }, + } +} + +func (A123) RightEV() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + -0.231970687246286, -0.785830238742067, 0.408248290463864, + -0.525322093301234, -0.086751339256628, -0.816496580927726, + -0.818673499356181, 0.612327560228810, 0.408248290463863, + }, + } +} + +// AntisymRandom is a anti-symmetric random matrix. All its eigenvalues are +// imaginary with one zero if the order is odd. +type AntisymRandom struct { + mat blas64.General +} + +func NewAntisymRandom(n int, rnd *rand.Rand) AntisymRandom { + a := zeros(n, n, n) + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + r := rnd.NormFloat64() + a.Data[i*a.Stride+j] = r + a.Data[j*a.Stride+i] = -r + } + } + return AntisymRandom{a} +} + +func (a AntisymRandom) Matrix() blas64.General { + return cloneGeneral(a.mat) +} + +func (AntisymRandom) Eigenvalues() []complex128 { + return nil +} + +// Circulant is a generally non-symmetric matrix given by +// A[i,j] = 1 + (j-i+n)%n. +// For example, for n=5, +// [ 1 2 3 4 5 ] +// [ 5 1 2 3 4 ] +// A = [ 4 5 1 2 3 ] +// [ 3 4 5 1 2 ] +// [ 2 3 4 5 1 ] +// It has real and complex eigenvalues, some possibly repeated. +type Circulant int + +func (c Circulant) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(1 + (j-i+n)%n) + } + } + return a +} + +func (c Circulant) Eigenvalues() []complex128 { + n := int(c) + w := rootsOfUnity(n) + ev := make([]complex128, n) + for k := 0; k < n; k++ { + ev[k] = complex(float64(n), 0) + } + for i := n - 1; i > 0; i-- { + for k := 0; k < n; k++ { + ev[k] = ev[k]*w[k] + complex(float64(i), 0) + } + } + return ev +} + +// Clement is a generally non-symmetric matrix given by +// A[i,j] = i+1, if j == i+1, +// = n-i, if j == i-1, +// = 0, otherwise. +// For example, for n=5, +// [ . 1 . . . ] +// [ 4 . 2 . . ] +// A = [ . 3 . 3 . ] +// [ . . 2 . 4 ] +// [ . . . 1 . ] +// It has n distinct real eigenvalues. +type Clement int + +func (c Clement) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + if i < n-1 { + a.Data[i*a.Stride+i+1] = float64(i + 1) + } + if i > 0 { + a.Data[i*a.Stride+i-1] = float64(n - i) + } + } + return a +} + +func (c Clement) Eigenvalues() []complex128 { + n := int(c) + ev := make([]complex128, n) + for i := range ev { + ev[i] = complex(float64(-n+2*i+1), 0) + } + return ev +} + +// Creation is a singular non-symmetric matrix given by +// A[i,j] = i, if j == i-1, +// = 0, otherwise. +// For example, for n=5, +// [ . . . . . ] +// [ 1 . . . . ] +// A = [ . 2 . . . ] +// [ . . 3 . . ] +// [ . . . 4 . ] +// Zero is its only eigenvalue. +type Creation int + +func (c Creation) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = float64(i) + } + return a +} + +func (c Creation) Eigenvalues() []complex128 { + return make([]complex128, int(c)) +} + +// Diagonal is a diagonal matrix given by +// A[i,j] = i+1, if i == j, +// = 0, otherwise. +// For example, for n=5, +// [ 1 . . . . ] +// [ . 2 . . . ] +// A = [ . . 3 . . ] +// [ . . . 4 . ] +// [ . . . . 5 ] +// It has n real eigenvalues {1,...,n}. +type Diagonal int + +func (d Diagonal) Matrix() blas64.General { + n := int(d) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = float64(i) + } + return a +} + +func (d Diagonal) Eigenvalues() []complex128 { + n := int(d) + ev := make([]complex128, n) + for i := range ev { + ev[i] = complex(float64(i), 0) + } + return ev +} + +// Downshift is a non-singular upper Hessenberg matrix given by +// A[i,j] = 1, if (i-j+n)%n == 1, +// = 0, otherwise. +// For example, for n=5, +// [ . . . . 1 ] +// [ 1 . . . . ] +// A = [ . 1 . . . ] +// [ . . 1 . . ] +// [ . . . 1 . ] +// Its eigenvalues are the complex roots of unity. +type Downshift int + +func (d Downshift) Matrix() blas64.General { + n := int(d) + a := zeros(n, n, n) + a.Data[n-1] = 1 + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + } + return a +} + +func (d Downshift) Eigenvalues() []complex128 { + return rootsOfUnity(int(d)) +} + +// Fibonacci is an upper Hessenberg matrix with 3 distinct real eigenvalues. For +// example, for n=5, +// [ . 1 . . . ] +// [ 1 1 . . . ] +// A = [ . 1 1 . . ] +// [ . . 1 1 . ] +// [ . . . 1 1 ] +type Fibonacci int + +func (f Fibonacci) Matrix() blas64.General { + n := int(f) + a := zeros(n, n, n) + if n > 1 { + a.Data[1] = 1 + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + a.Data[i*a.Stride+i] = 1 + } + return a +} + +func (f Fibonacci) Eigenvalues() []complex128 { + n := int(f) + ev := make([]complex128, n) + if n == 0 || n == 1 { + return ev + } + phi := 0.5 * (1 + math.Sqrt(5)) + ev[0] = complex(phi, 0) + for i := 1; i < n-1; i++ { + ev[i] = 1 + 0i + } + ev[n-1] = complex(1-phi, 0) + return ev +} + +// Gear is a singular non-symmetric matrix with real eigenvalues. For example, +// for n=5, +// [ . 1 . . 1 ] +// [ 1 . 1 . . ] +// A = [ . 1 . 1 . ] +// [ . . 1 . 1 ] +// [-1 . . 1 . ] +type Gear int + +func (g Gear) Matrix() blas64.General { + n := int(g) + a := zeros(n, n, n) + if n == 1 { + return a + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = 1 + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + } + a.Data[n-1] = 1 + a.Data[(n-1)*a.Stride] = -1 + return a +} + +func (g Gear) Eigenvalues() []complex128 { + n := int(g) + ev := make([]complex128, n) + if n == 0 || n == 1 { + return ev + } + if n == 2 { + ev[0] = complex(0, 1) + ev[1] = complex(0, -1) + return ev + } + w := 0 + ev[w] = math.Pi / 2 + w++ + phi := (n - 1) / 2 + for p := 1; p <= phi; p++ { + ev[w] = complex(float64(2*p)*math.Pi/float64(n), 0) + w++ + } + phi = n / 2 + for p := 1; p <= phi; p++ { + ev[w] = complex(float64(2*p-1)*math.Pi/float64(n), 0) + w++ + } + for i, v := range ev { + ev[i] = complex(2*math.Cos(real(v)), 0) + } + return ev +} + +// Grcar is an upper Hessenberg matrix given by +// A[i,j] = -1 if i == j+1, +// = 1 if i <= j and j <= i+k, +// = 0 otherwise. +// For example, for n=5 and k=2, +// [ 1 1 1 . . ] +// [ -1 1 1 1 . ] +// A = [ . -1 1 1 1 ] +// [ . . -1 1 1 ] +// [ . . . -1 1 ] +// The matrix has sensitive eigenvalues but they are not given explicitly. +type Grcar struct { + N int + K int +} + +func (g Grcar) Matrix() blas64.General { + n := g.N + a := zeros(n, n, n) + for k := 0; k <= g.K; k++ { + for i := 0; i < n-k; i++ { + a.Data[i*a.Stride+i+k] = 1 + } + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = -1 + } + return a +} + +func (Grcar) Eigenvalues() []complex128 { + return nil +} + +// Hanowa is a non-symmetric non-singular matrix of even order given by +// A[i,j] = alpha if i == j, +// = -i-1 if i < n/2 and j == i + n/2, +// = i+1-n/2 if i >= n/2 and j == i - n/2, +// = 0 otherwise. +// The matrix has complex eigenvalues. +type Hanowa struct { + N int // Order of the matrix, must be even. + Alpha float64 +} + +func (h Hanowa) Matrix() blas64.General { + if h.N&0x1 != 0 { + panic("lapack: matrix order must be even") + } + n := h.N + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = h.Alpha + } + for i := 0; i < n/2; i++ { + a.Data[i*a.Stride+i+n/2] = float64(-i - 1) + } + for i := n / 2; i < n; i++ { + a.Data[i*a.Stride+i-n/2] = float64(i + 1 - n/2) + } + return a +} + +func (h Hanowa) Eigenvalues() []complex128 { + if h.N&0x1 != 0 { + panic("lapack: matrix order must be even") + } + n := int(h.N) + ev := make([]complex128, n) + for i := 0; i < n/2; i++ { + ev[2*i] = complex(h.Alpha, float64(-i-1)) + ev[2*i+1] = complex(h.Alpha, float64(i+1)) + } + return ev +} + +// Lesp is a tridiagonal, generally non-symmetric matrix given by +// A[i,j] = -2*i-5 if i == j, +// = 1/(i+1) if i == j-1, +// = j+1 if i == j+1. +// For example, for n=5, +// [ -5 2 . . . ] +// [ 1/2 -7 3 . . ] +// A = [ . 1/3 -9 4 . ] +// [ . . 1/4 -11 5 ] +// [ . . . 1/5 -13 ]. +// The matrix has sensitive eigenvalues but they are not given explicitly. +type Lesp int + +func (l Lesp) Matrix() blas64.General { + n := int(l) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = float64(-2*i - 5) + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = float64(i + 2) + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 / float64(i+1) + } + return a +} + +func (Lesp) Eigenvalues() []complex128 { + return nil +} + +// Rutis is the 4×4 non-symmetric matrix +// [ 4 -5 0 3 ] +// A = [ 0 4 -3 -5 ] +// [ 5 -3 4 0 ] +// [ 3 0 5 4 ] +// It has two distinct real eigenvalues and a pair of complex eigenvalues. +type Rutis struct{} + +func (Rutis) Matrix() blas64.General { + return blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 4, -5, 0, 3, + 0, 4, -3, -5, + 5, -3, 4, 0, + 3, 0, 5, 4, + }, + } +} + +func (Rutis) Eigenvalues() []complex128 { + return []complex128{12, 1 + 5i, 1 - 5i, 2} +} + +// Tris is a tridiagonal matrix given by +// A[i,j] = x if i == j-1, +// = y if i == j, +// = z if i == j+1. +// If x*z is negative, the matrix has complex eigenvalues. +type Tris struct { + N int + X, Y, Z float64 +} + +func (t Tris) Matrix() blas64.General { + n := t.N + a := zeros(n, n, n) + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = t.X + } + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = t.Y + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = t.Z + } + return a +} + +func (t Tris) Eigenvalues() []complex128 { + n := int(t.N) + ev := make([]complex128, n) + for i := range ev { + angle := float64(i+1) * math.Pi / float64(n+1) + arg := t.X * t.Z + if arg >= 0 { + ev[i] = complex(t.Y+2*math.Sqrt(arg)*math.Cos(angle), 0) + } else { + ev[i] = complex(t.Y, 2*math.Sqrt(-arg)*math.Cos(angle)) + } + } + return ev +} + +// Wilk4 is a 4×4 lower triangular matrix with 4 distinct real eigenvalues. +type Wilk4 struct{} + +func (Wilk4) Matrix() blas64.General { + return blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 0.9143e-4, 0.0, 0.0, 0.0, + 0.8762, 0.7156e-4, 0.0, 0.0, + 0.7943, 0.8143, 0.9504e-4, 0.0, + 0.8017, 0.6123, 0.7165, 0.7123e-4, + }, + } +} + +func (Wilk4) Eigenvalues() []complex128 { + return []complex128{ + 0.9504e-4, 0.9143e-4, 0.7156e-4, 0.7123e-4, + } +} + +// Wilk12 is a 12×12 lower Hessenberg matrix with 12 distinct real eigenvalues. +type Wilk12 struct{} + +func (Wilk12) Matrix() blas64.General { + return blas64.General{ + Rows: 12, + Cols: 12, + Stride: 12, + Data: []float64{ + 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 7, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 5, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, + } +} + +func (Wilk12) Eigenvalues() []complex128 { + return []complex128{ + 32.2288915015722210, + 20.1989886458770691, + 12.3110774008685340, + 6.9615330855671154, + 3.5118559485807528, + 1.5539887091319704, + 0.6435053190136506, + 0.2847497205488856, + 0.1436465181918488, + 0.0812276683076552, + 0.0495074140194613, + 0.0310280683208907, + } +} + +// Wilk20 is a 20×20 lower Hessenberg matrix. If the parameter is 0, the matrix +// has 20 distinct real eigenvalues. If the parameter is 1e-10, the matrix has 6 +// real eigenvalues and 7 pairs of complex eigenvalues. +type Wilk20 float64 + +func (w Wilk20) Matrix() blas64.General { + a := zeros(20, 20, 20) + for i := 0; i < 20; i++ { + a.Data[i*a.Stride+i] = float64(i + 1) + } + for i := 0; i < 19; i++ { + a.Data[i*a.Stride+i+1] = 20 + } + a.Data[19*a.Stride] = float64(w) + return a +} + +func (w Wilk20) Eigenvalues() []complex128 { + if float64(w) == 0 { + ev := make([]complex128, 20) + for i := range ev { + ev[i] = complex(float64(i+1), 0) + } + return ev + } + return nil +} + +// Zero is a matrix with all elements equal to zero. +type Zero int + +func (z Zero) Matrix() blas64.General { + n := int(z) + return zeros(n, n, n) +} + +func (z Zero) Eigenvalues() []complex128 { + n := int(z) + return make([]complex128, n) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlahr2data.json.gz b/vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlahr2data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..7652126afd729e72194c4025c7865532ac6707d1 GIT binary patch literal 28251 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 ef$Q(E?x1Xv2 literal 0 HcmV?d00001 diff --git a/vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlaqr5data.json.gz b/vendor/gonum.org/v1/gonum/lapack/testlapack/testdata/dlaqr5data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..9e629480b659636d23a5a70ad74133c499c21689 GIT binary patch literal 1342926 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

u$6aQ%jfxq+U%%WObi)z<= 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%0AjyQDlWfKbqc0NDdOpACeMSJ0c9?b3^IL_?YP0 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�)6WeE#RIU^jh6V-VxV*Wq+SP7 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°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 V?L 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

MS&^hZ+l*Rtps_qxb5Ze)H%U(jN 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

&7j58eJ*V7VY}n=sLMrUH5bMV;LzXL(91z&( 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°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 z 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

;O}IyAC#*!E&6; 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%0DO*Ko4G|ZQ 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

Pxk&X2oM&i+bE-Q!ue^)G`aMevWNemqwgXcj! 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

N7^ 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 r || ku+1 > c { + panic("mat: band out of range") + } + bc := kl + ku + 1 + if data != nil && len(data) != min(r, c+kl)*bc { + panic(ErrShape) + } + if data == nil { + data = make([]float64, min(r, c+kl)*bc) + } + return &BandDense{ + mat: blas64.Band{ + Rows: r, + Cols: c, + KL: kl, + KU: ku, + Stride: bc, + Data: data, + }, + } +} + +// NewDiagonalRect is a convenience function that returns a diagonal matrix represented by a +// BandDense. The length of data must be min(r, c) otherwise NewDiagonalRect will panic. +func NewDiagonalRect(r, c int, data []float64) *BandDense { + return NewBandDense(r, c, 0, 0, data) +} + +// Dims returns the number of rows and columns in the matrix. +func (b *BandDense) Dims() (r, c int) { + return b.mat.Rows, b.mat.Cols +} + +// Bandwidth returns the upper and lower bandwidths of the matrix. +func (b *BandDense) Bandwidth() (kl, ku int) { + return b.mat.KL, b.mat.KU +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (b *BandDense) T() Matrix { + return Transpose{b} +} + +// TBand performs an implicit transpose by returning the receiver inside a TransposeBand. +func (b *BandDense) TBand() Banded { + return TransposeBand{b} +} + +// RawBand returns the underlying blas64.Band used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.Band. +func (b *BandDense) RawBand() blas64.Band { + return b.mat +} + +// DoNonZero calls the function fn for each of the non-zero elements of b. The function fn +// takes a row/column index and the element value of b at (i, j). +func (b *BandDense) DoNonZero(fn func(i, j int, v float64)) { + for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ { + for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ { + v := b.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } +} + +// DoRowNonZero calls the function fn for each of the non-zero elements of row i of b. The function fn +// takes a row/column index and the element value of b at (i, j). +func (b *BandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { + if i < 0 || b.mat.Rows <= i { + panic(ErrRowAccess) + } + for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ { + v := b.at(i, j) + if v != 0 { + fn(i, j, v) + } + } +} + +// DoColNonZero calls the function fn for each of the non-zero elements of column j of b. The function fn +// takes a row/column index and the element value of b at (i, j). +func (b *BandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { + if j < 0 || b.mat.Cols <= j { + panic(ErrColAccess) + } + for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ { + if i-b.mat.KL <= j && j < i+b.mat.KU+1 { + v := b.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/band_test.go b/vendor/gonum.org/v1/gonum/mat/band_test.go new file mode 100644 index 00000000..f24d7f5c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/band_test.go @@ -0,0 +1,377 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "reflect" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestNewBand(t *testing.T) { + for i, test := range []struct { + data []float64 + r, c int + kl, ku int + mat *BandDense + dense *Dense + }{ + { + data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, -1, + 19, 20, -1, -1, + }, + r: 6, c: 6, + kl: 1, ku: 2, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 6, + Cols: 6, + KL: 1, + KU: 2, + Stride: 4, + Data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, -1, + 19, 20, -1, -1, + }, + }, + }, + dense: NewDense(6, 6, []float64{ + 1, 2, 3, 0, 0, 0, + 4, 5, 6, 7, 0, 0, + 0, 8, 9, 10, 11, 0, + 0, 0, 12, 13, 14, 15, + 0, 0, 0, 16, 17, 18, + 0, 0, 0, 0, 19, 20, + }), + }, + { + data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, -1, + 19, 20, -1, -1, + 21, -1, -1, -1, + }, + r: 10, c: 6, + kl: 1, ku: 2, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 10, + Cols: 6, + KL: 1, + KU: 2, + Stride: 4, + Data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, -1, + 19, 20, -1, -1, + 21, -1, -1, -1, + }, + }, + }, + dense: NewDense(10, 6, []float64{ + 1, 2, 3, 0, 0, 0, + 4, 5, 6, 7, 0, 0, + 0, 8, 9, 10, 11, 0, + 0, 0, 12, 13, 14, 15, + 0, 0, 0, 16, 17, 18, + 0, 0, 0, 0, 19, 20, + 0, 0, 0, 0, 0, 21, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + }), + }, + { + data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + }, + r: 6, c: 10, + kl: 1, ku: 2, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 6, + Cols: 10, + KL: 1, + KU: 2, + Stride: 4, + Data: []float64{ + -1, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + }, + }, + }, + dense: NewDense(6, 10, []float64{ + 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, + 0, 8, 9, 10, 11, 0, 0, 0, 0, 0, + 0, 0, 12, 13, 14, 15, 0, 0, 0, 0, + 0, 0, 0, 16, 17, 18, 19, 0, 0, 0, + 0, 0, 0, 0, 20, 21, 22, 23, 0, 0, + }), + }, + } { + band := NewBandDense(test.r, test.c, test.kl, test.ku, test.data) + rows, cols := band.Dims() + + if rows != test.r { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.r) + } + if cols != test.c { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.c) + } + if !reflect.DeepEqual(band, test.mat) { + t.Errorf("unexpected value via reflect for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.mat) { + t.Errorf("unexpected value via mat.Equal for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.dense) { + t.Errorf("unexpected value via mat.Equal(band, dense) for test %d:\ngot:\n% v\nwant:\n% v", i, Formatted(band), Formatted(test.dense)) + } + } +} + +func TestNewDiagonalRect(t *testing.T) { + for i, test := range []struct { + data []float64 + r, c int + mat *BandDense + dense *Dense + }{ + { + data: []float64{1, 2, 3, 4, 5, 6}, + r: 6, c: 6, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 6, + Cols: 6, + Stride: 1, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + }, + dense: NewDense(6, 6, []float64{ + 1, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 6, + }), + }, + { + data: []float64{1, 2, 3, 4, 5, 6}, + r: 7, c: 6, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 7, + Cols: 6, + Stride: 1, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + }, + dense: NewDense(7, 6, []float64{ + 1, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, + }), + }, + { + data: []float64{1, 2, 3, 4, 5, 6}, + r: 6, c: 7, + mat: &BandDense{ + mat: blas64.Band{ + Rows: 6, + Cols: 7, + Stride: 1, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + }, + dense: NewDense(6, 7, []float64{ + 1, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 6, 0, + }), + }, + } { + band := NewDiagonalRect(test.r, test.c, test.data) + rows, cols := band.Dims() + + if rows != test.r { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.r) + } + if cols != test.c { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.c) + } + if !reflect.DeepEqual(band, test.mat) { + t.Errorf("unexpected value via reflect for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.mat) { + t.Errorf("unexpected value via mat.Equal for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.dense) { + t.Errorf("unexpected value via mat.Equal(band, dense) for test %d:\ngot:\n% v\nwant:\n% v", i, Formatted(band), Formatted(test.dense)) + } + } +} + +func TestBandAtSet(t *testing.T) { + // 2 3 4 0 0 0 + // 5 6 7 8 0 0 + // 0 9 10 11 12 0 + // 0 0 13 14 15 16 + // 0 0 0 17 18 19 + // 0 0 0 0 21 22 + band := NewBandDense(6, 6, 1, 2, []float64{ + -1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, -1, + 21, 22, -1, -1, + }) + + rows, cols := band.Dims() + kl, ku := band.Bandwidth() + + // Explicitly test all indexes. + want := bandImplicit{rows, cols, kl, ku, func(i, j int) float64 { + return float64(i*(kl+ku) + j + kl + 1) + }} + for i := 0; i < 6; i++ { + for j := 0; j < 6; j++ { + if band.At(i, j) != want.At(i, j) { + t.Errorf("unexpected value for band.At(%d, %d): got:%v want:%v", i, j, band.At(i, j), want.At(i, j)) + } + } + } + // Do that same thing via a call to Equal. + if !Equal(band, want) { + t.Errorf("unexpected value via mat.Equal:\ngot:\n% v\nwant:\n% v", Formatted(band), Formatted(want)) + } + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { band.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { band.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { band.SetBand(row, 0, 1.2) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { band.SetBand(0, col, 1.2) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + }{ + {row: 0, col: 3}, + {row: 0, col: 4}, + {row: 0, col: 5}, + {row: 1, col: 4}, + {row: 1, col: 5}, + {row: 2, col: 5}, + {row: 2, col: 0}, + {row: 3, col: 1}, + {row: 4, col: 2}, + {row: 5, col: 3}, + } { + panicked, message := panics(func() { band.SetBand(st.row, st.col, 1.2) }) + if !panicked || message != ErrBandSet.Error() { + t.Errorf("expected panic for %+v %s", st, message) + } + } + + for _, st := range []struct { + row, col int + orig, new float64 + }{ + {row: 1, col: 2, orig: 7, new: 15}, + {row: 2, col: 3, orig: 11, new: 15}, + } { + if e := band.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + band.SetBand(st.row, st.col, st.new) + if e := band.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetBand(%[1]d, %d, %v): got: %v want: %[3]v", st.row, st.col, st.new, e) + } + } +} + +// bandImplicit is an implicit band matrix returning val(i, j) +// for the value at (i, j). +type bandImplicit struct { + r, c, kl, ku int + val func(i, j int) float64 +} + +func (b bandImplicit) Dims() (r, c int) { + return b.r, b.c +} + +func (b bandImplicit) T() Matrix { + return Transpose{b} +} + +func (b bandImplicit) At(i, j int) float64 { + if i < 0 || b.r <= i { + panic("row") + } + if j < 0 || b.c <= j { + panic("col") + } + if j < i-b.kl || i+b.ku < j { + return 0 + } + return b.val(i, j) +} diff --git a/vendor/gonum.org/v1/gonum/mat/cblas_test.go b/vendor/gonum.org/v1/gonum/mat/cblas_test.go new file mode 100644 index 00000000..7371e8ba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cblas_test.go @@ -0,0 +1,16 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build cblas + +package mat + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/netlib/blas" +) + +func init() { + blas64.Use(blas.Implementation{}) +} diff --git a/vendor/gonum.org/v1/gonum/mat/cholesky.go b/vendor/gonum.org/v1/gonum/mat/cholesky.go new file mode 100644 index 00000000..fa4e91c6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cholesky.go @@ -0,0 +1,479 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" +) + +const ( + badTriangle = "mat: invalid triangle" + badCholesky = "mat: invalid Cholesky factorization" +) + +// Cholesky is a type for creating and using the Cholesky factorization of a +// symmetric positive definite matrix. +// +// Cholesky methods may only be called on a value that has been successfully +// initialized by a call to Factorize that has returned true. Calls to methods +// of an unsuccessful Cholesky factorization will panic. +type Cholesky struct { + // The chol pointer must never be retained as a pointer outside the Cholesky + // struct, either by returning chol outside the struct or by setting it to + // a pointer coming from outside. The same prohibition applies to the data + // slice within chol. + chol *TriDense + cond float64 +} + +// updateCond updates the condition number of the Cholesky decomposition. If +// norm > 0, then that norm is used as the norm of the original matrix A, otherwise +// the norm is estimated from the decomposition. +func (c *Cholesky) updateCond(norm float64) { + n := c.chol.mat.N + work := getFloats(3*n, false) + defer putFloats(work) + if norm < 0 { + // This is an approximation. By the definition of a norm, + // |AB| <= |A| |B|. + // Since A = U^T*U, we get for the condition number κ that + // κ(A) := |A| |A^-1| = |U^T*U| |A^-1| <= |U^T| |U| |A^-1|, + // so this will overestimate the condition number somewhat. + // The norm of the original factorized matrix cannot be stored + // because of update possibilities. + unorm := lapack64.Lantr(CondNorm, c.chol.mat, work) + lnorm := lapack64.Lantr(CondNormTrans, c.chol.mat, work) + norm = unorm * lnorm + } + sym := c.chol.asSymBlas() + iwork := getInts(n, false) + v := lapack64.Pocon(sym, norm, work, iwork) + putInts(iwork) + c.cond = 1 / v +} + +// Cond returns the condition number of the factorized matrix. +func (c *Cholesky) Cond() float64 { + return c.cond +} + +// Factorize calculates the Cholesky decomposition of the matrix A and returns +// whether the matrix is positive definite. If Factorize returns false, the +// factorization must not be used. +func (c *Cholesky) Factorize(a Symmetric) (ok bool) { + n := a.Symmetric() + if c.isZero() { + c.chol = NewTriDense(n, Upper, nil) + } else { + c.chol = NewTriDense(n, Upper, use(c.chol.mat.Data, n*n)) + } + copySymIntoTriangle(c.chol, a) + + sym := c.chol.asSymBlas() + work := getFloats(c.chol.mat.N, false) + norm := lapack64.Lansy(CondNorm, sym, work) + putFloats(work) + _, ok = lapack64.Potrf(sym) + if ok { + c.updateCond(norm) + } else { + c.Reset() + } + return ok +} + +// Reset resets the factorization so that it can be reused as the receiver of a +// dimensionally restricted operation. +func (c *Cholesky) Reset() { + if !c.isZero() { + c.chol.Reset() + } + c.cond = math.Inf(1) +} + +// SetFromU sets the Cholesky decomposition from the given triangular matrix. +// SetFromU panics if t is not upper triangular. Note that t is copied into, +// not stored inside, the receiver. +func (c *Cholesky) SetFromU(t *TriDense) { + n, kind := t.Triangle() + if kind != Upper { + panic("cholesky: matrix must be upper triangular") + } + if c.isZero() { + c.chol = NewTriDense(n, Upper, nil) + } else { + c.chol = NewTriDense(n, Upper, use(c.chol.mat.Data, n*n)) + } + c.chol.Copy(t) + c.updateCond(-1) +} + +// Clone makes a copy of the input Cholesky into the receiver, overwriting the +// previous value of the receiver. Clone does not place any restrictions on receiver +// shape. Clone panics if the input Cholesky is not the result of a valid decomposition. +func (c *Cholesky) Clone(chol *Cholesky) { + if !chol.valid() { + panic(badCholesky) + } + n := chol.Size() + if c.isZero() { + c.chol = NewTriDense(n, Upper, nil) + } else { + c.chol = NewTriDense(n, Upper, use(c.chol.mat.Data, n*n)) + } + c.chol.Copy(chol.chol) + c.cond = chol.cond +} + +// Size returns the dimension of the factorized matrix. +func (c *Cholesky) Size() int { + if !c.valid() { + panic(badCholesky) + } + return c.chol.mat.N +} + +// Det returns the determinant of the matrix that has been factorized. +func (c *Cholesky) Det() float64 { + if !c.valid() { + panic(badCholesky) + } + return math.Exp(c.LogDet()) +} + +// LogDet returns the log of the determinant of the matrix that has been factorized. +func (c *Cholesky) LogDet() float64 { + if !c.valid() { + panic(badCholesky) + } + var det float64 + for i := 0; i < c.chol.mat.N; i++ { + det += 2 * math.Log(c.chol.mat.Data[i*c.chol.mat.Stride+i]) + } + return det +} + +// Solve finds the matrix m that solves A * m = b where A is represented +// by the Cholesky decomposition, placing the result in m. +func (c *Cholesky) Solve(m *Dense, b Matrix) error { + if !c.valid() { + panic(badCholesky) + } + n := c.chol.mat.N + bm, bn := b.Dims() + if n != bm { + panic(ErrShape) + } + + m.reuseAs(bm, bn) + if b != m { + m.Copy(b) + } + blas64.Trsm(blas.Left, blas.Trans, 1, c.chol.mat, m.mat) + blas64.Trsm(blas.Left, blas.NoTrans, 1, c.chol.mat, m.mat) + if c.cond > ConditionTolerance { + return Condition(c.cond) + } + return nil +} + +// SolveChol finds the matrix m that solves A * m = B where A and B are represented +// by their Cholesky decompositions a and b, placing the result in the receiver. +func (a *Cholesky) SolveChol(m *Dense, b *Cholesky) error { + if !a.valid() || !b.valid() { + panic(badCholesky) + } + bn := b.chol.mat.N + if a.chol.mat.N != bn { + panic(ErrShape) + } + + m.reuseAsZeroed(bn, bn) + m.Copy(b.chol.T()) + blas64.Trsm(blas.Left, blas.Trans, 1, a.chol.mat, m.mat) + blas64.Trsm(blas.Left, blas.NoTrans, 1, a.chol.mat, m.mat) + blas64.Trmm(blas.Right, blas.NoTrans, 1, b.chol.mat, m.mat) + if a.cond > ConditionTolerance { + return Condition(a.cond) + } + return nil +} + +// SolveVec finds the vector v that solves A * v = b where A is represented +// by the Cholesky decomposition, placing the result in v. +func (c *Cholesky) SolveVec(v, b *VecDense) error { + if !c.valid() { + panic(badCholesky) + } + n := c.chol.mat.N + vn := b.Len() + if vn != n { + panic(ErrShape) + } + if v != b { + v.checkOverlap(b.mat) + } + v.reuseAs(n) + if v != b { + v.CopyVec(b) + } + blas64.Trsv(blas.Trans, c.chol.mat, v.mat) + blas64.Trsv(blas.NoTrans, c.chol.mat, v.mat) + if c.cond > ConditionTolerance { + return Condition(c.cond) + } + return nil + +} + +// UTo extracts the n×n upper triangular matrix U from a Cholesky +// decomposition into dst and returns the result. If dst is nil a new +// TriDense is allocated. +// A = U^T * U. +func (c *Cholesky) UTo(dst *TriDense) *TriDense { + if !c.valid() { + panic(badCholesky) + } + n := c.chol.mat.N + if dst == nil { + dst = NewTriDense(n, Upper, make([]float64, n*n)) + } else { + dst.reuseAs(n, Upper) + } + dst.Copy(c.chol) + return dst +} + +// LTo extracts the n×n lower triangular matrix L from a Cholesky +// decomposition into dst and returns the result. If dst is nil a new +// TriDense is allocated. +// A = L * L^T. +func (c *Cholesky) LTo(dst *TriDense) *TriDense { + if !c.valid() { + panic(badCholesky) + } + n := c.chol.mat.N + if dst == nil { + dst = NewTriDense(n, Lower, make([]float64, n*n)) + } else { + dst.reuseAs(n, Lower) + } + dst.Copy(c.chol.TTri()) + return dst +} + +// To reconstructs the original positive definite matrix given its +// Cholesky decomposition into dst and returns the result. If dst is nil +// a new SymDense is allocated. +func (c *Cholesky) To(dst *SymDense) *SymDense { + if !c.valid() { + panic(badCholesky) + } + n := c.chol.mat.N + if dst == nil { + dst = NewSymDense(n, make([]float64, n*n)) + } else { + dst.reuseAs(n) + } + dst.SymOuterK(1, c.chol.T()) + return dst +} + +// InverseTo computes the inverse of the matrix represented by its Cholesky +// factorization and stores the result into s. If the factorized +// matrix is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally be +// avoided where possible, for example by using the Solve routines. +func (c *Cholesky) InverseTo(s *SymDense) error { + if !c.valid() { + panic(badCholesky) + } + // TODO(btracey): Replace this code with a direct call to Dpotri when it + // is available. + s.reuseAs(c.chol.mat.N) + // If: + // chol(A) = U^T * U + // Then: + // chol(A^-1) = S * S^T + // where S = U^-1 + var t TriDense + err := t.InverseTri(c.chol) + s.SymOuterK(1, &t) + return err +} + +// SymRankOne performs a rank-1 update of the original matrix A and refactorizes +// its Cholesky factorization, storing the result into the receiver. That is, if +// in the original Cholesky factorization +// U^T * U = A, +// in the updated factorization +// U'^T * U' = A + alpha * x * x^T = A'. +// +// Note that when alpha is negative, the updating problem may be ill-conditioned +// and the results may be inaccurate, or the updated matrix A' may not be +// positive definite and not have a Cholesky factorization. SymRankOne returns +// whether the updated matrix A' is positive definite. +// +// SymRankOne updates a Cholesky factorization in O(n²) time. The Cholesky +// factorization computation from scratch is O(n³). +func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x *VecDense) (ok bool) { + if !orig.valid() { + panic(badCholesky) + } + n := orig.Size() + if x.Len() != n { + panic(ErrShape) + } + if orig != c { + if c.isZero() { + c.chol = NewTriDense(n, Upper, nil) + } else if c.chol.mat.N != n { + panic(ErrShape) + } + c.chol.Copy(orig.chol) + } + + if alpha == 0 { + return true + } + + // Algorithms for updating and downdating the Cholesky factorization are + // described, for example, in + // - J. J. Dongarra, J. R. Bunch, C. B. Moler, G. W. Stewart: LINPACK + // Users' Guide. SIAM (1979), pages 10.10--10.14 + // or + // - P. E. Gill, G. H. Golub, W. Murray, and M. A. Saunders: Methods for + // modifying matrix factorizations. Mathematics of Computation 28(126) + // (1974), Method C3 on page 521 + // + // The implementation is based on LINPACK code + // http://www.netlib.org/linpack/dchud.f + // http://www.netlib.org/linpack/dchdd.f + // and + // https://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=2646 + // + // According to http://icl.cs.utk.edu/lapack-forum/archives/lapack/msg00301.html + // LINPACK is released under BSD license. + // + // See also: + // - M. A. Saunders: Large-scale Linear Programming Using the Cholesky + // Factorization. Technical Report Stanford University (1972) + // http://i.stanford.edu/pub/cstr/reports/cs/tr/72/252/CS-TR-72-252.pdf + // - Matthias Seeger: Low rank updates for the Cholesky decomposition. + // EPFL Technical Report 161468 (2004) + // http://infoscience.epfl.ch/record/161468 + + work := getFloats(n, false) + defer putFloats(work) + blas64.Copy(n, x.RawVector(), blas64.Vector{1, work}) + + if alpha > 0 { + // Compute rank-1 update. + if alpha != 1 { + blas64.Scal(n, math.Sqrt(alpha), blas64.Vector{1, work}) + } + umat := c.chol.mat + stride := umat.Stride + for i := 0; i < n; i++ { + // Compute parameters of the Givens matrix that zeroes + // the i-th element of x. + c, s, r, _ := blas64.Rotg(umat.Data[i*stride+i], work[i]) + if r < 0 { + // Multiply by -1 to have positive diagonal + // elemnts. + r *= -1 + c *= -1 + s *= -1 + } + umat.Data[i*stride+i] = r + if i < n-1 { + // Multiply the extended factorization matrix by + // the Givens matrix from the left. Only + // the i-th row and x are modified. + blas64.Rot(n-i-1, + blas64.Vector{1, umat.Data[i*stride+i+1 : i*stride+n]}, + blas64.Vector{1, work[i+1 : n]}, + c, s) + } + } + c.updateCond(-1) + return true + } + + // Compute rank-1 downdate. + alpha = math.Sqrt(-alpha) + if alpha != 1 { + blas64.Scal(n, alpha, blas64.Vector{1, work}) + } + // Solve U^T * p = x storing the result into work. + ok = lapack64.Trtrs(blas.Trans, c.chol.RawTriangular(), blas64.General{ + Rows: n, + Cols: 1, + Stride: 1, + Data: work, + }) + if !ok { + // The original matrix is singular. Should not happen, because + // the factorization is valid. + panic(badCholesky) + } + norm := blas64.Nrm2(n, blas64.Vector{1, work}) + if norm >= 1 { + // The updated matrix is not positive definite. + return false + } + norm = math.Sqrt((1 + norm) * (1 - norm)) + cos := getFloats(n, false) + defer putFloats(cos) + sin := getFloats(n, false) + defer putFloats(sin) + for i := n - 1; i >= 0; i-- { + // Compute parameters of Givens matrices that zero elements of p + // backwards. + cos[i], sin[i], norm, _ = blas64.Rotg(norm, work[i]) + if norm < 0 { + norm *= -1 + cos[i] *= -1 + sin[i] *= -1 + } + } + umat := c.chol.mat + stride := umat.Stride + for i := n - 1; i >= 0; i-- { + // Apply Givens matrices to U. + // TODO(vladimir-ch): Use workspace to avoid modifying the + // receiver in case an invalid factorization is created. + blas64.Rot(n-i, blas64.Vector{1, work[i:n]}, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]}, cos[i], sin[i]) + if umat.Data[i*stride+i] == 0 { + // The matrix is singular (may rarely happen due to + // floating-point effects?). + ok = false + } else if umat.Data[i*stride+i] < 0 { + // Diagonal elements should be positive. If it happens + // that on the i-th row the diagonal is negative, + // multiply U from the left by an identity matrix that + // has -1 on the i-th row. + blas64.Scal(n-i, -1, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]}) + } + } + if ok { + c.updateCond(-1) + } else { + c.Reset() + } + return ok +} + +func (c *Cholesky) isZero() bool { + return c.chol == nil +} + +func (c *Cholesky) valid() bool { + return !c.isZero() && !c.chol.IsZero() +} diff --git a/vendor/gonum.org/v1/gonum/mat/cholesky_example_test.go b/vendor/gonum.org/v1/gonum/mat/cholesky_example_test.go new file mode 100644 index 00000000..8f75d79b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cholesky_example_test.go @@ -0,0 +1,121 @@ +// Copyright ©2015 The gonum 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 mat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/mat" +) + +func ExampleCholesky() { + // Construct a symmetric positive definite matrix. + tmp := mat.NewDense(4, 4, []float64{ + 2, 6, 8, -4, + 1, 8, 7, -2, + 2, 2, 1, 7, + 8, -2, -2, 1, + }) + var a mat.SymDense + a.SymOuterK(1, tmp) + + fmt.Printf("a = %0.4v\n", mat.Formatted(&a, mat.Prefix(" "))) + + // Compute the cholesky factorization. + var chol mat.Cholesky + if ok := chol.Factorize(&a); !ok { + fmt.Println("a matrix is not positive semi-definite.") + } + + // Find the determinant. + fmt.Printf("\nThe determinant of a is %0.4g\n\n", chol.Det()) + + // Use the factorization to solve the system of equations a * x = b. + b := mat.NewVecDense(4, []float64{1, 2, 3, 4}) + var x mat.VecDense + if err := chol.SolveVec(&x, b); err != nil { + fmt.Println("Matrix is near singular: ", err) + } + fmt.Println("Solve a * x = b") + fmt.Printf("x = %0.4v\n", mat.Formatted(&x, mat.Prefix(" "))) + + // Extract the factorization and check that it equals the original matrix. + t := chol.LTo(nil) + var test mat.Dense + test.Mul(t, t.T()) + fmt.Println() + fmt.Printf("L * L^T = %0.4v\n", mat.Formatted(&a, mat.Prefix(" "))) + + // Output: + // a = ⎡120 114 -4 -16⎤ + // ⎢114 118 11 -24⎥ + // ⎢ -4 11 58 17⎥ + // ⎣-16 -24 17 73⎦ + // + // The determinant of a is 1.543e+06 + // + // Solve a * x = b + // x = ⎡ -0.239⎤ + // ⎢ 0.2732⎥ + // ⎢-0.04681⎥ + // ⎣ 0.1031⎦ + // + // L * L^T = ⎡120 114 -4 -16⎤ + // ⎢114 118 11 -24⎥ + // ⎢ -4 11 58 17⎥ + // ⎣-16 -24 17 73⎦ +} + +func ExampleCholesky_SymRankOne() { + a := mat.NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }) + fmt.Printf("A = %0.4v\n", mat.Formatted(a, mat.Prefix(" "))) + + // Compute the Cholesky factorization. + var chol mat.Cholesky + if ok := chol.Factorize(a); !ok { + fmt.Println("matrix a is not positive definite.") + } + + x := mat.NewVecDense(4, []float64{0, 0, 0, 1}) + fmt.Printf("\nx = %0.4v\n", mat.Formatted(x, mat.Prefix(" "))) + + // Rank-1 update the factorization. + chol.SymRankOne(&chol, 1, x) + // Rank-1 update the matrix a. + a.SymRankOne(a, 1, x) + + au := chol.To(nil) + + // Print the matrix that was updated directly. + fmt.Printf("\nA' = %0.4v\n", mat.Formatted(a, mat.Prefix(" "))) + // Print the matrix recovered from the factorization. + fmt.Printf("\nU'^T * U' = %0.4v\n", mat.Formatted(au, mat.Prefix(" "))) + + // Output: + // A = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 20⎦ + // + // x = ⎡0⎤ + // ⎢0⎥ + // ⎢0⎥ + // ⎣1⎦ + // + // A' = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 21⎦ + // + // U'^T * U' = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 21⎦ +} diff --git a/vendor/gonum.org/v1/gonum/mat/cholesky_test.go b/vendor/gonum.org/v1/gonum/mat/cholesky_test.go new file mode 100644 index 00000000..6a5c853d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cholesky_test.go @@ -0,0 +1,453 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestCholesky(t *testing.T) { + for _, test := range []struct { + a *SymDense + + cond float64 + want *TriDense + posdef bool + }{ + { + a: NewSymDense(3, []float64{ + 4, 1, 1, + 0, 2, 3, + 0, 0, 6, + }), + cond: 37, + want: NewTriDense(3, true, []float64{ + 2, 0.5, 0.5, + 0, 1.3228756555322954, 2.0788046015507495, + 0, 0, 1.195228609334394, + }), + posdef: true, + }, + } { + _, n := test.a.Dims() + for _, chol := range []*Cholesky{ + {}, + {chol: NewTriDense(n-1, true, nil)}, + {chol: NewTriDense(n, true, nil)}, + {chol: NewTriDense(n+1, true, nil)}, + } { + ok := chol.Factorize(test.a) + if ok != test.posdef { + t.Errorf("unexpected return from Cholesky factorization: got: ok=%t want: ok=%t", ok, test.posdef) + } + fc := DenseCopyOf(chol.chol) + if !Equal(fc, test.want) { + t.Error("incorrect Cholesky factorization") + } + if math.Abs(test.cond-chol.cond) > 1e-13 { + t.Errorf("Condition number mismatch: Want %v, got %v", test.cond, chol.cond) + } + U := chol.UTo(nil) + aCopy := DenseCopyOf(test.a) + var a Dense + a.Mul(U.TTri(), U) + if !EqualApprox(&a, aCopy, 1e-14) { + t.Error("unexpected Cholesky factor product") + } + + L := chol.LTo(nil) + a.Mul(L, L.TTri()) + if !EqualApprox(&a, aCopy, 1e-14) { + t.Error("unexpected Cholesky factor product") + } + } + } +} + +func TestCholeskySolve(t *testing.T) { + for _, test := range []struct { + a *SymDense + b *Dense + ans *Dense + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewDense(2, 1, []float64{5, 6}), + ans: NewDense(2, 1, []float64{5, 6}), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 37, 71, 101, + }), + b: NewDense(3, 1, []float64{5, 6, 7}), + ans: NewDense(3, 1, []float64{0.20745069393718094, -0.17421475529583694, 0.11577794010226464}), + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + + var x Dense + chol.Solve(&x, test.b) + if !EqualApprox(&x, test.ans, 1e-12) { + t.Error("incorrect Cholesky solve solution") + } + + var ans Dense + ans.Mul(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + t.Error("incorrect Cholesky solve solution product") + } + } +} + +func TestCholeskySolveChol(t *testing.T) { + for _, test := range []struct { + a, b *SymDense + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + }, + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewSymDense(2, []float64{ + 2, 0, + 0, 2, + }), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 59, 83, 71, + 37, 71, 101, + }), + b: NewSymDense(3, []float64{ + 2, -1, 0, + -1, 2, -1, + 0, -1, 2, + }), + }, + } { + var chola, cholb Cholesky + ok := chola.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure for a: not positive definite") + } + ok = cholb.Factorize(test.b) + if !ok { + t.Fatal("unexpected Cholesky factorization failure for b: not positive definite") + } + + var x Dense + chola.SolveChol(&x, &cholb) + + var ans Dense + ans.Mul(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + var y Dense + y.Solve(test.a, test.b) + t.Errorf("incorrect Cholesky solve solution product\ngot solution:\n%.4v\nwant solution\n%.4v", + Formatted(&x), Formatted(&y)) + } + } +} + +func TestCholeskySolveVec(t *testing.T) { + for _, test := range []struct { + a *SymDense + b *VecDense + ans *VecDense + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewVecDense(2, []float64{5, 6}), + ans: NewVecDense(2, []float64{5, 6}), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + b: NewVecDense(3, []float64{5, 6, 7}), + ans: NewVecDense(3, []float64{0.20745069393718094, -0.17421475529583694, 0.11577794010226464}), + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + + var x VecDense + chol.SolveVec(&x, test.b) + if !EqualApprox(&x, test.ans, 1e-12) { + t.Error("incorrect Cholesky solve solution") + } + + var ans VecDense + ans.MulVec(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + t.Error("incorrect Cholesky solve solution product") + } + } +} + +func TestCholeskyTo(t *testing.T) { + for _, test := range []*SymDense{ + NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + } { + var chol Cholesky + ok := chol.Factorize(test) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + s := chol.To(nil) + + if !EqualApprox(s, test, 1e-12) { + t.Errorf("Cholesky reconstruction not equal to original matrix.\nWant:\n% v\nGot:\n% v\n", Formatted(test), Formatted(s)) + } + } +} + +func TestCloneCholesky(t *testing.T) { + for _, test := range []*SymDense{ + NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + } { + var chol Cholesky + ok := chol.Factorize(test) + if !ok { + panic("bad test") + } + var chol2 Cholesky + chol2.Clone(&chol) + + if chol.cond != chol2.cond { + t.Errorf("condition number mismatch from zero") + } + if !Equal(chol.chol, chol2.chol) { + t.Errorf("chol mismatch from zero") + } + + // Corrupt chol2 and try again + chol2.cond = math.NaN() + chol2.chol = NewTriDense(2, Upper, nil) + chol2.Clone(&chol) + if chol.cond != chol2.cond { + t.Errorf("condition number mismatch from non-zero") + } + if !Equal(chol.chol, chol2.chol) { + t.Errorf("chol mismatch from non-zero") + } + } +} + +func TestCholeskyInverseTo(t *testing.T) { + for _, n := range []int{1, 3, 5, 9} { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + var s SymDense + s.SymOuterK(1, NewDense(n, n, data)) + + var chol Cholesky + ok := chol.Factorize(&s) + if !ok { + t.Errorf("Bad test, cholesky decomposition failed") + } + + var sInv SymDense + chol.InverseTo(&sInv) + + var ans Dense + ans.Mul(&sInv, &s) + if !equalApprox(eye(n), &ans, 1e-8, false) { + var diff Dense + diff.Sub(eye(n), &ans) + t.Errorf("SymDense times Cholesky inverse not identity. Norm diff = %v", Norm(&diff, 2)) + } + } +} + +func TestCholeskySymRankOne(t *testing.T) { + rand.Seed(1) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 20, 50, 100} { + for k := 0; k < 10; k++ { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + + var a SymDense + a.SymOuterK(1, NewDense(n, n, data)) + + xdata := make([]float64, n) + for i := range xdata { + xdata[i] = rand.NormFloat64() + } + x := NewVecDense(n, xdata) + + var chol Cholesky + ok := chol.Factorize(&a) + if !ok { + t.Errorf("Bad random test, Cholesky factorization failed") + continue + } + + alpha := rand.Float64() + ok = chol.SymRankOne(&chol, alpha, x) + if !ok { + t.Errorf("n=%v, alpha=%v: unexpected failure", n, alpha) + continue + } + a.SymRankOne(&a, alpha, x) + + var achol SymDense + chol.To(&achol) + if !EqualApprox(&achol, &a, 1e-13) { + t.Errorf("n=%v, alpha=%v: mismatch between updated matrix and from Cholesky:\nupdated:\n%v\nfrom Cholesky:\n%v", + n, alpha, Formatted(&a), Formatted(&achol)) + } + } + } + + for i, test := range []struct { + a *SymDense + alpha float64 + x []float64 + + wantOk bool + }{ + { + // Update (to positive definite matrix). + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: 1, + x: []float64{0, 0, 0, 1}, + wantOk: true, + }, + { + // Downdate to singular matrix. + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: -1, + x: []float64{0, 0, 0, 1}, + wantOk: false, + }, + { + // Downdate to positive definite matrix. + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: -1 / 2, + x: []float64{0, 0, 0, 1}, + wantOk: true, + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Errorf("Case %v: bad test, Cholesky factorization failed", i) + continue + } + + x := NewVecDense(len(test.x), test.x) + ok = chol.SymRankOne(&chol, test.alpha, x) + if !ok { + if test.wantOk { + t.Errorf("Case %v: unexpected failure from SymRankOne", i) + } + continue + } + if ok && !test.wantOk { + t.Errorf("Case %v: expected a failure from SymRankOne", i) + } + + a := test.a + a.SymRankOne(a, test.alpha, x) + + var achol SymDense + chol.To(&achol) + if !EqualApprox(&achol, a, 1e-13) { + t.Errorf("Case %v: mismatch between updated matrix and from Cholesky:\nupdated:\n%v\nfrom Cholesky:\n%v", + i, Formatted(a), Formatted(&achol)) + } + } +} + +func BenchmarkCholeskySmall(b *testing.B) { + benchmarkCholesky(b, 2) +} + +func BenchmarkCholeskyMedium(b *testing.B) { + benchmarkCholesky(b, testblas.MediumMat) +} + +func BenchmarkCholeskyLarge(b *testing.B) { + benchmarkCholesky(b, testblas.LargeMat) +} + +func benchmarkCholesky(b *testing.B, n int) { + base := make([]float64, n*n) + for i := range base { + base[i] = rand.Float64() + } + bm := NewDense(n, n, base) + bm.Mul(bm.T(), bm) + am := NewSymDense(n, bm.mat.Data) + + var chol Cholesky + b.ResetTimer() + for i := 0; i < b.N; i++ { + ok := chol.Factorize(am) + if !ok { + panic("not pos def") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/cmatrix.go b/vendor/gonum.org/v1/gonum/mat/cmatrix.go new file mode 100644 index 00000000..a2894237 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cmatrix.go @@ -0,0 +1,71 @@ +// Copyright ©2013 The gonum 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 mat + +// CMatrix is the basic matrix interface type for complex matrices. +type CMatrix interface { + // Dims returns the dimensions of a Matrix. + Dims() (r, c int) + + // At returns the value of a matrix element at row i, column j. + // It will panic if i or j are out of bounds for the matrix. + At(i, j int) complex128 + + // H returns the conjugate transpose of the Matrix. Whether H + // returns a copy of the underlying data is implementation dependent. + // This method may be implemented using the Conjugate type, which + // provides an implicit matrix conjugate transpose. + H() CMatrix +} + +var ( + _ CMatrix = Conjugate{} + _ Unconjugator = Conjugate{} +) + +// Conjugate is a type for performing an implicit matrix conjugate transpose. +// It implements the Matrix interface, returning values from the conjugate +// transpose of the matrix within. +type Conjugate struct { + CMatrix CMatrix +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Matrix field. +func (t Conjugate) At(i, j int) complex128 { + z := t.CMatrix.At(j, i) + return complex(real(z), -imag(z)) +} + +// Dims returns the dimensions of the transposed matrix. The number of rows returned +// is the number of columns in the Matrix field, and the number of columns is +// the number of rows in the Matrix field. +func (t Conjugate) Dims() (r, c int) { + c, r = t.CMatrix.Dims() + return r, c +} + +// H performs an implicit conjugate transpose by returning the Matrix field. +func (t Conjugate) H() CMatrix { + return t.CMatrix +} + +// Unconjugate returns the Matrix field. +func (t Conjugate) Unconjugate() CMatrix { + return t.CMatrix +} + +// Unconjugator is a type that can undo an implicit conjugate transpose. +type Unconjugator interface { + // Note: This interface is needed to unify all of the Conjugate types. In + // the cmat128 methods, we need to test if the Matrix has been implicitly + // transposed. If this is checked by testing for the specific Conjugate type + // then the behavior will be different if the user uses H() or HTri() for a + // triangular matrix. + + // Unconjugate returns the underlying Matrix stored for the implicit + // conjugate transpose. + Unconjugate() CMatrix +} diff --git a/vendor/gonum.org/v1/gonum/mat/consts.go b/vendor/gonum.org/v1/gonum/mat/consts.go new file mode 100644 index 00000000..a7025fff --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/consts.go @@ -0,0 +1,54 @@ +// Copyright ©2016 The gonum 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 mat + +// TriKind represents the triangularity of the matrix. +type TriKind bool + +const ( + // Upper specifies an upper triangular matrix. + Upper TriKind = true + // Lower specifies a lower triangular matrix. + Lower TriKind = false +) + +// SVDKind specifies the treatment of singular vectors during an SVD +// factorization. +type SVDKind int + +const ( + // SVDNone specifies that no singular vectors should be computed during + // the decomposition. + SVDNone SVDKind = iota + 1 + // SVDThin computes the thin singular vectors, that is, it computes + // A = U~ * Σ * V~^T + // where U~ is of size m×min(m,n), Σ is a diagonal matrix of size min(m,n)×min(m,n) + // and V~ is of size n×min(m,n). + SVDThin + // SVDFull computes the full singular value decomposition, + // A = U * Σ * V^T + // where U is of size m×m, Σ is an m×n diagonal matrix, and V is an n×n matrix. + SVDFull +) + +// GSVDKind specifies the treatment of singular vectors during a GSVD +// factorization. +type GSVDKind int + +const ( + // GSVDU specifies that the U singular vectors should be computed during + // the decomposition. + GSVDU GSVDKind = 1 << iota + // GSVDV specifies that the V singular vectors should be computed during + // the decomposition. + GSVDV + // GSVDQ specifies that the Q singular vectors should be computed during + // the decomposition. + GSVDQ + + // GSVDNone specifies that no singular vector should be computed during + // the decomposition. + GSVDNone +) diff --git a/vendor/gonum.org/v1/gonum/mat/dense.go b/vendor/gonum.org/v1/gonum/mat/dense.go new file mode 100644 index 00000000..1fab99c2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/dense.go @@ -0,0 +1,534 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + dense *Dense + + _ Matrix = dense + _ Mutable = dense + + _ Cloner = dense + _ RowViewer = dense + _ ColViewer = dense + _ RawRowViewer = dense + _ Grower = dense + + _ RawMatrixSetter = dense + _ RawMatrixer = dense + + _ Reseter = dense +) + +// Dense is a dense matrix representation. +type Dense struct { + mat blas64.General + + capRows, capCols int +} + +// NewDense creates a new Dense matrix with r rows and c columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == r*c, data is +// used as the backing slice, and changes to the elements of the returned Dense +// will be reflected in data. If neither of these is true, NewDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +func NewDense(r, c int, data []float64) *Dense { + if data != nil && r*c != len(data) { + panic(ErrShape) + } + if data == nil { + data = make([]float64, r*c) + } + return &Dense{ + mat: blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: data, + }, + capRows: r, + capCols: c, + } +} + +// reuseAs resizes an empty matrix to a r×c matrix, +// or checks that a non-empty matrix is r×c. +// +// reuseAs must be kept in sync with reuseAsZeroed. +func (m *Dense) reuseAs(r, c int) { + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat.Error. + panic("mat: caps not correctly set") + } + if m.IsZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: use(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(ErrShape) + } +} + +// reuseAsZeroed resizes an empty matrix to a r×c matrix, +// or checks that a non-empty matrix is r×c. It zeroes +// all the elements of the matrix. +// +// reuseAsZeroed must be kept in sync with reuseAs. +func (m *Dense) reuseAsZeroed(r, c int) { + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat.Error. + panic("mat: caps not correctly set") + } + if m.IsZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useZeroed(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(ErrShape) + } + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } +} + +// untranspose untransposes a matrix if applicable. If a is an Untransposer, then +// untranspose returns the underlying matrix and true. If it is not, then it returns +// the input matrix and false. +func untranspose(a Matrix) (Matrix, bool) { + if ut, ok := a.(Untransposer); ok { + return ut.Untranspose(), true + } + return a, false +} + +// isolatedWorkspace returns a new dense matrix w with the size of a and +// returns a callback to defer which performs cleanup at the return of the call. +// This should be used when a method receiver is the same pointer as an input argument. +func (m *Dense) isolatedWorkspace(a Matrix) (w *Dense, restore func()) { + r, c := a.Dims() + w = getWorkspace(r, c, false) + return w, func() { + m.Copy(w) + putWorkspace(w) + } +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (m *Dense) Reset() { + // Row, Cols and Stride must be zeroed in unison. + m.mat.Rows, m.mat.Cols, m.mat.Stride = 0, 0, 0 + m.capRows, m.capCols = 0, 0 + m.mat.Data = m.mat.Data[:0] +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the +// receiver for size-restricted operations. Dense matrices can be zeroed using Reset. +func (m *Dense) IsZero() bool { + // It must be the case that m.Dims() returns + // zeros in this case. See comment in Reset(). + return m.mat.Stride == 0 +} + +// asTriDense returns a TriDense with the given size and side. The backing data +// of the TriDense is the same as the receiver. +func (m *Dense) asTriDense(n int, diag blas.Diag, uplo blas.Uplo) *TriDense { + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: m.mat.Stride, + Data: m.mat.Data, + Uplo: uplo, + Diag: diag, + }, + cap: n, + } +} + +// DenseCopyOf returns a newly allocated copy of the elements of a. +func DenseCopyOf(a Matrix) *Dense { + d := &Dense{} + d.Clone(a) + return d +} + +// SetRawMatrix sets the underlying blas64.General used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in b. +func (m *Dense) SetRawMatrix(b blas64.General) { + m.capRows, m.capCols = b.Rows, b.Cols + m.mat = b +} + +// RawMatrix returns the underlying blas64.General used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.General. +func (m *Dense) RawMatrix() blas64.General { return m.mat } + +// Dims returns the number of rows and columns in the matrix. +func (m *Dense) Dims() (r, c int) { return m.mat.Rows, m.mat.Cols } + +// Caps returns the number of rows and columns in the backing matrix. +func (m *Dense) Caps() (r, c int) { return m.capRows, m.capCols } + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (m *Dense) T() Matrix { + return Transpose{m} +} + +// ColView returns a VecDense reflecting the column j, backed by the matrix data. +// +// See ColViewer for more information. +func (m *Dense) ColView(j int) *VecDense { + if j >= m.mat.Cols || j < 0 { + panic(ErrColAccess) + } + return &VecDense{ + mat: blas64.Vector{ + Inc: m.mat.Stride, + Data: m.mat.Data[j : (m.mat.Rows-1)*m.mat.Stride+j+1], + }, + n: m.mat.Rows, + } +} + +// SetCol sets the values in the specified column of the matrix to the values +// in src. len(src) must equal the number of rows in the receiver. +func (m *Dense) SetCol(j int, src []float64) { + if j >= m.mat.Cols || j < 0 { + panic(ErrColAccess) + } + if len(src) != m.mat.Rows { + panic(ErrColLength) + } + + blas64.Copy(m.mat.Rows, + blas64.Vector{Inc: 1, Data: src}, + blas64.Vector{Inc: m.mat.Stride, Data: m.mat.Data[j:]}, + ) +} + +// SetRow sets the values in the specified rows of the matrix to the values +// in src. len(src) must equal the number of columns in the receiver. +func (m *Dense) SetRow(i int, src []float64) { + if i >= m.mat.Rows || i < 0 { + panic(ErrRowAccess) + } + if len(src) != m.mat.Cols { + panic(ErrRowLength) + } + + copy(m.rawRowView(i), src) +} + +// RowView returns row i of the matrix data represented as a column vector, +// backed by the matrix data. +// +// See RowViewer for more information. +func (m *Dense) RowView(i int) *VecDense { + if i >= m.mat.Rows || i < 0 { + panic(ErrRowAccess) + } + return &VecDense{ + mat: blas64.Vector{ + Inc: 1, + Data: m.rawRowView(i), + }, + n: m.mat.Cols, + } +} + +// RawRowView returns a slice backed by the same array as backing the +// receiver. +func (m *Dense) RawRowView(i int) []float64 { + if i >= m.mat.Rows || i < 0 { + panic(ErrRowAccess) + } + return m.rawRowView(i) +} + +func (m *Dense) rawRowView(i int) []float64 { + return m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+m.mat.Cols] +} + +// Slice returns a new Matrix that shares backing data with the receiver. +// The returned matrix starts at {i,j} of the receiver and extends k-i rows +// and l-j columns. The final row in the resulting matrix is k-1 and the +// final column is l-1. +// Slice panics with ErrIndexOutOfRange if the slice is outside the capacity +// of the receiver. +func (m *Dense) Slice(i, k, j, l int) Matrix { + mr, mc := m.Caps() + if i < 0 || mr <= i || j < 0 || mc <= j || k <= i || mr < k || l <= j || mc < l { + panic(ErrIndexOutOfRange) + } + t := *m + t.mat.Data = t.mat.Data[i*t.mat.Stride+j : (k-1)*t.mat.Stride+l] + t.mat.Rows = k - i + t.mat.Cols = l - j + t.capRows -= i + t.capCols -= j + return &t +} + +// Grow returns the receiver expanded by r rows and c columns. If the dimensions +// of the expanded matrix are outside the capacities of the receiver a new +// allocation is made, otherwise not. Note the receiver itself is not modified +// during the call to Grow. +func (m *Dense) Grow(r, c int) Matrix { + if r < 0 || c < 0 { + panic(ErrIndexOutOfRange) + } + if r == 0 && c == 0 { + return m + } + + r += m.mat.Rows + c += m.mat.Cols + + var t Dense + switch { + case m.mat.Rows == 0 || m.mat.Cols == 0: + t.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + // We zero because we don't know how the matrix will be used. + // In other places, the mat is immediately filled with a result; + // this is not the case here. + Data: useZeroed(m.mat.Data, r*c), + } + case r > m.capRows || c > m.capCols: + cr := max(r, m.capRows) + cc := max(c, m.capCols) + t.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: cc, + Data: make([]float64, cr*cc), + } + t.capRows = cr + t.capCols = cc + // Copy the complete matrix over to the new matrix. + // Including elements not currently visible. Use a temporary structure + // to avoid modifying the receiver. + var tmp Dense + tmp.mat = blas64.General{ + Rows: m.mat.Rows, + Cols: m.mat.Cols, + Stride: m.mat.Stride, + Data: m.mat.Data, + } + tmp.capRows = m.capRows + tmp.capCols = m.capCols + t.Copy(&tmp) + return &t + default: + t.mat = blas64.General{ + Data: m.mat.Data[:(r-1)*m.mat.Stride+c], + Rows: r, + Cols: c, + Stride: m.mat.Stride, + } + } + t.capRows = r + t.capCols = c + return &t +} + +// Clone makes a copy of a into the receiver, overwriting the previous value of +// the receiver. The clone operation does not make any restriction on shape and +// will not cause shadowing. +// +// See the Cloner interface for more information. +func (m *Dense) Clone(a Matrix) { + r, c := a.Dims() + mat := blas64.General{ + Rows: r, + Cols: c, + Stride: c, + } + m.capRows, m.capCols = r, c + + aU, trans := untranspose(a) + switch aU := aU.(type) { + case RawMatrixer: + amat := aU.RawMatrix() + mat.Data = make([]float64, r*c) + if trans { + for i := 0; i < r; i++ { + blas64.Copy(c, + blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) + } + } else { + for i := 0; i < r; i++ { + copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + } + case *VecDense: + amat := aU.mat + mat.Data = make([]float64, aU.n) + blas64.Copy(aU.n, + blas64.Vector{Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: 1, Data: mat.Data}) + default: + mat.Data = make([]float64, r*c) + w := *m + w.mat = mat + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + w.set(i, j, a.At(i, j)) + } + } + *m = w + return + } + m.mat = mat +} + +// Copy makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two matrices and +// returns the number of rows and columns it copied. If a aliases the receiver +// and is a transposed Dense or VecDense, with a non-unitary increment, Copy will +// panic. +// +// See the Copier interface for more information. +func (m *Dense) Copy(a Matrix) (r, c int) { + r, c = a.Dims() + if a == m { + return r, c + } + r = min(r, m.mat.Rows) + c = min(c, m.mat.Cols) + if r == 0 || c == 0 { + return 0, 0 + } + + aU, trans := untranspose(a) + switch aU := aU.(type) { + case RawMatrixer: + amat := aU.RawMatrix() + if trans { + if amat.Stride != 1 { + m.checkOverlap(amat) + } + for i := 0; i < r; i++ { + blas64.Copy(c, + blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{Inc: 1, Data: m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]}) + } + } else { + switch o := offset(m.mat.Data, amat.Data); { + case o < 0: + for i := r - 1; i >= 0; i-- { + copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + case o > 0: + for i := 0; i < r; i++ { + copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + default: + // Nothing to do. + } + } + case *VecDense: + var n, stride int + amat := aU.mat + if trans { + if amat.Inc != 1 { + m.checkOverlap(aU.asGeneral()) + } + n = c + stride = 1 + } else { + n = r + stride = m.mat.Stride + } + if amat.Inc == 1 && stride == 1 { + copy(m.mat.Data, amat.Data[:n]) + break + } + switch o := offset(m.mat.Data, amat.Data); { + case o < 0: + blas64.Copy(n, + blas64.Vector{Inc: -amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: -stride, Data: m.mat.Data}) + case o > 0: + blas64.Copy(n, + blas64.Vector{Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: stride, Data: m.mat.Data}) + default: + // Nothing to do. + } + default: + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m.set(i, j, a.At(i, j)) + } + } + } + + return r, c +} + +// Stack appends the rows of b onto the rows of a, placing the result into the +// receiver with b placed in the greater indexed rows. Stack will panic if the +// two input matrices do not have the same number of columns or the constructed +// stacked matrix is not the same shape as the receiver. +func (m *Dense) Stack(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ac != bc || m == a || m == b { + panic(ErrShape) + } + + m.reuseAs(ar+br, ac) + + m.Copy(a) + w := m.Slice(ar, ar+br, 0, bc).(*Dense) + w.Copy(b) +} + +// Augment creates the augmented matrix of a and b, where b is placed in the +// greater indexed columns. Augment will panic if the two input matrices do +// not have the same number of rows or the constructed augmented matrix is +// not the same shape as the receiver. +func (m *Dense) Augment(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || m == a || m == b { + panic(ErrShape) + } + + m.reuseAs(ar, ac+bc) + + m.Copy(a) + w := m.Slice(0, br, ac, ac+bc).(*Dense) + w.Copy(b) +} diff --git a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go new file mode 100644 index 00000000..db18e735 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go @@ -0,0 +1,719 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// Add adds a and b element-wise, placing the result in the receiver. Add +// will panic if the two matrices do not have the same shape. +func (m *Dense) Add(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v + bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)+b.At(r, c)) + } + } +} + +// Sub subtracts the matrix b from a, placing the result in the receiver. Sub +// will panic if the two matrices do not have the same shape. +func (m *Dense) Sub(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v - bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)-b.At(r, c)) + } + } +} + +// MulElem performs element-wise multiplication of a and b, placing the result +// in the receiver. MulElem will panic if the two matrices do not have the same +// shape. +func (m *Dense) MulElem(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v * bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)*b.At(r, c)) + } + } +} + +// DivElem performs element-wise division of a by b, placing the result +// in the receiver. DivElem will panic if the two matrices do not have the same +// shape. +func (m *Dense) DivElem(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v / bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)/b.At(r, c)) + } + } +} + +// Inverse computes the inverse of the matrix a, storing the result into the +// receiver. If a is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally +// be avoided where possible, for example by using the Solve routines. +func (m *Dense) Inverse(a Matrix) error { + // TODO(btracey): Special case for RawTriangular, etc. + r, c := a.Dims() + if r != c { + panic(ErrSquare) + } + m.reuseAs(a.Dims()) + aU, aTrans := untranspose(a) + switch rm := aU.(type) { + case RawMatrixer: + if m != aU || aTrans { + if m == aU || m.checkOverlap(rm.RawMatrix()) { + tmp := getWorkspace(r, c, false) + tmp.Copy(a) + m.Copy(tmp) + putWorkspace(tmp) + break + } + m.Copy(a) + } + default: + m.Copy(a) + } + ipiv := getInts(r, false) + defer putInts(ipiv) + ok := lapack64.Getrf(m.mat, ipiv) + if !ok { + return Condition(math.Inf(1)) + } + work := getFloats(4*r, false) // must be at least 4*r for cond. + lapack64.Getri(m.mat, ipiv, work, -1) + if int(work[0]) > 4*r { + l := int(work[0]) + putFloats(work) + work = getFloats(l, false) + } else { + work = work[:4*r] + } + defer putFloats(work) + lapack64.Getri(m.mat, ipiv, work, len(work)) + norm := lapack64.Lange(CondNorm, m.mat, work) + rcond := lapack64.Gecon(CondNorm, m.mat, norm, work, ipiv) // reuse ipiv + if rcond == 0 { + return Condition(math.Inf(1)) + } + cond := 1 / rcond + if cond > ConditionTolerance { + return Condition(cond) + } + return nil +} + +// Mul takes the matrix product of a and b, placing the result in the receiver. +// If the number of columns in a does not equal the number of rows in b, Mul will panic. +func (m *Dense) Mul(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + + if ac != br { + panic(ErrShape) + } + + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + m.reuseAs(ar, bc) + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + aT := blas.NoTrans + if aTrans { + aT = blas.Trans + } + bT := blas.NoTrans + if bTrans { + bT = blas.Trans + } + + // Some of the cases do not have a transpose option, so create + // temporary memory. + // C = A^T * B = (B^T * A)^T + // C^T = B^T * A. + if aUrm, ok := aU.(RawMatrixer); ok { + amat := aUrm.RawMatrix() + if restore == nil { + m.checkOverlap(amat) + } + if bUrm, ok := bU.(RawMatrixer); ok { + bmat := bUrm.RawMatrix() + if restore == nil { + m.checkOverlap(bmat) + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + if bU, ok := bU.(RawSymmetricer); ok { + bmat := bU.RawSymmetric() + if aTrans { + c := getWorkspace(ac, ar, false) + blas64.Symm(blas.Left, 1, bmat, amat, 0, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + blas64.Symm(blas.Right, 1, bmat, amat, 0, m.mat) + return + } + if bU, ok := bU.(RawTriangular); ok { + // Trmm updates in place, so copy aU first. + bmat := bU.RawTriangular() + if aTrans { + c := getWorkspace(ac, ar, false) + var tmp Dense + tmp.SetRawMatrix(amat) + c.Copy(&tmp) + bT := blas.Trans + if bTrans { + bT = blas.NoTrans + } + blas64.Trmm(blas.Left, bT, 1, bmat, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + m.Copy(a) + blas64.Trmm(blas.Right, bT, 1, bmat, m.mat) + return + } + if bU, ok := bU.(*VecDense); ok { + m.checkOverlap(bU.asGeneral()) + bvec := bU.RawVector() + if bTrans { + // {ar,1} x {1,bc}, which is not a vector. + // Instead, construct B as a General. + bmat := blas64.General{ + Rows: bc, + Cols: 1, + Stride: bvec.Inc, + Data: bvec.Data, + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + cvec := blas64.Vector{ + Inc: m.mat.Stride, + Data: m.mat.Data, + } + blas64.Gemv(aT, 1, amat, bvec, 0, cvec) + return + } + } + if bUrm, ok := bU.(RawMatrixer); ok { + bmat := bUrm.RawMatrix() + if restore == nil { + m.checkOverlap(bmat) + } + if aU, ok := aU.(RawSymmetricer); ok { + amat := aU.RawSymmetric() + if bTrans { + c := getWorkspace(bc, br, false) + blas64.Symm(blas.Right, 1, amat, bmat, 0, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + blas64.Symm(blas.Left, 1, amat, bmat, 0, m.mat) + return + } + if aU, ok := aU.(RawTriangular); ok { + // Trmm updates in place, so copy bU first. + amat := aU.RawTriangular() + if bTrans { + c := getWorkspace(bc, br, false) + var tmp Dense + tmp.SetRawMatrix(bmat) + c.Copy(&tmp) + aT := blas.Trans + if aTrans { + aT = blas.NoTrans + } + blas64.Trmm(blas.Right, aT, 1, amat, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + m.Copy(b) + blas64.Trmm(blas.Left, aT, 1, amat, m.mat) + return + } + if aU, ok := aU.(*VecDense); ok { + m.checkOverlap(aU.asGeneral()) + avec := aU.RawVector() + if aTrans { + // {1,ac} x {ac, bc} + // Transpose B so that the vector is on the right. + cvec := blas64.Vector{ + Inc: 1, + Data: m.mat.Data, + } + bT := blas.Trans + if bTrans { + bT = blas.NoTrans + } + blas64.Gemv(bT, 1, bmat, avec, 0, cvec) + return + } + // {ar,1} x {1,bc} which is not a vector result. + // Instead, construct A as a General. + amat := blas64.General{ + Rows: ar, + Cols: 1, + Stride: avec.Inc, + Data: avec.Data, + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + } + + row := getFloats(ac, false) + defer putFloats(row) + for r := 0; r < ar; r++ { + for i := range row { + row[i] = a.At(r, i) + } + for c := 0; c < bc; c++ { + var v float64 + for i, e := range row { + v += e * b.At(i, c) + } + m.mat.Data[r*m.mat.Stride+c] = v + } + } +} + +// strictCopy copies a into m panicking if the shape of a and m differ. +func strictCopy(m *Dense, a Matrix) { + r, c := m.Copy(a) + if r != m.mat.Rows || c != m.mat.Cols { + // Panic with a string since this + // is not a user-facing panic. + panic(ErrShape.Error()) + } +} + +// Exp calculates the exponential of the matrix a, e^a, placing the result +// in the receiver. Exp will panic with matrix.ErrShape if a is not square. +// +// Exp uses the scaling and squaring method described in section 3 of +// http://www.cs.cornell.edu/cv/researchpdf/19ways+.pdf. +func (m *Dense) Exp(a Matrix) { + r, c := a.Dims() + if r != c { + panic(ErrShape) + } + + var w *Dense + if m.IsZero() { + m.reuseAsZeroed(r, r) + w = m + } else { + w = getWorkspace(r, r, true) + } + for i := 0; i < r*r; i += r + 1 { + w.mat.Data[i] = 1 + } + + const ( + terms = 10 + scaling = 4 + ) + + small := getWorkspace(r, r, false) + small.Scale(math.Pow(2, -scaling), a) + power := getWorkspace(r, r, false) + power.Copy(small) + + var ( + tmp = getWorkspace(r, r, false) + factI = 1. + ) + for i := 1.; i < terms; i++ { + factI *= i + + // This is OK to do because power and tmp are + // new Dense values so all rows are contiguous. + // TODO(kortschak) Make this explicit in the NewDense doc comment. + for j, v := range power.mat.Data { + tmp.mat.Data[j] = v / factI + } + + w.Add(w, tmp) + if i < terms-1 { + tmp.Mul(power, small) + tmp, power = power, tmp + } + } + putWorkspace(small) + putWorkspace(power) + for i := 0; i < scaling; i++ { + tmp.Mul(w, w) + tmp, w = w, tmp + } + putWorkspace(tmp) + + if w != m { + m.Copy(w) + putWorkspace(w) + } +} + +// Pow calculates the integral power of the matrix a to n, placing the result +// in the receiver. Pow will panic if n is negative or if a is not square. +func (m *Dense) Pow(a Matrix, n int) { + if n < 0 { + panic("matrix: illegal power") + } + r, c := a.Dims() + if r != c { + panic(ErrShape) + } + + m.reuseAs(r, c) + + // Take possible fast paths. + switch n { + case 0: + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + m.mat.Data[i*m.mat.Stride+i] = 1 + } + return + case 1: + m.Copy(a) + return + case 2: + m.Mul(a, a) + return + } + + // Perform iterative exponentiation by squaring in work space. + w := getWorkspace(r, r, false) + w.Copy(a) + s := getWorkspace(r, r, false) + s.Copy(a) + x := getWorkspace(r, r, false) + for n--; n > 0; n >>= 1 { + if n&1 != 0 { + x.Mul(w, s) + w, x = x, w + } + if n != 1 { + x.Mul(s, s) + s, x = x, s + } + } + m.Copy(w) + putWorkspace(w) + putWorkspace(s) + putWorkspace(x) +} + +// Scale multiplies the elements of a by f, placing the result in the receiver. +// +// See the Scaler interface for more information. +func (m *Dense) Scale(f float64, a Matrix) { + ar, ac := a.Dims() + + m.reuseAs(ar, ac) + + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + amat := rm.RawMatrix() + if m == aU || m.checkOverlap(amat) { + var restore func() + m, restore = m.isolatedWorkspace(a) + defer restore() + } + if !aTrans { + for ja, jm := 0, 0; ja < ar*amat.Stride; ja, jm = ja+amat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v * f + } + } + } else { + for ja, jm := 0, 0; ja < ac*amat.Stride; ja, jm = ja+amat.Stride, jm+1 { + for i, v := range amat.Data[ja : ja+ar] { + m.mat.Data[i*m.mat.Stride+jm] = v * f + } + } + } + return + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, f*a.At(r, c)) + } + } +} + +// Apply applies the function fn to each of the elements of a, placing the +// resulting matrix in the receiver. The function fn takes a row/column +// index and element value and returns some function of that tuple. +func (m *Dense) Apply(fn func(i, j int, v float64) float64, a Matrix) { + ar, ac := a.Dims() + + m.reuseAs(ar, ac) + + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + amat := rm.RawMatrix() + if m == aU || m.checkOverlap(amat) { + var restore func() + m, restore = m.isolatedWorkspace(a) + defer restore() + } + if !aTrans { + for j, ja, jm := 0, 0, 0; ja < ar*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = fn(j, i, v) + } + } + } else { + for j, ja, jm := 0, 0, 0; ja < ac*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+1 { + for i, v := range amat.Data[ja : ja+ar] { + m.mat.Data[i*m.mat.Stride+jm] = fn(i, j, v) + } + } + } + return + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, fn(r, c, a.At(r, c))) + } + } +} + +// RankOne performs a rank-one update to the matrix a and stores the result +// in the receiver. If a is zero, see Outer. +// m = a + alpha * x * y' +func (m *Dense) RankOne(a Matrix, alpha float64, x, y *VecDense) { + ar, ac := a.Dims() + if x.Len() != ar { + panic(ErrShape) + } + if y.Len() != ac { + panic(ErrShape) + } + + m.checkOverlap(x.asGeneral()) + m.checkOverlap(y.asGeneral()) + + var w Dense + if m == a { + w = *m + } + w.reuseAs(ar, ac) + + // Copy over to the new memory if necessary + if m != a { + w.Copy(a) + } + blas64.Ger(alpha, x.mat, y.mat, w.mat) + *m = w +} + +// Outer calculates the outer product of x and y, and stores the result +// in the receiver. +// m = alpha * x * y' +// In order to update an existing matrix, see RankOne. +func (m *Dense) Outer(alpha float64, x, y *VecDense) { + r := x.Len() + c := y.Len() + + // Copied from reuseAs with use replaced by useZeroed + // and a final zero of the matrix elements if we pass + // the shape checks. + // TODO(kortschak): Factor out into reuseZeroedAs if + // we find another case that needs it. + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat.Error. + panic("mat: caps not correctly set") + } + if m.IsZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useZeroed(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + } else if r != m.mat.Rows || c != m.mat.Cols { + panic(ErrShape) + } else { + m.checkOverlap(x.asGeneral()) + m.checkOverlap(y.asGeneral()) + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } + } + + blas64.Ger(alpha, x.mat, y.mat, m.mat) +} diff --git a/vendor/gonum.org/v1/gonum/mat/dense_test.go b/vendor/gonum.org/v1/gonum/mat/dense_test.go new file mode 100644 index 00000000..34b37cc3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/dense_test.go @@ -0,0 +1,2005 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "fmt" + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +func asBasicMatrix(d *Dense) Matrix { return (*basicMatrix)(d) } +func asBasicSymmetric(s *SymDense) Matrix { return (*basicSymmetric)(s) } +func asBasicTriangular(t *TriDense) Triangular { return (*basicTriangular)(t) } + +func TestNewDense(t *testing.T) { + for i, test := range []struct { + a []float64 + rows, cols int + min, max float64 + fro float64 + mat *Dense + }{ + { + []float64{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + }, + 3, 3, + 0, 0, + 0, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + }, + 3, 3, + 1, 1, + 3, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }, + 3, 3, + 0, 1, + 1.7320508075688772, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{1, 0, 0, 0, 1, 0, 0, 0, 1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + -1, 0, 0, + 0, -1, 0, + 0, 0, -1, + }, + 3, 3, + -1, 0, + 1.7320508075688772, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{-1, 0, 0, 0, -1, 0, 0, 0, -1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 2, 3, + 4, 5, 6, + }, + 2, 3, + 1, 6, + 9.539392014169458, + &Dense{ + mat: blas64.General{ + Rows: 2, Cols: 3, + Stride: 3, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + capRows: 2, capCols: 3, + }, + }, + { + []float64{ + 1, 2, + 3, 4, + 5, 6, + }, + 3, 2, + 1, 6, + 9.539392014169458, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 2, + Stride: 2, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + capRows: 3, capCols: 2, + }, + }, + } { + m := NewDense(test.rows, test.cols, test.a) + rows, cols := m.Dims() + if rows != test.rows { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.rows) + } + if cols != test.cols { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.cols) + } + if min := Min(m); min != test.min { + t.Errorf("unexpected min for test %d: got: %v want: %v", i, min, test.min) + } + if max := Max(m); max != test.max { + t.Errorf("unexpected max for test %d: got: %v want: %v", i, max, test.max) + } + if fro := Norm(m, 2); math.Abs(Norm(m, 2)-test.fro) > 1e-14 { + t.Errorf("unexpected Frobenius norm for test %d: got: %v want: %v", i, fro, test.fro) + } + if !reflect.DeepEqual(m, test.mat) { + t.Errorf("unexpected matrix for test %d", i) + } + if !Equal(m, test.mat) { + t.Errorf("matrix does not equal expected matrix for test %d", i) + } + } +} + +func TestAtSet(t *testing.T) { + for test, af := range [][][]float64{ + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // even + {{1, 2}, {4, 5}, {7, 8}}, // wide + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, //skinny + } { + m := NewDense(flatten(af)) + rows, cols := m.Dims() + for i := 0; i < rows; i++ { + for j := 0; j < cols; j++ { + if m.At(i, j) != af[i][j] { + t.Errorf("unexpected value for At(%d, %d) for test %d: got: %v want: %v", + i, j, test, m.At(i, j), af[i][j]) + } + + v := float64(i * j) + m.Set(i, j, v) + if m.At(i, j) != v { + t.Errorf("unexpected value for At(%d, %d) after Set(%[1]d, %d, %v) for test %d: got: %v want: %[3]v", + i, j, v, test, m.At(i, j)) + } + } + } + // Check access out of bounds fails + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.Set(row, 0, 1.2) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.Set(0, col, 1.2) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + } +} + +func TestSetRowColumn(t *testing.T) { + for _, as := range [][][]float64{ + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, + } { + for ri, row := range as { + a := NewDense(flatten(as)) + m := &Dense{} + m.Clone(a) + a.SetRow(ri, make([]float64, a.mat.Cols)) + m.Sub(m, a) + nt := Norm(m, 2) + nr := floats.Norm(row, 2) + if math.Abs(nt-nr) > 1e-14 { + t.Errorf("Row %d norm mismatch, want: %g, got: %g", ri, nr, nt) + } + } + + for ci := range as[0] { + a := NewDense(flatten(as)) + m := &Dense{} + m.Clone(a) + a.SetCol(ci, make([]float64, a.mat.Rows)) + col := make([]float64, a.mat.Rows) + for j := range col { + col[j] = float64(ci + 1 + j*a.mat.Cols) + } + m.Sub(m, a) + nt := Norm(m, 2) + nc := floats.Norm(col, 2) + if math.Abs(nt-nc) > 1e-14 { + t.Errorf("Column %d norm mismatch, want: %g, got: %g", ci, nc, nt) + } + } + } +} + +func TestRowColView(t *testing.T) { + for _, test := range []struct { + mat [][]float64 + }{ + { + mat: [][]float64{ + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10}, + {11, 12, 13, 14, 15}, + {16, 17, 18, 19, 20}, + {21, 22, 23, 24, 25}, + }, + }, + { + mat: [][]float64{ + {1, 2, 3, 4}, + {6, 7, 8, 9}, + {11, 12, 13, 14}, + {16, 17, 18, 19}, + {21, 22, 23, 24}, + }, + }, + { + mat: [][]float64{ + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10}, + {11, 12, 13, 14, 15}, + {16, 17, 18, 19, 20}, + }, + }, + } { + // This over cautious approach to building a matrix data + // slice is to ensure that changes to flatten in the future + // do not mask a regression to the issue identified in + // gonum/matrix#110. + rows, cols, flat := flatten(test.mat) + m := NewDense(rows, cols, flat[:len(flat):len(flat)]) + + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access rows=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access cols=%d c=%d", cols, col) + } + } + + for i := 0; i < rows; i++ { + vr := m.RowView(i) + if vr.Len() != cols { + t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols) + } + for j := 0; j < cols; j++ { + if got := vr.At(j, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v", + j, got, test.mat[i][j]) + } + } + } + for j := 0; j < cols; j++ { + vc := m.ColView(j) + if vc.Len() != rows { + t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows) + } + for i := 0; i < rows; i++ { + if got := vc.At(i, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v", + i, got, test.mat[i][j]) + } + } + } + m = m.Slice(1, rows-1, 1, cols-1).(*Dense) + for i := 1; i < rows-1; i++ { + vr := m.RowView(i - 1) + if vr.Len() != cols-2 { + t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols-2) + } + for j := 1; j < cols-1; j++ { + if got := vr.At(j-1, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v", + j-1, got, test.mat[i][j]) + } + } + } + for j := 1; j < cols-1; j++ { + vc := m.ColView(j - 1) + if vc.Len() != rows-2 { + t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows-2) + } + for i := 1; i < rows-1; i++ { + if got := vc.At(i-1, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v", + i-1, got, test.mat[i][j]) + } + } + } + } +} + +func TestGrow(t *testing.T) { + m := &Dense{} + m = m.Grow(10, 10).(*Dense) + rows, cols := m.Dims() + capRows, capCols := m.Caps() + if rows != 10 { + t.Errorf("unexpected value for rows: got: %d want: 10", rows) + } + if cols != 10 { + t.Errorf("unexpected value for cols: got: %d want: 10", cols) + } + if capRows != 10 { + t.Errorf("unexpected value for capRows: got: %d want: 10", capRows) + } + if capCols != 10 { + t.Errorf("unexpected value for capCols: got: %d want: 10", capCols) + } + + // Test grow within caps is in-place. + m.Set(1, 1, 1) + v := m.Slice(1, 5, 1, 5).(*Dense) + if v.At(0, 0) != m.At(1, 1) { + t.Errorf("unexpected viewed element value: got: %v want: %v", v.At(0, 0), m.At(1, 1)) + } + v = v.Grow(5, 5).(*Dense) + if !Equal(v, m.Slice(1, 10, 1, 10)) { + t.Error("unexpected view value after grow") + } + + // Test grow bigger than caps copies. + v = v.Grow(5, 5).(*Dense) + if !Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) { + t.Error("unexpected mismatched common view value after grow") + } + v.Set(0, 0, 0) + if Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) { + t.Error("unexpected matching view value after grow past capacity") + } + + // Test grow uses existing data slice when matrix is zero size. + v.Reset() + p, l := &v.mat.Data[:1][0], cap(v.mat.Data) + *p = 1 // This element is at position (-1, -1) relative to v and so should not be visible. + v = v.Grow(5, 5).(*Dense) + if &v.mat.Data[:1][0] != p { + t.Error("grow unexpectedly copied slice within cap limit") + } + if cap(v.mat.Data) != l { + t.Errorf("unexpected change in data slice capacity: got: %d want: %d", cap(v.mat.Data), l) + } + if v.At(0, 0) != 0 { + t.Errorf("unexpected value for At(0, 0): got: %v want: 0", v.At(0, 0)) + } +} + +func TestAdd(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{2, 2, 2}, {2, 2, 2}, {2, 2, 2}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{2, 0, 0}, {0, 2, 0}, {0, 0, 2}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-2, 0, 0}, {0, -2, 0}, {0, 0, -2}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{2, 4, 6}, {8, 10, 12}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Add(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Add(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Add(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.Add(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Add(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Adder interface { + Add(a, b Matrix) + } + rd := receiver.(Adder) + rd.Add(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Add(a, b) + } + testTwoInput(t, "Add", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestSub(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 0, 0}, {0, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Sub(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Sub(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Sub(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.Sub(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Sub(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Suber interface { + Sub(a, b Matrix) + } + rd := receiver.(Suber) + rd.Sub(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Sub(a, b) + } + testTwoInput(t, "Sub", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestMulElem(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4, 9}, {16, 25, 36}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.MulElem(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.MulElem(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.MulElem(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.MulElem(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).MulElem(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type ElemMuler interface { + MulElem(a, b Matrix) + } + rd := receiver.(ElemMuler) + rd.MulElem(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.MulElem(a, b) + } + testTwoInput(t, "MulElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +// A comparison that treats NaNs as equal, for testing. +func (m *Dense) same(b Matrix) bool { + br, bc := b.Dims() + if br != m.mat.Rows || bc != m.mat.Cols { + return false + } + for r := 0; r < br; r++ { + for c := 0; c < bc; c++ { + if av, bv := m.At(r, c), b.At(r, c); av != bv && !(math.IsNaN(av) && math.IsNaN(bv)) { + return false + } + } + } + return true +} + +func TestDivElem(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{math.Inf(1), math.NaN(), math.NaN()}, {math.NaN(), math.Inf(1), math.NaN()}, {math.NaN(), math.NaN(), math.Inf(1)}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 1, 1}, {1, 1, 1}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.DivElem(a, b) + if !temp.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.DivElem(a, b) + if !temp.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.DivElem(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.DivElem(a, b) + if !a.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).DivElem(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type ElemDiver interface { + DivElem(a, b Matrix) + } + rd := receiver.(ElemDiver) + rd.DivElem(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.DivElem(a, b) + } + testTwoInput(t, "DivElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestMul(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{3, 3, 3}, {3, 3, 3}, {3, 3, 3}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2}, {3, 4}, {5, 6}}, + [][]float64{{22, 28}, {49, 64}}, + }, + { + [][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}}, + [][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}}, + [][]float64{{0, 2, 2}, {0, 2, 2}, {0, 2, 2}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Mul(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Mul(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Mul(a, b) }) + if !panicked || message != "blas: index of c out of range" { + if message != "" { + t.Errorf("expected runtime panic for nil data slice: got %q", message) + } else { + t.Error("expected runtime panic for nil data slice") + } + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Mul(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Muler interface { + Mul(a, b Matrix) + } + rd := receiver.(Muler) + rd.Mul(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeMul := func(ar, ac, br, bc int) bool { + return ac == br + } + testTwoInput(t, "Mul", &Dense{}, method, denseComparison, legalTypesAll, legalSizeMul, 1e-14) +} + +func randDense(size int, rho float64, rnd func() float64) (*Dense, error) { + if size == 0 { + return nil, ErrZeroLength + } + d := &Dense{ + mat: blas64.General{ + Rows: size, Cols: size, Stride: size, + Data: make([]float64, size*size), + }, + capRows: size, capCols: size, + } + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + if rand.Float64() < rho { + d.Set(i, j, rnd()) + } + } + } + return d, nil +} + +func TestExp(t *testing.T) { + for i, test := range []struct { + a [][]float64 + want [][]float64 + mod func(*Dense) + }{ + { + a: [][]float64{{-49, 24}, {-64, 31}}, + want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}}, + }, + { + a: [][]float64{{-49, 24}, {-64, 31}}, + want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 3, 1, 3).(*Dense) + }, + }, + { + a: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + want: [][]float64{{2.71828182845905, 0, 0}, {0, 2.71828182845905, 0}, {0, 0, 2.71828182845905}}, + }, + } { + var got Dense + if test.mod != nil { + test.mod(&got) + } + got.Exp(NewDense(flatten(test.a))) + if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) { + t.Errorf("unexpected result for Exp test %d", i) + } + } +} + +func TestPow(t *testing.T) { + for i, test := range []struct { + a [][]float64 + n int + mod func(*Dense) + want [][]float64 + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 0, + want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 0, + want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 1, + want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 1, + want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 2, + want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 2, + want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 3, + want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 3, + want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + } { + var got Dense + if test.mod != nil { + test.mod(&got) + } + got.Pow(NewDense(flatten(test.a)), test.n) + if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) { + t.Errorf("unexpected result for Pow test %d", i) + } + } +} + +func TestScale(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, a Matrix) { + type Scaler interface { + Scale(f float64, a Matrix) + } + rd := receiver.(Scaler) + rd.Scale(f, a) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(f, a) + } + testOneInput(t, "Scale", &Dense{}, method, denseComparison, isAnyType, isAnySize, 1e-14) + } +} + +func TestPowN(t *testing.T) { + for i, test := range []struct { + a [][]float64 + mod func(*Dense) + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + } { + for n := 1; n <= 14; n++ { + var got, want Dense + if test.mod != nil { + test.mod(&got) + } + got.Pow(NewDense(flatten(test.a)), n) + want.iterativePow(NewDense(flatten(test.a)), n) + if !Equal(&got, &want) { + t.Errorf("unexpected result for iterative Pow test %d", i) + } + } + } +} + +func (m *Dense) iterativePow(a Matrix, n int) { + m.Clone(a) + for i := 1; i < n; i++ { + m.Mul(m, a) + } +} + +func TestCloneT(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4}, {2, 5}, {3, 6}}, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + var got, gotT Dense + + for j := 0; j < 2; j++ { + got.Clone(a.T()) + if !Equal(&got, want) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + gotT.Clone(got.T()) + if !Equal(&gotT, a) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + + zero(got.mat.Data) + } + } +} + +func TestCopyT(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4}, {2, 5}, {3, 6}}, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + ar, ac := a.Dims() + got := NewDense(ac, ar, nil) + rr := NewDense(ar, ac, nil) + + for j := 0; j < 2; j++ { + got.Copy(a.T()) + if !Equal(got, want) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + rr.Copy(got.T()) + if !Equal(rr, a) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + + zero(got.mat.Data) + } + } +} + +func TestCopyDenseAlias(t *testing.T) { + for _, trans := range []bool{false, true} { + for di := 0; di < 2; di++ { + for dj := 0; dj < 2; dj++ { + for si := 0; si < 2; si++ { + for sj := 0; sj < 2; sj++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + src := a.Slice(si, si+2, sj, sj+2) + want := DenseCopyOf(src) + got := a.Slice(di, di+2, dj, dj+2).(*Dense) + + if trans { + panicked, _ := panics(func() { got.Copy(src.T()) }) + if !panicked { + t.Errorf("expected panic for transpose aliased copy with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v", + di, dj, si, sj, Formatted(got), Formatted(want), + ) + } + continue + } + + got.Copy(src) + if !Equal(got, want) { + t.Errorf("unexpected aliased copy result with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v", + di, dj, si, sj, Formatted(got), Formatted(want), + ) + } + } + } + } + } + } +} + +func TestCopyVecDenseAlias(t *testing.T) { + for _, horiz := range []bool{false, true} { + for do := 0; do < 2; do++ { + for di := 0; di < 3; di++ { + for si := 0; si < 3; si++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + var src *VecDense + var want *Dense + if horiz { + src = a.RowView(si) + want = DenseCopyOf(a.Slice(si, si+1, 0, 2)) + } else { + src = a.ColView(si) + want = DenseCopyOf(a.Slice(0, 2, si, si+1)) + } + + var got *Dense + if horiz { + got = a.Slice(di, di+1, do, do+2).(*Dense) + got.Copy(src.T()) + } else { + got = a.Slice(do, do+2, di, di+1).(*Dense) + got.Copy(src) + } + + if !Equal(got, want) { + t.Errorf("unexpected aliased copy result with offsets dst(%d) src(%d):\ngot:\n%v\nwant:\n%v", + di, si, Formatted(got), Formatted(want), + ) + } + } + } + } + } +} + +func identity(r, c int, v float64) float64 { return v } + +func TestApply(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + fn func(r, c int, v float64) float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + identity, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + identity, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + identity, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + identity, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + identity, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{2, 4, 6}, {8, 10, 12}}, + func(r, c int, v float64) float64 { return v * 2 }, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 2, 0}, {0, 5, 0}}, + func(r, c int, v float64) float64 { + if c == 1 { + return v + } + return 0 + }, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 0, 0}, {4, 5, 6}}, + func(r, c int, v float64) float64 { + if r == 1 { + return v + } + return 0 + }, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + var got Dense + + for j := 0; j < 2; j++ { + got.Apply(test.fn, a) + if !Equal(&got, want) { + t.Errorf("unexpected result for test %d iteration %d: got: %v want: %v", i, j, got.mat.Data, want.mat.Data) + } + } + } + + for _, fn := range []func(r, c int, v float64) float64{ + identity, + func(r, c int, v float64) float64 { + if r < c { + return v + } + return -v + }, + func(r, c int, v float64) float64 { + if r%2 == 0 && c%2 == 0 { + return v + } + return -v + }, + func(_, _ int, v float64) float64 { return v * v }, + func(_, _ int, v float64) float64 { return -v }, + } { + method := func(receiver, x Matrix) { + type Applier interface { + Apply(func(r, c int, v float64) float64, Matrix) + } + rd := receiver.(Applier) + rd.Apply(fn, x) + } + denseComparison := func(receiver, x *Dense) { + receiver.Apply(fn, x) + } + testOneInput(t, "Apply", &Dense{}, method, denseComparison, isAnyType, isAnySize, 0) + } +} + +func TestClone(t *testing.T) { + for i, test := range []struct { + a [][]float64 + i, j int + v float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + 1, 1, + 1, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + 0, 0, + 0, + }, + } { + a := NewDense(flatten(test.a)) + b := *a + a.Clone(a) + a.Set(test.i, test.j, test.v) + + if Equal(&b, a) { + t.Errorf("unexpected mirror of write to cloned matrix for test %d: %v cloned and altered = %v", + i, a, &b) + } + } +} + +// TODO(kortschak) Roll this into testOneInput when it exists. +func TestCopyPanic(t *testing.T) { + for _, a := range []*Dense{ + {}, + {mat: blas64.General{Rows: 1}}, + {mat: blas64.General{Cols: 1}}, + } { + var rows, cols int + m := NewDense(1, 1, nil) + panicked, message := panics(func() { rows, cols = m.Copy(a) }) + if panicked { + t.Errorf("unexpected panic: %v", message) + } + if rows != 0 { + t.Errorf("unexpected rows: got: %d want: 0", rows) + } + if cols != 0 { + t.Errorf("unexpected cols: got: %d want: 0", cols) + } + } +} + +func TestStack(t *testing.T) { + for i, test := range []struct { + a, b, e [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var s Dense + s.Stack(a, b) + + if !Equal(&s, NewDense(flatten(test.e))) { + t.Errorf("unexpected result for Stack test %d: %v stack %v = %v", i, a, b, s) + } + } + + method := func(receiver, a, b Matrix) { + type Stacker interface { + Stack(a, b Matrix) + } + rd := receiver.(Stacker) + rd.Stack(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Stack(a, b) + } + testTwoInput(t, "Stack", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameWidth, 0) +} + +func TestAugment(t *testing.T) { + for i, test := range []struct { + a, b, e [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + [][]float64{{1, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1}, {0, 0, 1, 1, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var s Dense + s.Augment(a, b) + + if !Equal(&s, NewDense(flatten(test.e))) { + t.Errorf("unexpected result for Augment test %d: %v augment %v = %v", i, a, b, s) + } + } + + method := func(receiver, a, b Matrix) { + type Augmenter interface { + Augment(a, b Matrix) + } + rd := receiver.(Augmenter) + rd.Augment(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Augment(a, b) + } + testTwoInput(t, "Augment", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameHeight, 0) +} + +func TestRankOne(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + m [][]float64 + alpha float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + m: [][]float64{{2}}, + alpha: -3, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + m: [][]float64{{2}, {-3}, {5}}, + alpha: -3, + }, + + { + x: []float64{5}, + y: []float64{10, 15, 8}, + m: [][]float64{{2, -3, 5}}, + alpha: -3, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + m: [][]float64{ + {2, -3}, + {4, -1}, + }, + alpha: -3, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + m: [][]float64{ + {2, 3}, + {4, 5}, + {6, 7}, + }, + alpha: -3, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + m: [][]float64{ + {2, 3, 6}, + {4, 5, 7}, + }, + alpha: -3, + }, + } { + want := &Dense{} + xm := NewDense(len(test.x), 1, test.x) + ym := NewDense(1, len(test.y), test.y) + + want.Mul(xm, ym) + want.Scale(test.alpha, want) + want.Add(want, NewDense(flatten(test.m))) + + a := NewDense(flatten(test.m)) + m := &Dense{} + // Check with a new matrix + m.RankOne(a, test.alpha, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y)) + if !Equal(m, want) { + t.Errorf("unexpected result for RankOne test %d iteration 0: got: %+v want: %+v", i, m, want) + } + // Check with the same matrix + a.RankOne(a, test.alpha, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y)) + if !Equal(a, want) { + t.Errorf("unexpected result for Outer test %d iteration 1: got: %+v want: %+v", i, m, want) + } + } +} + +func TestOuter(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + }, + + { + x: []float64{5}, + y: []float64{10, 15, 8}, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + }, + } { + for _, f := range []float64{0.5, 1, 3} { + want := &Dense{} + xm := NewDense(len(test.x), 1, test.x) + ym := NewDense(1, len(test.y), test.y) + + want.Mul(xm, ym) + want.Scale(f, want) + + var m Dense + for j := 0; j < 2; j++ { + // Check with a new matrix - and then again. + m.Outer(f, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y)) + if !Equal(&m, want) { + t.Errorf("unexpected result for Outer test %d iteration %d scale %v: got: %+v want: %+v", i, j, f, m, want) + } + } + } + } +} + +func TestInverse(t *testing.T) { + for i, test := range []struct { + a Matrix + want Matrix // nil indicates that a is singular. + tol float64 + }{ + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }), + tol: 1e-14, + }, + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }).T(), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }).T(), + tol: 1e-14, + }, + + // This case does not fail, but we do not guarantee that. The success + // is because the receiver and the input are aligned in the call to + // inverse. If there was a misalignment, the result would likely be + // incorrect and no shadowing panic would occur. + { + a: asBasicMatrix(NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + })), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }), + tol: 1e-14, + }, + + // The following case fails as it does not follow the shadowing rules. + // Specifically, the test extracts the underlying *Dense, and uses + // it as a receiver with the basicMatrix as input. The basicMatrix type + // allows shadowing of the input data without providing the Raw method + // required for detection of shadowing. + // + // We specifically state we do not check this case. + // + // { + // a: asBasicMatrix(NewDense(3, 3, []float64{ + // 8, 1, 6, + // 3, 5, 7, + // 4, 9, 2, + // })).T(), + // want: NewDense(3, 3, []float64{ + // 0.147222222222222, -0.144444444444444, 0.063888888888889, + // -0.061111111111111, 0.022222222222222, 0.105555555555556, + // -0.019444444444444, 0.188888888888889, -0.102777777777778, + // }).T(), + // tol: 1e-14, + // }, + + { + a: NewDense(4, 4, []float64{ + 5, 2, 8, 7, + 4, 5, 8, 2, + 8, 5, 3, 2, + 8, 7, 7, 5, + }), + want: NewDense(4, 4, []float64{ + 0.100548446069470, 0.021937842778793, 0.334552102376599, -0.283363802559415, + -0.226691042047532, -0.067641681901280, -0.281535648994515, 0.457038391224863, + 0.080438756855576, 0.217550274223035, 0.067641681901280, -0.226691042047532, + 0.043875685557587, -0.244972577696527, -0.235831809872029, 0.330895795246801, + }), + tol: 1e-14, + }, + + // Tests with singular matrix. + { + a: NewDense(1, 1, []float64{ + 0, + }), + }, + { + a: NewDense(2, 2, []float64{ + 0, 0, + 0, 0, + }), + }, + { + a: NewDense(2, 2, []float64{ + 0, 0, + 0, 1, + }), + }, + { + a: NewDense(3, 3, []float64{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 20, 20, + 0, 0, 20, 20, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + }), + }, + { + a: NewDense(5, 5, []float64{ + 0, 1, 0, 0, 0, + 4, 0, 2, 0, 0, + 0, 3, 0, 3, 0, + 0, 0, 2, 0, 4, + 0, 0, 0, 1, 0, + }), + }, + { + a: NewDense(5, 5, []float64{ + 4, -1, -1, -1, -1, + -1, 4, -1, -1, -1, + -1, -1, 4, -1, -1, + -1, -1, -1, 4, -1, + -1, -1, -1, -1, 4, + }), + }, + { + a: NewDense(5, 5, []float64{ + 2, -1, 0, 0, -1, + -1, 2, -1, 0, 0, + 0, -1, 2, -1, 0, + 0, 0, -1, 2, -1, + -1, 0, 0, -1, 2, + }), + }, + { + a: NewDense(5, 5, []float64{ + 1, 2, 3, 5, 8, + 2, 3, 5, 8, 13, + 3, 5, 8, 13, 21, + 5, 8, 13, 21, 34, + 8, 13, 21, 34, 55, + }), + }, + { + a: NewDense(8, 8, []float64{ + 611, 196, -192, 407, -8, -52, -49, 29, + 196, 899, 113, -192, -71, -43, -8, -44, + -192, 113, 899, 196, 61, 49, 8, 52, + 407, -192, 196, 611, 8, 44, 59, -23, + -8, -71, 61, 8, 411, -599, 208, 208, + -52, -43, 49, 44, -599, 411, 208, 208, + -49, -8, 8, 59, 208, 208, 99, -911, + 29, -44, 52, -23, 208, 208, -911, 99, + }), + }, + } { + var got Dense + err := got.Inverse(test.a) + if test.want == nil { + if err == nil { + t.Errorf("Case %d: expected error for singular matrix", i) + } + continue + } + if err != nil { + t.Errorf("Case %d: unexpected error: %v", i, err) + continue + } + if !equalApprox(&got, test.want, test.tol, false) { + t.Errorf("Case %d, inverse mismatch.", i) + } + var m Dense + m.Mul(&got, test.a) + r, _ := test.a.Dims() + d := make([]float64, r*r) + for i := 0; i < r*r; i += r + 1 { + d[i] = 1 + } + eye := NewDense(r, r, d) + if !equalApprox(eye, &m, 1e-14, false) { + t.Errorf("Case %d, A^-1 * A != I", i) + } + + var tmp Dense + tmp.Clone(test.a) + aU, transposed := untranspose(test.a) + if transposed { + switch aU := aU.(type) { + case *Dense: + err = aU.Inverse(test.a) + case *basicMatrix: + err = (*Dense)(aU).Inverse(test.a) + default: + continue + } + m.Mul(aU, &tmp) + } else { + switch a := test.a.(type) { + case *Dense: + err = a.Inverse(test.a) + m.Mul(a, &tmp) + case *basicMatrix: + err = (*Dense)(a).Inverse(test.a) + m.Mul(a, &tmp) + default: + continue + } + } + if err != nil { + t.Errorf("Error computing inverse: %v", err) + } + if !equalApprox(eye, &m, 1e-14, false) { + t.Errorf("Case %d, A^-1 * A != I", i) + fmt.Println(Formatted(&m)) + } + } +} + +var ( + wd *Dense +) + +func BenchmarkMulDense100Half(b *testing.B) { denseMulBench(b, 100, 0.5) } +func BenchmarkMulDense100Tenth(b *testing.B) { denseMulBench(b, 100, 0.1) } +func BenchmarkMulDense1000Half(b *testing.B) { denseMulBench(b, 1000, 0.5) } +func BenchmarkMulDense1000Tenth(b *testing.B) { denseMulBench(b, 1000, 0.1) } +func BenchmarkMulDense1000Hundredth(b *testing.B) { denseMulBench(b, 1000, 0.01) } +func BenchmarkMulDense1000Thousandth(b *testing.B) { denseMulBench(b, 1000, 0.001) } +func denseMulBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, d) + wd = &n + } +} + +func BenchmarkPreMulDense100Half(b *testing.B) { densePreMulBench(b, 100, 0.5) } +func BenchmarkPreMulDense100Tenth(b *testing.B) { densePreMulBench(b, 100, 0.1) } +func BenchmarkPreMulDense1000Half(b *testing.B) { densePreMulBench(b, 1000, 0.5) } +func BenchmarkPreMulDense1000Tenth(b *testing.B) { densePreMulBench(b, 1000, 0.1) } +func BenchmarkPreMulDense1000Hundredth(b *testing.B) { densePreMulBench(b, 1000, 0.01) } +func BenchmarkPreMulDense1000Thousandth(b *testing.B) { densePreMulBench(b, 1000, 0.001) } +func densePreMulBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + wd = NewDense(size, size, nil) + b.StartTimer() + for i := 0; i < b.N; i++ { + wd.Mul(a, d) + } +} + +func BenchmarkRow10(b *testing.B) { rowBench(b, 10) } +func BenchmarkRow100(b *testing.B) { rowBench(b, 100) } +func BenchmarkRow1000(b *testing.B) { rowBench(b, 1000) } + +func rowBench(b *testing.B, size int) { + a, _ := randDense(size, 1, rand.NormFloat64) + _, c := a.Dims() + dst := make([]float64, c) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + Row(dst, 0, a) + } +} + +func BenchmarkExp10(b *testing.B) { expBench(b, 10) } +func BenchmarkExp100(b *testing.B) { expBench(b, 100) } +func BenchmarkExp1000(b *testing.B) { expBench(b, 1000) } + +func expBench(b *testing.B, size int) { + a, _ := randDense(size, 1, rand.NormFloat64) + + b.ResetTimer() + var m Dense + for i := 0; i < b.N; i++ { + m.Exp(a) + } +} + +func BenchmarkPow10_3(b *testing.B) { powBench(b, 10, 3) } +func BenchmarkPow100_3(b *testing.B) { powBench(b, 100, 3) } +func BenchmarkPow1000_3(b *testing.B) { powBench(b, 1000, 3) } +func BenchmarkPow10_4(b *testing.B) { powBench(b, 10, 4) } +func BenchmarkPow100_4(b *testing.B) { powBench(b, 100, 4) } +func BenchmarkPow1000_4(b *testing.B) { powBench(b, 1000, 4) } +func BenchmarkPow10_5(b *testing.B) { powBench(b, 10, 5) } +func BenchmarkPow100_5(b *testing.B) { powBench(b, 100, 5) } +func BenchmarkPow1000_5(b *testing.B) { powBench(b, 1000, 5) } +func BenchmarkPow10_6(b *testing.B) { powBench(b, 10, 6) } +func BenchmarkPow100_6(b *testing.B) { powBench(b, 100, 6) } +func BenchmarkPow1000_6(b *testing.B) { powBench(b, 1000, 6) } +func BenchmarkPow10_7(b *testing.B) { powBench(b, 10, 7) } +func BenchmarkPow100_7(b *testing.B) { powBench(b, 100, 7) } +func BenchmarkPow1000_7(b *testing.B) { powBench(b, 1000, 7) } +func BenchmarkPow10_8(b *testing.B) { powBench(b, 10, 8) } +func BenchmarkPow100_8(b *testing.B) { powBench(b, 100, 8) } +func BenchmarkPow1000_8(b *testing.B) { powBench(b, 1000, 8) } +func BenchmarkPow10_9(b *testing.B) { powBench(b, 10, 9) } +func BenchmarkPow100_9(b *testing.B) { powBench(b, 100, 9) } +func BenchmarkPow1000_9(b *testing.B) { powBench(b, 1000, 9) } + +func powBench(b *testing.B, size, n int) { + a, _ := randDense(size, 1, rand.NormFloat64) + + b.ResetTimer() + var m Dense + for i := 0; i < b.N; i++ { + m.Pow(a, n) + } +} + +func BenchmarkMulTransDense100Half(b *testing.B) { denseMulTransBench(b, 100, 0.5) } +func BenchmarkMulTransDense100Tenth(b *testing.B) { denseMulTransBench(b, 100, 0.1) } +func BenchmarkMulTransDense1000Half(b *testing.B) { denseMulTransBench(b, 1000, 0.5) } +func BenchmarkMulTransDense1000Tenth(b *testing.B) { denseMulTransBench(b, 1000, 0.1) } +func BenchmarkMulTransDense1000Hundredth(b *testing.B) { denseMulTransBench(b, 1000, 0.01) } +func BenchmarkMulTransDense1000Thousandth(b *testing.B) { denseMulTransBench(b, 1000, 0.001) } +func denseMulTransBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, d.T()) + wd = &n + } +} + +func BenchmarkMulTransDenseSym100Half(b *testing.B) { denseMulTransSymBench(b, 100, 0.5) } +func BenchmarkMulTransDenseSym100Tenth(b *testing.B) { denseMulTransSymBench(b, 100, 0.1) } +func BenchmarkMulTransDenseSym1000Half(b *testing.B) { denseMulTransSymBench(b, 1000, 0.5) } +func BenchmarkMulTransDenseSym1000Tenth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.1) } +func BenchmarkMulTransDenseSym1000Hundredth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.01) } +func BenchmarkMulTransDenseSym1000Thousandth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.001) } +func denseMulTransSymBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, a.T()) + wd = &n + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/doc.go b/vendor/gonum.org/v1/gonum/mat/doc.go new file mode 100644 index 00000000..eecb742c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/doc.go @@ -0,0 +1,173 @@ +// Copyright ©2015 The gonum 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 mat provides implementations of float64 and complex128 matrix +// structures and linear algebra operations on them. +// +// Overview +// +// This section provides a quick overview of the mat package. The following +// sections provide more in depth commentary. +// +// mat provides: +// - Interfaces for Matrix classes (Matrix, Symmetric, Triangular) +// - Concrete implementations (Dense, SymDense, TriDense) +// - Methods and functions for using matrix data (Add, Trace, SymRankOne) +// - Types for constructing and using matrix factorizations (QR, LU) +// - The complementary types for complex matrices, CMatrix, CSymDense, etc. +// +// A matrix may be constructed through the corresponding New function. If no +// backing array is provided the matrix will be initialized to all zeros. +// // Allocate a zeroed real matrix of size 3×5 +// zero := mat.NewDense(3, 5, nil) +// If a backing data slice is provided, the matrix will have those elements. +// Matrices are all stored in row-major format. +// // Generate a 6×6 matrix of random values. +// data := make([]float64, 36) +// for i := range data { +// data[i] = rand.NormFloat64() +// } +// a := mat.NewDense(6, 6, data) +// Operations involving matrix data are implemented as functions when the values +// of the matrix remain unchanged +// tr := mat.Trace(a) +// and are implemented as methods when the operation modifies the receiver. +// zero.Copy(a) +// +// Receivers must be the correct size for the matrix operations, otherwise the +// operation will panic. As a special case for convenience, a zero-value matrix +// will be modified to have the correct size, allocating data if necessary. +// var c mat.Dense // construct a new zero-sized matrix +// c.Mul(a, a) // c is automatically adjusted to be 6×6 +// +// Zero-value of a matrix +// +// A zero-value matrix is either the Go language definition of a zero-value or +// is a zero-sized matrix with zero-length stride. Matrix implementations may have +// a Reset method to revert the receiver into a zero-valued matrix and an IsZero +// method that returns whether the matrix is zero-valued. +// So the following will all result in a zero-value matrix. +// - var a mat.Dense +// - a := NewDense(0, 0, make([]float64, 0, 100)) +// - a.Reset() +// A zero-value matrix can not be sliced even if it does have an adequately sized +// backing data slice, but can be expanded using its Grow method if it exists. +// +// The Matrix Interfaces +// +// The Matrix interface is the common link between the concrete types of real +// matrices, The Matrix interface is defined by three functions: Dims, which +// returns the dimensions of the Matrix, At, which returns the element in the +// specified location, and T for returning a Transpose (discussed later). All of +// the concrete types can perform these behaviors and so implement the interface. +// Methods and functions are designed to use this interface, so in particular the method +// func (m *Dense) Mul(a, b Matrix) +// constructs a *Dense from the result of a multiplication with any Matrix types, +// not just *Dense. Where more restrictive requirements must be met, there are also the +// Symmetric and Triangular interfaces. For example, in +// func (s *SymDense) AddSym(a, b Symmetric) +// the Symmetric interface guarantees a symmetric result. +// +// The CMatrix interface plays the same role for complex matrices. The difference +// is that the CMatrix type has the H method instead T, for returning the conjugate +// transpose. +// +// (Conjugate) Transposes +// +// The T method is used for transposition on real matrices, and H is used for +// conjugate transposition on complex matrices. For example, c.Mul(a.T(), b) computes +// c = a^T * b. The mat types implement this method implicitly — +// see the Transpose and Conjugate types for more details. Note that some +// operations have a transpose as part of their definition, as in *SymDense.SymOuterK. +// +// Matrix Factorization +// +// Matrix factorizations, such as the LU decomposition, typically have their own +// specific data storage, and so are each implemented as a specific type. The +// factorization can be computed through a call to Factorize +// var lu mat.LU +// lu.Factorize(a) +// The elements of the factorization can be extracted through methods on the +// factorized type, i.e. *LU.UTo. The factorization types can also be used directly, +// as in *Dense.SolveCholesky. Some factorizations can be updated directly, +// without needing to update the original matrix and refactorize, +// as in *LU.RankOne. +// +// BLAS and LAPACK +// +// BLAS and LAPACK are the standard APIs for linear algebra routines. Many +// operations in mat are implemented using calls to the wrapper functions +// in gonum/blas/blas64 and gonum/lapack/lapack64 and their complex equivalents. +// By default, blas64 and lapack64 call the native Go implementations of the +// routines. Alternatively, it is possible to use C-based implementations of the +// APIs through the respective cgo packages and "Use" functions. The Go +// implementation of LAPACK (used by default) makes calls +// through blas64, so if a cgo BLAS implementation is registered, the lapack64 +// calls will be partially executed in Go and partially executed in C. +// +// Type Switching +// +// The Matrix abstraction enables efficiency as well as interoperability. Go's +// type reflection capabilities are used to choose the most efficient routine +// given the specific concrete types. For example, in +// c.Mul(a, b) +// if a and b both implement RawMatrixer, that is, they can be represented as a +// blas64.General, blas64.Gemm (general matrix multiplication) is called, while +// instead if b is a RawSymmetricer blas64.Symm is used (general-symmetric +// multiplication), and if b is a *VecDense blas64.Gemv is used. +// +// There are many possible type combinations and special cases. No specific guarantees +// are made about the performance of any method, and in particular, note that an +// abstract matrix type may be copied into a concrete type of the corresponding +// value. If there are specific special cases that are needed, please submit a +// pull-request or file an issue. +// +// Invariants +// +// Matrix input arguments to functions are never directly modified. If an operation +// changes Matrix data, the mutated matrix will be the receiver of a function. +// +// For convenience, a matrix may be used as both a receiver and as an input, e.g. +// a.Pow(a, 6) +// v.SolveVec(a.T(), v) +// though in many cases this will cause an allocation (see Element Aliasing). +// An exception to this rule is Copy, which does not allow a.Copy(a.T()). +// +// Element Aliasing +// +// Most methods in mat modify receiver data. It is forbidden for the modified +// data region of the receiver to overlap the used data area of the input +// arguments. The exception to this rule is when the method receiver is equal to one +// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. +// +// This prohibition is to help avoid subtle mistakes when the method needs to read +// from and write to the same data region. There are ways to make mistakes using the +// mat API, and mat functions will detect and complain about those. +// There are many ways to make mistakes by excursion from the mat API via +// interaction with raw matrix values. +// +// If you need to read the rest of this section to understand the behavior of +// your program, you are being clever. Don't be clever. If you must be clever, +// blas64 and lapack64 may be used to call the behavior directly. +// +// mat will use the following rules to detect overlap between the receiver and one +// of the inputs: +// - the input implements one of the Raw methods, and +// - the Raw type matches that of the receiver or +// one is a RawMatrixer and the other is a RawVectorer, and +// - the address ranges of the backing data slices overlap, and +// - the strides differ or there is an overlap in the used data elements. +// If such an overlap is detected, the method will panic. +// +// The following cases will not panic: +// - the data slices do not overlap, +// - there is pointer identity between the receiver and input values after +// the value has been untransposed if necessary. +// +// mat will not attempt to detect element overlap if the input does not implement a +// Raw method, or if the Raw method differs from that of the receiver except when a +// conversion has occurred through a mat API function. Method behavior is undefined +// if there is undetected overlap. +// +package mat // import "gonum.org/v1/gonum/mat" diff --git a/vendor/gonum.org/v1/gonum/mat/eigen.go b/vendor/gonum.org/v1/gonum/mat/eigen.go new file mode 100644 index 00000000..0c677a8a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/eigen.go @@ -0,0 +1,260 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +const ( + badFact = "mat: use without successful factorization" + badNoVect = "mat: eigenvectors not computed" +) + +// EigenSym is a type for creating and manipulating the Eigen decomposition of +// symmetric matrices. +type EigenSym struct { + vectorsComputed bool + + values []float64 + vectors *Dense +} + +// Factorize computes the eigenvalue decomposition of the symmetric matrix a. +// The Eigen decomposition is defined as +// A = P * D * P^-1 +// where D is a diagonal matrix containing the eigenvalues of the matrix, and +// P is a matrix of the eigenvectors of A. If the vectors input argument is +// false, the eigenvectors are not computed. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, methods that require a successful factorization will panic. +func (e *EigenSym) Factorize(a Symmetric, vectors bool) (ok bool) { + n := a.Symmetric() + sd := NewSymDense(n, nil) + sd.CopySym(a) + + jobz := lapack.EVJob(lapack.None) + if vectors { + jobz = lapack.ComputeEV + } + w := make([]float64, n) + work := []float64{0} + lapack64.Syev(jobz, sd.mat, w, work, -1) + + work = getFloats(int(work[0]), false) + ok = lapack64.Syev(jobz, sd.mat, w, work, len(work)) + putFloats(work) + if !ok { + e.vectorsComputed = false + e.values = nil + e.vectors = nil + return false + } + e.vectorsComputed = vectors + e.values = w + e.vectors = NewDense(n, n, sd.mat.Data) + return true +} + +// succFact returns whether the receiver contains a successful factorization. +func (e *EigenSym) succFact() bool { + return len(e.values) != 0 +} + +// Values extracts the eigenvalues of the factorized matrix. If dst is +// non-nil, the values are stored in-place into dst. In this case +// dst must have length n, otherwise Values will panic. If dst is +// nil, then a new slice will be allocated of the proper length and filled +// with the eigenvalues. +// +// Values panics if the Eigen decomposition was not successful. +func (e *EigenSym) Values(dst []float64) []float64 { + if !e.succFact() { + panic(badFact) + } + if dst == nil { + dst = make([]float64, len(e.values)) + } + if len(dst) != len(e.values) { + panic(ErrSliceLengthMismatch) + } + copy(dst, e.values) + return dst +} + +// EigenvectorsSym extracts the eigenvectors of the factorized matrix and stores +// them in the receiver. Each eigenvector is a column corresponding to the +// respective eigenvalue returned by e.Values. +// +// EigenvectorsSym panics if the factorization was not successful or if the +// decomposition did not compute the eigenvectors. +func (m *Dense) EigenvectorsSym(e *EigenSym) { + if !e.succFact() { + panic(badFact) + } + if !e.vectorsComputed { + panic(badNoVect) + } + m.reuseAs(len(e.values), len(e.values)) + m.Copy(e.vectors) +} + +// Eigen is a type for creating and using the eigenvalue decomposition of a dense matrix. +type Eigen struct { + n int // The size of the factorized matrix. + + right bool // have the right eigenvectors been computed + left bool // have the left eigenvectors been computed + + values []complex128 + rVectors *Dense + lVectors *Dense +} + +// succFact returns whether the receiver contains a successful factorization. +func (e *Eigen) succFact() bool { + return len(e.values) != 0 +} + +// Factorize computes the eigenvalues of the square matrix a, and optionally +// the eigenvectors. +// +// A right eigenvalue/eigenvector combination is defined by +// A * x_r = λ * x_r +// where x_r is the column vector called an eigenvector, and λ is the corresponding +// eigenvector. +// +// Similarly, a left eigenvalue/eigenvector combination is defined by +// x_l * A = λ * x_l +// The eigenvalues, but not the eigenvectors, are the same for both decompositions. +// +// Typically eigenvectors refer to right eigenvectors. +// +// In all cases, Eigen computes the eigenvalues of the matrix. If right and left +// are true, then the right and left eigenvectors will be computed, respectively. +// Eigen panics if the input matrix is not square. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, methods that require a successful factorization will panic. +func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) { + // TODO(btracey): Change implementation to store VecDenses as a *CMat when + // #308 is resolved. + + // Copy a because it is modified during the Lapack call. + r, c := a.Dims() + if r != c { + panic(ErrShape) + } + var sd Dense + sd.Clone(a) + + var vl, vr Dense + var jobvl lapack.LeftEVJob = lapack.None + var jobvr lapack.RightEVJob = lapack.None + if left { + vl = *NewDense(r, r, nil) + jobvl = lapack.ComputeLeftEV + } + if right { + vr = *NewDense(c, c, nil) + jobvr = lapack.ComputeRightEV + } + + wr := getFloats(c, false) + defer putFloats(wr) + wi := getFloats(c, false) + defer putFloats(wi) + + work := []float64{0} + lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, -1) + work = getFloats(int(work[0]), false) + first := lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, len(work)) + putFloats(work) + + if first != 0 { + e.values = nil + return false + } + e.n = r + e.right = right + e.left = left + e.lVectors = &vl + e.rVectors = &vr + values := make([]complex128, r) + for i, v := range wr { + values[i] = complex(v, wi[i]) + } + e.values = values + return true +} + +// Values extracts the eigenvalues of the factorized matrix. If dst is +// non-nil, the values are stored in-place into dst. In this case +// dst must have length n, otherwise Values will panic. If dst is +// nil, then a new slice will be allocated of the proper length and +// filed with the eigenvalues. +// +// Values panics if the Eigen decomposition was not successful. +func (e *Eigen) Values(dst []complex128) []complex128 { + if !e.succFact() { + panic(badFact) + } + if dst == nil { + dst = make([]complex128, e.n) + } + if len(dst) != e.n { + panic(ErrSliceLengthMismatch) + } + copy(dst, e.values) + return dst +} + +// Vectors returns the right eigenvectors of the decomposition. Vectors +// will panic if the right eigenvectors were not computed during the factorization, +// or if the factorization was not successful. +// +// The returned matrix will contain the right eigenvectors of the decomposition +// in the columns of the n×n matrix in the same order as their eigenvalues. +// If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// BUG: This signature and behavior will change when issue #308 is resolved. +func (e *Eigen) Vectors() *Dense { + if !e.succFact() { + panic(badFact) + } + if !e.right { + panic(badNoVect) + } + return DenseCopyOf(e.rVectors) +} + +// LeftVectors returns the left eigenvectors of the decomposition. LeftVectors +// will panic if the left eigenvectors were not computed during the factorization. +// or if the factorization was not successful. +// +// See the documentation in lapack64.Geev for the format of the vectors. +// +// BUG: This signature and behavior will change when issue #308 is resolved. +func (e *Eigen) LeftVectors() *Dense { + if !e.succFact() { + panic(badFact) + } + if !e.left { + panic(badNoVect) + } + return DenseCopyOf(e.lVectors) +} diff --git a/vendor/gonum.org/v1/gonum/mat/eigen_test.go b/vendor/gonum.org/v1/gonum/mat/eigen_test.go new file mode 100644 index 00000000..1980fbe4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/eigen_test.go @@ -0,0 +1,164 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestEigen(t *testing.T) { + for i, test := range []struct { + a *Dense + + values []complex128 + left *Dense + right *Dense + }{ + { + a: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + values: []complex128{1, 1, 1}, + left: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + right: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + }, + } { + var e1, e2, e3, e4 Eigen + ok := e1.Factorize(test.a, true, true) + if !ok { + panic("bad factorization") + } + e2.Factorize(test.a, false, true) + e3.Factorize(test.a, true, false) + e4.Factorize(test.a, false, false) + + v1 := e1.Values(nil) + if !cmplxEqual(v1, test.values) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !Equal(e1.LeftVectors(), test.left) { + t.Errorf("left eigenvector mismatch. Case %v", i) + } + if !Equal(e1.Vectors(), test.right) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + + // Check that the eigenvectors and values are the same in all combinations. + if !cmplxEqual(v1, e2.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !cmplxEqual(v1, e3.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !cmplxEqual(v1, e4.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !Equal(e1.Vectors(), e2.Vectors()) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + if !Equal(e1.LeftVectors(), e3.LeftVectors()) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + + // TODO(btracey): Also add in a test for correctness when #308 is + // resolved and we have a CMat.Mul(). + } +} + +func cmplxEqual(v1, v2 []complex128) bool { + for i, v := range v1 { + if v != v2[i] { + return false + } + } + return true +} + +func TestSymEigen(t *testing.T) { + // Hand coded tests with results from lapack. + for _, test := range []struct { + mat *SymDense + + values []float64 + vectors *Dense + }{ + { + mat: NewSymDense(3, []float64{8, 2, 4, 2, 6, 10, 4, 10, 5}), + values: []float64{-4.707679201365891, 6.294580208480216, 17.413098992885672}, + vectors: NewDense(3, 3, []float64{ + -0.127343483135656, -0.902414161226903, -0.411621572466779, + -0.664177720955769, 0.385801900032553, -0.640331827193739, + 0.736648893495999, 0.191847792659746, -0.648492738712395, + }), + }, + } { + var es EigenSym + ok := es.Factorize(test.mat, true) + if !ok { + t.Errorf("bad factorization") + } + if !floats.EqualApprox(test.values, es.values, 1e-14) { + t.Errorf("Eigenvalue mismatch") + } + if !EqualApprox(test.vectors, es.vectors, 1e-14) { + t.Errorf("Eigenvector mismatch") + } + + var es2 EigenSym + es2.Factorize(test.mat, false) + if !floats.EqualApprox(es2.values, es.values, 1e-14) { + t.Errorf("Eigenvalue mismatch when no vectors computed") + } + } + + // Randomized tests + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{3, 5, 10, 70} { + for cas := 0; cas < 10; cas++ { + a := make([]float64, n*n) + for i := range a { + a[i] = rnd.NormFloat64() + } + s := NewSymDense(n, a) + var es EigenSym + ok := es.Factorize(s, true) + if !ok { + t.Errorf("Bad test") + } + + // Check that the eigenvectors are orthonormal. + if !isOrthonormal(es.vectors, 1e-8) { + t.Errorf("Eigenvectors not orthonormal") + } + + // Check that the eigenvalues are actually eigenvalues. + for i := 0; i < n; i++ { + v := NewVecDense(n, Col(nil, i, es.vectors)) + var m VecDense + m.MulVec(s, v) + + var scal VecDense + scal.ScaleVec(es.values[i], v) + + if !EqualApprox(&m, &scal, 1e-8) { + t.Errorf("Eigenvalue does not match") + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/errors.go b/vendor/gonum.org/v1/gonum/mat/errors.go new file mode 100644 index 00000000..38bd7d5a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/errors.go @@ -0,0 +1,148 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "fmt" + "runtime" + + "gonum.org/v1/gonum/lapack" +) + +// Condition is the condition number of a matrix. The condition +// number is defined as |A| * |A^-1|. +// +// One important use of Condition is during linear solve routines (finding x such +// that A * x = b). The condition number of A indicates the accuracy of +// the computed solution. A Condition error will be returned if the condition +// number of A is sufficiently large. If A is exactly singular to working precision, +// Condition == ∞, and the solve algorithm may have completed early. If Condition +// is large and finite the solve algorithm will be performed, but the computed +// solution may be innacurate. Due to the nature of finite precision arithmetic, +// the value of Condition is only an approximate test of singularity. +type Condition float64 + +func (c Condition) Error() string { + return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c) +} + +// ConditionTolerance is the tolerance limit of the condition number. If the +// condition number is above this value, the matrix is considered singular. +const ConditionTolerance = 1e16 + +const ( + // CondNorm is the matrix norm used for computing the condition number by routines + // in the matrix packages. + CondNorm = lapack.MaxRowSum + + // CondNormTrans is the norm used to compute on A^T to get the same result as + // computing CondNorm on A. + CondNormTrans = lapack.MaxColumnSum +) + +const stackTraceBufferSize = 1 << 20 + +// Maybe will recover a panic with a type mat.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func Maybe(fn func()) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + fn() + return +} + +// MaybeFloat will recover a panic with a type mat.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func MaybeFloat(fn func() float64) (f float64, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + return fn(), nil +} + +// MaybeComplex will recover a panic with a type mat.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func MaybeComplex(fn func() complex128) (f complex128, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + return fn(), nil +} + +// Error represents matrix handling errors. These errors can be recovered by Maybe wrappers. +type Error struct{ string } + +func (err Error) Error() string { return err.string } + +var ( + ErrIndexOutOfRange = Error{"matrix: index out of range"} + ErrRowAccess = Error{"matrix: row index out of range"} + ErrColAccess = Error{"matrix: column index out of range"} + ErrVectorAccess = Error{"matrix: vector index out of range"} + ErrZeroLength = Error{"matrix: zero length in matrix definition"} + ErrRowLength = Error{"matrix: row length mismatch"} + ErrColLength = Error{"matrix: col length mismatch"} + ErrSquare = Error{"matrix: expect square matrix"} + ErrNormOrder = Error{"matrix: invalid norm order for matrix"} + ErrSingular = Error{"matrix: matrix is singular"} + ErrShape = Error{"matrix: dimension mismatch"} + ErrIllegalStride = Error{"matrix: illegal stride"} + ErrPivot = Error{"matrix: malformed pivot list"} + ErrTriangle = Error{"matrix: triangular storage mismatch"} + ErrTriangleSet = Error{"matrix: triangular set out of bounds"} + ErrBandSet = Error{"matrix: band set out of bounds"} + ErrSliceLengthMismatch = Error{"matrix: input slice length mismatch"} + ErrNotPSD = Error{"matrix: input not positive symmetric definite"} + ErrFailedEigen = Error{"matrix: eigendecomposition not successful"} +) + +// ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers. +type ErrorStack struct { + Err error + + // StackTrace is the stack trace + // recovered by Maybe, MaybeFloat + // or MaybeComplex. + StackTrace string +} + +func (err ErrorStack) Error() string { return err.Err.Error() } diff --git a/vendor/gonum.org/v1/gonum/mat/errors_test.go b/vendor/gonum.org/v1/gonum/mat/errors_test.go new file mode 100644 index 00000000..7a1a7dd7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/errors_test.go @@ -0,0 +1,56 @@ +// Copyright ©2013 The gonum 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 mat + +import "testing" + +func leaksPanic(fn func()) (panicked bool) { + defer func() { + r := recover() + panicked = r != nil + }() + Maybe(fn) + return +} + +func TestMaybe(t *testing.T) { + for i, test := range []struct { + fn func() + panics bool + errors bool + }{ + { + fn: func() {}, + panics: false, + errors: false, + }, + { + fn: func() { panic("panic") }, + panics: true, + errors: false, + }, + { + fn: func() { panic(Error{"panic"}) }, + panics: false, + errors: true, + }, + } { + panicked := leaksPanic(test.fn) + if panicked != test.panics { + t.Errorf("unexpected panic state for test %d: got: panicked=%t want: panicked=%t", + i, panicked, test.panics) + } + if test.errors { + err := Maybe(test.fn) + stack, ok := err.(ErrorStack) + if !ok { + t.Errorf("unexpected error type: got:%T want:%T", stack, ErrorStack{}) + } + if stack.StackTrace == "" { + t.Error("expected non-empty stack trace") + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/fao_data_test.go b/vendor/gonum.org/v1/gonum/mat/fao_data_test.go new file mode 100644 index 00000000..e32e1676 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/fao_data_test.go @@ -0,0 +1,122 @@ +// Copyright ©2017 The gonum 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 mat_test + +import "gonum.org/v1/gonum/mat" + +// FAO is a dataset extracted from Food and Agriculture Organization of the +// United Nations "FAO Statistical Pocketbook: World Food and Agriculture 2015". +// pp49-52. +var FAO = struct { + Africa *mat.Dense + Asia *mat.Dense + LatinAmericaCaribbean *mat.Dense + Oceania *mat.Dense +}{ + Africa: mat.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 35.3, 38, 30.7, // Employment in agriculture (%) + 9.2, 20.3, 25.2, // Employment in agriculture, female (%) + 3163, 14718, 20667, // Energy consump, power irrigation (mln kWh) + + 2597, 2717, 2903, // Dietary energy supply (kcal/pc/day) + 113, 116, 123, // Average dietary energy supply adequacy (%) + 58, 55, 52, // Dietary en supp, cereals/roots/tubers (%) + 18.6, 15, 10.8, // Prevalence of undernourishment (%) + 8832, 10241, 13915, // GDP per capita (US$, PPP) + -0.4, -0.2, 50.7, // Cereal import dependency ratio (%) + 78.5, 83, 88.7, // Improved water source (% pop) + + // Production indices (2004-06=100) + 73, 90, 121, // Net food + 72, 89, 123, // Net crops + 82, 92, 123, // Cereals + 51, 77, 141, // Vegetable oils + 74, 94, 119, // Roots and tubers + 58, 86, 127, // Fruit and vegetables + 86, 93, 132, // Sugar + 76, 92, 115, // Livestock + 83, 89, 114, // Milk + 74, 91, 118, // Meat + 72, 92, 119, // Fish + }), + + Asia: mat.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 30.9, 24.5, 27.6, // Employment in agriculture (%) + 40.9, 29.4, 31.1, // Employment in agriculture, female (%) + 7614, 38316, 82411, // Energy consump, power irrigation (mln kWh) + + 2320, 2402, 2581, // Dietary energy supply (kcal/pc/day) + 107, 110, 117, // Average dietary energy supply adequacy (%) + 66, 65, 63, // Dietary en supp, cereals/roots/tubers (%) + 27.6, 25.7, 19.8, // Prevalence of undernourishment (%) + 3315, 3421, 4575, // GDP per capita (US$, PPP) + 25.9, 28.1, 42, // Cereal import dependency ratio (%) + 55.5, 61.1, 68.7, // Improved water source (% pop) + + // Production indices (2004-06=100) + 60, 82, 129, // Net food + 59, 82, 127, // Net crops + 66, 79, 131, // Cereals + 58, 79, 128, // Vegetable oils + 50, 80, 133, // Roots and tubers + 58, 82, 124, // Fruit and vegetables + 76, 94, 114, // Sugar + 65, 84, 126, // Livestock + 59, 77, 125, // Milk + 67, 87, 127, // Meat + 65, 90, 119, // Fish + }), + + LatinAmericaCaribbean: mat.NewDense(14, 3, []float64{ + // 1990, 2000, 2014 + 19.5, 14.2, 15.8, // Employment in agriculture (%) + 13.7, 6.2, 7.6, // Employment in agriculture, female (%) + + 2669, 2787, 3069, // Dietary energy supply (kcal/pc/day) + 117, 120, 129, // Average dietary energy supply adequacy (%) + 42, 41, 40, // Dietary en supp, cereals/roots/tubers (%) + 14.7, 12.1, 5.5, // Prevalence of undernourishment (%) + 9837, 10976, 13915, // GDP per capita (US$, PPP) + 13, 12, 49.7, // Cereal import dependency ratio (%) + 85.1, 89.8, 94, // Improved water source (% pop) + + // Production indices (2004-06=100) + 60, 83, 129, // Net food + 64, 83, 131, // Net crops + 62, 88, 139, // Cereals + 58, 84, 123, // Livestock + 82, 107, 71, // Fish + }), + + Oceania: mat.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 6.2, 17.1, 3.8, // Employment in agriculture (%) + 4.5, 3.9, 4.4, // Employment in agriculture, female (%) + 415, 1028, 8667, // Energy consump, power irrigation (mln kWh) + + 2454, 2436, 2542, // Dietary energy supply (kcal/pc/day) + 113, 112, 114, // Average dietary energy supply adequacy (%) + 49, 50, 48, // Dietary en supp, cereals/roots/tubers (%) + 15.7, 16.1, 14.2, // Prevalence of undernourishment (%) + 2269, 2536, 3110, // GDP per capita (US$, PPP) + 95.2, 95.9, 95.4, // Cereal import dependency ratio (%) + 49.7, 53.2, 55.5, // Improved water source (% pop) + + // Production indices (2004-06=100) + 72, 99, 116, // Net food + 69, 105, 126, // Net crops + 77, 113, 117, // Cereals + 41, 122, 215, // Vegetable oils + 80, 90, 110, // Roots and tubers + 66, 88, 104, // Fruit and vegetables + 70, 104, 71, // Sugar + 79, 97, 107, // Livestock + 56, 92, 113, // Milk + 79, 96, 105, // Meat + 51, 78, 85, // Fish + }), +} diff --git a/vendor/gonum.org/v1/gonum/mat/format.go b/vendor/gonum.org/v1/gonum/mat/format.go new file mode 100644 index 00000000..8ab70ed3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/format.go @@ -0,0 +1,238 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "fmt" + "strconv" +) + +// Formatted returns a fmt.Formatter for the matrix m using the given options. +func Formatted(m Matrix, options ...FormatOption) fmt.Formatter { + f := formatter{ + matrix: m, + dot: '.', + } + for _, o := range options { + o(&f) + } + return f +} + +type formatter struct { + matrix Matrix + prefix string + margin int + dot byte + squeeze bool +} + +// FormatOption is a functional option for matrix formatting. +type FormatOption func(*formatter) + +// Prefix sets the formatted prefix to the string p. Prefix is a string that is prepended to +// each line of output. +func Prefix(p string) FormatOption { + return func(f *formatter) { f.prefix = p } +} + +// Excerpt sets the maximum number of rows and columns to print at the margins of the matrix +// to m. If m is zero or less all elements are printed. +func Excerpt(m int) FormatOption { + return func(f *formatter) { f.margin = m } +} + +// DotByte sets the dot character to b. The dot character is used to replace zero elements +// if the result is printed with the fmt ' ' verb flag. Without a DotByte option, the default +// dot character is '.'. +func DotByte(b byte) FormatOption { + return func(f *formatter) { f.dot = b } +} + +// Squeeze sets the printing behaviour to minimise column width for each individual column. +func Squeeze() FormatOption { + return func(f *formatter) { f.squeeze = true } +} + +// Format satisfies the fmt.Formatter interface. +func (f formatter) Format(fs fmt.State, c rune) { + if c == 'v' && fs.Flag('#') { + fmt.Fprintf(fs, "%#v", f.matrix) + return + } + format(f.matrix, f.prefix, f.margin, f.dot, f.squeeze, fs, c) +} + +// format prints a pretty representation of m to the fs io.Writer. The format character c +// specifies the numerical representation of of elements; valid values are those for float64 +// specified in the fmt package, with their associated flags. In addition to this, a space +// preceding a verb indicates that zero values should be represented by the dot character. +// The printed range of the matrix can be limited by specifying a positive value for margin; +// If margin is greater than zero, only the first and last margin rows/columns of the matrix +// are output. If squeeze is true, column widths are determined on a per-column basis. +// +// format will not provide Go syntax output. +func format(m Matrix, prefix string, margin int, dot byte, squeeze bool, fs fmt.State, c rune) { + rows, cols := m.Dims() + + var printed int + if margin <= 0 { + printed = rows + if cols > printed { + printed = cols + } + } else { + printed = margin + } + + prec, pOk := fs.Precision() + if !pOk { + prec = -1 + } + + var ( + maxWidth int + widths widther + buf, pad []byte + ) + if squeeze { + widths = make(columnWidth, cols) + } else { + widths = new(uniformWidth) + } + switch c { + case 'v', 'e', 'E', 'f', 'F', 'g', 'G': + if c == 'v' { + buf, maxWidth = maxCellWidth(m, 'g', printed, prec, widths) + } else { + buf, maxWidth = maxCellWidth(m, c, printed, prec, widths) + } + default: + fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) + return + } + width, _ := fs.Width() + width = max(width, maxWidth) + pad = make([]byte, max(width, 2)) + for i := range pad { + pad[i] = ' ' + } + + first := true + if rows > 2*printed || cols > 2*printed { + first = false + fmt.Fprintf(fs, "Dims(%d, %d)\n", rows, cols) + } + + skipZero := fs.Flag(' ') + for i := 0; i < rows; i++ { + if !first { + fmt.Fprint(fs, prefix) + } + first = false + var el string + switch { + case rows == 1: + fmt.Fprint(fs, "[") + el = "]" + case i == 0: + fmt.Fprint(fs, "⎡") + el = "⎤\n" + case i < rows-1: + fmt.Fprint(fs, "⎢") + el = "⎥\n" + default: + fmt.Fprint(fs, "⎣") + el = "⎦" + } + + for j := 0; j < cols; j++ { + if j >= printed && j < cols-printed { + j = cols - printed - 1 + if i == 0 || i == rows-1 { + fmt.Fprint(fs, "... ... ") + } else { + fmt.Fprint(fs, " ") + } + continue + } + + v := m.At(i, j) + if v == 0 && skipZero { + buf = buf[:1] + buf[0] = dot + } else { + if c == 'v' { + buf = strconv.AppendFloat(buf[:0], v, 'g', prec, 64) + } else { + buf = strconv.AppendFloat(buf[:0], v, byte(c), prec, 64) + } + } + if fs.Flag('-') { + fs.Write(buf) + fs.Write(pad[:widths.width(j)-len(buf)]) + } else { + fs.Write(pad[:widths.width(j)-len(buf)]) + fs.Write(buf) + } + + if j < cols-1 { + fs.Write(pad[:2]) + } + } + + fmt.Fprint(fs, el) + + if i >= printed-1 && i < rows-printed && 2*printed < rows { + i = rows - printed - 1 + fmt.Fprintf(fs, "%s .\n%[1]s .\n%[1]s .\n", prefix) + continue + } + } +} + +func maxCellWidth(m Matrix, c rune, printed, prec int, w widther) ([]byte, int) { + var ( + buf = make([]byte, 0, 64) + rows, cols = m.Dims() + max int + ) + for i := 0; i < rows; i++ { + if i >= printed-1 && i < rows-printed && 2*printed < rows { + i = rows - printed - 1 + continue + } + for j := 0; j < cols; j++ { + if j >= printed && j < cols-printed { + continue + } + + buf = strconv.AppendFloat(buf, m.At(i, j), byte(c), prec, 64) + if len(buf) > max { + max = len(buf) + } + if len(buf) > w.width(j) { + w.setWidth(j, len(buf)) + } + buf = buf[:0] + } + } + return buf, max +} + +type widther interface { + width(i int) int + setWidth(i, w int) +} + +type uniformWidth int + +func (u *uniformWidth) width(_ int) int { return int(*u) } +func (u *uniformWidth) setWidth(_, w int) { *u = uniformWidth(w) } + +type columnWidth []int + +func (c columnWidth) width(i int) int { return c[i] } +func (c columnWidth) setWidth(i, w int) { c[i] = w } diff --git a/vendor/gonum.org/v1/gonum/mat/format_example_test.go b/vendor/gonum.org/v1/gonum/mat/format_example_test.go new file mode 100644 index 00000000..59f26c70 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/format_example_test.go @@ -0,0 +1,112 @@ +// Copyright ©2015 The gonum 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 mat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/mat" +) + +func ExampleFormatted() { + a := mat.NewDense(3, 3, []float64{1, 2, 3, 0, 4, 5, 0, 0, 6}) + + // Create a matrix formatting value with a prefix and calculating each column + // width individually... + fa := mat.Formatted(a, mat.Prefix(" "), mat.Squeeze()) + + // and then print with and without zero value elements. + fmt.Printf("with all values:\na = %v\n\n", fa) + fmt.Printf("with only non-zero values:\na = % v\n\n", fa) + + // Modify the matrix... + a.Set(0, 2, 0) + + // and print it without zero value elements. + fmt.Printf("after modification with only non-zero values:\na = % v\n\n", fa) + + // Modify the matrix again... + a.Set(0, 2, 123.456) + + // and print it using scientific notation for large exponents. + fmt.Printf("after modification with scientific notation:\na = %.2g\n\n", fa) + // See golang.org/pkg/fmt/ floating-point verbs for a comprehensive list. + + // Output: + // with all values: + // a = ⎡1 2 3⎤ + // ⎢0 4 5⎥ + // ⎣0 0 6⎦ + // + // with only non-zero values: + // a = ⎡1 2 3⎤ + // ⎢. 4 5⎥ + // ⎣. . 6⎦ + // + // after modification with only non-zero values: + // a = ⎡1 2 .⎤ + // ⎢. 4 5⎥ + // ⎣. . 6⎦ + // + // after modification with scientific notation: + // a = ⎡1 2 1.2e+02⎤ + // ⎢0 4 5⎥ + // ⎣0 0 6⎦ +} + +func ExampleExcerpt() { + // Excerpt allows diagnostic display of very large + // matrices and vectors. + + // The big matrix is too large to properly print... + big := mat.NewDense(100, 100, nil) + for i := 0; i < 100; i++ { + big.Set(i, i, 1) + } + + // so only print corner excerpts of the matrix. + fmt.Printf("excerpt big identity matrix: %v\n\n", + mat.Formatted(big, mat.Prefix(" "), mat.Excerpt(3))) + + // The long vector is also too large, ... + long := mat.NewVecDense(100, nil) + for i := 0; i < 100; i++ { + long.SetVec(i, float64(i)) + } + + // ... so print end excerpts of the vector, + fmt.Printf("excerpt long column vector: %v\n\n", + mat.Formatted(long, mat.Prefix(" "), mat.Excerpt(3))) + // or its transpose. + fmt.Printf("excerpt long row vector: %v\n", + mat.Formatted(long.T(), mat.Prefix(" "), mat.Excerpt(3))) + + // Output: + // excerpt big identity matrix: Dims(100, 100) + // ⎡1 0 0 ... ... 0 0 0⎤ + // ⎢0 1 0 0 0 0⎥ + // ⎢0 0 1 0 0 0⎥ + // . + // . + // . + // ⎢0 0 0 1 0 0⎥ + // ⎢0 0 0 0 1 0⎥ + // ⎣0 0 0 ... ... 0 0 1⎦ + // + // excerpt long column vector: Dims(100, 1) + // ⎡ 0⎤ + // ⎢ 1⎥ + // ⎢ 2⎥ + // . + // . + // . + // ⎢97⎥ + // ⎢98⎥ + // ⎣99⎦ + // + // excerpt long row vector: Dims(1, 100) + // [ 0 1 2 ... ... 97 98 99] + +} diff --git a/vendor/gonum.org/v1/gonum/mat/format_test.go b/vendor/gonum.org/v1/gonum/mat/format_test.go new file mode 100644 index 00000000..2b725571 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/format_test.go @@ -0,0 +1,150 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "fmt" + "math" + "testing" +) + +func TestFormat(t *testing.T) { + type rp struct { + format string + output string + } + sqrt := func(_, _ int, v float64) float64 { return math.Sqrt(v) } + for i, test := range []struct { + m fmt.Formatter + rep []rp + }{ + // Dense matrix representation + { + Formatted(NewDense(3, 3, []float64{0, 0, 0, 0, 0, 0, 0, 0, 0})), + []rp{ + {"%v", "⎡0 0 0⎤\n⎢0 0 0⎥\n⎣0 0 0⎦"}, + {"% f", "⎡. . .⎤\n⎢. . .⎥\n⎣. . .⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{0, 0, 0, 0, 0, 0, 0, 0, 0}}, capRows:3, capCols:3}"}, + {"%s", "%!s(*mat.Dense=Dims(3, 3))"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 1, 1, 1, 1, 1, 1, 1, 1})), + []rp{ + {"%v", "⎡1 1 1⎤\n⎢1 1 1⎥\n⎣1 1 1⎦"}, + {"% f", "⎡1 1 1⎤\n⎢1 1 1⎥\n⎣1 1 1⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 1, 1, 1, 1, 1, 1, 1, 1}), Prefix("\t")), + []rp{ + {"%v", "⎡1 1 1⎤\n\t⎢1 1 1⎥\n\t⎣1 1 1⎦"}, + {"% f", "⎡1 1 1⎤\n\t⎢1 1 1⎥\n\t⎣1 1 1⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 0, 0, 0, 1, 0, 0, 0, 1})), + []rp{ + {"%v", "⎡1 0 0⎤\n⎢0 1 0⎥\n⎣0 0 1⎦"}, + {"% f", "⎡1 . .⎤\n⎢. 1 .⎥\n⎣. . 1⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 0, 0, 0, 1, 0, 0, 0, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(2, 3, []float64{1, 2, 3, 4, 5, 6})), + []rp{ + {"%v", "⎡1 2 3⎤\n⎣4 5 6⎦"}, + {"% f", "⎡1 2 3⎤\n⎣4 5 6⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{1, 2, 3, 4, 5, 6}}, capRows:2, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 2, []float64{1, 2, 3, 4, 5, 6})), + []rp{ + {"%v", "⎡1 2⎤\n⎢3 4⎥\n⎣5 6⎦"}, + {"% f", "⎡1 2⎤\n⎢3 4⎥\n⎣5 6⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:2, Stride:2, Data:[]float64{1, 2, 3, 4, 5, 6}}, capRows:3, capCols:2}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(2, 3, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m) + }(), + []rp{ + {"%v", "⎡ 0 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00 1.41⎤\n⎣1.73 2.00 2.24⎦"}, + {"% f", "⎡ . 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:2, capCols:3}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(3, 2, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m) + }(), + []rp{ + {"%v", "⎡ 0 1⎤\n⎢1.4142135623730951 1.7320508075688772⎥\n⎣ 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00⎤\n⎢1.41 1.73⎥\n⎣2.00 2.24⎦"}, + {"% f", "⎡ . 1⎤\n⎢1.4142135623730951 1.7320508075688772⎥\n⎣ 2 2.23606797749979⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:3, Cols:2, Stride:2, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:3, capCols:2}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(2, 3, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m, Squeeze()) + }(), + []rp{ + {"%v", "⎡ 0 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00 1.41⎤\n⎣1.73 2.00 2.24⎦"}, + {"% f", "⎡ . 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%#v", "&mat.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:2, capCols:3}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(1, 10, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(1, 10)\n[ 1 2 3 ... ... 8 9 10]"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(10, 1, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(10, 1)\n⎡ 1⎤\n⎢ 2⎥\n⎢ 3⎥\n .\n .\n .\n⎢ 8⎥\n⎢ 9⎥\n⎣10⎦"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(10, 10, nil) + for i := 0; i < 10; i++ { + m.Set(i, i, 1) + } + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(10, 10)\n⎡1 0 0 ... ... 0 0 0⎤\n⎢0 1 0 0 0 0⎥\n⎢0 0 1 0 0 0⎥\n .\n .\n .\n⎢0 0 0 1 0 0⎥\n⎢0 0 0 0 1 0⎥\n⎣0 0 0 ... ... 0 0 1⎦"}, + }, + }, + } { + for j, rp := range test.rep { + got := fmt.Sprintf(rp.format, test.m) + if got != rp.output { + t.Errorf("unexpected format result test %d part %d:\ngot:\n%s\nwant:\n%s", i, j, got, rp.output) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/gsvd.go b/vendor/gonum.org/v1/gonum/mat/gsvd.go new file mode 100644 index 00000000..663a0729 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/gsvd.go @@ -0,0 +1,371 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// GSVD is a type for creating and using the Generalized Singular Value Decomposition +// (GSVD) of a matrix. +// +// The factorization is a linear transformation of the data sets from the given +// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" +// spaces. +type GSVD struct { + kind GSVDKind + + r, p, c, k, l int + s1, s2 []float64 + a, b, u, v, q blas64.General + + work []float64 + iwork []int +} + +// Factorize computes the generalized singular value decomposition (GSVD) of the input +// the r×c matrix A and the p×c matrix B. The singular values of A and B are computed +// in all cases, while the singular vectors are optionally computed depending on the +// input kind. +// +// The full singular value decomposition (kind == GSVDU|GSVDV|GSVDQ) deconstructs A and B as +// A = U * Σ₁ * [ 0 R ] * Q^T +// +// B = V * Σ₂ * [ 0 R ] * Q^T +// where Σ₁ and Σ₂ are r×(k+l) and p×(k+l) diagonal matrices of singular values, and +// U, V and Q are r×r, p×p and c×c orthogonal matrices of singular vectors. k+l is the +// effective numerical rank of the matrix [ A^T B^T ]^T. +// +// It is frequently not necessary to compute the full GSVD. Computation time and +// storage costs can be reduced using the appropriate kind. Either only the singular +// values can be computed (kind == SVDNone), or in conjunction with specific singular +// vectors (kind bit set according to matrix.GSVDU, matrix.GSVDV and matrix.GSVDQ). +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) { + r, c := a.Dims() + gsvd.r, gsvd.c = r, c + p, c := b.Dims() + gsvd.p = p + if gsvd.c != c { + panic(ErrShape) + } + var jobU, jobV, jobQ lapack.GSVDJob + switch { + default: + panic("gsvd: bad input kind") + case kind == GSVDNone: + jobU = lapack.GSVDNone + jobV = lapack.GSVDNone + jobQ = lapack.GSVDNone + case (GSVDU|GSVDV|GSVDQ)&kind != 0: + if GSVDU&kind != 0 { + jobU = lapack.GSVDU + gsvd.u = blas64.General{ + Rows: r, + Cols: r, + Stride: r, + Data: use(gsvd.u.Data, r*r), + } + } + if GSVDV&kind != 0 { + jobV = lapack.GSVDV + gsvd.v = blas64.General{ + Rows: p, + Cols: p, + Stride: p, + Data: use(gsvd.v.Data, p*p), + } + } + if GSVDQ&kind != 0 { + jobQ = lapack.GSVDQ + gsvd.q = blas64.General{ + Rows: c, + Cols: c, + Stride: c, + Data: use(gsvd.q.Data, c*c), + } + } + } + + // A and B are destroyed on call, so copy the matrices. + aCopy := DenseCopyOf(a) + bCopy := DenseCopyOf(b) + + gsvd.s1 = use(gsvd.s1, c) + gsvd.s2 = use(gsvd.s2, c) + + gsvd.iwork = useInt(gsvd.iwork, c) + + gsvd.work = use(gsvd.work, 1) + lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, -1, gsvd.iwork) + gsvd.work = use(gsvd.work, int(gsvd.work[0])) + gsvd.k, gsvd.l, ok = lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, len(gsvd.work), gsvd.iwork) + if ok { + gsvd.a = aCopy.mat + gsvd.b = bCopy.mat + gsvd.kind = kind + } + return ok +} + +// Kind returns the matrix.GSVDKind of the decomposition. If no decomposition has been +// computed, Kind returns 0. +func (gsvd *GSVD) Kind() GSVDKind { + return gsvd.kind +} + +// Rank returns the k and l terms of the rank of [ A^T B^T ]^T. +func (gsvd *GSVD) Rank() (k, l int) { + return gsvd.k, gsvd.l +} + +// GeneralizedValues returns the generalized singular values of the factorized matrices. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and GeneralizedValues will +// panic with matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// GeneralizedValues will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if v == nil { + v = make([]float64, d-k) + } + if len(v) != d-k { + panic(ErrSliceLengthMismatch) + } + floats.DivTo(v, gsvd.s1[k:d], gsvd.s2[k:d]) + return v +} + +// ValuesA returns the singular values of the factorized A matrix. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and ValuesA will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// ValuesA will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) ValuesA(s []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if s == nil { + s = make([]float64, d-k) + } + if len(s) != d-k { + panic(ErrSliceLengthMismatch) + } + copy(s, gsvd.s1[k:min(r, c)]) + return s +} + +// ValuesB returns the singular values of the factorized B matrix. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and ValuesB will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// ValuesB will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) ValuesB(s []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if s == nil { + s = make([]float64, d-k) + } + if len(s) != d-k { + panic(ErrSliceLengthMismatch) + } + copy(s, gsvd.s2[k:d]) + return s +} + +// ZeroRTo extracts the matrix [ 0 R ] from the singular value decomposition, storing +// the result in-place into dst. [ 0 R ] is size (k+l)×c. +// If dst is nil, a new matrix is allocated. The resulting ZeroR matrix is returned. +// +// ZeroRTo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) ZeroRTo(dst *Dense) *Dense { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + l := gsvd.l + h := min(k+l, r) + if dst == nil { + dst = NewDense(k+l, c, nil) + } else { + dst.reuseAsZeroed(k+l, c) + } + a := Dense{ + mat: gsvd.a, + capRows: r, + capCols: c, + } + dst.Slice(0, h, c-k-l, c).(*Dense). + Copy(a.Slice(0, h, c-k-l, c)) + if r < k+l { + b := Dense{ + mat: gsvd.b, + capRows: gsvd.p, + capCols: c, + } + dst.Slice(r, k+l, c+r-k-l, c).(*Dense). + Copy(b.Slice(r-k, l, c+r-k-l, c)) + } + return dst +} + +// SigmaATo extracts the matrix Σ₁ from the singular value decomposition, storing +// the result in-place into dst. Σ₁ is size r×(k+l). +// If dst is nil, a new matrix is allocated. The resulting SigmaA matrix is returned. +// +// SigmaATo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) SigmaATo(dst *Dense) *Dense { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + k := gsvd.k + l := gsvd.l + if dst == nil { + dst = NewDense(r, k+l, nil) + } else { + dst.reuseAsZeroed(r, k+l) + } + for i := 0; i < k; i++ { + dst.set(i, i, 1) + } + for i := k; i < min(r, k+l); i++ { + dst.set(i, i, gsvd.s1[i]) + } + return dst +} + +// SigmaBTo extracts the matrix Σ₂ from the singular value decomposition, storing +// the result in-place into dst. Σ₂ is size p×(k+l). +// If dst is nil, a new matrix is allocated. The resulting SigmaB matrix is returned. +// +// SigmaBTo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) SigmaBTo(dst *Dense) *Dense { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + p := gsvd.p + k := gsvd.k + l := gsvd.l + if dst == nil { + dst = NewDense(p, k+l, nil) + } else { + dst.reuseAsZeroed(p, k+l) + } + for i := 0; i < min(l, r-k); i++ { + dst.set(i, i+k, gsvd.s2[k+i]) + } + for i := r - k; i < l; i++ { + dst.set(i, i+k, 1) + } + return dst +} + +// UTo extracts the matrix U from the singular value decomposition, storing +// the result in-place into dst. U is size r×r. +// If dst is nil, a new matrix is allocated. The resulting U matrix is returned. +// +// UTo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) UTo(dst *Dense) *Dense { + if gsvd.kind&GSVDU == 0 { + panic("mat: improper GSVD kind") + } + r := gsvd.u.Rows + c := gsvd.u.Cols + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + tmp := &Dense{ + mat: gsvd.u, + capRows: r, + capCols: c, + } + dst.Copy(tmp) + return dst +} + +// VTo extracts the matrix V from the singular value decomposition, storing +// the result in-place into dst. V is size p×p. +// If dst is nil, a new matrix is allocated. The resulting V matrix is returned. +// +// VTo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) VTo(dst *Dense) *Dense { + if gsvd.kind&GSVDV == 0 { + panic("mat: improper GSVD kind") + } + r := gsvd.v.Rows + c := gsvd.v.Cols + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + tmp := &Dense{ + mat: gsvd.v, + capRows: r, + capCols: c, + } + dst.Copy(tmp) + return dst +} + +// QTo extracts the matrix Q from the singular value decomposition, storing +// the result in-place into dst. Q is size c×c. +// If dst is nil, a new matrix is allocated. The resulting Q matrix is returned. +// +// QTo will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) QTo(dst *Dense) *Dense { + if gsvd.kind&GSVDQ == 0 { + panic("mat: improper GSVD kind") + } + r := gsvd.q.Rows + c := gsvd.q.Cols + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + tmp := &Dense{ + mat: gsvd.q, + capRows: r, + capCols: c, + } + dst.Copy(tmp) + return dst +} diff --git a/vendor/gonum.org/v1/gonum/mat/gsvd_example_test.go b/vendor/gonum.org/v1/gonum/mat/gsvd_example_test.go new file mode 100644 index 00000000..48898ccc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/gsvd_example_test.go @@ -0,0 +1,85 @@ +// Copyright ©2017 The gonum 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 mat_test + +import ( + "fmt" + "log" + "math" + + "gonum.org/v1/gonum/mat" +) + +func ExampleGSVD() { + // Perform a GSVD factorization on food production/consumption data for the + // three years 1990, 2000 and 2014, for Africa and Latin America/Caribbean. + // + // See Lee et al. doi:10.1371/journal.pone.0030098 and + // Alter at al. doi:10.1073/pnas.0530258100 for more details. + var gsvd mat.GSVD + ok := gsvd.Factorize(FAO.Africa, FAO.LatinAmericaCaribbean, mat.GSVDU|mat.GSVDV|mat.GSVDQ) + if !ok { + log.Fatal("GSVD factorization failed") + } + + u := gsvd.UTo(nil) + v := gsvd.VTo(nil) + + s1 := gsvd.ValuesA(nil) + s2 := gsvd.ValuesB(nil) + + fmt.Printf("Africa\n\ts1 = %.4f\n\n\tU = %.4f\n\n", + s1, mat.Formatted(u, mat.Prefix("\t "), mat.Excerpt(2))) + fmt.Printf("Latin America/Caribbean\n\ts2 = %.4f\n\n\tV = %.4f\n", + s2, mat.Formatted(v, mat.Prefix("\t "), mat.Excerpt(2))) + + var q mat.Dense + q.Mul(gsvd.ZeroRTo(nil), gsvd.QTo(nil)) + fmt.Printf("\nCommon basis vectors\n\n\tQ^T = %.4f\n", + mat.Formatted(q.T(), mat.Prefix("\t "))) + + // Calculate the antisymmetric angular distances for each eigenvariable. + fmt.Println("\nSignificance:") + for i := 0; i < 3; i++ { + fmt.Printf("\teigenvar_%d: %+.4f\n", i, math.Atan(s1[i]/s2[i])-math.Pi/4) + } + + // Output: + // + // Africa + // s1 = [1.0000 0.9344 0.5118] + // + // U = Dims(21, 21) + // ⎡-0.0005 0.0142 ... ... -0.0060 -0.0055⎤ + // ⎢-0.0010 0.0019 0.0071 0.0075⎥ + // . + // . + // . + // ⎢-0.0007 -0.0024 0.9999 -0.0001⎥ + // ⎣-0.0010 -0.0016 ... ... -0.0001 0.9999⎦ + // + // Latin America/Caribbean + // s2 = [0.0047 0.3563 0.8591] + // + // V = Dims(14, 14) + // ⎡ 0.1362 0.0008 ... ... 0.0700 0.2636⎤ + // ⎢ 0.1830 -0.0040 0.2908 0.7834⎥ + // . + // . + // . + // ⎢-0.2598 -0.0324 0.9339 -0.2170⎥ + // ⎣-0.8386 0.1494 ... ... -0.1639 0.4121⎦ + // + // Common basis vectors + // + // Q^T = ⎡ -8172.4084 -4524.2933 4813.9616⎤ + // ⎢ 22581.8020 12397.1070 -16364.8933⎥ + // ⎣ -8910.8462 -10902.1488 15762.8719⎦ + // + // Significance: + // eigenvar_0: +0.7807 + // eigenvar_1: +0.4211 + // eigenvar_2: -0.2482 +} diff --git a/vendor/gonum.org/v1/gonum/mat/gsvd_test.go b/vendor/gonum.org/v1/gonum/mat/gsvd_test.go new file mode 100644 index 00000000..6e8ef0f5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/gsvd_test.go @@ -0,0 +1,117 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestGSVD(t *testing.T) { + const tol = 1e-10 + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, p, n int + }{ + {5, 3, 5}, + {5, 3, 3}, + {3, 3, 5}, + {5, 5, 5}, + {5, 5, 3}, + {3, 5, 5}, + {150, 150, 150}, + {200, 150, 150}, + {150, 150, 200}, + {150, 200, 150}, + {200, 200, 150}, + {150, 200, 200}, + } { + m := test.m + p := test.p + n := test.n + for trial := 0; trial < 10; trial++ { + a := NewDense(m, n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rnd.NormFloat64() + } + aCopy := DenseCopyOf(a) + + b := NewDense(p, n, nil) + for i := range b.mat.Data { + b.mat.Data[i] = rnd.NormFloat64() + } + bCopy := DenseCopyOf(b) + + // Test Full decomposition. + var gsvd GSVD + ok := gsvd.Factorize(a, b, GSVDU|GSVDV|GSVDQ) + if !ok { + t.Errorf("GSVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to GSVD.Factorize with GSVDU|GSVDV|GSVDQ") + } + if !Equal(b, bCopy) { + t.Errorf("B changed during call to GSVD.Factorize with GSVDU|GSVDV|GSVDQ") + } + c, s, sigma1, sigma2, zeroR, u, v, q := extractGSVD(&gsvd) + var ansU, ansV, d1R, d2R Dense + ansU.Product(u.T(), a, q) + ansV.Product(v.T(), b, q) + d1R.Mul(sigma1, zeroR) + d2R.Mul(sigma2, zeroR) + if !EqualApprox(&ansU, &d1R, tol) { + t.Errorf("Answer mismatch with GSVDU|GSVDV|GSVDQ\nU^T * A * Q:\n% 0.2f\nΣ₁ * [ 0 R ]:\n% 0.2f", + Formatted(&ansU), Formatted(&d1R)) + } + if !EqualApprox(&ansV, &d2R, tol) { + t.Errorf("Answer mismatch with GSVDU|GSVDV|GSVDQ\nV^T * B *Q:\n% 0.2f\nΣ₂ * [ 0 R ]:\n% 0.2f", + Formatted(&d2R), Formatted(&ansV)) + } + + // Check C^2 + S^2 = I. + for i := range c { + d := c[i]*c[i] + s[i]*s[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("c_%d^2 + s_%d^2 != 1: got: %v", i, i, d) + } + } + + // Test None decomposition. + ok = gsvd.Factorize(a, b, GSVDNone) + if !ok { + t.Errorf("GSVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to GSVD with GSVDNone") + } + if !Equal(b, bCopy) { + t.Errorf("B changed during call to GSVD with GSVDNone") + } + cNone := gsvd.ValuesA(nil) + if !floats.EqualApprox(c, cNone, tol) { + t.Errorf("Singular value mismatch between GSVDU|GSVDV|GSVDQ and GSVDNone decomposition") + } + sNone := gsvd.ValuesB(nil) + if !floats.EqualApprox(s, sNone, tol) { + t.Errorf("Singular value mismatch between GSVDU|GSVDV|GSVDQ and GSVDNone decomposition") + } + } + } +} + +func extractGSVD(gsvd *GSVD) (c, s []float64, s1, s2, zR, u, v, q *Dense) { + s1 = gsvd.SigmaATo(nil) + s2 = gsvd.SigmaBTo(nil) + zR = gsvd.ZeroRTo(nil) + u = gsvd.UTo(nil) + v = gsvd.VTo(nil) + q = gsvd.QTo(nil) + c = gsvd.ValuesA(nil) + s = gsvd.ValuesB(nil) + return c, s, s1, s2, zR, u, v, q +} diff --git a/vendor/gonum.org/v1/gonum/mat/hogsvd.go b/vendor/gonum.org/v1/gonum/mat/hogsvd.go new file mode 100644 index 00000000..2d3c0403 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/hogsvd.go @@ -0,0 +1,213 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "errors" + + "gonum.org/v1/gonum/blas/blas64" +) + +// HOGSVD is a type for creating and using the Higher Order Generalized Singular Value +// Decomposition (HOGSVD) of a set of matrices. +// +// The factorization is a linear transformation of the data sets from the given +// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" +// spaces. +type HOGSVD struct { + n int + v *Dense + b []Dense + + err error +} + +// Factorize computes the higher order generalized singular value decomposition (HOGSVD) +// of the n input r_i×c column tall matrices in m. HOGSV extends the GSVD case from 2 to n +// input matrices. +// +// M_0 = U_0 * Σ_0 * V^T +// M_1 = U_1 * Σ_1 * V^T +// . +// . +// . +// M_{n-1} = U_{n-1} * Σ_{n-1} * V^T +// +// where U_i are r_i×c matrices of singular vectors, Σ are c×c matrices singular values, and V +// is a c×c matrix of singular vectors. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (gsvd *HOGSVD) Factorize(m ...Matrix) (ok bool) { + // Factorize performs the HOGSVD factorisation + // essentially as described by Ponnapalli et al. + // https://doi.org/10.1371/journal.pone.0028072 + + if len(m) < 2 { + panic("hogsvd: too few matrices") + } + gsvd.n = 0 + + r, c := m[0].Dims() + a := make([]Cholesky, len(m)) + var ts SymDense + for i, d := range m { + rd, cd := d.Dims() + if rd < cd { + gsvd.err = ErrShape + return false + } + if rd > r { + r = rd + } + if cd != c { + panic(ErrShape) + } + ts.Reset() + ts.SymOuterK(1, d.T()) + ok = a[i].Factorize(&ts) + if !ok { + gsvd.err = errors.New("hogsvd: cholesky decomposition failed") + return false + } + } + + s := getWorkspace(c, c, true) + defer putWorkspace(s) + sij := getWorkspace(c, c, false) + defer putWorkspace(sij) + for i, ai := range a { + for _, aj := range a[i+1:] { + gsvd.err = ai.SolveChol(sij, &aj) + if gsvd.err != nil { + return false + } + s.Add(s, sij) + + gsvd.err = aj.SolveChol(sij, &ai) + if gsvd.err != nil { + return false + } + s.Add(s, sij) + } + } + s.Scale(1/float64(len(m)*(len(m)-1)), s) + + var eig Eigen + ok = eig.Factorize(s.T(), false, true) + if !ok { + gsvd.err = errors.New("hogsvd: eigen decomposition failed") + return false + } + v := eig.Vectors() + for j := 0; j < c; j++ { + cv := v.ColView(j) + cv.ScaleVec(1/blas64.Nrm2(c, cv.mat), cv) + } + + b := make([]Dense, len(m)) + biT := getWorkspace(c, r, false) + defer putWorkspace(biT) + for i, d := range m { + // All calls to reset will leave a zeroed + // matrix with capacity to store the result + // without additional allocation. + biT.Reset() + gsvd.err = biT.Solve(v, d.T()) + if gsvd.err != nil { + return false + } + b[i].Clone(biT.T()) + } + + gsvd.n = len(m) + gsvd.v = v + gsvd.b = b + return true +} + +// Err returns the reason for a factorization failure. +func (gsvd *HOGSVD) Err() error { + return gsvd.err +} + +// Len returns the number of matrices that have been factorized. If Len returns +// zero, the factorization was not successful. +func (gsvd *HOGSVD) Len() int { + return gsvd.n +} + +// UTo extracts the matrix U_n from the singular value decomposition, storing +// the result in-place into dst. U_n is size r×c. +// If dst is nil, a new matrix is allocated. The resulting U matrix is returned. +// +// UTo will panic if the receiver does not contain a successful factorization. +func (gsvd *HOGSVD) UTo(dst *Dense, n int) *Dense { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + if n < 0 || gsvd.n <= n { + panic("hogsvd: invalid index") + } + + if dst == nil { + r, c := gsvd.b[n].Dims() + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(gsvd.b[n].Dims()) + } + dst.Copy(&gsvd.b[n]) + for j, f := range gsvd.Values(nil, n) { + v := dst.ColView(j) + v.ScaleVec(1/f, v) + } + return dst +} + +// Values returns the nth set of singular values of the factorized system. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length c, and Values will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// Values will panic if the receiver does not contain a successful factorization. +func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + if n < 0 || gsvd.n <= n { + panic("hogsvd: invalid index") + } + + r, c := gsvd.b[n].Dims() + if s == nil { + s = make([]float64, c) + } else if len(s) != c { + panic(ErrSliceLengthMismatch) + } + for j := 0; j < c; j++ { + s[j] = blas64.Nrm2(r, gsvd.b[n].ColView(j).mat) + } + return s +} + +// VTo extracts the matrix V from the singular value decomposition, storing +// the result in-place into dst. V is size c×c. +// If dst is nil, a new matrix is allocated. The resulting V matrix is returned. +// +// VTo will panic if the receiver does not contain a successful factorization. +func (gsvd *HOGSVD) VTo(dst *Dense) *Dense { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + if dst == nil { + r, c := gsvd.v.Dims() + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(gsvd.v.Dims()) + } + dst.Copy(gsvd.v) + return dst +} diff --git a/vendor/gonum.org/v1/gonum/mat/hogsvd_example_test.go b/vendor/gonum.org/v1/gonum/mat/hogsvd_example_test.go new file mode 100644 index 00000000..a1651448 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/hogsvd_example_test.go @@ -0,0 +1,134 @@ +// Copyright ©2017 The gonum 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 mat_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/mat" +) + +func ExampleHOGSVD() { + // Perform an HOGSVD factorization on food production/consumption data for the + // three years 1990, 2000 and 2014. + // + // See Ponnapalli et al. doi:10.1371/journal.pone.0028072 and + // Alter at al. doi:10.1073/pnas.0530258100 for more details. + var gsvd mat.HOGSVD + ok := gsvd.Factorize(FAO.Africa, FAO.Asia, FAO.LatinAmericaCaribbean, FAO.Oceania) + if !ok { + log.Fatalf("HOGSVD factorization failed: %v", gsvd.Err()) + } + + for i, n := range []string{"Africa", "Asia", "Latin America/Caribbean", "Oceania"} { + u := gsvd.UTo(nil, i) + s := gsvd.Values(nil, i) + fmt.Printf("%s\n\ts_%d = %.4f\n\n\tU_%[2]d = %.4[4]f\n", + n, i, s, mat.Formatted(u, mat.Prefix("\t "))) + } + + v := gsvd.VTo(nil) + fmt.Printf("\nCommon basis vectors\n\n\tV^T = %.4f", + mat.Formatted(v.T(), mat.Prefix("\t "))) + + // Output: + // + // Africa + // s_0 = [45507.3278 18541.9293 21503.0778] + // + // U_0 = ⎡-0.0005 -0.0039 -0.0019⎤ + // ⎢-0.0010 -0.0007 -0.0012⎥ + // ⎢-1.0000 -0.0507 -0.9964⎥ + // ⎢-0.0022 -0.2906 -0.0415⎥ + // ⎢ 0.0001 -0.0127 -0.0016⎥ + // ⎢ 0.0003 -0.0067 -0.0010⎥ + // ⎢ 0.0003 -0.0022 -0.0003⎥ + // ⎢-0.0086 -0.9550 0.0734⎥ + // ⎢ 0.0017 0.0002 0.0059⎥ + // ⎢-0.0002 -0.0088 -0.0014⎥ + // ⎢-0.0006 -0.0078 -0.0001⎥ + // ⎢-0.0005 -0.0076 0.0003⎥ + // ⎢ 0.0001 -0.0090 0.0008⎥ + // ⎢-0.0005 -0.0050 0.0029⎥ + // ⎢-0.0011 -0.0078 -0.0012⎥ + // ⎢-0.0014 -0.0058 -0.0002⎥ + // ⎢ 0.0007 -0.0095 0.0020⎥ + // ⎢-0.0008 -0.0081 -0.0009⎥ + // ⎢ 0.0004 -0.0092 0.0006⎥ + // ⎢-0.0007 -0.0079 -0.0006⎥ + // ⎣-0.0011 -0.0076 -0.0010⎦ + // Asia + // s_1 = [77228.2804 8413.7024 14711.1879] + // + // U_1 = ⎡ 0.0005 -0.0080 0.0011⎤ + // ⎢ 0.0008 -0.0108 0.0016⎥ + // ⎢-0.9998 0.0612 0.9949⎥ + // ⎢ 0.0007 -0.5734 -0.0468⎥ + // ⎢ 0.0001 -0.0265 -0.0022⎥ + // ⎢ 0.0001 -0.0165 -0.0019⎥ + // ⎢ 0.0000 -0.0070 -0.0013⎥ + // ⎢ 0.0196 -0.8148 0.0893⎥ + // ⎢ 0.0002 -0.0063 0.0012⎥ + // ⎢-0.0001 -0.0135 -0.0013⎥ + // ⎢-0.0004 -0.0135 0.0019⎥ + // ⎢-0.0005 -0.0132 0.0014⎥ + // ⎢ 0.0003 -0.0155 0.0045⎥ + // ⎢-0.0003 -0.0130 0.0025⎥ + // ⎢-0.0007 -0.0105 0.0016⎥ + // ⎢-0.0006 -0.0129 0.0007⎥ + // ⎢-0.0006 -0.0178 -0.0023⎥ + // ⎢-0.0003 -0.0149 0.0016⎥ + // ⎢-0.0001 -0.0134 0.0030⎥ + // ⎢-0.0004 -0.0154 0.0010⎥ + // ⎣-0.0009 -0.0147 -0.0019⎦ + // Latin America/Caribbean + // s_2 = [274.1364 20736.3116 729.6947] + // + // U_2 = ⎡ 0.1060 -0.0021 0.0174⎤ + // ⎢ 0.1415 -0.0016 0.0289⎥ + // ⎢ 0.2350 -0.2669 -0.9212⎥ + // ⎢ 0.0290 -0.0118 -0.0429⎥ + // ⎢ 0.0226 -0.0043 -0.0213⎥ + // ⎢ 0.0117 -0.0016 -0.0197⎥ + // ⎢-0.6263 -0.9635 0.2234⎥ + // ⎢ 0.2334 -0.0013 0.1275⎥ + // ⎢-0.0358 -0.0085 -0.0498⎥ + // ⎢-0.1238 -0.0054 0.0313⎥ + // ⎢-0.0421 -0.0059 0.0528⎥ + // ⎢-0.1471 -0.0056 0.0350⎥ + // ⎢-0.2158 -0.0052 -0.0044⎥ + // ⎣-0.6154 -0.0078 -0.2717⎦ + // Oceania + // s_3 = [8954.1914 6942.6316 17233.0561] + // + // U_3 = ⎡-0.0080 -0.0012 -0.0040⎤ + // ⎢ 0.0004 -0.0014 0.0001⎥ + // ⎢ 0.9973 -0.0315 0.9991⎥ + // ⎢ 0.0473 -0.7426 -0.0359⎥ + // ⎢ 0.0018 -0.0342 -0.0020⎥ + // ⎢-0.0005 -0.0148 -0.0016⎥ + // ⎢-0.0004 -0.0047 -0.0007⎥ + // ⎢-0.0246 -0.6642 -0.0138⎥ + // ⎢ 0.0003 -0.0287 -0.0023⎥ + // ⎢-0.0011 -0.0148 -0.0014⎥ + // ⎢-0.0108 -0.0198 -0.0039⎥ + // ⎢-0.0149 -0.0183 -0.0048⎥ + // ⎢-0.0178 -0.0208 -0.0075⎥ + // ⎢-0.0266 -0.0063 -0.0016⎥ + // ⎢-0.0012 -0.0234 -0.0006⎥ + // ⎢-0.0084 -0.0184 -0.0030⎥ + // ⎢-0.0232 -0.0191 -0.0124⎥ + // ⎢-0.0072 -0.0226 -0.0035⎥ + // ⎢-0.0150 -0.0144 -0.0045⎥ + // ⎢-0.0068 -0.0227 -0.0034⎥ + // ⎣-0.0127 -0.0136 -0.0049⎦ + // + // Common basis vectors + // + // V^T = ⎡-0.0897 -0.4460 -0.8905⎤ + // ⎢-0.4911 -0.5432 -0.6810⎥ + // ⎣ 0.0644 0.2841 0.9566⎦ +} diff --git a/vendor/gonum.org/v1/gonum/mat/hogsvd_test.go b/vendor/gonum.org/v1/gonum/mat/hogsvd_test.go new file mode 100644 index 00000000..5838b61b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/hogsvd_test.go @@ -0,0 +1,87 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "math/rand" + "testing" +) + +func TestHOGSVD(t *testing.T) { + const tol = 1e-10 + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + r, c int + }{ + {5, 3}, + {5, 5}, + {150, 150}, + {200, 150}, + + // Calculating A_i*A_j^T and A_j*A_i^T fails for wide matrices. + {3, 5}, + } { + r := test.r + c := test.c + for n := 3; n < 6; n++ { + data := make([]Matrix, n) + dataCopy := make([]*Dense, n) + for trial := 0; trial < 10; trial++ { + for i := range data { + d := NewDense(r, c, nil) + for j := range d.mat.Data { + d.mat.Data[j] = rnd.Float64() + } + data[i] = d + dataCopy[i] = DenseCopyOf(d) + } + + var gsvd HOGSVD + ok := gsvd.Factorize(data...) + if r >= c { + if !ok { + t.Errorf("HOGSVD factorization failed for %d %d×%d matrices: %v", n, r, c, gsvd.Err()) + continue + } + } else { + if ok { + t.Errorf("HOGSVD factorization unexpectedly succeeded for for %d %d×%d matrices", n, r, c) + } + continue + } + for i := range data { + if !Equal(data[i], dataCopy[i]) { + t.Errorf("A changed during call to HOGSVD.Factorize") + } + } + u, s, v := extractHOGSVD(&gsvd) + for i, want := range data { + var got Dense + sigma := NewDense(c, c, nil) + for j := 0; j < c; j++ { + sigma.Set(j, j, s[i][j]) + } + + got.Product(u[i], sigma, v.T()) + if !EqualApprox(&got, want, tol) { + t.Errorf("test %d n=%d trial %d: unexpected answer\nU_%[4]d * S_%[4]d * V^T:\n% 0.2f\nD_%d:\n% 0.2f", + cas, n, trial, i, Formatted(&got, Excerpt(5)), i, Formatted(want, Excerpt(5))) + } + } + } + } + } +} + +func extractHOGSVD(gsvd *HOGSVD) (u []*Dense, s [][]float64, v *Dense) { + u = make([]*Dense, gsvd.Len()) + s = make([][]float64, gsvd.Len()) + for i := 0; i < gsvd.Len(); i++ { + u[i] = gsvd.UTo(nil, i) + s[i] = gsvd.Values(nil, i) + } + v = gsvd.VTo(nil) + return u, s, v +} diff --git a/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go new file mode 100644 index 00000000..9633b21b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go @@ -0,0 +1,227 @@ +// Copyright ©2014 The gonum 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 file must be kept in sync with index_no_bound_checks.go. + +//+build bounds + +package mat + +// At returns the element at row i, column j. +func (m *Dense) At(i, j int) float64 { + return m.at(i, j) +} + +func (m *Dense) at(i, j int) float64 { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + return m.mat.Data[i*m.mat.Stride+j] +} + +// Set sets the element at row i, column j to the value v. +func (m *Dense) Set(i, j int, v float64) { + m.set(i, j, v) +} + +func (m *Dense) set(i, j int, v float64) { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + m.mat.Data[i*m.mat.Stride+j] = v +} + +// At returns the element at row i. +// It panics if i is out of bounds or if j is not zero. +func (v *VecDense) At(i, j int) float64 { + if j != 0 { + panic(ErrColAccess) + } + return v.at(i) +} + +func (v *VecDense) at(i int) float64 { + if uint(i) >= uint(v.n) { + panic(ErrRowAccess) + } + return v.mat.Data[i*v.mat.Inc] +} + +// SetVec sets the element at row i to the value val. +// It panics if i is out of bounds. +func (v *VecDense) SetVec(i int, val float64) { + v.setVec(i, val) +} + +func (v *VecDense) setVec(i int, val float64) { + if uint(i) >= uint(v.n) { + panic(ErrVectorAccess) + } + v.mat.Data[i*v.mat.Inc] = val +} + +// At returns the element at row i and column j. +func (t *SymDense) At(i, j int) float64 { + return t.at(i, j) +} + +func (t *SymDense) at(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + if i > j { + i, j = j, i + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetSym sets the elements at (i,j) and (j,i) to the value v. +func (t *SymDense) SetSym(i, j int, v float64) { + t.set(i, j, v) +} + +func (t *SymDense) set(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + if i > j { + i, j = j, i + } + t.mat.Data[i*t.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (t *TriDense) At(i, j int) float64 { + return t.at(i, j) +} + +func (t *TriDense) at(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetTri sets the element of the triangular matrix at row i, column j to the value v. +// It panics if the location is outside the appropriate half of the matrix. +func (t *TriDense) SetTri(i, j int, v float64) { + t.set(i, j, v) +} + +func (t *TriDense) set(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(ErrTriangleSet) + } + t.mat.Data[i*t.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (b *BandDense) At(i, j int) float64 { + return b.at(i, j) +} + +func (b *BandDense) at(i, j int) float64 { + if uint(i) >= uint(b.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(b.mat.Cols) { + panic(ErrColAccess) + } + pj := j + b.mat.KL - i + if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { + return 0 + } + return b.mat.Data[i*b.mat.Stride+pj] +} + +// SetBand sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (b *BandDense) SetBand(i, j int, v float64) { + b.set(i, j, v) +} + +func (b *BandDense) set(i, j int, v float64) { + if uint(i) >= uint(b.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(b.mat.Cols) { + panic(ErrColAccess) + } + pj := j + b.mat.KL - i + if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { + panic(ErrBandSet) + } + b.mat.Data[i*b.mat.Stride+pj] = v +} + +// At returns the element at row i, column j. +func (s *SymBandDense) At(i, j int) float64 { + return s.at(i, j) +} + +func (s *SymBandDense) at(i, j int) float64 { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + if i > j { + i, j = j, i + } + pj := j - i + if s.mat.K+1 <= pj { + return 0 + } + return s.mat.Data[i*s.mat.Stride+pj] +} + +// SetSymBand sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (s *SymBandDense) SetSymBand(i, j int, v float64) { + s.set(i, j, v) +} + +func (s *SymBandDense) set(i, j int, v float64) { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + if i > j { + i, j = j, i + } + pj := j - i + if s.mat.K+1 <= pj { + panic(ErrBandSet) + } + s.mat.Data[i*s.mat.Stride+pj] = v +} diff --git a/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go new file mode 100644 index 00000000..2aa378cb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go @@ -0,0 +1,228 @@ +// Copyright ©2014 The gonum 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 file must be kept in sync with index_bound_checks.go. + +//+build !bounds + +package mat + +// At returns the element at row i, column j. +func (m *Dense) At(i, j int) float64 { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + return m.at(i, j) +} + +func (m *Dense) at(i, j int) float64 { + return m.mat.Data[i*m.mat.Stride+j] +} + +// Set sets the element at row i, column j to the value v. +func (m *Dense) Set(i, j int, v float64) { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + m.set(i, j, v) +} + +func (m *Dense) set(i, j int, v float64) { + m.mat.Data[i*m.mat.Stride+j] = v +} + +// At returns the element at row i. +// It panics if i is out of bounds or if j is not zero. +func (v *VecDense) At(i, j int) float64 { + if uint(i) >= uint(v.n) { + panic(ErrRowAccess) + } + if j != 0 { + panic(ErrColAccess) + } + return v.at(i) +} + +func (v *VecDense) at(i int) float64 { + return v.mat.Data[i*v.mat.Inc] +} + +// SetVec sets the element at row i to the value val. +// It panics if i is out of bounds. +func (v *VecDense) SetVec(i int, val float64) { + if uint(i) >= uint(v.n) { + panic(ErrVectorAccess) + } + v.setVec(i, val) +} + +func (v *VecDense) setVec(i int, val float64) { + v.mat.Data[i*v.mat.Inc] = val +} + +// At returns the element at row i and column j. +func (s *SymDense) At(i, j int) float64 { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + return s.at(i, j) +} + +func (s *SymDense) at(i, j int) float64 { + if i > j { + i, j = j, i + } + return s.mat.Data[i*s.mat.Stride+j] +} + +// SetSym sets the elements at (i,j) and (j,i) to the value v. +func (s *SymDense) SetSym(i, j int, v float64) { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + s.set(i, j, v) +} + +func (s *SymDense) set(i, j int, v float64) { + if i > j { + i, j = j, i + } + s.mat.Data[i*s.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (t *TriDense) At(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + return t.at(i, j) +} + +func (t *TriDense) at(i, j int) float64 { + isUpper := t.triKind() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetTri sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate half of the matrix. +func (t *TriDense) SetTri(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(ErrTriangleSet) + } + t.set(i, j, v) +} + +func (t *TriDense) set(i, j int, v float64) { + t.mat.Data[i*t.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (b *BandDense) At(i, j int) float64 { + if uint(i) >= uint(b.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(b.mat.Cols) { + panic(ErrColAccess) + } + return b.at(i, j) +} + +func (b *BandDense) at(i, j int) float64 { + pj := j + b.mat.KL - i + if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { + return 0 + } + return b.mat.Data[i*b.mat.Stride+pj] +} + +// SetBand sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (b *BandDense) SetBand(i, j int, v float64) { + if uint(i) >= uint(b.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(b.mat.Cols) { + panic(ErrColAccess) + } + pj := j + b.mat.KL - i + if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { + panic(ErrBandSet) + } + b.set(i, j, v) +} + +func (b *BandDense) set(i, j int, v float64) { + pj := j + b.mat.KL - i + b.mat.Data[i*b.mat.Stride+pj] = v +} + +// At returns the element at row i, column j. +func (s *SymBandDense) At(i, j int) float64 { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + return s.at(i, j) +} + +func (s *SymBandDense) at(i, j int) float64 { + if i > j { + i, j = j, i + } + pj := j - i + if s.mat.K+1 <= pj { + return 0 + } + return s.mat.Data[i*s.mat.Stride+pj] +} + +// SetSymBand sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (s *SymBandDense) SetSymBand(i, j int, v float64) { + if uint(i) >= uint(s.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(ErrColAccess) + } + s.set(i, j, v) +} + +func (s *SymBandDense) set(i, j int, v float64) { + if i > j { + i, j = j, i + } + pj := j - i + if s.mat.K+1 <= pj { + panic(ErrBandSet) + } + s.mat.Data[i*s.mat.Stride+pj] = v +} diff --git a/vendor/gonum.org/v1/gonum/mat/inner.go b/vendor/gonum.org/v1/gonum/mat/inner.go new file mode 100644 index 00000000..1acc615e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/inner.go @@ -0,0 +1,102 @@ +// Copyright ©2014 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Inner computes the generalized inner product +// x^T A y +// between vectors x and y with matrix A. This is only a true inner product if +// A is symmetric positive definite, though the operation works for any matrix A. +// +// Inner panics if x.Len != m or y.Len != n when A is an m x n matrix. +func Inner(x *VecDense, A Matrix, y *VecDense) float64 { + m, n := A.Dims() + if x.Len() != m { + panic(ErrShape) + } + if y.Len() != n { + panic(ErrShape) + } + if m == 0 || n == 0 { + return 0 + } + + var sum float64 + + switch b := A.(type) { + case RawSymmetricer: + bmat := b.RawSymmetric() + if bmat.Uplo != blas.Upper { + // Panic as a string not a mat.Error. + panic(badSymTriangle) + } + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + if xi != 0 { + if y.mat.Inc == 1 { + sum += xi * f64.DotUnitary( + bmat.Data[i*bmat.Stride+i:i*bmat.Stride+n], + y.mat.Data[i:], + ) + } else { + sum += xi * f64.DotInc( + bmat.Data[i*bmat.Stride+i:i*bmat.Stride+n], + y.mat.Data[i*y.mat.Inc:], uintptr(n-i), + 1, uintptr(y.mat.Inc), + 0, 0, + ) + } + } + yi := y.at(i) + if i != n-1 && yi != 0 { + if x.mat.Inc == 1 { + sum += yi * f64.DotUnitary( + bmat.Data[i*bmat.Stride+i+1:i*bmat.Stride+n], + x.mat.Data[i+1:], + ) + } else { + sum += yi * f64.DotInc( + bmat.Data[i*bmat.Stride+i+1:i*bmat.Stride+n], + x.mat.Data[(i+1)*x.mat.Inc:], uintptr(n-i-1), + 1, uintptr(x.mat.Inc), + 0, 0, + ) + } + } + } + case RawMatrixer: + bmat := b.RawMatrix() + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + if xi != 0 { + if y.mat.Inc == 1 { + sum += xi * f64.DotUnitary( + bmat.Data[i*bmat.Stride:i*bmat.Stride+n], + y.mat.Data, + ) + } else { + sum += xi * f64.DotInc( + bmat.Data[i*bmat.Stride:i*bmat.Stride+n], + y.mat.Data, uintptr(n), + 1, uintptr(y.mat.Inc), + 0, 0, + ) + } + } + } + default: + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + for j := 0; j < y.Len(); j++ { + sum += xi * A.At(i, j) * y.at(j) + } + } + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/mat/inner_test.go b/vendor/gonum.org/v1/gonum/mat/inner_test.go new file mode 100644 index 00000000..05a76b72 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/inner_test.go @@ -0,0 +1,181 @@ +// Copyright ©2014 The gonum 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 mat + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/blas/testblas" +) + +func TestInner(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + m [][]float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + m: [][]float64{{2}}, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + m: [][]float64{{2}, {-3}, {5}}, + }, + { + x: []float64{5}, + y: []float64{10, 15}, + m: [][]float64{{2, -3}}, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + m: [][]float64{ + {2, -3}, + {4, -1}, + }, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + m: [][]float64{ + {2, 3}, + {4, 5}, + {6, 7}, + }, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + m: [][]float64{ + {2, 3, 6}, + {4, 5, 7}, + }, + }, + } { + for _, inc := range []struct{ x, y int }{ + {1, 1}, + {1, 2}, + {2, 1}, + {2, 2}, + } { + x := NewDense(1, len(test.x), test.x) + m := NewDense(flatten(test.m)) + mWant := NewDense(flatten(test.m)) + y := NewDense(len(test.y), 1, test.y) + + var tmp, cell Dense + tmp.Mul(mWant, y) + cell.Mul(x, &tmp) + + rm, cm := cell.Dims() + if rm != 1 { + t.Errorf("Test %d result doesn't have 1 row", i) + } + if cm != 1 { + t.Errorf("Test %d result doesn't have 1 column", i) + } + + want := cell.At(0, 0) + got := Inner(makeVecDenseInc(inc.x, test.x), m, makeVecDenseInc(inc.y, test.y)) + if got != want { + t.Errorf("Test %v: want %v, got %v", i, want, got) + } + } + } +} + +func TestInnerSym(t *testing.T) { + for _, inc := range []struct{ x, y int }{ + {1, 1}, + {1, 2}, + {2, 1}, + {2, 2}, + } { + n := 10 + xData := make([]float64, n) + yData := make([]float64, n) + data := make([]float64, n*n) + for i := 0; i < n; i++ { + xData[i] = float64(i) + yData[i] = float64(i) + for j := i; j < n; j++ { + data[i*n+j] = float64(i*n + j) + data[j*n+i] = data[i*n+j] + } + } + x := makeVecDenseInc(inc.x, xData) + y := makeVecDenseInc(inc.y, yData) + m := NewDense(n, n, data) + ans := Inner(x, m, y) + sym := NewSymDense(n, data) + // Poison the lower half of data to ensure it is not used. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + data[i*n+j] = math.NaN() + } + } + + if math.Abs(Inner(x, sym, y)-ans) > 1e-14 { + t.Error("inner different symmetric and dense") + } + } +} + +func makeVecDenseInc(inc int, f []float64) *VecDense { + v := &VecDense{ + n: len(f), + mat: blas64.Vector{ + Inc: inc, + Data: make([]float64, (len(f)-1)*inc+1), + }, + } + + // Contaminate backing data in all positions... + const base = 100 + for i := range v.mat.Data { + v.mat.Data[i] = float64(i + base) + } + + // then write real elements. + for i := range f { + v.mat.Data[i*inc] = f[i] + } + return v +} + +func benchmarkInner(b *testing.B, m, n int) { + x := NewVecDense(m, nil) + randomSlice(x.mat.Data) + y := NewVecDense(n, nil) + randomSlice(y.mat.Data) + data := make([]float64, m*n) + randomSlice(data) + mat := &Dense{mat: blas64.General{Rows: m, Cols: n, Stride: n, Data: data}, capRows: m, capCols: n} + b.ResetTimer() + for i := 0; i < b.N; i++ { + Inner(x, mat, y) + } +} + +func BenchmarkInnerSmSm(b *testing.B) { + benchmarkInner(b, testblas.SmallMat, testblas.SmallMat) +} + +func BenchmarkInnerMedMed(b *testing.B) { + benchmarkInner(b, testblas.MediumMat, testblas.MediumMat) +} + +func BenchmarkInnerLgLg(b *testing.B) { + benchmarkInner(b, testblas.LargeMat, testblas.LargeMat) +} + +func BenchmarkInnerLgSm(b *testing.B) { + benchmarkInner(b, testblas.LargeMat, testblas.SmallMat) +} diff --git a/vendor/gonum.org/v1/gonum/mat/io.go b/vendor/gonum.org/v1/gonum/mat/io.go new file mode 100644 index 00000000..db429bfa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/io.go @@ -0,0 +1,360 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "encoding/binary" + "errors" + "io" + "math" +) + +const ( + // maxLen is the biggest slice/array len one can create on a 32/64b platform. + maxLen = int64(int(^uint(0) >> 1)) +) + +var ( + sizeInt64 = binary.Size(int64(0)) + sizeFloat64 = binary.Size(float64(0)) + + errTooBig = errors.New("mat: resulting data slice too big") + errTooSmall = errors.New("mat: input slice too small") + errBadBuffer = errors.New("mat: data buffer size mismatch") + errBadSize = errors.New("mat: invalid dimension") +) + +// MarshalBinary encodes the receiver into a binary form and returns the result. +// +// Dense is little-endian encoded as follows: +// 0 - 7 number of rows (int64) +// 8 - 15 number of columns (int64) +// 16 - .. matrix data elements (float64) +// [0,0] [0,1] ... [0,ncols-1] +// [1,0] [1,1] ... [1,ncols-1] +// ... +// [nrows-1,0] ... [nrows-1,ncols-1] +func (m Dense) MarshalBinary() ([]byte, error) { + bufLen := int64(m.mat.Rows)*int64(m.mat.Cols)*int64(sizeFloat64) + 2*int64(sizeInt64) + if bufLen <= 0 { + // bufLen is too big and has wrapped around. + return nil, errTooBig + } + + p := 0 + buf := make([]byte, bufLen) + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(m.mat.Rows)) + p += sizeInt64 + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(m.mat.Cols)) + p += sizeInt64 + + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(m.at(i, j))) + p += sizeFloat64 + } + } + + return buf, nil +} + +// MarshalBinaryTo encodes the receiver into a binary form and writes it into w. +// MarshalBinaryTo returns the number of bytes written into w and an error, if any. +// +// See MarshalBinary for the on-disk layout. +func (m Dense) MarshalBinaryTo(w io.Writer) (int, error) { + var n int + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], uint64(m.mat.Rows)) + nn, err := w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + binary.LittleEndian.PutUint64(buf[:], uint64(m.mat.Cols)) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + binary.LittleEndian.PutUint64(buf[:], math.Float64bits(m.at(i, j))) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + } + } + + return n, nil +} + +// UnmarshalBinary decodes the binary form into the receiver. +// It panics if the receiver is a non-zero Dense matrix. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows or columns is negative, +// - an error is returned if the resulting Dense matrix is too +// big for the current architecture (e.g. a 16GB matrix written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so +// it should not be used on untrusted data. +func (m *Dense) UnmarshalBinary(data []byte) error { + if !m.IsZero() { + panic("mat: unmarshal into non-zero matrix") + } + + if len(data) < 2*sizeInt64 { + return errTooSmall + } + + p := 0 + rows := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + cols := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + if rows < 0 || cols < 0 { + return errBadSize + } + + size := rows * cols + if int(size) < 0 || size > maxLen { + return errTooBig + } + + if len(data) != int(size)*sizeFloat64+2*sizeInt64 { + return errBadBuffer + } + + m.reuseAs(int(rows), int(cols)) + for i := range m.mat.Data { + m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) + p += sizeFloat64 + } + + return nil +} + +// UnmarshalBinaryFrom decodes the binary form into the receiver and returns +// the number of bytes read and an error if any. +// It panics if the receiver is a non-zero Dense matrix. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows or columns is negative, +// - an error is returned if the resulting Dense matrix is too +// big for the current architecture (e.g. a 16GB matrix written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so +// it should not be used on untrusted data. +func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) { + if !m.IsZero() { + panic("mat: unmarshal into non-zero matrix") + } + + var ( + n int + buf [8]byte + ) + nn, err := readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + rows := int64(binary.LittleEndian.Uint64(buf[:])) + + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + cols := int64(binary.LittleEndian.Uint64(buf[:])) + if rows < 0 || cols < 0 { + return n, errBadSize + } + + size := rows * cols + if int(size) < 0 || size > maxLen { + return n, errTooBig + } + + m.reuseAs(int(rows), int(cols)) + for i := range m.mat.Data { + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(buf[:])) + } + + return n, nil +} + +// MarshalBinary encodes the receiver into a binary form and returns the result. +// +// VecDense is little-endian encoded as follows: +// 0 - 7 number of elements (int64) +// 8 - .. vector's data elements (float64) +func (v VecDense) MarshalBinary() ([]byte, error) { + bufLen := int64(sizeInt64) + int64(v.n)*int64(sizeFloat64) + if bufLen <= 0 { + // bufLen is too big and has wrapped around. + return nil, errTooBig + } + + p := 0 + buf := make([]byte, bufLen) + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(v.n)) + p += sizeInt64 + + for i := 0; i < v.n; i++ { + binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(v.at(i))) + p += sizeFloat64 + } + + return buf, nil +} + +// MarshalBinaryTo encodes the receiver into a binary form, writes it to w and +// returns the number of bytes written and an error if any. +// +// See MarshalBainry for the on-disk format. +func (v VecDense) MarshalBinaryTo(w io.Writer) (int, error) { + var ( + n int + buf [8]byte + ) + + binary.LittleEndian.PutUint64(buf[:], uint64(v.n)) + nn, err := w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + + for i := 0; i < v.n; i++ { + binary.LittleEndian.PutUint64(buf[:], math.Float64bits(v.at(i))) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + } + + return n, nil +} + +// UnmarshalBinary decodes the binary form into the receiver. +// It panics if the receiver is a non-zero VecDense. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows is negative, +// - an error is returned if the resulting VecDense is too +// big for the current architecture (e.g. a 16GB vector written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled vector, and so +// it should not be used on untrusted data. +func (v *VecDense) UnmarshalBinary(data []byte) error { + if !v.IsZero() { + panic("mat: unmarshal into non-zero vector") + } + + p := 0 + n := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + if n < 0 { + return errBadSize + } + if n > maxLen { + return errTooBig + } + if len(data) != int(n)*sizeFloat64+sizeInt64 { + return errBadBuffer + } + + v.reuseAs(int(n)) + for i := range v.mat.Data { + v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) + p += sizeFloat64 + } + + return nil +} + +// UnmarshalBinaryFrom decodes the binary form into the receiver, from the +// io.Reader and returns the number of bytes read and an error if any. +// It panics if the receiver is a non-zero VecDense. +// +// See MarshalBinary for the on-disk layout. +// See UnmarshalBinary for the list of sanity checks performed on the input. +func (v *VecDense) UnmarshalBinaryFrom(r io.Reader) (int, error) { + if !v.IsZero() { + panic("mat: unmarshal into non-zero vector") + } + + var ( + n int + buf [8]byte + ) + nn, err := readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + sz := int64(binary.LittleEndian.Uint64(buf[:])) + if sz < 0 { + return n, errBadSize + } + if sz > maxLen { + return n, errTooBig + } + + v.reuseAs(int(sz)) + for i := range v.mat.Data { + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(buf[:])) + } + + if n != sizeInt64+int(sz)*sizeFloat64 { + return n, io.ErrUnexpectedEOF + } + + return n, nil +} + +// readFull reads from r into buf until it has read len(buf). +// It returns the number of bytes copied and an error if fewer bytes were read. +// If an EOF happens after reading fewer than len(buf) bytes, io.ErrUnexpectedEOF is returned. +func readFull(r io.Reader, buf []byte) (int, error) { + var n int + var err error + for n < len(buf) && err == nil { + var nn int + nn, err = r.Read(buf[n:]) + n += nn + } + if n == len(buf) { + return n, nil + } + if err == io.EOF { + return n, io.ErrUnexpectedEOF + } + return n, err +} diff --git a/vendor/gonum.org/v1/gonum/mat/io_test.go b/vendor/gonum.org/v1/gonum/mat/io_test.go new file mode 100644 index 00000000..e2dd639d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/io_test.go @@ -0,0 +1,731 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "bytes" + "encoding" + "io" + "io/ioutil" + "math" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + _ encoding.BinaryMarshaler = (*Dense)(nil) + _ encoding.BinaryUnmarshaler = (*Dense)(nil) + _ encoding.BinaryMarshaler = (*VecDense)(nil) + _ encoding.BinaryUnmarshaler = (*VecDense)(nil) +) + +var denseData = []struct { + raw []byte + want *Dense + eq func(got, want Matrix) bool +}{ + { + raw: []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + want: NewDense(0, 0, []float64{}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewDense(2, 2, []float64{1, 2, 3, 4}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewDense(2, 3, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewDense(3, 2, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(0, 2, 0, 2).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(1, 3, 1, 3).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(0, 3, 1, 3).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xff\x00\x00\x00\x00\x00\x00\xf0\u007f\x01\x00\x00\x00\x00\x00\xf8\u007f"), + want: NewDense(1, 4, []float64{0, math.Inf(-1), math.Inf(+1), math.NaN()}), + eq: func(got, want Matrix) bool { + for _, v := range []bool{ + got.At(0, 0) == 0, + math.IsInf(got.At(0, 1), -1), + math.IsInf(got.At(0, 2), +1), + math.IsNaN(got.At(0, 3)), + } { + if !v { + return false + } + } + return true + }, + }, +} + +func TestDenseMarshal(t *testing.T) { + for i, test := range denseData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + 2*sizeInt64 + if len(buf) != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, len(buf)) + } + + if !bytes.Equal(buf, test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf), + string(test.raw), + ) + continue + } + } +} + +func TestDenseMarshalTo(t *testing.T) { + for i, test := range denseData { + buf := new(bytes.Buffer) + n, err := test.want.MarshalBinaryTo(buf) + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + 2*sizeInt64 + if n != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, n) + } + + if !bytes.Equal(buf.Bytes(), test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf.Bytes()), + string(test.raw), + ) + continue + } + } +} + +func TestDenseUnmarshal(t *testing.T) { + for i, test := range denseData { + var v Dense + err := v.UnmarshalBinary(test.raw) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestDenseUnmarshalFrom(t *testing.T) { + for i, test := range denseData { + var v Dense + buf := bytes.NewReader(test.raw) + n, err := v.UnmarshalBinaryFrom(buf) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if n != len(test.raw) { + t.Errorf("error decoding test-%d: lengths differ.\n got=%d\nwant=%d\n", + i, n, len(test.raw), + ) + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestDenseUnmarshalFromError(t *testing.T) { + test := denseData[1] + for i, tt := range []struct { + beg int + end int + }{ + { + beg: 0, + end: len(test.raw) - 1, + }, + { + beg: 0, + end: len(test.raw) - sizeFloat64, + }, + { + beg: 0, + end: 0, + }, + { + beg: 0, + end: 1, + }, + { + beg: 0, + end: sizeInt64, + }, + { + beg: 0, + end: sizeInt64 - 1, + }, + { + beg: 0, + end: sizeInt64 + 1, + }, + { + beg: 0, + end: 2*sizeInt64 - 1, + }, + { + beg: 0, + end: 2 * sizeInt64, + }, + { + beg: 0, + end: 2*sizeInt64 + 1, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64 - 1, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64 + 1, + }, + } { + buf := bytes.NewReader(test.raw[tt.beg:tt.end]) + var m Dense + _, err := m.UnmarshalBinaryFrom(buf) + if err != io.ErrUnexpectedEOF { + t.Errorf("test #%d: error decoding. got=%v. want=%v\n", i, err, io.ErrUnexpectedEOF) + } + } +} + +func TestDenseIORoundTrip(t *testing.T) { + for i, test := range denseData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + var got Dense + err = got.UnmarshalBinary(buf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&got, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &got, test.want) + } + + wbuf := new(bytes.Buffer) + _, err = test.want.MarshalBinaryTo(wbuf) + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + if !bytes.Equal(buf, wbuf.Bytes()) { + t.Errorf("r/w test #%d encoding via MarshalBinary and MarshalBinaryTo differ:\nwith-stream: %q\n no-stream: %q\n", + i, wbuf.Bytes(), buf, + ) + } + + var wgot Dense + _, err = wgot.UnmarshalBinaryFrom(wbuf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&wgot, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &wgot, test.want) + } + } +} + +var vectorData = []struct { + raw []byte + want *VecDense + eq func(got, want Matrix) bool +}{ + { + raw: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), + want: NewVecDense(0, []float64{}), + eq: Equal, + }, + { + raw: []byte("\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewVecDense(4, []float64{1, 2, 3, 4}), + eq: Equal, + }, + { + raw: []byte("\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewVecDense(6, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewVecDense(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@"), + want: NewVecDense(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(0, 3), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewVecDense(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(1, 4), + eq: Equal, + }, + { + raw: []byte("\b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @"), + want: NewVecDense(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(0, 8), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x18@"), + want: &VecDense{ + mat: blas64.Vector{ + Data: []float64{0, 1, 2, 3, 4, 5, 6}, + Inc: 3, + }, + n: 3, + }, + eq: Equal, + }, + { + raw: []byte("\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xff\x00\x00\x00\x00\x00\x00\xf0\u007f\x01\x00\x00\x00\x00\x00\xf8\u007f"), + want: NewVecDense(4, []float64{0, math.Inf(-1), math.Inf(+1), math.NaN()}), + eq: func(got, want Matrix) bool { + for _, v := range []bool{ + got.At(0, 0) == 0, + math.IsInf(got.At(1, 0), -1), + math.IsInf(got.At(2, 0), +1), + math.IsNaN(got.At(3, 0)), + } { + if !v { + return false + } + } + return true + }, + }, +} + +func TestVecDenseMarshal(t *testing.T) { + for i, test := range vectorData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + sizeInt64 + if len(buf) != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, len(buf)) + } + + if !bytes.Equal(buf, test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf), + string(test.raw), + ) + continue + } + } +} + +func TestVecDenseMarshalTo(t *testing.T) { + for i, test := range vectorData { + buf := new(bytes.Buffer) + n, err := test.want.MarshalBinaryTo(buf) + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + sizeInt64 + if n != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, n) + } + + if !bytes.Equal(buf.Bytes(), test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf.Bytes()), + string(test.raw), + ) + continue + } + } +} + +func TestVecDenseUnmarshal(t *testing.T) { + for i, test := range vectorData { + var v VecDense + err := v.UnmarshalBinary(test.raw) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestVecDenseUnmarshalFrom(t *testing.T) { + for i, test := range vectorData { + var v VecDense + buf := bytes.NewReader(test.raw) + n, err := v.UnmarshalBinaryFrom(buf) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if n != len(test.raw) { + t.Errorf("error decoding test-%d: lengths differ.\n got=%d\nwant=%d\n", + i, + n, + len(test.raw), + ) + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestVecDenseUnmarshalFromError(t *testing.T) { + test := vectorData[1] + for i, tt := range []struct { + beg int + end int + }{ + { + beg: 0, + end: len(test.raw) - 1, + }, + { + beg: 0, + end: len(test.raw) - sizeFloat64, + }, + { + beg: 0, + end: 0, + }, + { + beg: 0, + end: 1, + }, + { + beg: 0, + end: sizeInt64, + }, + { + beg: 0, + end: sizeInt64 - 1, + }, + { + beg: 0, + end: sizeInt64 + 1, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64 - 1, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64 + 1, + }, + } { + buf := bytes.NewReader(test.raw[tt.beg:tt.end]) + var v VecDense + _, err := v.UnmarshalBinaryFrom(buf) + if err != io.ErrUnexpectedEOF { + t.Errorf("test #%d: error decoding. got=%v. want=%v\n", i, err, io.ErrUnexpectedEOF) + } + } +} + +func TestVecDenseIORoundTrip(t *testing.T) { + for i, test := range vectorData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + var got VecDense + err = got.UnmarshalBinary(buf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + if !test.eq(&got, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &got, test.want) + } + + wbuf := new(bytes.Buffer) + _, err = test.want.MarshalBinaryTo(wbuf) + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + if !bytes.Equal(buf, wbuf.Bytes()) { + t.Errorf("test #%d encoding via MarshalBinary and MarshalBinaryTo differ:\nwith-stream: %q\n no-stream: %q\n", + i, wbuf.Bytes(), buf, + ) + } + + var wgot VecDense + _, err = wgot.UnmarshalBinaryFrom(wbuf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&wgot, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &wgot, test.want) + } + } +} + +func BenchmarkMarshalDense10(b *testing.B) { marshalBinaryBenchDense(b, 10) } +func BenchmarkMarshalDense100(b *testing.B) { marshalBinaryBenchDense(b, 100) } +func BenchmarkMarshalDense1000(b *testing.B) { marshalBinaryBenchDense(b, 1000) } +func BenchmarkMarshalDense10000(b *testing.B) { marshalBinaryBenchDense(b, 10000) } + +func marshalBinaryBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + m := NewDense(1, size, data) + b.ResetTimer() + + for n := 0; n < b.N; n++ { + m.MarshalBinary() + } +} + +func BenchmarkUnmarshalDense10(b *testing.B) { unmarshalBinaryBenchDense(b, 10) } +func BenchmarkUnmarshalDense100(b *testing.B) { unmarshalBinaryBenchDense(b, 100) } +func BenchmarkUnmarshalDense1000(b *testing.B) { unmarshalBinaryBenchDense(b, 1000) } +func BenchmarkUnmarshalDense10000(b *testing.B) { unmarshalBinaryBenchDense(b, 10000) } + +func unmarshalBinaryBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewDense(1, size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var m Dense + m.UnmarshalBinary(buf) + } +} + +func BenchmarkMarshalToDense10(b *testing.B) { marshalBinaryToBenchDense(b, 10) } +func BenchmarkMarshalToDense100(b *testing.B) { marshalBinaryToBenchDense(b, 100) } +func BenchmarkMarshalToDense1000(b *testing.B) { marshalBinaryToBenchDense(b, 1000) } +func BenchmarkMarshalToDense10000(b *testing.B) { marshalBinaryToBenchDense(b, 10000) } + +func marshalBinaryToBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + m := NewDense(1, size, data) + w := ioutil.Discard + b.ResetTimer() + + for n := 0; n < b.N; n++ { + m.MarshalBinaryTo(w) + } +} + +type readerTest struct { + buf []byte + pos int +} + +func (r *readerTest) Read(data []byte) (int, error) { + n := copy(data, r.buf[r.pos:r.pos+len(data)]) + r.pos += n + return n, nil +} + +func (r *readerTest) reset() { + r.pos = 0 +} + +func BenchmarkUnmarshalFromDense10(b *testing.B) { unmarshalBinaryFromBenchDense(b, 10) } +func BenchmarkUnmarshalFromDense100(b *testing.B) { unmarshalBinaryFromBenchDense(b, 100) } +func BenchmarkUnmarshalFromDense1000(b *testing.B) { unmarshalBinaryFromBenchDense(b, 1000) } +func BenchmarkUnmarshalFromDense10000(b *testing.B) { unmarshalBinaryFromBenchDense(b, 10000) } + +func unmarshalBinaryFromBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewDense(1, size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + r := &readerTest{buf: buf} + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var m Dense + m.UnmarshalBinaryFrom(r) + r.reset() + } +} + +func BenchmarkMarshalVecDense10(b *testing.B) { marshalBinaryBenchVecDense(b, 10) } +func BenchmarkMarshalVecDense100(b *testing.B) { marshalBinaryBenchVecDense(b, 100) } +func BenchmarkMarshalVecDense1000(b *testing.B) { marshalBinaryBenchVecDense(b, 1000) } +func BenchmarkMarshalVecDense10000(b *testing.B) { marshalBinaryBenchVecDense(b, 10000) } + +func marshalBinaryBenchVecDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + vec := NewVecDense(size, data) + b.ResetTimer() + + for n := 0; n < b.N; n++ { + vec.MarshalBinary() + } +} + +func BenchmarkUnmarshalVecDense10(b *testing.B) { unmarshalBinaryBenchVecDense(b, 10) } +func BenchmarkUnmarshalVecDense100(b *testing.B) { unmarshalBinaryBenchVecDense(b, 100) } +func BenchmarkUnmarshalVecDense1000(b *testing.B) { unmarshalBinaryBenchVecDense(b, 1000) } +func BenchmarkUnmarshalVecDense10000(b *testing.B) { unmarshalBinaryBenchVecDense(b, 10000) } + +func unmarshalBinaryBenchVecDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewVecDense(size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var vec VecDense + vec.UnmarshalBinary(buf) + } +} + +func BenchmarkMarshalToVecDense10(b *testing.B) { marshalBinaryToBenchVecDense(b, 10) } +func BenchmarkMarshalToVecDense100(b *testing.B) { marshalBinaryToBenchVecDense(b, 100) } +func BenchmarkMarshalToVecDense1000(b *testing.B) { marshalBinaryToBenchVecDense(b, 1000) } +func BenchmarkMarshalToVecDense10000(b *testing.B) { marshalBinaryToBenchVecDense(b, 10000) } + +func marshalBinaryToBenchVecDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + vec := NewVecDense(size, data) + w := ioutil.Discard + b.ResetTimer() + + for n := 0; n < b.N; n++ { + vec.MarshalBinaryTo(w) + } +} + +func BenchmarkUnmarshalFromVecDense10(b *testing.B) { unmarshalBinaryFromBenchVecDense(b, 10) } +func BenchmarkUnmarshalFromVecDense100(b *testing.B) { unmarshalBinaryFromBenchVecDense(b, 100) } +func BenchmarkUnmarshalFromVecDense1000(b *testing.B) { unmarshalBinaryFromBenchVecDense(b, 1000) } +func BenchmarkUnmarshalFromVecDense10000(b *testing.B) { unmarshalBinaryFromBenchVecDense(b, 10000) } + +func unmarshalBinaryFromBenchVecDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewVecDense(size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + r := &readerTest{buf: buf} + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var vec VecDense + vec.UnmarshalBinaryFrom(r) + r.reset() + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/list_test.go b/vendor/gonum.org/v1/gonum/mat/list_test.go new file mode 100644 index 00000000..5f0cdafa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/list_test.go @@ -0,0 +1,1151 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "fmt" + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +// legalSizeSameRectangular returns whether the two matrices have the same rectangular shape. +func legalSizeSameRectangular(ar, ac, br, bc int) bool { + if ar != br { + return false + } + if ac != bc { + return false + } + return true +} + +// legalSizeSameSquare returns whether the two matrices have the same square shape. +func legalSizeSameSquare(ar, ac, br, bc int) bool { + if ar != br { + return false + } + if ac != bc { + return false + } + if ar != ac { + return false + } + return true +} + +// legalSizeSameHeight returns whether the two matrices have the same number of rows. +func legalSizeSameHeight(ar, _, br, _ int) bool { + return ar == br +} + +// legalSizeSameWidth returns whether the two matrices have the same number of columns. +func legalSizeSameWidth(_, ac, _, bc int) bool { + return ac == bc +} + +// legalSizeSolve returns whether the two matrices can be used in a linear solve. +func legalSizeSolve(ar, ac, br, bc int) bool { + return ar == br +} + +// legalSizeSameVec returns whether the two matrices are column vectors of the +// same dimension. +func legalSizeSameVec(ar, ac, br, bc int) bool { + return ac == 1 && bc == 1 && ar == br +} + +// isAnySize returns true for all matrix sizes. +func isAnySize(ar, ac int) bool { + return true +} + +// isAnySize2 returns true for all matrix sizes. +func isAnySize2(ar, ac, br, bc int) bool { + return true +} + +// isAnyVecDense returns true for any column vector sizes. +func isAnyVecDense(ar, ac int) bool { + return ac == 1 +} + +// isSquare returns whether the input matrix is square. +func isSquare(r, c int) bool { + return r == c +} + +// sameAnswerFloat returns whether the two inputs are both NaN or are equal. +func sameAnswerFloat(a, b interface{}) bool { + if math.IsNaN(a.(float64)) { + return math.IsNaN(b.(float64)) + } + return a.(float64) == b.(float64) +} + +// sameAnswerFloatApproxTol returns a function that determines whether its two +// inputs are both NaN or within tol of each other. +func sameAnswerFloatApproxTol(tol float64) func(a, b interface{}) bool { + return func(a, b interface{}) bool { + if math.IsNaN(a.(float64)) { + return math.IsNaN(b.(float64)) + } + return floats.EqualWithinAbsOrRel(a.(float64), b.(float64), tol, tol) + } +} + +func sameAnswerF64SliceOfSlice(a, b interface{}) bool { + for i, v := range a.([][]float64) { + if same := floats.Same(v, b.([][]float64)[i]); !same { + return false + } + } + return true +} + +// sameAnswerBool returns whether the two inputs have the same value. +func sameAnswerBool(a, b interface{}) bool { + return a.(bool) == b.(bool) +} + +// isAnyType returns true for all Matrix types. +func isAnyType(Matrix) bool { + return true +} + +// legalTypesAll returns true for all Matrix types. +func legalTypesAll(a, b Matrix) bool { + return true +} + +// legalTypeSym returns whether a is a Symmetric. +func legalTypeSym(a Matrix) bool { + _, ok := a.(Symmetric) + return ok +} + +// legalTypesSym returns whether both input arguments are Symmetric. +func legalTypesSym(a, b Matrix) bool { + if _, ok := a.(Symmetric); !ok { + return false + } + if _, ok := b.(Symmetric); !ok { + return false + } + return true +} + +// legalTypeVec returns whether v is a *VecDense. +func legalTypeVec(v Matrix) bool { + _, ok := v.(*VecDense) + return ok +} + +// legalTypesVecVec returns whether both inputs are *VecDense. +func legalTypesVecVec(a, b Matrix) bool { + if _, ok := a.(*VecDense); !ok { + return false + } + if _, ok := b.(*VecDense); !ok { + return false + } + return true +} + +// legalTypesNotVecVec returns whether the first input is an arbitrary Matrix +// and the second input is a *VecDense. +func legalTypesNotVecVec(a, b Matrix) bool { + _, ok := b.(*VecDense) + return ok +} + +// legalDims returns whether {m,n} is a valid dimension of the given matrix type. +func legalDims(a Matrix, m, n int) bool { + switch t := a.(type) { + default: + panic("legal dims type not coded") + case Untransposer: + return legalDims(t.Untranspose(), n, m) + case *Dense, *basicMatrix: + if m < 0 || n < 0 { + return false + } + return true + case *SymDense, *TriDense, *basicSymmetric, *basicTriangular: + if m < 0 || n < 0 || m != n { + return false + } + return true + case *VecDense: + if m < 0 || n < 0 { + return false + } + return n == 1 + } +} + +// returnAs returns the matrix a with the type of t. Used for making a concrete +// type and changing to the basic form. +func returnAs(a, t Matrix) Matrix { + switch mat := a.(type) { + default: + panic("unknown type for a") + case *Dense: + switch t.(type) { + default: + panic("bad type") + case *Dense: + return mat + case *basicMatrix: + return asBasicMatrix(mat) + } + case *SymDense: + switch t.(type) { + default: + panic("bad type") + case *SymDense: + return mat + case *basicSymmetric: + return asBasicSymmetric(mat) + } + case *TriDense: + switch t.(type) { + default: + panic("bad type") + case *TriDense: + return mat + case *basicTriangular: + return asBasicTriangular(mat) + } + } +} + +// retranspose returns the matrix m inside an Untransposer of the type +// of a. +func retranspose(a, m Matrix) Matrix { + switch a.(type) { + case TransposeTri: + return TransposeTri{m.(Triangular)} + case Transpose: + return Transpose{m} + case Untransposer: + panic("unknown transposer type") + default: + panic("a is not an untransposer") + } +} + +// makeRandOf returns a new randomly filled m×n matrix of the underlying matrix type. +func makeRandOf(a Matrix, m, n int) Matrix { + var rMatrix Matrix + switch t := a.(type) { + default: + panic("unknown type for make rand of") + case Untransposer: + rMatrix = retranspose(a, makeRandOf(t.Untranspose(), n, m)) + case *Dense, *basicMatrix: + mat := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + mat.Set(i, j, rand.NormFloat64()) + } + } + rMatrix = returnAs(mat, t) + case *VecDense: + if m == 0 && n == 0 { + return &VecDense{} + } + if n != 1 { + panic(fmt.Sprintf("bad vector size: m = %v, n = %v", m, n)) + } + length := m + inc := 1 + if t.mat.Inc != 0 { + inc = t.mat.Inc + } + mat := &VecDense{ + mat: blas64.Vector{ + Inc: inc, + Data: make([]float64, inc*(length-1)+1), + }, + n: length, + } + for i := 0; i < length; i++ { + mat.SetVec(i, rand.NormFloat64()) + } + return mat + case *SymDense, *basicSymmetric: + if m != n { + panic("bad size") + } + mat := NewSymDense(n, nil) + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + mat.SetSym(i, j, rand.NormFloat64()) + } + } + rMatrix = returnAs(mat, t) + case *TriDense, *basicTriangular: + if m != n { + panic("bad size") + } + + // This is necessary because we are making + // a triangle from the zero value, which + // always returns upper as true. + var triKind TriKind + switch t := t.(type) { + case *TriDense: + triKind = t.triKind() + case *basicTriangular: + triKind = (*TriDense)(t).triKind() + } + + mat := NewTriDense(n, triKind, nil) + if triKind == Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + mat.SetTri(i, j, rand.NormFloat64()) + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= i; j++ { + mat.SetTri(i, j, rand.NormFloat64()) + } + } + } + rMatrix = returnAs(mat, t) + } + if mr, mc := rMatrix.Dims(); mr != m || mc != n { + panic(fmt.Sprintf("makeRandOf for %T returns wrong size: %d×%d != %d×%d", a, m, n, mr, mc)) + } + return rMatrix +} + +// makeCopyOf returns a copy of the matrix. +func makeCopyOf(a Matrix) Matrix { + switch t := a.(type) { + default: + panic("unknown type in makeCopyOf") + case Untransposer: + return retranspose(a, makeCopyOf(t.Untranspose())) + case *Dense, *basicMatrix: + var m Dense + m.Clone(a) + return returnAs(&m, t) + case *SymDense, *basicSymmetric: + n := t.(Symmetric).Symmetric() + m := NewSymDense(n, nil) + m.CopySym(t.(Symmetric)) + return returnAs(m, t) + case *TriDense, *basicTriangular: + n, upper := t.(Triangular).Triangle() + m := NewTriDense(n, upper, nil) + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + m.SetTri(i, j, t.At(i, j)) + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + m.SetTri(i, j, t.At(i, j)) + } + } + } + return returnAs(m, t) + case *VecDense: + m := &VecDense{ + mat: blas64.Vector{ + Inc: t.mat.Inc, + Data: make([]float64, t.mat.Inc*(t.n-1)+1), + }, + n: t.n, + } + copy(m.mat.Data, t.mat.Data) + return m + } +} + +// sameType returns true if a and b have the same underlying type. +func sameType(a, b Matrix) bool { + return reflect.ValueOf(a).Type() == reflect.ValueOf(b).Type() +} + +// maybeSame returns true if the two matrices could be represented by the same +// pointer. +func maybeSame(receiver, a Matrix) bool { + rr, rc := receiver.Dims() + u, trans := a.(Untransposer) + if trans { + a = u.Untranspose() + } + if !sameType(receiver, a) { + return false + } + ar, ac := a.Dims() + if rr != ar || rc != ac { + return false + } + if _, ok := a.(Triangular); ok { + // They are both triangular types. The TriType needs to match + _, aKind := a.(Triangular).Triangle() + _, rKind := receiver.(Triangular).Triangle() + if aKind != rKind { + return false + } + } + return true +} + +// equalApprox returns whether the elements of a and b are the same to within +// the tolerance. If ignoreNaN is true the test is relaxed such that NaN == NaN. +func equalApprox(a, b Matrix, tol float64, ignoreNaN bool) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + return false + } + if ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if !floats.EqualWithinAbsOrRel(a.At(i, j), b.At(i, j), tol, tol) { + if ignoreNaN && math.IsNaN(a.At(i, j)) && math.IsNaN(b.At(i, j)) { + continue + } + return false + } + } + } + return true +} + +// equal returns true if the matrices have equal entries. +func equal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + return false + } + if ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.At(i, j) != b.At(i, j) { + return false + } + } + } + return true +} + +// isDiagonal returns whether a is a diagonal matrix. +func isDiagonal(a Matrix) bool { + r, c := a.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + if a.At(i, j) != 0 && i != j { + return false + } + } + } + return true +} + +// equalDiagonal returns whether a and b are equal on the diagonal. +func equalDiagonal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := a.Dims() + if min(ar, ac) != min(br, bc) { + return false + } + for i := 0; i < min(ar, ac); i++ { + if a.At(i, i) != b.At(i, i) { + return false + } + } + return true +} + +// underlyingData extracts the underlying data of the matrix a. +func underlyingData(a Matrix) []float64 { + switch t := a.(type) { + default: + panic("matrix type not implemented for extracting underlying data") + case Untransposer: + return underlyingData(t.Untranspose()) + case *Dense: + return t.mat.Data + case *SymDense: + return t.mat.Data + case *TriDense: + return t.mat.Data + case *VecDense: + return t.mat.Data + } +} + +// testMatrices is a list of matrix types to test. +// The TriDense types have actual sizes because the return from Triangular is +// only valid when n == 0. +var testMatrices = []Matrix{ + &Dense{}, + &SymDense{}, + NewTriDense(3, true, nil), + NewTriDense(3, false, nil), + NewVecDense(0, nil), + &VecDense{mat: blas64.Vector{Inc: 10}}, + &basicMatrix{}, + &basicSymmetric{}, + &basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Upper}}, + &basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Lower}}, + + Transpose{&Dense{}}, + Transpose{NewTriDense(3, true, nil)}, + TransposeTri{NewTriDense(3, true, nil)}, + Transpose{NewTriDense(3, false, nil)}, + TransposeTri{NewTriDense(3, false, nil)}, + Transpose{NewVecDense(0, nil)}, + Transpose{&VecDense{mat: blas64.Vector{Inc: 10}}}, + Transpose{&basicMatrix{}}, + Transpose{&basicSymmetric{}}, + Transpose{&basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Upper}}}, + Transpose{&basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Lower}}}, +} + +var sizes = []struct { + ar, ac int +}{ + {1, 1}, + {1, 3}, + {3, 1}, + + {6, 6}, + {6, 11}, + {11, 6}, +} + +func testOneInputFunc(t *testing.T, + // name is the name of the function being tested. + name string, + + // f is the function being tested. + f func(a Matrix) interface{}, + + // denseComparison performs the same operation, but using Dense matrices for + // comparison. + denseComparison func(a *Dense) interface{}, + + // sameAnswer compares the result from two different evaluations of the function + // and returns true if they are the same. The specific function being tested + // determines the definition of "same". It may mean identical or it may mean + // approximately equal. + sameAnswer func(a, b interface{}) bool, + + // legalType returns true if the type of the input is a legal type for the + // input of the function. + legalType func(a Matrix) bool, + + // legalSize returns true if the size is valid for the function. + legalSize func(r, c int) bool, +) { + for _, aMat := range testMatrices { + for _, test := range sizes { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac) + var want interface{} + if dimsOK { + var aDense Dense + aDense.Clone(a) + want = denseComparison(&aDense) + } + aCopy := makeCopyOf(a) + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + errStr := fmt.Sprintf("%v(%T), size: %#v, atrans %t", name, aType, test, aTrans) + var got interface{} + panicked, err := panics(func() { got = f(a) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !sameAnswer(want, got) { + t.Errorf("Answer mismatch: %s", errStr) + } + } + } +} + +var sizePairs = []struct { + ar, ac, br, bc int +}{ + {1, 1, 1, 1}, + {6, 6, 6, 6}, + {7, 7, 7, 7}, + + {1, 1, 1, 5}, + {1, 1, 5, 1}, + {1, 5, 1, 1}, + {5, 1, 1, 1}, + + {5, 5, 5, 1}, + {5, 5, 1, 5}, + {5, 1, 5, 5}, + {1, 5, 5, 5}, + + {6, 6, 6, 11}, + {6, 6, 11, 6}, + {6, 11, 6, 6}, + {11, 6, 6, 6}, + {11, 11, 11, 6}, + {11, 11, 6, 11}, + {11, 6, 11, 11}, + {6, 11, 11, 11}, + + {1, 1, 5, 5}, + {1, 5, 1, 5}, + {1, 5, 5, 1}, + {5, 1, 1, 5}, + {5, 1, 5, 1}, + {5, 5, 1, 1}, + {6, 6, 11, 11}, + {6, 11, 6, 11}, + {6, 11, 11, 6}, + {11, 6, 6, 11}, + {11, 6, 11, 6}, + {11, 11, 6, 6}, + + {1, 1, 17, 11}, + {1, 1, 11, 17}, + {1, 11, 1, 17}, + {1, 17, 1, 11}, + {1, 11, 17, 1}, + {1, 17, 11, 1}, + {11, 1, 1, 17}, + {17, 1, 1, 11}, + {11, 1, 17, 1}, + {17, 1, 11, 1}, + {11, 17, 1, 1}, + {17, 11, 1, 1}, + + {6, 6, 1, 11}, + {6, 6, 11, 1}, + {6, 11, 6, 1}, + {6, 1, 6, 11}, + {6, 11, 1, 6}, + {6, 1, 11, 6}, + {11, 6, 6, 1}, + {1, 6, 6, 11}, + {11, 6, 1, 6}, + {1, 6, 11, 6}, + {11, 1, 6, 6}, + {1, 11, 6, 6}, + + {6, 6, 17, 1}, + {6, 6, 1, 17}, + {6, 1, 6, 17}, + {6, 17, 6, 1}, + {6, 1, 17, 6}, + {6, 17, 1, 6}, + {1, 6, 6, 17}, + {17, 6, 6, 1}, + {1, 6, 17, 6}, + {17, 6, 1, 6}, + {1, 17, 6, 6}, + {17, 1, 6, 6}, + + {6, 6, 17, 11}, + {6, 6, 11, 17}, + {6, 11, 6, 17}, + {6, 17, 6, 11}, + {6, 11, 17, 6}, + {6, 17, 11, 6}, + {11, 6, 6, 17}, + {17, 6, 6, 11}, + {11, 6, 17, 6}, + {17, 6, 11, 6}, + {11, 17, 6, 6}, + {17, 11, 6, 6}, +} + +func testTwoInputFunc(t *testing.T, + // name is the name of the function being tested. + name string, + + // f is the function being tested. + f func(a, b Matrix) interface{}, + + // denseComparison performs the same operation, but using Dense matrices for + // comparison. + denseComparison func(a, b *Dense) interface{}, + + // sameAnswer compares the result from two different evaluations of the function + // and returns true if they are the same. The specific function being tested + // determines the definition of "same". It may mean identical or it may mean + // approximately equal. + sameAnswer func(a, b interface{}) bool, + + // legalType returns true if the types of the inputs are legal for the + // input of the function. + legalType func(a, b Matrix) bool, + + // legalSize returns true if the sizes are valid for the function. + legalSize func(ar, ac, br, bc int) bool, +) { + for _, aMat := range testMatrices { + for _, bMat := range testMatrices { + // Loop over all of the size combinations (bigger, smaller, etc.). + for _, test := range sizePairs { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat, bMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + if !legalDims(bMat, test.br, test.bc) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + b := makeRandOf(bMat, test.br, test.bc) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) + var want interface{} + if dimsOK { + var aDense, bDense Dense + aDense.Clone(a) + bDense.Clone(b) + want = denseComparison(&aDense, &bDense) + } + aCopy := makeCopyOf(a) + bCopy := makeCopyOf(b) + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + bType, bTrans := untranspose(b) + errStr := fmt.Sprintf("%v(%T, %T), size: %#v, atrans %t, btrans %t", name, aType, bType, test, aTrans, bTrans) + var got interface{} + panicked, err := panics(func() { got = f(a, b) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !equal(b, bCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !sameAnswer(want, got) { + t.Errorf("Answer mismatch: %s", errStr) + } + } + } + } +} + +// testOneInput tests a method that has one matrix input argument +func testOneInput(t *testing.T, + // name is the name of the method being tested. + name string, + + // receiver is a value of the receiver type. + receiver Matrix, + + // method is the generalized receiver.Method(a). + method func(receiver, a Matrix), + + // denseComparison performs the same operation as method, but with dense + // matrices for comparison with the result. + denseComparison func(receiver, a *Dense), + + // legalTypes returns whether the concrete types in Matrix are valid for + // the method. + legalType func(a Matrix) bool, + + // legalSize returns whether the matrix sizes are valid for the method. + legalSize func(ar, ac int) bool, + + // tol is the tolerance for equality when comparing method results. + tol float64, +) { + for _, aMat := range testMatrices { + for _, test := range sizes { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac) + var want Dense + if dimsOK { + var aDense Dense + aDense.Clone(a) + denseComparison(&want, &aDense) + } + aCopy := makeCopyOf(a) + + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + errStr := fmt.Sprintf("%T.%s(%T), size: %#v, atrans %v", receiver, name, aType, test, aTrans) + zero := makeRandOf(receiver, 0, 0) + panicked, err := panics(func() { method(zero, a) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !equalApprox(zero, &want, tol, false) { + t.Errorf("Answer mismatch with zero receiver: %s.\nGot:\n% v\nWant:\n% v\n", errStr, Formatted(zero), Formatted(&want)) + continue + } + + // Test the method with a non-zero-value of the receiver. + // The receiver has been overwritten in place so use its size + // to construct a new random matrix. + rr, rc := zero.Dims() + neverZero := makeRandOf(receiver, rr, rc) + panicked, _ = panics(func() { method(neverZero, a) }) + if panicked { + t.Errorf("Panicked with non-zero receiver: %s", errStr) + } + if !equalApprox(neverZero, &want, tol, false) { + t.Errorf("Answer mismatch non-zero receiver: %s", errStr) + } + + // Test with an incorrectly sized matrix. + switch receiver.(type) { + default: + panic("matrix type not coded for incorrect receiver size") + case *Dense: + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + wrongSize = makeRandOf(receiver, rr, rc+1) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of columns: %s", errStr) + } + case *TriDense, *SymDense: + // Add to the square size. + wrongSize := makeRandOf(receiver, rr+1, rc+1) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong size: %s", errStr) + } + case *VecDense: + // Add to the column length. + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + } + + // The receiver and the input may share a matrix pointer + // if the type and size of the receiver and one of the + // arguments match. Test the method works properly + // when this is the case. + aMaybeSame := maybeSame(neverZero, a) + if aMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame) }) + if panicked { + t.Errorf("Panics when a maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when a maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when a maybeSame: %s", errStr) + } + } + } + } + } +} + +// testTwoInput tests a method that has two input arguments. +func testTwoInput(t *testing.T, + // name is the name of the method being tested. + name string, + + // receiver is a value of the receiver type. + receiver Matrix, + + // method is the generalized receiver.Method(a, b). + method func(receiver, a, b Matrix), + + // denseComparison performs the same operation as method, but with dense + // matrices for comparison with the result. + denseComparison func(receiver, a, b *Dense), + + // legalTypes returns whether the concrete types in Matrix are valid for + // the method. + legalTypes func(a, b Matrix) bool, + + // legalSize returns whether the matrix sizes are valid for the method. + legalSize func(ar, ac, br, bc int) bool, + + // tol is the tolerance for equality when comparing method results. + tol float64, +) { + for _, aMat := range testMatrices { + for _, bMat := range testMatrices { + // Loop over all of the size combinations (bigger, smaller, etc.). + for _, test := range sizePairs { + // Skip the test if any argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalTypes(aMat, bMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + if !legalDims(bMat, test.br, test.bc) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + b := makeRandOf(bMat, test.br, test.bc) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) + var want Dense + if dimsOK { + var aDense, bDense Dense + aDense.Clone(a) + bDense.Clone(b) + denseComparison(&want, &aDense, &bDense) + } + aCopy := makeCopyOf(a) + bCopy := makeCopyOf(b) + + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + bType, bTrans := untranspose(b) + errStr := fmt.Sprintf("%T.%s(%T, %T), sizes: %#v, atrans %v, btrans %v", receiver, name, aType, bType, test, aTrans, bTrans) + zero := makeRandOf(receiver, 0, 0) + panicked, err := panics(func() { method(zero, a, b) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !equal(b, bCopy) { + t.Errorf("Second input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + wasZero, zero := zero, nil // Nil-out zero so we detect illegal use. + // NaN equality is allowed because of 0/0 in DivElem test. + if !equalApprox(wasZero, &want, tol, true) { + t.Errorf("Answer mismatch with zero receiver: %s", errStr) + continue + } + + // Test the method with a non-zero-value of the receiver. + // The receiver has been overwritten in place so use its size + // to construct a new random matrix. + rr, rc := wasZero.Dims() + neverZero := makeRandOf(receiver, rr, rc) + panicked, message := panics(func() { method(neverZero, a, b) }) + if panicked { + t.Errorf("Panicked with non-zero receiver: %s: %s", errStr, message) + } + // NaN equality is allowed because of 0/0 in DivElem test. + if !equalApprox(neverZero, &want, tol, true) { + t.Errorf("Answer mismatch non-zero receiver: %s", errStr) + } + + // Test with an incorrectly sized matrix. + switch receiver.(type) { + default: + panic("matrix type not coded for incorrect receiver size") + case *Dense: + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + wrongSize = makeRandOf(receiver, rr, rc+1) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of columns: %s", errStr) + } + case *TriDense, *SymDense: + // Add to the square size. + wrongSize := makeRandOf(receiver, rr+1, rc+1) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong size: %s", errStr) + } + case *VecDense: + // Add to the column length. + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + } + + // The receiver and an input may share a matrix pointer + // if the type and size of the receiver and one of the + // arguments match. Test the method works properly + // when this is the case. + aMaybeSame := maybeSame(neverZero, a) + bMaybeSame := maybeSame(neverZero, b) + if aMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame, b) }) + if panicked { + t.Errorf("Panics when a maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when a maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when a maybeSame: %s", errStr) + } + } + } + if bMaybeSame { + bSame := makeCopyOf(b) + receiver = bSame + u, ok := bSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, a, bSame) }) + if panicked { + t.Errorf("Panics when b maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when b maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when b maybeSame: %s", errStr) + } + } + } + if aMaybeSame && bMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + // Ensure that b is the correct transpose type if applicable. + // The receiver is always a concrete type so use it. + bSame := receiver + u, ok = b.(Untransposer) + if ok { + bSame = retranspose(b, receiver) + } + // Compute the real answer for this case. It is different + // from the initial answer since now a and b have the + // same data. + zero = makeRandOf(wasZero, 0, 0) + method(zero, aSame, bSame) + wasZero, zero = zero, nil // Nil-out zero so we detect illegal use. + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame, bSame) }) + if panicked { + t.Errorf("Panics when both maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, wasZero, tol, false) { + t.Errorf("Wrong answer when both maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when both maybeSame: %s", errStr) + } + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/lq.go b/vendor/gonum.org/v1/gonum/mat/lq.go new file mode 100644 index 00000000..54c49336 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/lq.go @@ -0,0 +1,225 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// LQ is a type for creating and using the LQ factorization of a matrix. +type LQ struct { + lq *Dense + tau []float64 + cond float64 +} + +func (lq *LQ) updateCond(norm lapack.MatrixNorm) { + // Since A = L*Q, and Q is orthogonal, we get for the condition number κ + // κ(A) := |A| |A^-1| = |L*Q| |(L*Q)^-1| = |L| |Q^T * L^-1| + // = |L| |L^-1| = κ(L), + // where we used that fact that Q^-1 = Q^T. However, this assumes that + // the matrix norm is invariant under orthogonal transformations which + // is not the case for CondNorm. Hopefully the error is negligible: κ + // is only a qualitative measure anyway. + m := lq.lq.mat.Rows + work := getFloats(3*m, false) + iwork := getInts(m, false) + l := lq.lq.asTriDense(m, blas.NonUnit, blas.Lower) + v := lapack64.Trcon(norm, l.mat, work, iwork) + lq.cond = 1 / v + putFloats(work) + putInts(iwork) +} + +// Factorize computes the LQ factorization of an m×n matrix a where n <= m. The LQ +// factorization always exists even if A is singular. +// +// The LQ decomposition is a factorization of the matrix A such that A = L * Q. +// The matrix Q is an orthonormal n×n matrix, and L is an m×n upper triangular matrix. +// L and Q can be extracted from the LTo and QTo methods. +func (lq *LQ) Factorize(a Matrix) { + lq.factorize(a, CondNorm) +} + +func (lq *LQ) factorize(a Matrix, norm lapack.MatrixNorm) { + m, n := a.Dims() + if m > n { + panic(ErrShape) + } + k := min(m, n) + if lq.lq == nil { + lq.lq = &Dense{} + } + lq.lq.Clone(a) + work := []float64{0} + lq.tau = make([]float64, k) + lapack64.Gelqf(lq.lq.mat, lq.tau, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Gelqf(lq.lq.mat, lq.tau, work, len(work)) + putFloats(work) + lq.updateCond(norm) +} + +// Cond returns the condition number for the factorized matrix. +// Cond will panic if the receiver does not contain a successful factorization. +func (lq *LQ) Cond() float64 { + if lq.lq == nil || lq.lq.IsZero() { + panic("lq: no decomposition computed") + } + return lq.cond +} + +// TODO(btracey): Add in the "Reduced" forms for extracting the m×m orthogonal +// and upper triangular matrices. + +// LTo extracts the m×n lower trapezoidal matrix from a LQ decomposition. +// If dst is nil, a new matrix is allocated. The resulting L matrix is returned. +func (lq *LQ) LTo(dst *Dense) *Dense { + r, c := lq.lq.Dims() + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + // Disguise the LQ as a lower triangular. + t := &TriDense{ + mat: blas64.Triangular{ + N: r, + Stride: lq.lq.mat.Stride, + Data: lq.lq.mat.Data, + Uplo: blas.Lower, + Diag: blas.NonUnit, + }, + cap: lq.lq.capCols, + } + dst.Copy(t) + + if r == c { + return dst + } + // Zero right of the triangular. + for i := 0; i < r; i++ { + zero(dst.mat.Data[i*dst.mat.Stride+r : i*dst.mat.Stride+c]) + } + + return dst +} + +// QTo extracts the n×n orthonormal matrix Q from an LQ decomposition. +// If dst is nil, a new matrix is allocated. The resulting Q matrix is returned. +func (lq *LQ) QTo(dst *Dense) *Dense { + _, c := lq.lq.Dims() + if dst == nil { + dst = NewDense(c, c, nil) + } else { + dst.reuseAsZeroed(c, c) + } + q := dst.mat + + // Set Q = I. + ldq := q.Stride + for i := 0; i < c; i++ { + q.Data[i*ldq+i] = 1 + } + + // Construct Q from the elementary reflectors. + work := []float64{0} + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, len(work)) + putFloats(work) + + return dst +} + +// Solve finds a minimum-norm solution to a system of linear equations defined +// by the matrices A and b, where A is an m×n matrix represented in its LQ factorized +// form. If A is singular or near-singular a Condition error is returned. Please +// see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters. +// If trans == false, find the minimum norm solution of A * X = b. +// If trans == true, find X such that ||A*X - b||_2 is minimized. +// The solution matrix, X, is stored in place into m. +func (lq *LQ) Solve(m *Dense, trans bool, b Matrix) error { + r, c := lq.lq.Dims() + br, bc := b.Dims() + + // The LQ solve algorithm stores the result in-place into the right hand side. + // The storage for the answer must be large enough to hold both b and x. + // However, this method's receiver must be the size of x. Copy b, and then + // copy the result into m at the end. + if trans { + if c != br { + panic(ErrShape) + } + m.reuseAs(r, bc) + } else { + if r != br { + panic(ErrShape) + } + m.reuseAs(c, bc) + } + // Do not need to worry about overlap between m and b because x has its own + // independent storage. + x := getWorkspace(max(r, c), bc, false) + x.Copy(b) + t := lq.lq.asTriDense(lq.lq.mat.Rows, blas.NonUnit, blas.Lower).mat + if trans { + work := []float64{0} + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, len(work)) + putFloats(work) + + ok := lapack64.Trtrs(blas.Trans, t, x.mat) + if !ok { + return Condition(math.Inf(1)) + } + } else { + ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) + if !ok { + return Condition(math.Inf(1)) + } + for i := r; i < c; i++ { + zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) + } + work := []float64{0} + lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, len(work)) + putFloats(work) + } + // M was set above to be the correct size for the result. + m.Copy(x) + putWorkspace(x) + if lq.cond > ConditionTolerance { + return Condition(lq.cond) + } + return nil +} + +// SolveVec finds a minimum-norm solution to a system of linear equations. +// Please see LQ.Solve for the full documentation. +func (lq *LQ) SolveVec(v *VecDense, trans bool, b *VecDense) error { + if v != b { + v.checkOverlap(b.mat) + } + r, c := lq.lq.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the VecDenses as Dense and call the matrix code. + if trans { + v.reuseAs(r) + } else { + v.reuseAs(c) + } + return lq.Solve(v.asDense(), trans, b.asDense()) +} diff --git a/vendor/gonum.org/v1/gonum/mat/lq_test.go b/vendor/gonum.org/v1/gonum/mat/lq_test.go new file mode 100644 index 00000000..9902b62a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/lq_test.go @@ -0,0 +1,179 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math/rand" + "testing" +) + +func TestLQ(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + var lq LQ + lq.Factorize(a) + q := lq.QTo(nil) + + if !isOrthonormal(q, 1e-10) { + t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) + } + + l := lq.LTo(nil) + + var got Dense + got.Mul(l, q) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("LQ does not equal original matrix. \nWant: %v\nGot: %v", want, got) + } + } +} + +func TestSolveLQ(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {5, 10, 1}, + {5, 5, 3}, + {5, 10, 3}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + lq := &LQ{} + lq.Factorize(a) + lq.Solve(&x, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveLQVec(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewVecDense(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x VecDense + lq := &LQ{} + lq.Factorize(a) + lq.SolveVec(&x, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveLQCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + NewDense(2, 3, []float64{1, 0, 0, 0, 1e-20, 0}), + } { + m, _ := test.Dims() + var lq LQ + lq.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := lq.Solve(&x, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVecDense(m, nil) + var xvec VecDense + if err := lq.SolveVec(&xvec, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/lu.go b/vendor/gonum.org/v1/gonum/mat/lu.go new file mode 100644 index 00000000..ff0df0cf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/lu.go @@ -0,0 +1,373 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +const badSliceLength = "mat: improper slice length" + +// LU is a type for creating and using the LU factorization of a matrix. +type LU struct { + lu *Dense + pivot []int + cond float64 +} + +// updateCond updates the stored condition number of the matrix. anorm is the +// norm of the original matrix. If anorm is negative it will be estimated. +func (lu *LU) updateCond(anorm float64, norm lapack.MatrixNorm) { + n := lu.lu.mat.Cols + work := getFloats(4*n, false) + defer putFloats(work) + iwork := getInts(n, false) + defer putInts(iwork) + if anorm < 0 { + // This is an approximation. By the definition of a norm, + // |AB| <= |A| |B|. + // Since A = L*U, we get for the condition number κ that + // κ(A) := |A| |A^-1| = |L*U| |A^-1| <= |L| |U| |A^-1|, + // so this will overestimate the condition number somewhat. + // The norm of the original factorized matrix cannot be stored + // because of update possibilities. + u := lu.lu.asTriDense(n, blas.NonUnit, blas.Upper) + l := lu.lu.asTriDense(n, blas.Unit, blas.Lower) + unorm := lapack64.Lantr(norm, u.mat, work) + lnorm := lapack64.Lantr(norm, l.mat, work) + anorm = unorm * lnorm + } + v := lapack64.Gecon(norm, lu.lu.mat, anorm, work, iwork) + lu.cond = 1 / v +} + +// Factorize computes the LU factorization of the square matrix a and stores the +// result. The LU decomposition will complete regardless of the singularity of a. +// +// The LU factorization is computed with pivoting, and so really the decomposition +// is a PLU decomposition where P is a permutation matrix. The individual matrix +// factors can be extracted from the factorization using the Permutation method +// on Dense, and the LU LTo and UTo methods. +func (lu *LU) Factorize(a Matrix) { + lu.factorize(a, CondNorm) +} + +func (lu *LU) factorize(a Matrix, norm lapack.MatrixNorm) { + r, c := a.Dims() + if r != c { + panic(ErrSquare) + } + if lu.lu == nil { + lu.lu = NewDense(r, r, nil) + } else { + lu.lu.Reset() + lu.lu.reuseAs(r, r) + } + lu.lu.Copy(a) + if cap(lu.pivot) < r { + lu.pivot = make([]int, r) + } + lu.pivot = lu.pivot[:r] + work := getFloats(r, false) + anorm := lapack64.Lange(norm, lu.lu.mat, work) + putFloats(work) + lapack64.Getrf(lu.lu.mat, lu.pivot) + lu.updateCond(anorm, norm) +} + +// Cond returns the condition number for the factorized matrix. +// Cond will panic if the receiver does not contain a successful factorization. +func (lu *LU) Cond() float64 { + if lu.lu == nil || lu.lu.IsZero() { + panic("lu: no decomposition computed") + } + return lu.cond +} + +// Reset resets the factorization so that it can be reused as the receiver of a +// dimensionally restricted operation. +func (lu *LU) Reset() { + if lu.lu != nil { + lu.lu.Reset() + } + lu.pivot = lu.pivot[:0] +} + +func (lu *LU) isZero() bool { + return len(lu.pivot) == 0 +} + +// Det returns the determinant of the matrix that has been factorized. In many +// expressions, using LogDet will be more numerically stable. +func (lu *LU) Det() float64 { + det, sign := lu.LogDet() + return math.Exp(det) * sign +} + +// LogDet returns the log of the determinant and the sign of the determinant +// for the matrix that has been factorized. Numerical stability in product and +// division expressions is generally improved by working in log space. +func (lu *LU) LogDet() (det float64, sign float64) { + _, n := lu.lu.Dims() + logDiag := getFloats(n, false) + defer putFloats(logDiag) + sign = 1.0 + for i := 0; i < n; i++ { + v := lu.lu.at(i, i) + if v < 0 { + sign *= -1 + } + if lu.pivot[i] != i { + sign *= -1 + } + logDiag[i] = math.Log(math.Abs(v)) + } + return floats.Sum(logDiag), sign +} + +// Pivot returns pivot indices that enable the construction of the permutation +// matrix P (see Dense.Permutation). If swaps == nil, then new memory will be +// allocated, otherwise the length of the input must be equal to the size of the +// factorized matrix. +func (lu *LU) Pivot(swaps []int) []int { + _, n := lu.lu.Dims() + if swaps == nil { + swaps = make([]int, n) + } + if len(swaps) != n { + panic(badSliceLength) + } + // Perform the inverse of the row swaps in order to find the final + // row swap position. + for i := range swaps { + swaps[i] = i + } + for i := n - 1; i >= 0; i-- { + v := lu.pivot[i] + swaps[i], swaps[v] = swaps[v], swaps[i] + } + return swaps +} + +// RankOne updates an LU factorization as if a rank-one update had been applied to +// the original matrix A, storing the result into the receiver. That is, if in +// the original LU decomposition P * L * U = A, in the updated decomposition +// P * L * U = A + alpha * x * y^T. +func (lu *LU) RankOne(orig *LU, alpha float64, x, y *VecDense) { + // RankOne uses algorithm a1 on page 28 of "Multiple-Rank Updates to Matrix + // Factorizations for Nonlinear Analysis and Circuit Design" by Linzhong Deng. + // http://web.stanford.edu/group/SOL/dissertations/Linzhong-Deng-thesis.pdf + _, n := orig.lu.Dims() + if x.Len() != n { + panic(ErrShape) + } + if y.Len() != n { + panic(ErrShape) + } + if orig != lu { + if lu.isZero() { + if cap(lu.pivot) < n { + lu.pivot = make([]int, n) + } + lu.pivot = lu.pivot[:n] + if lu.lu == nil { + lu.lu = NewDense(n, n, nil) + } else { + lu.lu.reuseAs(n, n) + } + } else if len(lu.pivot) != n { + panic(ErrShape) + } + copy(lu.pivot, orig.pivot) + lu.lu.Copy(orig.lu) + } + + xs := getFloats(n, false) + defer putFloats(xs) + ys := getFloats(n, false) + defer putFloats(ys) + for i := 0; i < n; i++ { + xs[i] = x.at(i) + ys[i] = y.at(i) + } + + // Adjust for the pivoting in the LU factorization + for i, v := range lu.pivot { + xs[i], xs[v] = xs[v], xs[i] + } + + lum := lu.lu.mat + omega := alpha + for j := 0; j < n; j++ { + ujj := lum.Data[j*lum.Stride+j] + ys[j] /= ujj + theta := 1 + xs[j]*ys[j]*omega + beta := omega * ys[j] / theta + gamma := omega * xs[j] + omega -= beta * gamma + lum.Data[j*lum.Stride+j] *= theta + for i := j + 1; i < n; i++ { + xs[i] -= lum.Data[i*lum.Stride+j] * xs[j] + tmp := ys[i] + ys[i] -= lum.Data[j*lum.Stride+i] * ys[j] + lum.Data[i*lum.Stride+j] += beta * xs[i] + lum.Data[j*lum.Stride+i] += gamma * tmp + } + } + lu.updateCond(-1, CondNorm) +} + +// LTo extracts the lower triangular matrix from an LU factorization. +// If dst is nil, a new matrix is allocated. The resulting L matrix is returned. +func (lu *LU) LTo(dst *TriDense) *TriDense { + _, n := lu.lu.Dims() + if dst == nil { + dst = NewTriDense(n, Lower, nil) + } else { + dst.reuseAs(n, Lower) + } + // Extract the lower triangular elements. + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + dst.mat.Data[i*dst.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] + } + } + // Set ones on the diagonal. + for i := 0; i < n; i++ { + dst.mat.Data[i*dst.mat.Stride+i] = 1 + } + return dst +} + +// UTo extracts the upper triangular matrix from an LU factorization. +// If dst is nil, a new matrix is allocated. The resulting U matrix is returned. +func (lu *LU) UTo(dst *TriDense) *TriDense { + _, n := lu.lu.Dims() + if dst == nil { + dst = NewTriDense(n, Upper, nil) + } else { + dst.reuseAs(n, Upper) + } + // Extract the upper triangular elements. + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dst.mat.Data[i*dst.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] + } + } + return dst +} + +// Permutation constructs an r×r permutation matrix with the given row swaps. +// A permutation matrix has exactly one element equal to one in each row and column +// and all other elements equal to zero. swaps[i] specifies the row with which +// i will be swapped, which is equivalent to the non-zero column of row i. +func (m *Dense) Permutation(r int, swaps []int) { + m.reuseAs(r, r) + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+r]) + v := swaps[i] + if v < 0 || v >= r { + panic(ErrRowAccess) + } + m.mat.Data[i*m.mat.Stride+v] = 1 + } +} + +// Solve solves a system of linear equations using the LU decomposition of a matrix. +// It computes +// A * x = b if trans == false +// A^T * x = b if trans == true +// In both cases, A is represented in LU factorized form, and the matrix x is +// stored into m. +// +// If A is singular or near-singular a Condition error is returned. Please see +// the documentation for Condition for more information. +func (lu *LU) Solve(m *Dense, trans bool, b Matrix) error { + _, n := lu.lu.Dims() + br, bc := b.Dims() + if br != n { + panic(ErrShape) + } + // TODO(btracey): Should test the condition number instead of testing that + // the determinant is exactly zero. + if lu.Det() == 0 { + return Condition(math.Inf(1)) + } + + m.reuseAs(n, bc) + bU, _ := untranspose(b) + var restore func() + if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } else if rm, ok := bU.(RawMatrixer); ok { + m.checkOverlap(rm.RawMatrix()) + } + + m.Copy(b) + t := blas.NoTrans + if trans { + t = blas.Trans + } + lapack64.Getrs(t, lu.lu.mat, m.mat, lu.pivot) + if lu.cond > ConditionTolerance { + return Condition(lu.cond) + } + return nil +} + +// SolveVec solves a system of linear equations using the LU decomposition of a matrix. +// It computes +// A * x = b if trans == false +// A^T * x = b if trans == true +// In both cases, A is represented in LU factorized form, and the matrix x is +// stored into v. +// +// If A is singular or near-singular a Condition error is returned. Please see +// the documentation for Condition for more information. +func (lu *LU) SolveVec(v *VecDense, trans bool, b *VecDense) error { + _, n := lu.lu.Dims() + bn := b.Len() + if bn != n { + panic(ErrShape) + } + if v != b { + v.checkOverlap(b.mat) + } + // TODO(btracey): Should test the condition number instead of testing that + // the determinant is exactly zero. + if lu.Det() == 0 { + return Condition(math.Inf(1)) + } + + v.reuseAs(n) + var restore func() + if v == b { + v, restore = v.isolatedWorkspace(b) + defer restore() + } + v.CopyVec(b) + vMat := blas64.General{ + Rows: n, + Cols: 1, + Stride: v.mat.Inc, + Data: v.mat.Data, + } + t := blas.NoTrans + if trans { + t = blas.Trans + } + lapack64.Getrs(t, lu.lu.mat, vMat, lu.pivot) + if lu.cond > ConditionTolerance { + return Condition(lu.cond) + } + return nil +} diff --git a/vendor/gonum.org/v1/gonum/mat/lu_test.go b/vendor/gonum.org/v1/gonum/mat/lu_test.go new file mode 100644 index 00000000..c210670f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/lu_test.go @@ -0,0 +1,189 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math/rand" + "testing" +) + +func TestLUD(t *testing.T) { + for _, n := range []int{1, 5, 10, 11, 50} { + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + var lu LU + lu.Factorize(a) + + l := lu.LTo(nil) + u := lu.UTo(nil) + var p Dense + pivot := lu.Pivot(nil) + p.Permutation(n, pivot) + var got Dense + got.Product(&p, l, u) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("PLU does not equal original matrix.\nWant: %v\n Got: %v", want, got) + } + } +} + +func TestLURankOne(t *testing.T) { + for _, pivoting := range []bool{true} { + for _, n := range []int{3, 10, 50} { + // Construct a random LU factorization + lu := &LU{} + lu.lu = NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + lu.lu.Set(i, j, rand.Float64()) + } + } + lu.pivot = make([]int, n) + for i := range lu.pivot { + lu.pivot[i] = i + } + if pivoting { + // For each row, randomly swap with itself or a row after (like is done) + // in the actual LU factorization. + for i := range lu.pivot { + idx := i + rand.Intn(n-i) + lu.pivot[i], lu.pivot[idx] = lu.pivot[idx], lu.pivot[i] + } + } + // Apply a rank one update. Ensure the update magnitude is larger than + // the equal tolerance. + alpha := rand.Float64() + 1 + x := NewVecDense(n, nil) + y := NewVecDense(n, nil) + for i := 0; i < n; i++ { + x.setVec(i, rand.Float64()+1) + y.setVec(i, rand.Float64()+1) + } + a := luReconstruct(lu) + a.RankOne(a, alpha, x, y) + + var luNew LU + luNew.RankOne(lu, alpha, x, y) + lu.RankOne(lu, alpha, x, y) + + aR1New := luReconstruct(&luNew) + aR1 := luReconstruct(lu) + + if !Equal(aR1, aR1New) { + t.Error("Different answer when new receiver") + } + if !EqualApprox(aR1, a, 1e-10) { + t.Errorf("Rank one mismatch, pivot %v.\nWant: %v\nGot:%v\n", pivoting, a, aR1) + } + } + } +} + +// luReconstruct reconstructs the original A matrix from an LU decomposition. +func luReconstruct(lu *LU) *Dense { + var L, U TriDense + lu.LTo(&L) + lu.UTo(&U) + var P Dense + pivot := lu.Pivot(nil) + P.Permutation(len(pivot), pivot) + + var a Dense + a.Mul(&L, &U) + a.Mul(&P, &a) + return &a +} + +func TestSolveLU(t *testing.T) { + for _, test := range []struct { + n, bc int + }{ + {5, 5}, + {5, 10}, + {10, 5}, + } { + n := test.n + bc := test.bc + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + b := NewDense(n, bc, nil) + for i := 0; i < n; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.NormFloat64()) + } + } + var lu LU + lu.Factorize(a) + var x Dense + if err := lu.Solve(&x, false, b); err != nil { + continue + } + var got Dense + got.Mul(a, &x) + if !EqualApprox(&got, b, 1e-12) { + t.Errorf("Solve mismatch for non-singular matrix. n = %v, bc = %v.\nWant: %v\nGot: %v", n, bc, b, got) + } + } + // TODO(btracey): Add testOneInput test when such a function exists. +} + +func TestSolveLUCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + } { + m, _ := test.Dims() + var lu LU + lu.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := lu.Solve(&x, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVecDense(m, nil) + var xvec VecDense + if err := lu.SolveVec(&xvec, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} + +func TestSolveLUVec(t *testing.T) { + for _, n := range []int{5, 10} { + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + b := NewVecDense(n, nil) + for i := 0; i < n; i++ { + b.SetVec(i, rand.NormFloat64()) + } + var lu LU + lu.Factorize(a) + var x VecDense + if err := lu.SolveVec(&x, false, b); err != nil { + continue + } + var got VecDense + got.MulVec(a, &x) + if !EqualApprox(&got, b, 1e-12) { + t.Errorf("Solve mismatch n = %v.\nWant: %v\nGot: %v", n, b, got) + } + } + // TODO(btracey): Add testOneInput test when such a function exists. +} diff --git a/vendor/gonum.org/v1/gonum/mat/matrix.go b/vendor/gonum.org/v1/gonum/mat/matrix.go new file mode 100644 index 00000000..6ba51eaf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/matrix.go @@ -0,0 +1,881 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// Matrix is the basic matrix interface type. +type Matrix interface { + // Dims returns the dimensions of a Matrix. + Dims() (r, c int) + + // At returns the value of a matrix element at row i, column j. + // It will panic if i or j are out of bounds for the matrix. + At(i, j int) float64 + + // T returns the transpose of the Matrix. Whether T returns a copy of the + // underlying data is implementation dependent. + // This method may be implemented using the Transpose type, which + // provides an implicit matrix transpose. + T() Matrix +} + +var ( + _ Matrix = Transpose{} + _ Untransposer = Transpose{} +) + +// Transpose is a type for performing an implicit matrix transpose. It implements +// the Matrix interface, returning values from the transpose of the matrix within. +type Transpose struct { + Matrix Matrix +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Matrix field. +func (t Transpose) At(i, j int) float64 { + return t.Matrix.At(j, i) +} + +// Dims returns the dimensions of the transposed matrix. The number of rows returned +// is the number of columns in the Matrix field, and the number of columns is +// the number of rows in the Matrix field. +func (t Transpose) Dims() (r, c int) { + c, r = t.Matrix.Dims() + return r, c +} + +// T performs an implicit transpose by returning the Matrix field. +func (t Transpose) T() Matrix { + return t.Matrix +} + +// Untranspose returns the Matrix field. +func (t Transpose) Untranspose() Matrix { + return t.Matrix +} + +// Untransposer is a type that can undo an implicit transpose. +type Untransposer interface { + // Note: This interface is needed to unify all of the Transpose types. In + // the mat methods, we need to test if the Matrix has been implicitly + // transposed. If this is checked by testing for the specific Transpose type + // then the behavior will be different if the user uses T() or TTri() for a + // triangular matrix. + + // Untranspose returns the underlying Matrix stored for the implicit transpose. + Untranspose() Matrix +} + +// UntransposeBander is a type that can undo an implicit band transpose. +type UntransposeBander interface { + // Untranspose returns the underlying Banded stored for the implicit transpose. + UntransposeBand() Banded +} + +// UntransposeTrier is a type that can undo an implicit triangular transpose. +type UntransposeTrier interface { + // Untranspose returns the underlying Triangular stored for the implicit transpose. + UntransposeTri() Triangular +} + +// Mutable is a matrix interface type that allows elements to be altered. +type Mutable interface { + // Set alters the matrix element at row i, column j to v. + // It will panic if i or j are out of bounds for the matrix. + Set(i, j int, v float64) + + Matrix +} + +// A RowViewer can return a VecDense reflecting a row that is backed by the matrix +// data. The VecDense returned will have length equal to the number of columns. +type RowViewer interface { + RowView(i int) *VecDense +} + +// A RawRowViewer can return a slice of float64 reflecting a row that is backed by the matrix +// data. +type RawRowViewer interface { + RawRowView(i int) []float64 +} + +// A ColViewer can return a VecDense reflecting a column that is backed by the matrix +// data. The VecDense returned will have length equal to the number of rows. +type ColViewer interface { + ColView(j int) *VecDense +} + +// A RawColViewer can return a slice of float64 reflecting a column that is backed by the matrix +// data. +type RawColViewer interface { + RawColView(j int) []float64 +} + +// A Cloner can make a copy of a into the receiver, overwriting the previous value of the +// receiver. The clone operation does not make any restriction on shape and will not cause +// shadowing. +type Cloner interface { + Clone(a Matrix) +} + +// A Reseter can reset the matrix so that it can be reused as the receiver of a dimensionally +// restricted operation. This is commonly used when the matrix is being used as a workspace +// or temporary matrix. +// +// If the matrix is a view, using the reset matrix may result in data corruption in elements +// outside the view. +type Reseter interface { + Reset() +} + +// A Copier can make a copy of elements of a into the receiver. The submatrix copied +// starts at row and column 0 and has dimensions equal to the minimum dimensions of +// the two matrices. The number of row and columns copied is returned. +// Copy will copy from a source that aliases the receiver unless the source is transposed; +// an aliasing transpose copy will panic with the exception for a special case when +// the source data has a unitary increment or stride. +type Copier interface { + Copy(a Matrix) (r, c int) +} + +// A Grower can grow the size of the represented matrix by the given number of rows and columns. +// Growing beyond the size given by the Caps method will result in the allocation of a new +// matrix and copying of the elements. If Grow is called with negative increments it will +// panic with ErrIndexOutOfRange. +type Grower interface { + Caps() (r, c int) + Grow(r, c int) Matrix +} + +// A BandWidther represents a banded matrix and can return the left and right half-bandwidths, k1 and +// k2. +type BandWidther interface { + BandWidth() (k1, k2 int) +} + +// A RawMatrixSetter can set the underlying blas64.General used by the receiver. There is no restriction +// on the shape of the receiver. Changes to the receiver's elements will be reflected in the blas64.General.Data. +type RawMatrixSetter interface { + SetRawMatrix(a blas64.General) +} + +// A RawMatrixer can return a blas64.General representation of the receiver. Changes to the blas64.General.Data +// slice will be reflected in the original matrix, changes to the Rows, Cols and Stride fields will not. +type RawMatrixer interface { + RawMatrix() blas64.General +} + +// A RawVectorer can return a blas64.Vector representation of the receiver. Changes to the blas64.Vector.Data +// slice will be reflected in the original matrix, changes to the Inc field will not. +type RawVectorer interface { + RawVector() blas64.Vector +} + +// A NonZeroDoer can call a function for each non-zero element of the receiver. +// The parameters of the function are the element indices and its value. +type NonZeroDoer interface { + DoNonZero(func(i, j int, v float64)) +} + +// A RowNonZeroDoer can call a function for each non-zero element of a row of the receiver. +// The parameters of the function are the element indices and its value. +type RowNonZeroDoer interface { + DoRowNonZero(i int, fn func(i, j int, v float64)) +} + +// A ColNonZeroDoer can call a function for each non-zero element of a column of the receiver. +// The parameters of the function are the element indices and its value. +type ColNonZeroDoer interface { + DoColNonZero(j int, fn func(i, j int, v float64)) +} + +// TODO(btracey): Consider adding CopyCol/CopyRow if the behavior seems useful. +// TODO(btracey): Add in fast paths to Row/Col for the other concrete types +// (TriDense, etc.) as well as relevant interfaces (RowColer, RawRowViewer, etc.) + +// Col copies the elements in the jth column of the matrix into the slice dst. +// The length of the provided slice must equal the number of rows, unless the +// slice is nil in which case a new slice is first allocated. +func Col(dst []float64, j int, a Matrix) []float64 { + r, c := a.Dims() + if j < 0 || j >= c { + panic(ErrColAccess) + } + if dst == nil { + dst = make([]float64, r) + } else { + if len(dst) != r { + panic(ErrColLength) + } + } + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + m := rm.RawMatrix() + if aTrans { + copy(dst, m.Data[j*m.Stride:j*m.Stride+m.Cols]) + return dst + } + blas64.Copy(r, + blas64.Vector{Inc: m.Stride, Data: m.Data[j:]}, + blas64.Vector{Inc: 1, Data: dst}, + ) + return dst + } + for i := 0; i < r; i++ { + dst[i] = a.At(i, j) + } + return dst +} + +// Row copies the elements in the jth column of the matrix into the slice dst. +// The length of the provided slice must equal the number of columns, unless the +// slice is nil in which case a new slice is first allocated. +func Row(dst []float64, i int, a Matrix) []float64 { + r, c := a.Dims() + if i < 0 || i >= r { + panic(ErrColAccess) + } + if dst == nil { + dst = make([]float64, c) + } else { + if len(dst) != c { + panic(ErrRowLength) + } + } + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + m := rm.RawMatrix() + if aTrans { + blas64.Copy(c, + blas64.Vector{Inc: m.Stride, Data: m.Data[i:]}, + blas64.Vector{Inc: 1, Data: dst}, + ) + return dst + } + copy(dst, m.Data[i*m.Stride:i*m.Stride+m.Cols]) + return dst + } + for j := 0; j < c; j++ { + dst[j] = a.At(i, j) + } + return dst +} + +// Cond returns the condition number of the given matrix under the given norm. +// The condition number must be based on the 1-norm, 2-norm or ∞-norm. +// Cond will panic with matrix.ErrShape if the matrix has zero size. +// +// BUG(btracey): The computation of the 1-norm and ∞-norm for non-square matrices +// is innacurate, although is typically the right order of magnitude. See +// https://github.com/xianyi/OpenBLAS/issues/636. While the value returned will +// change with the resolution of this bug, the result from Cond will match the +// condition number used internally. +func Cond(a Matrix, norm float64) float64 { + m, n := a.Dims() + if m == 0 || n == 0 { + panic(ErrShape) + } + var lnorm lapack.MatrixNorm + switch norm { + default: + panic("mat: bad norm value") + case 1: + lnorm = lapack.MaxColumnSum + case 2: + var svd SVD + ok := svd.Factorize(a, SVDNone) + if !ok { + return math.Inf(1) + } + return svd.Cond() + case math.Inf(1): + lnorm = lapack.MaxRowSum + } + + if m == n { + // Use the LU decomposition to compute the condition number. + var lu LU + lu.factorize(a, lnorm) + return lu.Cond() + } + if m > n { + // Use the QR factorization to compute the condition number. + var qr QR + qr.factorize(a, lnorm) + return qr.Cond() + } + // Use the LQ factorization to compute the condition number. + var lq LQ + lq.factorize(a, lnorm) + return lq.Cond() +} + +// Det returns the determinant of the matrix a. In many expressions using LogDet +// will be more numerically stable. +func Det(a Matrix) float64 { + det, sign := LogDet(a) + return math.Exp(det) * sign +} + +// Dot returns the sum of the element-wise product of a and b. +// Dot panics if the matrix sizes are unequal. +func Dot(a, b *VecDense) float64 { + la := a.Len() + lb := b.Len() + if la != lb { + panic(ErrShape) + } + return blas64.Dot(la, a.mat, b.mat) +} + +// Equal returns whether the matrices a and b have the same size +// and are element-wise equal. +func Equal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + if rma, ok := aU.(RawMatrixer); ok { + if rmb, ok := bU.(RawMatrixer); ok { + ra := rma.RawMatrix() + rb := rmb.RawMatrix() + if aTrans == bTrans { + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { + return false + } + } + } + return true + } + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[j*rb.Stride+i] { + return false + } + } + } + return true + } + } + if rma, ok := aU.(RawSymmetricer); ok { + if rmb, ok := bU.(RawSymmetricer); ok { + ra := rma.RawSymmetric() + rb := rmb.RawSymmetric() + // Symmetric matrices are always upper and equal to their transpose. + for i := 0; i < ra.N; i++ { + for j := i; j < ra.N; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { + return false + } + } + } + return true + } + } + if ra, ok := aU.(*VecDense); ok { + if rb, ok := bU.(*VecDense); ok { + // If the raw vectors are the same length they must either both be + // transposed or both not transposed (or have length 1). + for i := 0; i < ra.n; i++ { + if ra.mat.Data[i*ra.mat.Inc] != rb.mat.Data[i*rb.mat.Inc] { + return false + } + } + return true + } + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.At(i, j) != b.At(i, j) { + return false + } + } + } + return true +} + +// EqualApprox returns whether the matrices a and b have the same size and contain all equal +// elements with tolerance for element-wise equality specified by epsilon. Matrices +// with non-equal shapes are not equal. +func EqualApprox(a, b Matrix, epsilon float64) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + if rma, ok := aU.(RawMatrixer); ok { + if rmb, ok := bU.(RawMatrixer); ok { + ra := rma.RawMatrix() + rb := rmb.RawMatrix() + if aTrans == bTrans { + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { + return false + } + } + } + return true + } + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[j*rb.Stride+i], epsilon, epsilon) { + return false + } + } + } + return true + } + } + if rma, ok := aU.(RawSymmetricer); ok { + if rmb, ok := bU.(RawSymmetricer); ok { + ra := rma.RawSymmetric() + rb := rmb.RawSymmetric() + // Symmetric matrices are always upper and equal to their transpose. + for i := 0; i < ra.N; i++ { + for j := i; j < ra.N; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { + return false + } + } + } + return true + } + } + if ra, ok := aU.(*VecDense); ok { + if rb, ok := bU.(*VecDense); ok { + // If the raw vectors are the same length they must either both be + // transposed or both not transposed (or have length 1). + for i := 0; i < ra.n; i++ { + if !floats.EqualWithinAbsOrRel(ra.mat.Data[i*ra.mat.Inc], rb.mat.Data[i*rb.mat.Inc], epsilon, epsilon) { + return false + } + } + return true + } + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if !floats.EqualWithinAbsOrRel(a.At(i, j), b.At(i, j), epsilon, epsilon) { + return false + } + } + } + return true +} + +// LogDet returns the log of the determinant and the sign of the determinant +// for the matrix that has been factorized. Numerical stability in product and +// division expressions is generally improved by working in log space. +func LogDet(a Matrix) (det float64, sign float64) { + // TODO(btracey): Add specialized routines for TriDense, etc. + var lu LU + lu.Factorize(a) + return lu.LogDet() +} + +// Max returns the largest element value of the matrix A. +// Max will panic with matrix.ErrShape if the matrix has zero size. +func Max(a Matrix) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(ErrShape) + } + // Max(A) = Max(A^T) + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + max := math.Inf(-1) + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + if v > max { + max = v + } + } + } + return max + case RawTriangular: + rm := m.RawTriangular() + // The max of a triangular is at least 0 unless the size is 1. + if rm.N == 1 { + return rm.Data[0] + } + max := 0.0 + if rm.Uplo == blas.Upper { + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v > max { + max = v + } + } + } + return max + } + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { + if v > max { + max = v + } + } + } + return max + case RawSymmetricer: + rm := m.RawSymmetric() + if rm.Uplo != blas.Upper { + panic(badSymTriangle) + } + max := math.Inf(-1) + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v > max { + max = v + } + } + } + return max + default: + r, c := aU.Dims() + max := math.Inf(-1) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := aU.At(i, j) + if v > max { + max = v + } + } + } + return max + } +} + +// Min returns the smallest element value of the matrix A. +// Min will panic with matrix.ErrShape if the matrix has zero size. +func Min(a Matrix) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(ErrShape) + } + // Min(A) = Min(A^T) + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + min := math.Inf(1) + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + if v < min { + min = v + } + } + } + return min + case RawTriangular: + rm := m.RawTriangular() + // The min of a triangular is at most 0 unless the size is 1. + if rm.N == 1 { + return rm.Data[0] + } + min := 0.0 + if rm.Uplo == blas.Upper { + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v < min { + min = v + } + } + } + return min + } + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { + if v < min { + min = v + } + } + } + return min + case RawSymmetricer: + rm := m.RawSymmetric() + if rm.Uplo != blas.Upper { + panic(badSymTriangle) + } + min := math.Inf(1) + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v < min { + min = v + } + } + } + return min + default: + r, c := aU.Dims() + min := math.Inf(1) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := aU.At(i, j) + if v < min { + min = v + } + } + } + return min + } +} + +// Norm returns the specified (induced) norm of the matrix a. See +// https://en.wikipedia.org/wiki/Matrix_norm for the definition of an induced norm. +// +// Valid norms are: +// 1 - The maximum absolute column sum +// 2 - Frobenius norm, the square root of the sum of the squares of the elements. +// Inf - The maximum absolute row sum. +// Norm will panic with ErrNormOrder if an illegal norm order is specified and +// with matrix.ErrShape if the matrix has zero size. +func Norm(a Matrix, norm float64) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(ErrShape) + } + aU, aTrans := untranspose(a) + var work []float64 + switch rma := aU.(type) { + case RawMatrixer: + rm := rma.RawMatrix() + n := normLapack(norm, aTrans) + if n == lapack.MaxColumnSum { + work = getFloats(rm.Cols, false) + defer putFloats(work) + } + return lapack64.Lange(n, rm, work) + case RawTriangular: + rm := rma.RawTriangular() + n := normLapack(norm, aTrans) + if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { + work = getFloats(rm.N, false) + defer putFloats(work) + } + return lapack64.Lantr(n, rm, work) + case RawSymmetricer: + rm := rma.RawSymmetric() + n := normLapack(norm, aTrans) + if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { + work = getFloats(rm.N, false) + defer putFloats(work) + } + return lapack64.Lansy(n, rm, work) + case *VecDense: + rv := rma.RawVector() + switch norm { + default: + panic("unreachable") + case 1: + if aTrans { + imax := blas64.Iamax(rma.n, rv) + return math.Abs(rma.At(imax, 0)) + } + return blas64.Asum(rma.n, rv) + case 2: + return blas64.Nrm2(rma.n, rv) + case math.Inf(1): + if aTrans { + return blas64.Asum(rma.n, rv) + } + imax := blas64.Iamax(rma.n, rv) + return math.Abs(rma.At(imax, 0)) + } + } + switch norm { + default: + panic("unreachable") + case 1: + var max float64 + for j := 0; j < c; j++ { + var sum float64 + for i := 0; i < r; i++ { + sum += math.Abs(a.At(i, j)) + } + if sum > max { + max = sum + } + } + return max + case 2: + var sum float64 + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := a.At(i, j) + sum += v * v + } + } + return math.Sqrt(sum) + case math.Inf(1): + var max float64 + for i := 0; i < r; i++ { + var sum float64 + for j := 0; j < c; j++ { + sum += math.Abs(a.At(i, j)) + } + if sum > max { + max = sum + } + } + return max + } +} + +// normLapack converts the float64 norm input in Norm to a lapack.MatrixNorm. +func normLapack(norm float64, aTrans bool) lapack.MatrixNorm { + switch norm { + case 1: + n := lapack.MaxColumnSum + if aTrans { + n = lapack.MaxRowSum + } + return n + case 2: + return lapack.NormFrob + case math.Inf(1): + n := lapack.MaxRowSum + if aTrans { + n = lapack.MaxColumnSum + } + return n + default: + panic(ErrNormOrder) + } +} + +// Sum returns the sum of the elements of the matrix. +func Sum(a Matrix) float64 { + // TODO(btracey): Add a fast path for the other supported matrix types. + + r, c := a.Dims() + var sum float64 + aU, _ := untranspose(a) + if rma, ok := aU.(RawMatrixer); ok { + rm := rma.RawMatrix() + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + sum += v + } + } + return sum + } + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + sum += a.At(i, j) + } + } + return sum +} + +// Trace returns the trace of the matrix. Trace will panic if the +// matrix is not square. +func Trace(a Matrix) float64 { + r, c := a.Dims() + if r != c { + panic(ErrSquare) + } + + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + case RawTriangular: + rm := m.RawTriangular() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + case RawSymmetricer: + rm := m.RawSymmetric() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + default: + var t float64 + for i := 0; i < r; i++ { + t += a.At(i, i) + } + return t + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// use returns a float64 slice with l elements, using f if it +// has the necessary capacity, otherwise creating a new slice. +func use(f []float64, l int) []float64 { + if l <= cap(f) { + return f[:l] + } + return make([]float64, l) +} + +// useZeroed returns a float64 slice with l elements, using f if it +// has the necessary capacity, otherwise creating a new slice. The +// elements of the returned slice are guaranteed to be zero. +func useZeroed(f []float64, l int) []float64 { + if l <= cap(f) { + f = f[:l] + zero(f) + return f + } + return make([]float64, l) +} + +// zero zeros the given slice's elements. +func zero(f []float64) { + for i := range f { + f[i] = 0 + } +} + +// useInt returns an int slice with l elements, using i if it +// has the necessary capacity, otherwise creating a new slice. +func useInt(i []int, l int) []int { + if l <= cap(i) { + return i[:l] + } + return make([]int, l) +} diff --git a/vendor/gonum.org/v1/gonum/mat/matrix_test.go b/vendor/gonum.org/v1/gonum/mat/matrix_test.go new file mode 100644 index 00000000..7a576529 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/matrix_test.go @@ -0,0 +1,624 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +func panics(fn func()) (panicked bool, message string) { + defer func() { + r := recover() + panicked = r != nil + message = fmt.Sprint(r) + }() + fn() + return +} + +func flatten(f [][]float64) (r, c int, d []float64) { + r = len(f) + if r == 0 { + panic("bad test: no row") + } + c = len(f[0]) + d = make([]float64, 0, r*c) + for _, row := range f { + if len(row) != c { + panic("bad test: ragged input") + } + d = append(d, row...) + } + return r, c, d +} + +func unflatten(r, c int, d []float64) [][]float64 { + m := make([][]float64, r) + for i := 0; i < r; i++ { + m[i] = d[i*c : (i+1)*c] + } + return m +} + +// eye returns a new identity matrix of size n×n. +func eye(n int) *Dense { + d := make([]float64, n*n) + for i := 0; i < n*n; i += n + 1 { + d[i] = 1 + } + return NewDense(n, n, d) +} + +func TestCol(t *testing.T) { + for id, af := range [][][]float64{ + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 10, 11, 12}, + }, + } { + a := NewDense(flatten(af)) + col := make([]float64, a.mat.Rows) + for j := range af[0] { + for i := range col { + col[i] = float64(i*a.mat.Cols + j + 1) + } + + if got := Col(nil, j, a); !reflect.DeepEqual(got, col) { + t.Errorf("test %d: unexpected values returned for dense col %d: got: %v want: %v", + id, j, got, col) + } + + got := make([]float64, a.mat.Rows) + if Col(got, j, a); !reflect.DeepEqual(got, col) { + t.Errorf("test %d: unexpected values filled for dense col %d: got: %v want: %v", + id, j, got, col) + } + } + } + + denseComparison := func(a *Dense) interface{} { + r, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = make([]float64, r) + for i := range ans[j] { + ans[j][i] = a.At(i, j) + } + } + return ans + } + + f := func(a Matrix) interface{} { + _, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = Col(nil, j, a) + } + return ans + } + testOneInputFunc(t, "Col", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) + + f = func(a Matrix) interface{} { + r, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = make([]float64, r) + Col(ans[j], j, a) + } + return ans + } + testOneInputFunc(t, "Col", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) +} + +func TestRow(t *testing.T) { + for id, af := range [][][]float64{ + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 10, 11, 12}, + }, + } { + a := NewDense(flatten(af)) + for i, row := range af { + if got := Row(nil, i, a); !reflect.DeepEqual(got, row) { + t.Errorf("test %d: unexpected values returned for dense row %d: got: %v want: %v", + id, i, got, row) + } + + got := make([]float64, len(row)) + if Row(got, i, a); !reflect.DeepEqual(got, row) { + t.Errorf("test %d: unexpected values filled for dense row %d: got: %v want: %v", + id, i, got, row) + } + } + } + + denseComparison := func(a *Dense) interface{} { + r, c := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = make([]float64, c) + for j := range ans[i] { + ans[i][j] = a.At(i, j) + } + } + return ans + } + + f := func(a Matrix) interface{} { + r, _ := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = Row(nil, i, a) + } + return ans + } + testOneInputFunc(t, "Row", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) + + f = func(a Matrix) interface{} { + r, c := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = make([]float64, c) + Row(ans[i], i, a) + } + return ans + } + testOneInputFunc(t, "Row", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) +} + +func TestCond(t *testing.T) { + for i, test := range []struct { + a *Dense + condOne float64 + condTwo float64 + condInf float64 + }{ + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }), + condOne: 16.0 / 3.0, + condTwo: 4.330127018922192, + condInf: 16.0 / 3.0, + }, + { + a: NewDense(4, 4, []float64{ + 2, 9, 3, 2, + 10, 9, 9, 3, + 1, 1, 5, 2, + 8, 4, 10, 2, + }), + condOne: 1 / 0.024740155174938, + condTwo: 34.521576567075087, + condInf: 1 / 0.012034465570035, + }, + { + a: NewDense(3, 3, []float64{ + 5, 6, 7, + 8, -2, 1, + 7, 7, 7}), + condOne: 30.769230769230749, + condTwo: 21.662689498448440, + condInf: 31.153846153846136, + }, + } { + orig := DenseCopyOf(test.a) + condOne := Cond(test.a, 1) + if !floats.EqualWithinAbsOrRel(test.condOne, condOne, 1e-13, 1e-13) { + t.Errorf("Case %d: one norm mismatch. Want %v, got %v", i, test.condOne, condOne) + } + if !Equal(test.a, orig) { + t.Errorf("Case %d: unexpected mutation of input matrix for one norm. Want %v, got %v", i, orig, test.a) + } + condTwo := Cond(test.a, 2) + if !floats.EqualWithinAbsOrRel(test.condTwo, condTwo, 1e-13, 1e-13) { + t.Errorf("Case %d: two norm mismatch. Want %v, got %v", i, test.condTwo, condTwo) + } + if !Equal(test.a, orig) { + t.Errorf("Case %d: unexpected mutation of input matrix for two norm. Want %v, got %v", i, orig, test.a) + } + condInf := Cond(test.a, math.Inf(1)) + if !floats.EqualWithinAbsOrRel(test.condInf, condInf, 1e-13, 1e-13) { + t.Errorf("Case %d: inf norm mismatch. Want %v, got %v", i, test.condInf, condInf) + } + if !Equal(test.a, orig) { + t.Errorf("Case %d: unexpected mutation of input matrix for inf norm. Want %v, got %v", i, orig, test.a) + } + } + + for _, test := range []struct { + name string + norm float64 + }{ + { + name: "CondOne", + norm: 1, + }, + { + name: "CondTwo", + norm: 2, + }, + { + name: "CondInf", + norm: math.Inf(1), + }, + } { + f := func(a Matrix) interface{} { + return Cond(a, test.norm) + } + denseComparison := func(a *Dense) interface{} { + return Cond(a, test.norm) + } + testOneInputFunc(t, test.name, f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) + } +} + +func TestDet(t *testing.T) { + for c, test := range []struct { + a *Dense + ans float64 + }{ + { + a: NewDense(2, 2, []float64{1, 0, 0, 1}), + ans: 1, + }, + { + a: NewDense(2, 2, []float64{1, 0, 0, -1}), + ans: -1, + }, + { + a: NewDense(3, 3, []float64{ + 1, 2, 0, + 0, 1, 2, + 0, 2, 1, + }), + ans: -3, + }, + { + a: NewDense(3, 3, []float64{ + 1, 2, 3, + 5, 7, 9, + 6, 9, 12, + }), + ans: 0, + }, + } { + a := DenseCopyOf(test.a) + det := Det(a) + if !Equal(a, test.a) { + t.Errorf("Input matrix changed during Det. Case %d.", c) + } + if !floats.EqualWithinAbsOrRel(det, test.ans, 1e-14, 1e-14) { + t.Errorf("Det mismatch case %d. Got %v, want %v", c, det, test.ans) + } + } + // Perform the normal list test to ensure it works for all types. + f := func(a Matrix) interface{} { + return Det(a) + } + denseComparison := func(a *Dense) interface{} { + return Det(a) + } + testOneInputFunc(t, "Det", f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isSquare) + + // Check that it gives approximately the same answer as Cholesky + // Ensure the input matrices are wider than tall so they are full rank + isWide := func(ar, ac int) bool { + return ar <= ac + } + f = func(a Matrix) interface{} { + ar, ac := a.Dims() + if !isWide(ar, ac) { + panic(ErrShape) + } + var tmp Dense + tmp.Mul(a, a.T()) + return Det(&tmp) + } + denseComparison = func(a *Dense) interface{} { + ar, ac := a.Dims() + if !isWide(ar, ac) { + panic(ErrShape) + } + var tmp SymDense + tmp.SymOuterK(1, a) + var chol Cholesky + ok := chol.Factorize(&tmp) + if !ok { + panic("bad chol test") + } + return chol.Det() + } + testOneInputFunc(t, "DetVsChol", f, denseComparison, sameAnswerFloatApproxTol(1e-10), isAnyType, isWide) +} + +func TestDot(t *testing.T) { + f := func(a, b Matrix) interface{} { + return Dot(a.(*VecDense), b.(*VecDense)) + } + denseComparison := func(a, b *Dense) interface{} { + ra, ca := a.Dims() + rb, cb := b.Dims() + if ra != rb || ca != cb { + panic(ErrShape) + } + var sum float64 + for i := 0; i < ra; i++ { + for j := 0; j < ca; j++ { + sum += a.At(i, j) * b.At(i, j) + } + } + return sum + } + testTwoInputFunc(t, "Dot", f, denseComparison, sameAnswerFloatApproxTol(1e-12), legalTypesVecVec, legalSizeSameVec) +} + +func TestEqual(t *testing.T) { + f := func(a, b Matrix) interface{} { + return Equal(a, b) + } + denseComparison := func(a, b *Dense) interface{} { + return Equal(a, b) + } + testTwoInputFunc(t, "Equal", f, denseComparison, sameAnswerBool, legalTypesAll, isAnySize2) +} + +func TestMax(t *testing.T) { + // A direct test of Max with *Dense arguments is in TestNewDense. + f := func(a Matrix) interface{} { + return Max(a) + } + denseComparison := func(a *Dense) interface{} { + return Max(a) + } + testOneInputFunc(t, "Max", f, denseComparison, sameAnswerFloat, isAnyType, isAnySize) +} + +func TestMin(t *testing.T) { + // A direct test of Min with *Dense arguments is in TestNewDense. + f := func(a Matrix) interface{} { + return Min(a) + } + denseComparison := func(a *Dense) interface{} { + return Min(a) + } + testOneInputFunc(t, "Min", f, denseComparison, sameAnswerFloat, isAnyType, isAnySize) +} + +func TestNorm(t *testing.T) { + for i, test := range []struct { + a [][]float64 + ord float64 + norm float64 + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: 1, + norm: 30, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: 2, + norm: 25.495097567963924, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: math.Inf(1), + norm: 33, + }, + { + a: [][]float64{{1, -2, -2}, {-4, 5, 6}}, + ord: 1, + norm: 8, + }, + { + a: [][]float64{{1, -2, -2}, {-4, 5, 6}}, + ord: math.Inf(1), + norm: 15, + }, + } { + a := NewDense(flatten(test.a)) + if math.Abs(Norm(a, test.ord)-test.norm) > 1e-14 { + t.Errorf("Mismatch test %d: %v norm = %f", i, test.a, test.norm) + } + } + + for _, test := range []struct { + name string + norm float64 + }{ + {"NormOne", 1}, + {"NormTwo", 2}, + {"NormInf", math.Inf(1)}, + } { + f := func(a Matrix) interface{} { + return Norm(a, test.norm) + } + denseComparison := func(a *Dense) interface{} { + return Norm(a, test.norm) + } + testOneInputFunc(t, test.name, f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) + } +} + +func TestNormZero(t *testing.T) { + for _, a := range []Matrix{ + &Dense{}, + &SymDense{}, + &SymDense{mat: blas64.Symmetric{Uplo: blas.Upper}}, + &TriDense{}, + &TriDense{mat: blas64.Triangular{Uplo: blas.Upper, Diag: blas.NonUnit}}, + &VecDense{}, + } { + for _, norm := range []float64{1, 2, math.Inf(1)} { + panicked, message := panics(func() { Norm(a, norm) }) + if !panicked { + t.Errorf("expected panic for Norm(&%T{}, %v)", a, norm) + } + if message != ErrShape.Error() { + t.Errorf("unexpected panic string for Norm(&%T{}, %v): got:%s want:%s", + a, norm, message, ErrShape.Error()) + } + } + } +} + +func TestSum(t *testing.T) { + f := func(a Matrix) interface{} { + return Sum(a) + } + denseComparison := func(a *Dense) interface{} { + return Sum(a) + } + testOneInputFunc(t, "Sum", f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) +} + +func TestTrace(t *testing.T) { + for _, test := range []struct { + a *Dense + trace float64 + }{ + { + a: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + trace: 15, + }, + } { + trace := Trace(test.a) + if trace != test.trace { + t.Errorf("Trace mismatch. Want %v, got %v", test.trace, trace) + } + } + f := func(a Matrix) interface{} { + return Trace(a) + } + denseComparison := func(a *Dense) interface{} { + return Trace(a) + } + testOneInputFunc(t, "Trace", f, denseComparison, sameAnswerFloat, isAnyType, isSquare) +} + +func TestDoer(t *testing.T) { + type MatrixDoer interface { + Matrix + NonZeroDoer + RowNonZeroDoer + ColNonZeroDoer + } + ones := func(n int) []float64 { + data := make([]float64, n) + for i := range data { + data[i] = 1 + } + return data + } + for i, m := range []MatrixDoer{ + NewTriDense(3, Lower, ones(3*3)), + NewTriDense(3, Upper, ones(3*3)), + NewBandDense(6, 6, 1, 1, ones(3*6)), + NewBandDense(6, 10, 1, 1, ones(3*6)), + NewBandDense(10, 6, 1, 1, ones(7*3)), + NewSymBandDense(3, 0, ones(3)), + NewSymBandDense(3, 1, ones(3*(1+1))), + NewSymBandDense(6, 1, ones(6*(1+1))), + NewSymBandDense(6, 2, ones(6*(2+1))), + } { + r, c := m.Dims() + + want := Sum(m) + + // got and fn sum the accessed elements in + // the Doer that is being operated on. + // fn also tests that the accessed elements + // are within the writable areas of the + // matrix to check that only valid elements + // are operated on. + var got float64 + fn := func(i, j int, v float64) { + got += v + switch m := m.(type) { + case MutableTriangular: + m.SetTri(i, j, v) + case MutableBanded: + m.SetBand(i, j, v) + case MutableSymBanded: + m.SetSymBand(i, j, v) + default: + panic("bad test: need mutable type") + } + } + + panicked, message := panics(func() { m.DoNonZero(fn) }) + if panicked { + t.Errorf("unexpected panic for Doer test %d: %q", i, message) + continue + } + if got != want { + t.Errorf("unexpected Doer sum: got:%f want:%f", got, want) + } + + // Reset got for testing with DoRowNonZero. + got = 0 + panicked, message = panics(func() { + for i := 0; i < r; i++ { + m.DoRowNonZero(i, fn) + } + }) + if panicked { + t.Errorf("unexpected panic for RowDoer test %d: %q", i, message) + continue + } + if got != want { + t.Errorf("unexpected RowDoer sum: got:%f want:%f", got, want) + } + + // Reset got for testing with DoColNonZero. + got = 0 + panicked, message = panics(func() { + for j := 0; j < c; j++ { + m.DoColNonZero(j, fn) + } + }) + if panicked { + t.Errorf("unexpected panic for ColDoer test %d: %q", i, message) + continue + } + if got != want { + t.Errorf("unexpected ColDoer sum: got:%f want:%f", got, want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/mul_test.go b/vendor/gonum.org/v1/gonum/mat/mul_test.go new file mode 100644 index 00000000..57ec17f2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/mul_test.go @@ -0,0 +1,283 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +// TODO: Need to add tests where one is overwritten. +func TestMulTypes(t *testing.T) { + for _, test := range []struct { + ar int + ac int + br int + bc int + Panics bool + }{ + { + ar: 5, + ac: 5, + br: 5, + bc: 5, + Panics: false, + }, + { + ar: 10, + ac: 5, + br: 5, + bc: 3, + Panics: false, + }, + { + ar: 10, + ac: 5, + br: 5, + bc: 8, + Panics: false, + }, + { + ar: 8, + ac: 10, + br: 10, + bc: 3, + Panics: false, + }, + { + ar: 8, + ac: 3, + br: 3, + bc: 10, + Panics: false, + }, + { + ar: 5, + ac: 8, + br: 8, + bc: 10, + Panics: false, + }, + { + ar: 5, + ac: 12, + br: 12, + bc: 8, + Panics: false, + }, + { + ar: 5, + ac: 7, + br: 8, + bc: 10, + Panics: true, + }, + } { + ar := test.ar + ac := test.ac + br := test.br + bc := test.bc + + // Generate random matrices + avec := make([]float64, ar*ac) + randomSlice(avec) + a := NewDense(ar, ac, avec) + + bvec := make([]float64, br*bc) + randomSlice(bvec) + + b := NewDense(br, bc, bvec) + + // Check that it panics if it is supposed to + if test.Panics { + c := NewDense(0, 0, nil) + fn := func() { + c.Mul(a, b) + } + pan, _ := panics(fn) + if !pan { + t.Errorf("Mul did not panic with dimension mismatch") + } + continue + } + + cvec := make([]float64, ar*bc) + + // Get correct matrix multiply answer from blas64.Gemm + blas64.Gemm(blas.NoTrans, blas.NoTrans, + 1, a.mat, b.mat, + 0, blas64.General{Rows: ar, Cols: bc, Stride: bc, Data: cvec}, + ) + + avecCopy := append([]float64{}, avec...) + bvecCopy := append([]float64{}, bvec...) + cvecCopy := append([]float64{}, cvec...) + + acomp := matComp{r: ar, c: ac, data: avecCopy} + bcomp := matComp{r: br, c: bc, data: bvecCopy} + ccomp := matComp{r: ar, c: bc, data: cvecCopy} + + // Do normal multiply with empty dense + d := NewDense(0, 0, nil) + + testMul(t, a, b, d, acomp, bcomp, ccomp, false, "zero receiver") + + // Normal multiply with existing receiver + c := NewDense(ar, bc, cvec) + randomSlice(cvec) + testMul(t, a, b, c, acomp, bcomp, ccomp, false, "existing receiver") + + // Cast a as a basic matrix + am := (*basicMatrix)(a) + bm := (*basicMatrix)(b) + d.Reset() + testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is zero") + d.Reset() + testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is zero") + d.Reset() + testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is zero") + randomSlice(cvec) + testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is full") + randomSlice(cvec) + testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is full") + randomSlice(cvec) + testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is full") + } +} + +func randomSlice(s []float64) { + for i := range s { + s[i] = rand.NormFloat64() + } +} + +type matComp struct { + r, c int + data []float64 +} + +func testMul(t *testing.T, a, b Matrix, c *Dense, acomp, bcomp, ccomp matComp, cvecApprox bool, name string) { + c.Mul(a, b) + var aDense *Dense + switch t := a.(type) { + case *Dense: + aDense = t + case *basicMatrix: + aDense = (*Dense)(t) + } + + var bDense *Dense + switch t := b.(type) { + case *Dense: + bDense = t + case *basicMatrix: + bDense = (*Dense)(t) + } + + if !denseEqual(aDense, acomp) { + t.Errorf("a changed unexpectedly for %v", name) + } + if !denseEqual(bDense, bcomp) { + t.Errorf("b changed unexpectedly for %v", name) + } + if cvecApprox { + if !denseEqualApprox(c, ccomp, 1e-14) { + t.Errorf("mul answer not within tol for %v", name) + } + return + } + + if !denseEqual(c, ccomp) { + t.Errorf("mul answer not equal for %v", name) + } +} + +type basicMatrix Dense + +func (m *basicMatrix) At(r, c int) float64 { + return (*Dense)(m).At(r, c) +} + +func (m *basicMatrix) Dims() (r, c int) { + return (*Dense)(m).Dims() +} + +func (m *basicMatrix) T() Matrix { + return Transpose{m} +} + +type basicSymmetric SymDense + +var _ Symmetric = &basicSymmetric{} + +func (m *basicSymmetric) At(r, c int) float64 { + return (*SymDense)(m).At(r, c) +} + +func (m *basicSymmetric) Dims() (r, c int) { + return (*SymDense)(m).Dims() +} + +func (m *basicSymmetric) T() Matrix { + return m +} + +func (m *basicSymmetric) Symmetric() int { + return (*SymDense)(m).Symmetric() +} + +type basicTriangular TriDense + +func (m *basicTriangular) At(r, c int) float64 { + return (*TriDense)(m).At(r, c) +} + +func (m *basicTriangular) Dims() (r, c int) { + return (*TriDense)(m).Dims() +} + +func (m *basicTriangular) T() Matrix { + return Transpose{m} +} + +func (m *basicTriangular) Triangle() (int, TriKind) { + return (*TriDense)(m).Triangle() +} + +func (m *basicTriangular) TTri() Triangular { + return TransposeTri{m} +} + +func denseEqual(a *Dense, acomp matComp) bool { + ar2, ac2 := a.Dims() + if ar2 != acomp.r { + return false + } + if ac2 != acomp.c { + return false + } + if !floats.Equal(a.mat.Data, acomp.data) { + return false + } + return true +} + +func denseEqualApprox(a *Dense, acomp matComp, tol float64) bool { + ar2, ac2 := a.Dims() + if ar2 != acomp.r { + return false + } + if ac2 != acomp.c { + return false + } + if !floats.EqualApprox(a.mat.Data, acomp.data, tol) { + return false + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/mat/offset.go b/vendor/gonum.org/v1/gonum/mat/offset.go new file mode 100644 index 00000000..01e7d34f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/offset.go @@ -0,0 +1,20 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !appengine + +package mat + +import "unsafe" + +// offset returns the number of float64 values b[0] is after a[0]. +func offset(a, b []float64) int { + if &a[0] == &b[0] { + return 0 + } + // This expression must be atomic with respect to GC moves. + // At this stage this is true, because the GC does not + // move. See https://golang.org/issue/12445. + return int(uintptr(unsafe.Pointer(&b[0]))-uintptr(unsafe.Pointer(&a[0]))) / int(unsafe.Sizeof(float64(0))) +} diff --git a/vendor/gonum.org/v1/gonum/mat/offset_appengine.go b/vendor/gonum.org/v1/gonum/mat/offset_appengine.go new file mode 100644 index 00000000..a4e7b27a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/offset_appengine.go @@ -0,0 +1,24 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build appengine + +package mat + +import "reflect" + +var sizeOfFloat64 = int(reflect.TypeOf(float64(0)).Size()) + +// offset returns the number of float64 values b[0] is after a[0]. +func offset(a, b []float64) int { + va0 := reflect.ValueOf(a).Index(0) + vb0 := reflect.ValueOf(b).Index(0) + if va0.Addr() == vb0.Addr() { + return 0 + } + // This expression must be atomic with respect to GC moves. + // At this stage this is true, because the GC does not + // move. See https://golang.org/issue/12445. + return int(vb0.UnsafeAddr()-va0.UnsafeAddr()) / sizeOfFloat64 +} diff --git a/vendor/gonum.org/v1/gonum/mat/pool.go b/vendor/gonum.org/v1/gonum/mat/pool.go new file mode 100644 index 00000000..7adb3275 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/pool.go @@ -0,0 +1,236 @@ +// Copyright ©2014 The gonum 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 mat + +import ( + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var tab64 = [64]byte{ + 0x3f, 0x00, 0x3a, 0x01, 0x3b, 0x2f, 0x35, 0x02, + 0x3c, 0x27, 0x30, 0x1b, 0x36, 0x21, 0x2a, 0x03, + 0x3d, 0x33, 0x25, 0x28, 0x31, 0x12, 0x1c, 0x14, + 0x37, 0x1e, 0x22, 0x0b, 0x2b, 0x0e, 0x16, 0x04, + 0x3e, 0x39, 0x2e, 0x34, 0x26, 0x1a, 0x20, 0x29, + 0x32, 0x24, 0x11, 0x13, 0x1d, 0x0a, 0x0d, 0x15, + 0x38, 0x2d, 0x19, 0x1f, 0x23, 0x10, 0x09, 0x0c, + 0x2c, 0x18, 0x0f, 0x08, 0x17, 0x07, 0x06, 0x05, +} + +// bits returns the ceiling of base 2 log of v. +// Approach based on http://stackoverflow.com/a/11398748. +func bits(v uint64) byte { + if v == 0 { + return 0 + } + v <<= 2 + v-- + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + v |= v >> 32 + return tab64[((v-(v>>1))*0x07EDD5E59A4E28C2)>>58] - 1 +} + +var ( + // pool contains size stratified workspace Dense pools. + // Each pool element i returns sized matrices with a data + // slice capped at 1<= 2*len(w.mat.Data) { + t.Errorf("r: %d c: %d -> len: %d cap: %d", i, j, len(w.mat.Data), cap(w.mat.Data)) + } + w.Set(0, 0, math.NaN()) + work[l] = w + } + for _, w := range work { + putWorkspace(w) + } + } + } + } +} + +var benchmat *Dense + +func poolBenchmark(n, r, c int, clear bool) { + for i := 0; i < n; i++ { + benchmat = getWorkspace(r, c, clear) + putWorkspace(benchmat) + } +} + +func newBenchmark(n, r, c int) { + for i := 0; i < n; i++ { + benchmat = NewDense(r, c, nil) + } +} + +func BenchmarkPool10by10Uncleared(b *testing.B) { poolBenchmark(b.N, 10, 10, false) } +func BenchmarkPool10by10Cleared(b *testing.B) { poolBenchmark(b.N, 10, 10, true) } +func BenchmarkNew10by10(b *testing.B) { newBenchmark(b.N, 10, 10) } +func BenchmarkPool100by100Uncleared(b *testing.B) { poolBenchmark(b.N, 100, 100, false) } +func BenchmarkPool100by100Cleared(b *testing.B) { poolBenchmark(b.N, 100, 100, true) } +func BenchmarkNew100by100(b *testing.B) { newBenchmark(b.N, 100, 100) } + +func BenchmarkMulWorkspaceDense100Half(b *testing.B) { denseMulWorkspaceBench(b, 100, 0.5) } +func BenchmarkMulWorkspaceDense100Tenth(b *testing.B) { denseMulWorkspaceBench(b, 100, 0.1) } +func BenchmarkMulWorkspaceDense1000Half(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.5) } +func BenchmarkMulWorkspaceDense1000Tenth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.1) } +func BenchmarkMulWorkspaceDense1000Hundredth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.01) } +func BenchmarkMulWorkspaceDense1000Thousandth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.001) } +func denseMulWorkspaceBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + a.Mul(a, d) + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/product.go b/vendor/gonum.org/v1/gonum/mat/product.go new file mode 100644 index 00000000..5a0343b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/product.go @@ -0,0 +1,193 @@ +// Copyright ©2015 The gonum 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 mat + +import "fmt" + +// Product calculates the product of the given factors and places the result in +// the receiver. The order of multiplication operations is optimized to minimize +// the number of floating point operations on the basis that all matrix +// multiplications are general. +func (m *Dense) Product(factors ...Matrix) { + // The operation order optimisation is the naive O(n^3) dynamic + // programming approach and does not take into consideration + // finer-grained optimisations that might be available. + // + // TODO(kortschak) Consider using the O(nlogn) or O(mlogn) + // algorithms that are available. e.g. + // + // e.g. http://www.jofcis.com/publishedpapers/2014_10_10_4299_4306.pdf + // + // In the case that this is replaced, retain this code in + // tests to compare against. + + r, c := m.Dims() + switch len(factors) { + case 0: + if r != 0 || c != 0 { + panic(ErrShape) + } + return + case 1: + m.reuseAs(factors[0].Dims()) + m.Copy(factors[0]) + return + case 2: + // Don't do work that we know the answer to. + m.Mul(factors[0], factors[1]) + return + } + + p := newMultiplier(m, factors) + p.optimize() + result := p.multiply() + m.reuseAs(result.Dims()) + m.Copy(result) + putWorkspace(result) +} + +// debugProductWalk enables debugging output for Product. +const debugProductWalk = false + +// multiplier performs operation order optimisation and tree traversal. +type multiplier struct { + // factors is the ordered set of + // factors to multiply. + factors []Matrix + // dims is the chain of factor + // dimensions. + dims []int + + // table contains the dynamic + // programming costs and subchain + // division indices. + table table +} + +func newMultiplier(m *Dense, factors []Matrix) *multiplier { + // Check size early, but don't yet + // allocate data for m. + r, c := m.Dims() + fr, fc := factors[0].Dims() // newMultiplier is only called with len(factors) > 2. + if !m.IsZero() { + if fr != r { + panic(ErrShape) + } + if _, lc := factors[len(factors)-1].Dims(); lc != c { + panic(ErrShape) + } + } + + dims := make([]int, len(factors)+1) + dims[0] = r + dims[len(dims)-1] = c + pc := fc + for i, f := range factors[1:] { + cr, cc := f.Dims() + dims[i+1] = cr + if pc != cr { + panic(ErrShape) + } + pc = cc + } + + return &multiplier{ + factors: factors, + dims: dims, + table: newTable(len(factors)), + } +} + +// optimize determines an optimal matrix multiply operation order. +func (p *multiplier) optimize() { + if debugProductWalk { + fmt.Printf("chain dims: %v\n", p.dims) + } + const maxInt = int(^uint(0) >> 1) + for f := 1; f < len(p.factors); f++ { + for i := 0; i < len(p.factors)-f; i++ { + j := i + f + p.table.set(i, j, entry{cost: maxInt}) + for k := i; k < j; k++ { + cost := p.table.at(i, k).cost + p.table.at(k+1, j).cost + p.dims[i]*p.dims[k+1]*p.dims[j+1] + if cost < p.table.at(i, j).cost { + p.table.set(i, j, entry{cost: cost, k: k}) + } + } + } + } +} + +// multiply walks the optimal operation tree found by optimize, +// leaving the final result in the stack. It returns the +// product, which may be copied but should be returned to +// the workspace pool. +func (p *multiplier) multiply() *Dense { + result, _ := p.multiplySubchain(0, len(p.factors)-1) + if debugProductWalk { + r, c := result.Dims() + fmt.Printf("\tpop result (%d×%d) cost=%d\n", r, c, p.table.at(0, len(p.factors)-1).cost) + } + return result.(*Dense) +} + +func (p *multiplier) multiplySubchain(i, j int) (m Matrix, intermediate bool) { + if i == j { + return p.factors[i], false + } + + a, aTmp := p.multiplySubchain(i, p.table.at(i, j).k) + b, bTmp := p.multiplySubchain(p.table.at(i, j).k+1, j) + + ar, ac := a.Dims() + br, bc := b.Dims() + if ac != br { + // Panic with a string since this + // is not a user-facing panic. + panic(ErrShape.Error()) + } + + if debugProductWalk { + fmt.Printf("\tpush f[%d] (%d×%d)%s * f[%d] (%d×%d)%s\n", + i, ar, ac, result(aTmp), j, br, bc, result(bTmp)) + } + + r := getWorkspace(ar, bc, false) + r.Mul(a, b) + if aTmp { + putWorkspace(a.(*Dense)) + } + if bTmp { + putWorkspace(b.(*Dense)) + } + return r, true +} + +type entry struct { + k int // is the chain subdivision index. + cost int // cost is the cost of the operation. +} + +// table is a row major n×n dynamic programming table. +type table struct { + n int + entries []entry +} + +func newTable(n int) table { + return table{n: n, entries: make([]entry, n*n)} +} + +func (t table) at(i, j int) entry { return t.entries[i*t.n+j] } +func (t table) set(i, j int, e entry) { t.entries[i*t.n+j] = e } + +type result bool + +func (r result) String() string { + if r { + return " (popped result)" + } + return "" +} diff --git a/vendor/gonum.org/v1/gonum/mat/product_test.go b/vendor/gonum.org/v1/gonum/mat/product_test.go new file mode 100644 index 00000000..2ce0e575 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/product_test.go @@ -0,0 +1,251 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "fmt" + "math/rand" + "testing" +) + +type dims struct{ r, c int } + +var productTests = []struct { + n int + factors []dims + product dims + panics bool +}{ + { + n: 1, + factors: []dims{{3, 4}}, + product: dims{3, 4}, + panics: false, + }, + { + n: 1, + factors: []dims{{2, 4}}, + product: dims{3, 4}, + panics: true, + }, + { + n: 3, + factors: []dims{{10, 30}, {30, 5}, {5, 60}}, + product: dims{10, 60}, + panics: false, + }, + { + n: 3, + factors: []dims{{100, 30}, {30, 5}, {5, 60}}, + product: dims{10, 60}, + panics: true, + }, + { + n: 7, + factors: []dims{{60, 5}, {5, 5}, {5, 4}, {4, 10}, {10, 22}, {22, 45}, {45, 10}}, + product: dims{60, 10}, + panics: false, + }, + { + n: 7, + factors: []dims{{60, 5}, {5, 5}, {5, 400}, {4, 10}, {10, 22}, {22, 45}, {45, 10}}, + product: dims{60, 10}, + panics: true, + }, + { + n: 3, + factors: []dims{{1, 1000}, {1000, 2}, {2, 2}}, + product: dims{1, 2}, + panics: false, + }, + + // Random chains. + { + n: 0, + product: dims{0, 0}, + panics: false, + }, + { + n: 2, + product: dims{60, 10}, + panics: false, + }, + { + n: 3, + product: dims{60, 10}, + panics: false, + }, + { + n: 4, + product: dims{60, 10}, + panics: false, + }, + { + n: 10, + product: dims{60, 10}, + panics: false, + }, +} + +func TestProduct(t *testing.T) { + for _, test := range productTests { + dimensions := test.factors + if dimensions == nil && test.n > 0 { + dimensions = make([]dims, test.n) + for i := range dimensions { + if i != 0 { + dimensions[i].r = dimensions[i-1].c + } + dimensions[i].c = rand.Intn(50) + 1 + } + dimensions[0].r = test.product.r + dimensions[test.n-1].c = test.product.c + } + factors := make([]Matrix, test.n) + for i, d := range dimensions { + data := make([]float64, d.r*d.c) + for i := range data { + data[i] = rand.Float64() + } + factors[i] = NewDense(d.r, d.c, data) + } + + want := &Dense{} + if !test.panics { + a := &Dense{} + for i, b := range factors { + if i == 0 { + want.Clone(b) + continue + } + a, want = want, &Dense{} + want.Mul(a, b) + } + } + + got := NewDense(test.product.r, test.product.c, nil) + panicked, message := panics(func() { + got.Product(factors...) + }) + if test.panics { + if !panicked { + t.Errorf("fail to panic with product chain dimensions: %+v result dimension: %+v", + dimensions, test.product) + } + continue + } else if panicked { + t.Errorf("unexpected panic %q with product chain dimensions: %+v result dimension: %+v", + message, dimensions, test.product) + continue + } + + if len(factors) > 0 { + p := newMultiplier(NewDense(test.product.r, test.product.c, nil), factors) + p.optimize() + gotCost := p.table.at(0, len(factors)-1).cost + expr, wantCost, ok := bestExpressionFor(dimensions) + if !ok { + t.Fatal("unexpected number of expressions in brute force expression search") + } + if gotCost != wantCost { + t.Errorf("unexpected cost for chain dimensions: %+v got: %v want: %v\n%s", + dimensions, got, want, expr) + } + } + + if !EqualApprox(got, want, 1e-14) { + t.Errorf("unexpected result from product chain dimensions: %+v", dimensions) + } + } +} + +// node is a subexpression node. +type node struct { + dims + left, right *node +} + +func (n *node) String() string { + if n.left == nil || n.right == nil { + rows, cols := n.shape() + return fmt.Sprintf("[%d×%d]", rows, cols) + } + rows, cols := n.shape() + return fmt.Sprintf("(%s * %s):[%d×%d]", n.left, n.right, rows, cols) +} + +// shape returns the dimensions of the result of the subexpression. +func (n *node) shape() (rows, cols int) { + if n.left == nil || n.right == nil { + return n.r, n.c + } + rows, _ = n.left.shape() + _, cols = n.right.shape() + return rows, cols +} + +// cost returns the cost to evaluate the subexpression. +func (n *node) cost() int { + if n.left == nil || n.right == nil { + return 0 + } + lr, lc := n.left.shape() + _, rc := n.right.shape() + return lr*lc*rc + n.left.cost() + n.right.cost() +} + +// expressionsFor returns a channel that can be used to iterate over all +// expressions of the given factor dimensions. +func expressionsFor(factors []dims) chan *node { + if len(factors) == 1 { + c := make(chan *node, 1) + c <- &node{dims: factors[0]} + close(c) + return c + } + c := make(chan *node) + go func() { + for i := 1; i < len(factors); i++ { + for left := range expressionsFor(factors[:i]) { + for right := range expressionsFor(factors[i:]) { + c <- &node{left: left, right: right} + } + } + } + close(c) + }() + return c +} + +// catalan returns the nth 0-based Catalan number. +func catalan(n int) int { + p := 1 + for k := n + 1; k < 2*n+1; k++ { + p *= k + } + for k := 2; k < n+2; k++ { + p /= k + } + return p +} + +// bestExpressonFor returns the lowest cost expression for the given expression +// factor dimensions, the cost of the expression and whether the number of +// expressions searched matches the Catalan number for the number of factors. +func bestExpressionFor(factors []dims) (exp *node, cost int, ok bool) { + const maxInt = int(^uint(0) >> 1) + min := maxInt + var best *node + var n int + for exp := range expressionsFor(factors) { + n++ + cost := exp.cost() + if cost < min { + min = cost + best = exp + } + } + return best, min, n == catalan(len(factors)-1) +} diff --git a/vendor/gonum.org/v1/gonum/mat/qr.go b/vendor/gonum.org/v1/gonum/mat/qr.go new file mode 100644 index 00000000..b89f8fb7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/qr.go @@ -0,0 +1,221 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// QR is a type for creating and using the QR factorization of a matrix. +type QR struct { + qr *Dense + tau []float64 + cond float64 +} + +func (qr *QR) updateCond(norm lapack.MatrixNorm) { + // Since A = Q*R, and Q is orthogonal, we get for the condition number κ + // κ(A) := |A| |A^-1| = |Q*R| |(Q*R)^-1| = |R| |R^-1 * Q^T| + // = |R| |R^-1| = κ(R), + // where we used that fact that Q^-1 = Q^T. However, this assumes that + // the matrix norm is invariant under orthogonal transformations which + // is not the case for CondNorm. Hopefully the error is negligible: κ + // is only a qualitative measure anyway. + n := qr.qr.mat.Cols + work := getFloats(3*n, false) + iwork := getInts(n, false) + r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper) + v := lapack64.Trcon(norm, r.mat, work, iwork) + putFloats(work) + putInts(iwork) + qr.cond = 1 / v +} + +// Factorize computes the QR factorization of an m×n matrix a where m >= n. The QR +// factorization always exists even if A is singular. +// +// The QR decomposition is a factorization of the matrix A such that A = Q * R. +// The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix. +// Q and R can be extracted using the QTo and RTo methods. +func (qr *QR) Factorize(a Matrix) { + qr.factorize(a, CondNorm) +} + +func (qr *QR) factorize(a Matrix, norm lapack.MatrixNorm) { + m, n := a.Dims() + if m < n { + panic(ErrShape) + } + k := min(m, n) + if qr.qr == nil { + qr.qr = &Dense{} + } + qr.qr.Clone(a) + work := []float64{0} + qr.tau = make([]float64, k) + lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1) + + work = getFloats(int(work[0]), false) + lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work)) + putFloats(work) + qr.updateCond(norm) +} + +// Cond returns the condition number for the factorized matrix. +// Cond will panic if the receiver does not contain a successful factorization. +func (qr *QR) Cond() float64 { + if qr.qr == nil || qr.qr.IsZero() { + panic("qr: no decomposition computed") + } + return qr.cond +} + +// TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal +// and upper triangular matrices. + +// RTo extracts the m×n upper trapezoidal matrix from a QR decomposition. +// If dst is nil, a new matrix is allocated. The resulting dst matrix is returned. +func (qr *QR) RTo(dst *Dense) *Dense { + r, c := qr.qr.Dims() + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + // Disguise the QR as an upper triangular + t := &TriDense{ + mat: blas64.Triangular{ + N: c, + Stride: qr.qr.mat.Stride, + Data: qr.qr.mat.Data, + Uplo: blas.Upper, + Diag: blas.NonUnit, + }, + cap: qr.qr.capCols, + } + dst.Copy(t) + + // Zero below the triangular. + for i := r; i < c; i++ { + zero(dst.mat.Data[i*dst.mat.Stride : i*dst.mat.Stride+c]) + } + + return dst +} + +// QTo extracts the m×m orthonormal matrix Q from a QR decomposition. +// If dst is nil, a new matrix is allocated. The resulting Q matrix is returned. +func (qr *QR) QTo(dst *Dense) *Dense { + r, _ := qr.qr.Dims() + if dst == nil { + dst = NewDense(r, r, nil) + } else { + dst.reuseAsZeroed(r, r) + } + + // Set Q = I. + for i := 0; i < r*r; i += r + 1 { + dst.mat.Data[i] = 1 + } + + // Construct Q from the elementary reflectors. + work := []float64{0} + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, len(work)) + putFloats(work) + + return dst +} + +// Solve finds a minimum-norm solution to a system of linear equations defined +// by the matrices A and b, where A is an m×n matrix represented in its QR factorized +// form. If A is singular or near-singular a Condition error is returned. Please +// see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters. +// If trans == false, find X such that ||A*X - b||_2 is minimized. +// If trans == true, find the minimum norm solution of A^T * X = b. +// The solution matrix, X, is stored in place into m. +func (qr *QR) Solve(m *Dense, trans bool, b Matrix) error { + r, c := qr.qr.Dims() + br, bc := b.Dims() + + // The QR solve algorithm stores the result in-place into the right hand side. + // The storage for the answer must be large enough to hold both b and x. + // However, this method's receiver must be the size of x. Copy b, and then + // copy the result into m at the end. + if trans { + if c != br { + panic(ErrShape) + } + m.reuseAs(r, bc) + } else { + if r != br { + panic(ErrShape) + } + m.reuseAs(c, bc) + } + // Do not need to worry about overlap between m and b because x has its own + // independent storage. + x := getWorkspace(max(r, c), bc, false) + x.Copy(b) + t := qr.qr.asTriDense(qr.qr.mat.Cols, blas.NonUnit, blas.Upper).mat + if trans { + ok := lapack64.Trtrs(blas.Trans, t, x.mat) + if !ok { + return Condition(math.Inf(1)) + } + for i := c; i < r; i++ { + zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) + } + work := []float64{0} + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work)) + putFloats(work) + } else { + work := []float64{0} + lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1) + work = getFloats(int(work[0]), false) + lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work)) + putFloats(work) + + ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) + if !ok { + return Condition(math.Inf(1)) + } + } + // M was set above to be the correct size for the result. + m.Copy(x) + putWorkspace(x) + if qr.cond > ConditionTolerance { + return Condition(qr.cond) + } + return nil +} + +// SolveVec finds a minimum-norm solution to a system of linear equations. +// Please see QR.Solve for the full documentation. +func (qr *QR) SolveVec(v *VecDense, trans bool, b *VecDense) error { + if v != b { + v.checkOverlap(b.mat) + } + r, c := qr.qr.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the VecDenses as Dense and call the matrix code. + if trans { + v.reuseAs(r) + } else { + v.reuseAs(c) + } + return qr.Solve(v.asDense(), trans, b.asDense()) +} diff --git a/vendor/gonum.org/v1/gonum/mat/qr_test.go b/vendor/gonum.org/v1/gonum/mat/qr_test.go new file mode 100644 index 00000000..71a2d6e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/qr_test.go @@ -0,0 +1,205 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestQR(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + var qr QR + qr.Factorize(a) + q := qr.QTo(nil) + + if !isOrthonormal(q, 1e-10) { + t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) + } + + r := qr.RTo(nil) + + var got Dense + got.Mul(q, r) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("QR does not equal original matrix. \nWant: %v\nGot: %v", want, got) + } + } +} + +func isOrthonormal(q *Dense, tol float64) bool { + m, n := q.Dims() + if m != n { + return false + } + for i := 0; i < m; i++ { + for j := i; j < m; j++ { + dot := blas64.Dot(m, + blas64.Vector{Inc: 1, Data: q.mat.Data[i*q.mat.Stride:]}, + blas64.Vector{Inc: 1, Data: q.mat.Data[j*q.mat.Stride:]}, + ) + // Dot product should be 1 if i == j and 0 otherwise. + if i == j && math.Abs(dot-1) > tol { + return false + } + if i != j && math.Abs(dot) > tol { + return false + } + } + } + return true +} + +func TestSolveQR(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {10, 5, 1}, + {5, 5, 3}, + {10, 5, 3}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + var qr QR + qr.Factorize(a) + qr.Solve(&x, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveQRVec(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewVecDense(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x VecDense + var qr QR + qr.Factorize(a) + qr.SolveVec(&x, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveQRCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + NewDense(3, 2, []float64{1, 0, 0, 1e-20, 0, 0}), + } { + m, _ := test.Dims() + var qr QR + qr.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := qr.Solve(&x, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVecDense(m, nil) + var xvec VecDense + if err := qr.SolveVec(&xvec, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/shadow.go b/vendor/gonum.org/v1/gonum/mat/shadow.go new file mode 100644 index 00000000..91ed21f9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/shadow.go @@ -0,0 +1,280 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +const ( + // regionOverlap is the panic string used for the general case + // of a matrix region overlap between a source and destination. + regionOverlap = "mat: bad region: overlap" + + // regionIdentity is the panic string used for the specific + // case of complete agreement between a source and a destination. + regionIdentity = "mat: bad region: identical" + + // mismatchedStrides is the panic string used for overlapping + // data slices with differing strides. + mismatchedStrides = "mat: bad region: different strides" +) + +// checkOverlap returns false if the receiver does not overlap data elements +// referenced by the parameter and panics otherwise. +// +// checkOverlap methods return a boolean to allow the check call to be added to a +// boolean expression, making use of short-circuit operators. + +func (m *Dense) checkOverlap(a blas64.General) bool { + mat := m.RawMatrix() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.Cols == a.Cols && mat.Rows == a.Rows && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know m is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know m is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.Cols, a.Cols = a.Cols, mat.Cols + } + if rectanglesOverlap(off, mat.Cols, a.Cols, mat.Stride) { + panic(regionOverlap) + } + return false +} + +func (s *SymDense) checkOverlap(a blas64.Symmetric) bool { + mat := s.RawSymmetric() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.N == a.N && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know s is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know s is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.N, a.N = a.N, mat.N + // If we created the matrix it will always + // be in the upper triangle, but don't trust + // that this is the case. + mat.Uplo, a.Uplo = a.Uplo, mat.Uplo + } + if trianglesOverlap(off, mat.N, a.N, mat.Stride, mat.Uplo == blas.Upper, a.Uplo == blas.Upper) { + panic(regionOverlap) + } + return false +} + +func (t *TriDense) checkOverlap(a blas64.Triangular) bool { + mat := t.RawTriangular() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.N == a.N && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know t is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know t is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.N, a.N = a.N, mat.N + mat.Uplo, a.Uplo = a.Uplo, mat.Uplo + } + if trianglesOverlap(off, mat.N, a.N, mat.Stride, mat.Uplo == blas.Upper, a.Uplo == blas.Upper) { + panic(regionOverlap) + } + return false +} + +func (v *VecDense) checkOverlap(a blas64.Vector) bool { + mat := v.mat + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.Inc == a.Inc && len(mat.Data) == len(a.Data) { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know v is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know v is completely after a. + return false + } + + if mat.Inc != a.Inc { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if mat.Inc == 1 || off&mat.Inc == 0 { + panic(regionOverlap) + } + return false +} + +// rectanglesOverlap returns whether the strided rectangles a and b overlap +// when b is offset by off elements after a but has at least one element before +// the end of a. off must be positive. a and b have aCols and bCols respectively. +// +// rectanglesOverlap works by shifting both matrices left such that the left +// column of a is at 0. The column indexes are flattened by obtaining the shifted +// relative left and right column positions modulo the common stride. This allows +// direct comparison of the column offsets when the matrix backing data slices +// are known to overlap. +func rectanglesOverlap(off, aCols, bCols, stride int) bool { + if stride == 1 { + // Unit stride means overlapping data + // slices must overlap as matrices. + return true + } + + // Flatten the shifted matrix column positions + // so a starts at 0, modulo the common stride. + aTo := aCols + // The mod stride operations here make the from + // and to indexes comparable between a and b when + // the data slices of a and b overlap. + bFrom := off % stride + bTo := (bFrom + bCols) % stride + + if bTo == 0 || bFrom < bTo { + // b matrix is not wrapped: compare for + // simple overlap. + return bFrom < aTo + } + + // b strictly wraps and so must overlap with a. + return true +} + +// trianglesOverlap returns whether the strided triangles a and b overlap +// when b is offset by off elements after a but has at least one element before +// the end of a. off must be positive. a and b are aSize×aSize and bSize×bSize +// respectively. +func trianglesOverlap(off, aSize, bSize, stride int, aUpper, bUpper bool) bool { + if !rectanglesOverlap(off, aSize, bSize, stride) { + // Fast return if bounding rectangles do not overlap. + return false + } + + // Find location of b relative to a. + rowOffset := off / stride + colOffset := off % stride + if (off+bSize)%stride < colOffset { + // We have wrapped, so readjust offsets. + rowOffset++ + colOffset -= stride + } + + if aUpper { + // Check whether the upper left of b + // is in the triangle of a + if rowOffset >= 0 && rowOffset <= colOffset { + return true + } + // Check whether the upper right of b + // is in the triangle of a. + return bUpper && rowOffset < colOffset+bSize + } + + // Check whether the upper left of b + // is in the triangle of a + if colOffset >= 0 && rowOffset >= colOffset { + return true + } + if bUpper { + // Check whether the upper right corner of b + // is in a or the upper row of b spans a row + // of a. + return rowOffset > colOffset+bSize || colOffset < 0 + } + if colOffset < 0 { + // Check whether the lower left of a + // is in the triangle of b or below + // the diagonal of a. This requires a + // swap of reference origin. + return -rowOffset+aSize > -colOffset + } + // Check whether the lower left of b + // is in the triangle of a or below + // the diagonal of a. + return rowOffset+bSize > colOffset +} diff --git a/vendor/gonum.org/v1/gonum/mat/shadow_test.go b/vendor/gonum.org/v1/gonum/mat/shadow_test.go new file mode 100644 index 00000000..564d9e66 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/shadow_test.go @@ -0,0 +1,274 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +func TestDenseOverlaps(t *testing.T) { + type view struct { + i, j, r, c int + *Dense + } + + rnd := rand.New(rand.NewSource(1)) + + for r := 1; r < 20; r++ { + for c := 1; c < 20; c++ { + m := NewDense(r, c, nil) + panicked, message := panics(func() { m.checkOverlap(m.RawMatrix()) }) + if !panicked { + t.Error("expected matrix overlap with self") + } + if message != regionIdentity { + t.Errorf("unexpected panic message for self overlap: got: %q want: %q", message, regionIdentity) + } + + for i := 0; i < 1000; i++ { + var views [2]view + for k := range views { + if r > 1 { + views[k].i = rnd.Intn(r - 1) + views[k].r = rnd.Intn(r-views[k].i-1) + 1 + } else { + views[k].r = 1 + } + if c > 1 { + views[k].j = rnd.Intn(c - 1) + views[k].c = rnd.Intn(c-views[k].j-1) + 1 + } else { + views[k].c = 1 + } + views[k].Dense = m.Slice(views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c).(*Dense) + + panicked, _ = panics(func() { m.checkOverlap(views[k].RawMatrix()) }) + if !panicked { + t.Errorf("expected matrix (%d×%d) overlap with view {rows=%d:%d, cols=%d:%d}", + r, c, views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c) + } + panicked, _ = panics(func() { views[k].checkOverlap(m.RawMatrix()) }) + if !panicked { + t.Errorf("expected view {rows=%d:%d, cols=%d:%d} overlap with parent (%d×%d)", + views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c, r, c) + } + } + + overlapRows := intervalsOverlap( + interval{views[0].i, views[0].i + views[0].r}, + interval{views[1].i, views[1].i + views[1].r}, + ) + overlapCols := intervalsOverlap( + interval{views[0].j, views[0].j + views[0].c}, + interval{views[1].j, views[1].j + views[1].c}, + ) + want := overlapRows && overlapCols + + for k, v := range views { + w := views[1-k] + got, _ := panics(func() { v.checkOverlap(w.RawMatrix()) }) + if got != want { + t.Errorf("unexpected result for overlap test for {rows=%d:%d, cols=%d:%d} with {rows=%d:%d, cols=%d:%d}: got: %t want: %t", + v.i, v.i+v.r, v.j, v.j+v.c, + w.i, w.i+w.r, w.j, w.j+w.c, + got, want) + } + } + } + } + } +} + +func TestTriDenseOverlaps(t *testing.T) { + type view struct { + i, j, n int + *TriDense + } + + rnd := rand.New(rand.NewSource(1)) + + for _, parentKind := range []TriKind{Upper, Lower} { + for n := 1; n < 20; n++ { + data := make([]float64, n*n) + for i := range data { + data[i] = float64(i + 1) + } + m := NewDense(n, n, data) + mt := denseAsTriDense(m, parentKind) + panicked, message := panics(func() { mt.checkOverlap(mt.RawTriangular()) }) + if !panicked { + t.Error("expected matrix overlap with self") + } + if message != regionIdentity { + t.Errorf("unexpected panic message for self overlap: got: %q want: %q", message, regionIdentity) + } + + for i := 0; i < 1000; i++ { + var views [2]view + for k := range views { + if n > 1 { + views[k].i = rnd.Intn(n - 1) + views[k].j = rnd.Intn(n - 1) + views[k].n = rnd.Intn(n-max(views[k].i, views[k].j)-1) + 1 + } else { + views[k].n = 1 + } + viewKind := []TriKind{Upper, Lower}[rnd.Intn(2)] + views[k].TriDense = denseAsTriDense( + m.Slice(views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n).(*Dense), + viewKind) + + wantPanick := overlapsParentTriangle(views[k].i, views[k].j, views[k].n, parentKind, viewKind) + + panicked, _ = panics(func() { mt.checkOverlap(views[k].RawTriangular()) }) + if panicked != wantPanick { + t.Errorf("unexpected (%d×%d)%s overlap with view {rows=%d:%d, cols=%d:%d}%s got:%t want:%t\n% v\n\n% v\n", + n, n, kindString(parentKind), + views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n, kindString(viewKind), + panicked, wantPanick, + Formatted(mt), Formatted(views[k].TriDense)) + } + panicked, _ = panics(func() { views[k].checkOverlap(mt.RawTriangular()) }) + if panicked != wantPanick { + t.Errorf("unexpected {rows=%d:%d, cols=%d:%d}%s overlap with parent (%d×%d)%s got:%t want:%t\n% v\n\n% v\n", + views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n, kindString(viewKind), + n, n, kindString(parentKind), + panicked, wantPanick, + Formatted(views[k].TriDense), Formatted(mt)) + } + } + + want := overlapSiblingTriangles( + views[0].i, views[0].j, views[0].n, views[0].mat.Uplo == blas.Upper, + views[1].i, views[1].j, views[1].n, views[1].mat.Uplo == blas.Upper, + ) + + for k, v := range views { + w := views[1-k] + got, _ := panics(func() { v.checkOverlap(w.RawTriangular()) }) + if got != want { + t.Errorf("unexpected result for overlap test for {rows=%d:%d, cols=%d:%d}%s with {rows=%d:%d, cols=%d:%d}%s: got:%t want:%t\n% v\n\n% v\n", + v.i, v.i+v.n, v.j, v.j+v.n, kindString(v.mat.Uplo == blas.Upper), + w.i, w.i+w.n, w.j, w.j+w.n, kindString(w.mat.Uplo == blas.Upper), + got, want, + Formatted(v.TriDense), Formatted(w.TriDense)) + } + } + } + } + } +} + +type interval struct{ from, to int } + +func intervalsOverlap(a, b interval) bool { + return a.to > b.from && b.to > a.from +} + +func overlapsParentTriangle(i, j, n int, parent, view TriKind) bool { + switch parent { + case Upper: + if i <= j { + return true + } + if view == Upper { + return i < j+n + } + + case Lower: + if i >= j { + return true + } + if view == Lower { + return i+n > j + } + } + + return false +} + +func overlapSiblingTriangles(ai, aj, an int, aKind TriKind, bi, bj, bn int, bKind TriKind) bool { + for i := max(ai, bi); i < min(ai+an, bi+bn); i++ { + var a, b interval + + if aKind == Upper { + a = interval{from: aj - ai + i, to: aj + an} + } else { + a = interval{from: aj, to: aj - ai + i + 1} + } + + if bKind == Upper { + b = interval{from: bj - bi + i, to: bj + bn} + } else { + b = interval{from: bj, to: bj - bi + i + 1} + } + + if intervalsOverlap(a, b) { + return true + } + } + return false +} + +func kindString(k TriKind) string { + if k == Upper { + return "U" + } + return "L" +} + +// See https://github.com/gonum/matrix/issues/359 for details. +func TestIssue359(t *testing.T) { + for xi := 0; xi < 2; xi++ { + for xj := 0; xj < 2; xj++ { + for yi := 0; yi < 2; yi++ { + for yj := 0; yj < 2; yj++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + x := a.Slice(xi, xi+2, xj, xj+2).(*Dense) + y := a.Slice(yi, yi+2, yj, yj+2).(*Dense) + + panicked, _ := panics(func() { x.checkOverlap(y.mat) }) + if !panicked { + t.Errorf("expected panic for aliased with offsets x(%d,%d) y(%d,%d):\nx:\n%v\ny:\n%v", + xi, xj, yi, yj, Formatted(x), Formatted(y), + ) + } + } + } + } + } +} + +// denseAsTriDense returns a triangular matrix derived from the +// square matrix m, with the orientation specified by kind. +func denseAsTriDense(m *Dense, kind TriKind) *TriDense { + r, c := m.Dims() + if r != c { + panic(ErrShape) + } + n := r + uplo := blas.Lower + if kind == Upper { + uplo = blas.Upper + } + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: m.mat.Stride, + Data: m.mat.Data, + Uplo: uplo, + Diag: blas.NonUnit, + }, + cap: n, + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/solve.go b/vendor/gonum.org/v1/gonum/mat/solve.go new file mode 100644 index 00000000..ef3d00ef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/solve.go @@ -0,0 +1,127 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// Solve finds a minimum-norm solution to a system of linear equations defined +// by the matrices a and b. If A is singular or near-singular, a Condition error +// is returned. Please see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters: +// - if m >= n, find X such that ||A*X - B||_2 is minimized, +// - if m < n, find the minimum norm solution of A * X = B. +// The solution matrix, X, is stored in-place into the receiver. +func (m *Dense) Solve(a, b Matrix) error { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + panic(ErrShape) + } + m.reuseAs(ac, bc) + + // TODO(btracey): Add special cases for SymDense, etc. + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + switch rma := aU.(type) { + case RawTriangular: + side := blas.Left + tA := blas.NoTrans + if aTrans { + tA = blas.Trans + } + + switch rm := bU.(type) { + case RawMatrixer: + if m != bU || bTrans { + if m == bU || m.checkOverlap(rm.RawMatrix()) { + tmp := getWorkspace(br, bc, false) + tmp.Copy(b) + m.Copy(tmp) + putWorkspace(tmp) + break + } + m.Copy(b) + } + default: + if m != bU { + m.Copy(b) + } else if bTrans { + // m and b share data so Copy cannot be used directly. + tmp := getWorkspace(br, bc, false) + tmp.Copy(b) + m.Copy(tmp) + putWorkspace(tmp) + } + } + + rm := rma.RawTriangular() + blas64.Trsm(side, tA, 1, rm, m.mat) + work := getFloats(3*rm.N, false) + iwork := getInts(rm.N, false) + cond := lapack64.Trcon(CondNorm, rm, work, iwork) + putFloats(work) + putInts(iwork) + if cond > ConditionTolerance { + return Condition(cond) + } + return nil + } + + switch { + case ar == ac: + if a == b { + // x = I. + if ar == 1 { + m.mat.Data[0] = 1 + return nil + } + for i := 0; i < ar; i++ { + v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+ac] + zero(v) + v[i] = 1 + } + return nil + } + var lu LU + lu.Factorize(a) + return lu.Solve(m, false, b) + case ar > ac: + var qr QR + qr.Factorize(a) + return qr.Solve(m, false, b) + default: + var lq LQ + lq.Factorize(a) + return lq.Solve(m, false, b) + } +} + +// SolveVec finds a minimum-norm solution to a system of linear equations defined +// by the matrix a and the right-hand side vector b. If A is singular or +// near-singular, a Condition error is returned. Please see the documentation for +// Dense.Solve for more information. +func (v *VecDense) SolveVec(a Matrix, b *VecDense) error { + if v != b { + v.checkOverlap(b.mat) + } + _, c := a.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the VecDenses as Dense and call the matrix code. + v.reuseAs(c) + m := v.asDense() + // We conditionally create bm as m when b and v are identical + // to prevent the overlap detection code from identifying m + // and bm as overlapping but not identical. + bm := m + if v != b { + bm = b.asDense() + } + return m.Solve(a, bm) +} diff --git a/vendor/gonum.org/v1/gonum/mat/solve_test.go b/vendor/gonum.org/v1/gonum/mat/solve_test.go new file mode 100644 index 00000000..08ed5839 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/solve_test.go @@ -0,0 +1,296 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math/rand" + "testing" +) + +func TestSolve(t *testing.T) { + // Hand-coded cases. + for _, test := range []struct { + a [][]float64 + b [][]float64 + ans [][]float64 + shouldErr bool + }{ + { + a: [][]float64{{6}}, + b: [][]float64{{3}}, + ans: [][]float64{{0.5}}, + shouldErr: false, + }, + { + a: [][]float64{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + }, + b: [][]float64{ + {3}, + {2}, + {1}, + }, + ans: [][]float64{ + {3}, + {2}, + {1}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.5528}, + {0.9058, 0.6324, 0.8723}, + {0.1270, 0.0975, 0.7612}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + {0.958}, + }, + ans: [][]float64{ + {-0.932687281002860}, + {0.303963920182067}, + {1.375216503507109}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.5528}, + {0.9058, 0.6324, 0.8723}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + }, + ans: [][]float64{ + {0.25919787248965376}, + {-0.25560256266441034}, + {0.5432324059702451}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.9}, + {0.9058, 0.6324, 0.9}, + {0.1270, 0.0975, 0.1}, + {1.6, 2.8, -3.5}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + {-0.958}, + {1.452}, + }, + ans: [][]float64{ + {0.820970340787782}, + {-0.218604626527306}, + {-0.212938815234215}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.231, -1.65}, + {0.9058, 0.6324, 0.9, 0.72}, + {0.1270, 0.0975, 0.1, 1.723}, + {1.6, 2.8, -3.5, 0.987}, + {7.231, 9.154, 1.823, 0.9}, + }, + b: [][]float64{ + {0.278, 8.635}, + {0.547, 9.125}, + {-0.958, -0.762}, + {1.452, 1.444}, + {1.999, -7.234}, + }, + ans: [][]float64{ + {1.863006789511373, 44.467887791812750}, + {-1.127270935407224, -34.073794226035126}, + {-0.527926457947330, -8.032133759788573}, + {-0.248621916204897, -2.366366415805275}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0, 0}, + {0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + }, + ans: nil, + shouldErr: true, + }, + { + a: [][]float64{ + {0, 0}, + {0, 0}, + {0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + {1}, + }, + ans: nil, + shouldErr: true, + }, + { + a: [][]float64{ + {0, 0, 0}, + {0, 0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + }, + ans: nil, + shouldErr: true, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var ans *Dense + if test.ans != nil { + ans = NewDense(flatten(test.ans)) + } + + var x Dense + err := x.Solve(a, b) + if err != nil { + if !test.shouldErr { + t.Errorf("Unexpected solve error: %s", err) + } + continue + } + if err == nil && test.shouldErr { + t.Errorf("Did not error during solve.") + continue + } + if !EqualApprox(&x, ans, 1e-12) { + t.Errorf("Solve answer mismatch. Want %v, got %v", ans, x) + } + } + + // Random Cases. + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {5, 10, 1}, + {10, 5, 1}, + {5, 5, 7}, + {5, 10, 7}, + {10, 5, 7}, + {5, 5, 12}, + {5, 10, 12}, + {10, 5, 12}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + x.Solve(a, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b + var tmp, lhs, rhs Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + + // Use testTwoInput. + method := func(receiver, a, b Matrix) { + type Solver interface { + Solve(a, b Matrix) error + } + rd := receiver.(Solver) + rd.Solve(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Solve(a, b) + } + testTwoInput(t, "Solve", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSolve, 1e-7) +} + +func TestSolveVec(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + {10, 5}, + {5, 5}, + {5, 10}, + {10, 5}, + {5, 5}, + {5, 10}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + b := NewVecDense(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x VecDense + x.SolveVec(a, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b + var tmp, lhs, rhs Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + + // Use testTwoInput + method := func(receiver, a, b Matrix) { + type SolveVecer interface { + SolveVec(a Matrix, b *VecDense) error + } + rd := receiver.(SolveVecer) + rd.SolveVec(a, b.(*VecDense)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Solve(a, b) + } + testTwoInput(t, "SolveVec", &VecDense{}, method, denseComparison, legalTypesNotVecVec, legalSizeSolve, 1e-12) +} diff --git a/vendor/gonum.org/v1/gonum/mat/svd.go b/vendor/gonum.org/v1/gonum/mat/svd.go new file mode 100644 index 00000000..9d386d81 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/svd.go @@ -0,0 +1,190 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" +) + +// SVD is a type for creating and using the Singular Value Decomposition (SVD) +// of a matrix. +type SVD struct { + kind SVDKind + + s []float64 + u blas64.General + vt blas64.General +} + +// Factorize computes the singular value decomposition (SVD) of the input matrix +// A. The singular values of A are computed in all cases, while the singular +// vectors are optionally computed depending on the input kind. +// +// The full singular value decomposition (kind == SVDFull) deconstructs A as +// A = U * Σ * V^T +// where Σ is an m×n diagonal matrix of singular vectors, U is an m×m unitary +// matrix of left singular vectors, and V is an n×n matrix of right singular vectors. +// +// It is frequently not necessary to compute the full SVD. Computation time and +// storage costs can be reduced using the appropriate kind. Only the singular +// values can be computed (kind == SVDNone), or a "thin" representation of the +// singular vectors (kind = SVDThin). The thin representation can save a significant +// amount of memory if m >> n. See the documentation for the lapack.SVDKind values +// for more information. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (svd *SVD) Factorize(a Matrix, kind SVDKind) (ok bool) { + m, n := a.Dims() + var jobU, jobVT lapack.SVDJob + switch kind { + default: + panic("svd: bad input kind") + case SVDNone: + jobU = lapack.SVDNone + jobVT = lapack.SVDNone + case SVDFull: + // TODO(btracey): This code should be modified to have the smaller + // matrix written in-place into aCopy when the lapack/native/dgesvd + // implementation is complete. + svd.u = blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: use(svd.u.Data, m*m), + } + svd.vt = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: use(svd.vt.Data, n*n), + } + jobU = lapack.SVDAll + jobVT = lapack.SVDAll + case SVDThin: + // TODO(btracey): This code should be modified to have the larger + // matrix written in-place into aCopy when the lapack/native/dgesvd + // implementation is complete. + svd.u = blas64.General{ + Rows: m, + Cols: min(m, n), + Stride: min(m, n), + Data: use(svd.u.Data, m*min(m, n)), + } + svd.vt = blas64.General{ + Rows: min(m, n), + Cols: n, + Stride: n, + Data: use(svd.vt.Data, min(m, n)*n), + } + jobU = lapack.SVDInPlace + jobVT = lapack.SVDInPlace + } + + // A is destroyed on call, so copy the matrix. + aCopy := DenseCopyOf(a) + svd.kind = kind + svd.s = use(svd.s, min(m, n)) + + work := []float64{0} + lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, -1) + work = getFloats(int(work[0]), false) + ok = lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, len(work)) + putFloats(work) + if !ok { + svd.kind = 0 + } + return ok +} + +// Kind returns the matrix.SVDKind of the decomposition. If no decomposition has been +// computed, Kind returns 0. +func (svd *SVD) Kind() SVDKind { + return svd.kind +} + +// Cond returns the 2-norm condition number for the factorized matrix. Cond will +// panic if the receiver does not contain a successful factorization. +func (svd *SVD) Cond() float64 { + if svd.kind == 0 { + panic("svd: no decomposition computed") + } + return svd.s[0] / svd.s[len(svd.s)-1] +} + +// Values returns the singular values of the factorized matrix in decreasing order. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(m,n), and Values will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// Values will panic if the receiver does not contain a successful factorization. +func (svd *SVD) Values(s []float64) []float64 { + if svd.kind == 0 { + panic("svd: no decomposition computed") + } + if s == nil { + s = make([]float64, len(svd.s)) + } + if len(s) != len(svd.s) { + panic(ErrSliceLengthMismatch) + } + copy(s, svd.s) + return s +} + +// UTo extracts the matrix U from the singular value decomposition, storing +// the result in-place into dst. U is size m×m if svd.Kind() == SVDFull, +// of size m×min(m,n) if svd.Kind() == SVDThin, and UTo panics otherwise. +func (svd *SVD) UTo(dst *Dense) *Dense { + kind := svd.kind + if kind != SVDFull && kind != SVDThin { + panic("mat: improper SVD kind") + } + r := svd.u.Rows + c := svd.u.Cols + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + + tmp := &Dense{ + mat: svd.u, + capRows: r, + capCols: c, + } + dst.Copy(tmp) + + return dst +} + +// VTo extracts the matrix V from the singular value decomposition, storing +// the result in-place into dst. V is size n×n if svd.Kind() == SVDFull, +// of size n×min(m,n) if svd.Kind() == SVDThin, and VTo panics otherwise. +func (svd *SVD) VTo(dst *Dense) *Dense { + kind := svd.kind + if kind != SVDFull && kind != SVDThin { + panic("mat: improper SVD kind") + } + r := svd.vt.Rows + c := svd.vt.Cols + if dst == nil { + dst = NewDense(c, r, nil) + } else { + dst.reuseAs(c, r) + } + + tmp := &Dense{ + mat: svd.vt, + capRows: r, + capCols: c, + } + dst.Copy(tmp.T()) + + return dst +} diff --git a/vendor/gonum.org/v1/gonum/mat/svd_test.go b/vendor/gonum.org/v1/gonum/mat/svd_test.go new file mode 100644 index 00000000..54815c85 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/svd_test.go @@ -0,0 +1,172 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestSVD(t *testing.T) { + // Hand coded tests + for _, test := range []struct { + a *Dense + u *Dense + v *Dense + s []float64 + }{ + { + a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}), + u: NewDense(4, 2, []float64{ + -0.8174155604703632, -0.5760484367663209, + -0.5760484367663209, 0.8174155604703633, + 0, 0, + 0, 0, + }), + v: NewDense(2, 2, []float64{ + -0.4045535848337571, -0.9145142956773044, + -0.9145142956773044, 0.4045535848337571, + }), + s: []float64{5.464985704219041, 0.365966190626258}, + }, + { + // Issue #5. + a: NewDense(3, 11, []float64{ + 1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1, + 1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3, + }), + u: NewDense(3, 3, []float64{ + -0.5224167862273765, 0.7864430360363114, 0.3295270133658976, + -0.5739526766688285, -0.03852203026050301, -0.8179818935216693, + -0.6306021141833781, -0.6164603833618163, 0.4715056408282468, + }), + v: NewDense(11, 3, []float64{ + -0.08123293141915189, 0.08528085505260324, -0.013165501690885152, + -0.05423546426886932, 0.1102707844980355, 0.622210623111631, + 0, 0, 0, + -0.0245733326078166, 0.510179651760153, 0.25596360803140994, + 0, 0, 0, + 0, 0, 0, + -0.026997467150282436, -0.024989929445430496, -0.6353761248025164, + 0, 0, 0, + -0.029662131661052707, -0.3999088672621176, 0.3662470150802212, + -0.9798839760830571, 0.11328174160898856, -0.047702613241813366, + -0.16755466189153964, -0.7395268089170608, 0.08395240366704032, + }), + s: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628}, + }, + } { + var svd SVD + ok := svd.Factorize(test.a, SVDThin) + if !ok { + t.Errorf("SVD failed") + } + s, u, v := extractSVD(&svd) + if !floats.EqualApprox(s, test.s, 1e-10) { + t.Errorf("Singular value mismatch. Got %v, want %v.", s, test.s) + } + if !EqualApprox(u, test.u, 1e-10) { + t.Errorf("U mismatch.\nGot:\n%v\nWant:\n%v", Formatted(u), Formatted(test.u)) + } + if !EqualApprox(v, test.v, 1e-10) { + t.Errorf("V mismatch.\nGot:\n%v\nWant:\n%v", Formatted(v), Formatted(test.v)) + } + m, n := test.a.Dims() + sigma := NewDense(min(m, n), min(m, n), nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, s[i]) + } + + var ans Dense + ans.Product(u, sigma, v.T()) + if !EqualApprox(test.a, &ans, 1e-10) { + t.Errorf("A reconstruction mismatch.\nGot:\n%v\nWant:\n%v\n", Formatted(&ans), Formatted(test.a)) + } + } + + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 3}, + {3, 5}, + {150, 150}, + {200, 150}, + {150, 200}, + } { + m := test.m + n := test.n + for trial := 0; trial < 10; trial++ { + a := NewDense(m, n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.NormFloat64() + } + aCopy := DenseCopyOf(a) + + // Test Full decomposition. + var svd SVD + ok := svd.Factorize(a, SVDFull) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with full") + } + s, u, v := extractSVD(&svd) + sigma := NewDense(m, n, nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, s[i]) + } + var ansFull Dense + ansFull.Product(u, sigma, v.T()) + if !EqualApprox(&ansFull, a, 1e-8) { + t.Errorf("Answer mismatch when SVDFull") + } + + // Test Thin decomposition. + ok = svd.Factorize(a, SVDThin) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with Thin") + } + sThin, u, v := extractSVD(&svd) + if !floats.EqualApprox(s, sThin, 1e-8) { + t.Errorf("Singular value mismatch between Full and Thin decomposition") + } + sigma = NewDense(min(m, n), min(m, n), nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, sThin[i]) + } + ansFull.Reset() + ansFull.Product(u, sigma, v.T()) + if !EqualApprox(&ansFull, a, 1e-8) { + t.Errorf("Answer mismatch when SVDFull") + } + + // Test None decomposition. + ok = svd.Factorize(a, SVDNone) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with none") + } + sNone := make([]float64, min(m, n)) + svd.Values(sNone) + if !floats.EqualApprox(s, sNone, 1e-8) { + t.Errorf("Singular value mismatch between Full and None decomposition") + } + } + } +} + +func extractSVD(svd *SVD) (s []float64, u, v *Dense) { + return svd.Values(nil), svd.UTo(nil), svd.VTo(nil) +} diff --git a/vendor/gonum.org/v1/gonum/mat/symband.go b/vendor/gonum.org/v1/gonum/mat/symband.go new file mode 100644 index 00000000..986a3335 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/symband.go @@ -0,0 +1,175 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + symBandDense *SymBandDense + _ Matrix = symBandDense + _ Symmetric = symBandDense + _ Banded = symBandDense + _ RawSymBander = symBandDense + _ MutableSymBanded = symBandDense + + _ NonZeroDoer = symBandDense + _ RowNonZeroDoer = symBandDense + _ ColNonZeroDoer = symBandDense +) + +// SymBandDense represents a symmetric band matrix in dense storage format. +type SymBandDense struct { + mat blas64.SymmetricBand +} + +// MutableSymBanded is a symmetric band matrix interface type that allows elements +// to be altered. +type MutableSymBanded interface { + Symmetric + Bandwidth() (kl, ku int) + SetSymBand(i, j int, v float64) +} + +// A RawSymBander can return a blas64.SymmetricBand representation of the receiver. +// Changes to the blas64.SymmetricBand.Data slice will be reflected in the original +// matrix, changes to the N, K, Stride and Uplo fields will not. +type RawSymBander interface { + RawSymBand() blas64.SymmetricBand +} + +// NewSymBandDense creates a new SymBand matrix with n rows and columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*(k+1), +// data is used as the backing slice, and changes to the elements of the returned +// SymBandDense will be reflected in data. If neither of these is true, NewSymBandDense +// will panic. k must be at least zero and less than n, otherwise NewBandDense will panic. +// +// The data must be arranged in row-major order constructed by removing the zeros +// from the rows outside the band and aligning the diagonals. SymBandDense matrices +// are stored in the upper triangle. For example, the matrix +// 1 2 3 0 0 0 +// 2 4 5 6 0 0 +// 3 5 7 8 9 0 +// 0 6 8 10 11 12 +// 0 0 9 11 13 14 +// 0 0 0 12 14 15 +// becomes (* entries are never accessed) +// 1 2 3 +// 4 5 6 +// 7 8 9 +// 10 11 12 +// 13 14 * +// 15 * * +// which is passed to NewBandDense as []float64{1, 2, 3, 4, ...} with k=2. +// Only the values in the band portion of the matrix are used. +func NewSymBandDense(n, k int, data []float64) *SymBandDense { + if n < 0 || k < 0 { + panic("mat: negative dimension") + } + if k+1 > n { + panic("mat: band out of range") + } + bc := k + 1 + if data != nil && len(data) != n*bc { + panic(ErrShape) + } + if data == nil { + data = make([]float64, n*bc) + } + return &SymBandDense{ + mat: blas64.SymmetricBand{ + N: n, + K: k, + Stride: bc, + Uplo: blas.Upper, + Data: data, + }, + } +} + +// NewDiagonal is a convenience function that returns a diagonal matrix represented by a +// SymBandDense. The length of data must be n or data must be nil, otherwise NewDiagonal +// will panic. +func NewDiagonal(n int, data []float64) *SymBandDense { + return NewSymBandDense(n, 0, data) +} + +// Dims returns the number of rows and columns in the matrix. +func (s *SymBandDense) Dims() (r, c int) { + return s.mat.N, s.mat.N +} + +// Symmetric returns the size of the receiver. +func (s *SymBandDense) Symmetric() int { + return s.mat.N +} + +// Bandwidth returns the bandwidths of the matrix. +func (s *SymBandDense) Bandwidth() (kl, ku int) { + return s.mat.K, s.mat.K +} + +// T implements the Matrix interface. Symmetric matrices, by definition, are +// equal to their transpose, and this is a no-op. +func (s *SymBandDense) T() Matrix { + return s +} + +// TBand implements the Banded interface. +func (s *SymBandDense) TBand() Banded { + return s +} + +// RawSymBand returns the underlying blas64.SymBand used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.SymBand. +func (s *SymBandDense) RawSymBand() blas64.SymmetricBand { + return s.mat +} + +// DoNonZero calls the function fn for each of the non-zero elements of s. The function fn +// takes a row/column index and the element value of s at (i, j). +func (s *SymBandDense) DoNonZero(fn func(i, j int, v float64)) { + for i := 0; i < s.mat.N; i++ { + for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ { + v := s.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } +} + +// DoRowNonZero calls the function fn for each of the non-zero elements of row i of s. The function fn +// takes a row/column index and the element value of s at (i, j). +func (s *SymBandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { + if i < 0 || s.mat.N <= i { + panic(ErrRowAccess) + } + for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ { + v := s.at(i, j) + if v != 0 { + fn(i, j, v) + } + } +} + +// DoColNonZero calls the function fn for each of the non-zero elements of column j of s. The function fn +// takes a row/column index and the element value of s at (i, j). +func (s *SymBandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { + if j < 0 || s.mat.N <= j { + panic(ErrColAccess) + } + for i := 0; i < s.mat.N; i++ { + if i-s.mat.K <= j && j < i+s.mat.K+1 { + v := s.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/symband_test.go b/vendor/gonum.org/v1/gonum/mat/symband_test.go new file mode 100644 index 00000000..cf3e6808 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/symband_test.go @@ -0,0 +1,230 @@ +// Copyright ©2017 The gonum 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 mat + +import ( + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +func TestNewSymBand(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + k int + mat *SymBandDense + dense *Dense + }{ + { + data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 13, 14, -1, + 15, -1, -1, + }, + n: 6, + k: 2, + mat: &SymBandDense{ + mat: blas64.SymmetricBand{ + N: 6, + K: 2, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 13, 14, -1, + 15, -1, -1, + }, + }, + }, + dense: NewDense(6, 6, []float64{ + 1, 2, 3, 0, 0, 0, + 2, 4, 5, 6, 0, 0, + 3, 5, 7, 8, 9, 0, + 0, 6, 8, 10, 11, 12, + 0, 0, 9, 11, 13, 14, + 0, 0, 0, 12, 14, 15, + }), + }, + } { + band := NewSymBandDense(test.n, test.k, test.data) + rows, cols := band.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(band, test.mat) { + t.Errorf("unexpected value via reflect for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.mat) { + t.Errorf("unexpected value via mat.Equal for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.dense) { + t.Errorf("unexpected value via mat.Equal(band, dense) for test %d:\ngot:\n% v\nwant:\n% v", i, Formatted(band), Formatted(test.dense)) + } + } +} + +func TestNewDiagonal(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + mat *SymBandDense + dense *Dense + }{ + { + data: []float64{1, 2, 3, 4, 5, 6}, + n: 6, + mat: &SymBandDense{ + mat: blas64.SymmetricBand{ + N: 6, + Stride: 1, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + }, + dense: NewDense(6, 6, []float64{ + 1, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 6, + }), + }, + } { + band := NewDiagonal(test.n, test.data) + rows, cols := band.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(band, test.mat) { + t.Errorf("unexpected value via reflect for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.mat) { + t.Errorf("unexpected value via mat.Equal for test %d: got: %v want: %v", i, band, test.mat) + } + if !Equal(band, test.dense) { + t.Errorf("unexpected value via mat.Equal(band, dense) for test %d:\ngot:\n% v\nwant:\n% v", i, Formatted(band), Formatted(test.dense)) + } + } +} + +func TestSymBandAtSet(t *testing.T) { + // 1 2 3 0 0 0 + // 2 4 5 6 0 0 + // 3 5 7 8 9 0 + // 0 6 8 10 11 12 + // 0 0 9 11 13 14 + // 0 0 0 12 14 16 + band := NewSymBandDense(6, 2, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 13, 14, -1, + 16, -1, -1, + }) + + rows, cols := band.Dims() + kl, ku := band.Bandwidth() + + // Explicitly test all indexes. + want := bandImplicit{rows, cols, kl, ku, func(i, j int) float64 { + if i > j { + i, j = j, i + } + return float64(i*ku + j + 1) + }} + for i := 0; i < 6; i++ { + for j := 0; j < 6; j++ { + if band.At(i, j) != want.At(i, j) { + t.Errorf("unexpected value for band.At(%d, %d): got:%v want:%v", i, j, band.At(i, j), want.At(i, j)) + } + } + } + // Do that same thing via a call to Equal. + if !Equal(band, want) { + t.Errorf("unexpected value via mat.Equal:\ngot:\n% v\nwant:\n% v", Formatted(band), Formatted(want)) + } + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { band.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { band.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { band.SetSymBand(row, 0, 1.2) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { band.SetSymBand(0, col, 1.2) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + }{ + {row: 0, col: 3}, + {row: 0, col: 4}, + {row: 0, col: 5}, + {row: 1, col: 4}, + {row: 1, col: 5}, + {row: 2, col: 5}, + {row: 3, col: 0}, + {row: 4, col: 1}, + {row: 5, col: 2}, + } { + panicked, message := panics(func() { band.SetSymBand(st.row, st.col, 1.2) }) + if !panicked || message != ErrBandSet.Error() { + t.Errorf("expected panic for %+v %s", st, message) + } + } + + for _, st := range []struct { + row, col int + orig, new float64 + }{ + {row: 1, col: 2, orig: 5, new: 15}, + {row: 2, col: 3, orig: 8, new: 15}, + } { + if e := band.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + band.SetSymBand(st.row, st.col, st.new) + if e := band.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetSymBand(%[1]d, %d, %v): got: %v want: %[3]v", st.row, st.col, st.new, e) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/symmetric.go b/vendor/gonum.org/v1/gonum/mat/symmetric.go new file mode 100644 index 00000000..98802d94 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/symmetric.go @@ -0,0 +1,502 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + symDense *SymDense + + _ Matrix = symDense + _ Symmetric = symDense + _ RawSymmetricer = symDense + _ MutableSymmetric = symDense +) + +const ( + badSymTriangle = "mat: blas64.Symmetric not upper" + badSymCap = "mat: bad capacity for SymDense" +) + +// SymDense is a symmetric matrix that uses dense storage. SymDense +// matrices are stored in the upper triangle. +type SymDense struct { + mat blas64.Symmetric + cap int +} + +// Symmetric represents a symmetric matrix (where the element at {i, j} equals +// the element at {j, i}). Symmetric matrices are always square. +type Symmetric interface { + Matrix + // Symmetric returns the number of rows/columns in the matrix. + Symmetric() int +} + +// A RawSymmetricer can return a view of itself as a BLAS Symmetric matrix. +type RawSymmetricer interface { + RawSymmetric() blas64.Symmetric +} + +// A MutableSymmetric can set elements of a symmetric matrix. +type MutableSymmetric interface { + Symmetric + SetSym(i, j int, v float64) +} + +// NewSymDense creates a new Symmetric matrix with n rows and columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*n, data is +// used as the backing slice, and changes to the elements of the returned SymDense +// will be reflected in data. If neither of these is true, NewSymDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +// Only the values in the upper triangular portion of the matrix are used. +func NewSymDense(n int, data []float64) *SymDense { + if n < 0 { + panic("mat: negative dimension") + } + if data != nil && n*n != len(data) { + panic(ErrShape) + } + if data == nil { + data = make([]float64, n*n) + } + return &SymDense{ + mat: blas64.Symmetric{ + N: n, + Stride: n, + Data: data, + Uplo: blas.Upper, + }, + cap: n, + } +} + +// Dims returns the number of rows and columns in the matrix. +func (s *SymDense) Dims() (r, c int) { + return s.mat.N, s.mat.N +} + +// Caps returns the number of rows and columns in the backing matrix. +func (s *SymDense) Caps() (r, c int) { + return s.cap, s.cap +} + +// T implements the Matrix interface. Symmetric matrices, by definition, are +// equal to their transpose, and this is a no-op. +func (s *SymDense) T() Matrix { + return s +} + +func (s *SymDense) Symmetric() int { + return s.mat.N +} + +// RawSymmetric returns the matrix as a blas64.Symmetric. The returned +// value must be stored in upper triangular format. +func (s *SymDense) RawSymmetric() blas64.Symmetric { + return s.mat +} + +// SetRawSymmetric sets the underlying blas64.Symmetric used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in b. SetRawSymmetric will panic if b is not an upper-encoded symmetric +// matrix. +func (s *SymDense) SetRawSymmetric(b blas64.Symmetric) { + if b.Uplo != blas.Upper { + panic(badSymTriangle) + } + s.mat = b +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (s *SymDense) Reset() { + // N and Stride must be zeroed in unison. + s.mat.N, s.mat.Stride = 0, 0 + s.mat.Data = s.mat.Data[:0] +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the +// receiver for size-restricted operations. SymDense matrices can be zeroed using Reset. +func (s *SymDense) IsZero() bool { + // It must be the case that m.Dims() returns + // zeros in this case. See comment in Reset(). + return s.mat.N == 0 +} + +// reuseAs resizes an empty matrix to a n×n matrix, +// or checks that a non-empty matrix is n×n. +func (s *SymDense) reuseAs(n int) { + if s.mat.N > s.cap { + panic(badSymCap) + } + if s.IsZero() { + s.mat = blas64.Symmetric{ + N: n, + Stride: n, + Data: use(s.mat.Data, n*n), + Uplo: blas.Upper, + } + s.cap = n + return + } + if s.mat.Uplo != blas.Upper { + panic(badSymTriangle) + } + if s.mat.N != n { + panic(ErrShape) + } +} + +func (s *SymDense) isolatedWorkspace(a Symmetric) (w *SymDense, restore func()) { + n := a.Symmetric() + w = getWorkspaceSym(n, false) + return w, func() { + s.CopySym(w) + putWorkspaceSym(w) + } +} + +func (s *SymDense) AddSym(a, b Symmetric) { + n := a.Symmetric() + if n != b.Symmetric() { + panic(ErrShape) + } + s.reuseAs(n) + + if a, ok := a.(RawSymmetricer); ok { + if b, ok := b.(RawSymmetricer); ok { + amat, bmat := a.RawSymmetric(), b.RawSymmetric() + if s != a { + s.checkOverlap(amat) + } + if s != b { + s.checkOverlap(bmat) + } + for i := 0; i < n; i++ { + btmp := bmat.Data[i*bmat.Stride+i : i*bmat.Stride+n] + stmp := s.mat.Data[i*s.mat.Stride+i : i*s.mat.Stride+n] + for j, v := range amat.Data[i*amat.Stride+i : i*amat.Stride+n] { + stmp[j] = v + btmp[j] + } + } + return + } + } + + for i := 0; i < n; i++ { + stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + for j := i; j < n; j++ { + stmp[j] = a.At(i, j) + b.At(i, j) + } + } +} + +func (s *SymDense) CopySym(a Symmetric) int { + n := a.Symmetric() + n = min(n, s.mat.N) + if n == 0 { + return 0 + } + switch a := a.(type) { + case RawSymmetricer: + amat := a.RawSymmetric() + if amat.Uplo != blas.Upper { + panic(badSymTriangle) + } + for i := 0; i < n; i++ { + copy(s.mat.Data[i*s.mat.Stride+i:i*s.mat.Stride+n], amat.Data[i*amat.Stride+i:i*amat.Stride+n]) + } + default: + for i := 0; i < n; i++ { + stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + for j := i; j < n; j++ { + stmp[j] = a.At(i, j) + } + } + } + return n +} + +// SymRankOne performs a symetric rank-one update to the matrix a and stores +// the result in the receiver +// s = a + alpha * x * x' +func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x *VecDense) { + n := x.Len() + if a.Symmetric() != n { + panic(ErrShape) + } + s.reuseAs(n) + if s != a { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + s.CopySym(a) + } + blas64.Syr(alpha, x.mat, s.mat) +} + +// SymRankK performs a symmetric rank-k update to the matrix a and stores the +// result into the receiver. If a is zero, see SymOuterK. +// s = a + alpha * x * x' +func (s *SymDense) SymRankK(a Symmetric, alpha float64, x Matrix) { + n := a.Symmetric() + r, _ := x.Dims() + if r != n { + panic(ErrShape) + } + xMat, aTrans := untranspose(x) + var g blas64.General + if rm, ok := xMat.(RawMatrixer); ok { + g = rm.RawMatrix() + } else { + g = DenseCopyOf(x).mat + aTrans = false + } + if a != s { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + s.reuseAs(n) + s.CopySym(a) + } + t := blas.NoTrans + if aTrans { + t = blas.Trans + } + blas64.Syrk(t, alpha, g, 1, s.mat) +} + +// SymOuterK calculates the outer product of x with itself and stores +// the result into the receiver. It is equivalent to the matrix +// multiplication +// s = alpha * x * x'. +// In order to update an existing matrix, see SymRankOne. +func (s *SymDense) SymOuterK(alpha float64, x Matrix) { + n, _ := x.Dims() + switch { + case s.IsZero(): + s.mat = blas64.Symmetric{ + N: n, + Stride: n, + Data: useZeroed(s.mat.Data, n*n), + Uplo: blas.Upper, + } + s.cap = n + s.SymRankK(s, alpha, x) + case s.mat.Uplo != blas.Upper: + panic(badSymTriangle) + case s.mat.N == n: + if s == x { + w := getWorkspaceSym(n, true) + w.SymRankK(w, alpha, x) + s.CopySym(w) + putWorkspaceSym(w) + } else { + if rs, ok := x.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + // Only zero the upper triangle. + for i := 0; i < n; i++ { + ri := i * s.mat.Stride + zero(s.mat.Data[ri+i : ri+n]) + } + s.SymRankK(s, alpha, x) + } + default: + panic(ErrShape) + } +} + +// RankTwo performs a symmmetric rank-two update to the matrix a and stores +// the result in the receiver +// m = a + alpha * (x * y' + y * x') +func (s *SymDense) RankTwo(a Symmetric, alpha float64, x, y *VecDense) { + n := s.mat.N + if x.Len() != n { + panic(ErrShape) + } + if y.Len() != n { + panic(ErrShape) + } + var w SymDense + if s == a { + w = *s + } + w.reuseAs(n) + if s != a { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + w.CopySym(a) + } + blas64.Syr2(alpha, x.mat, y.mat, w.mat) + *s = w +} + +// ScaleSym multiplies the elements of a by f, placing the result in the receiver. +func (s *SymDense) ScaleSym(f float64, a Symmetric) { + n := a.Symmetric() + s.reuseAs(n) + if a, ok := a.(RawSymmetricer); ok { + amat := a.RawSymmetric() + if s != a { + s.checkOverlap(amat) + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = f * amat.Data[i*amat.Stride+j] + } + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = f * a.At(i, j) + } + } +} + +// SubsetSym extracts a subset of the rows and columns of the matrix a and stores +// the result in-place into the receiver. The resulting matrix size is +// len(set)×len(set). Specifically, at the conclusion of SubsetSym, +// s.At(i, j) equals a.At(set[i], set[j]). Note that the supplied set does not +// have to be a strict subset, dimension repeats are allowed. +func (s *SymDense) SubsetSym(a Symmetric, set []int) { + n := len(set) + na := a.Symmetric() + s.reuseAs(n) + var restore func() + if a == s { + s, restore = s.isolatedWorkspace(a) + defer restore() + } + + if a, ok := a.(RawSymmetricer); ok { + raw := a.RawSymmetric() + if s != a { + s.checkOverlap(raw) + } + for i := 0; i < n; i++ { + ssub := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + r := set[i] + rsub := raw.Data[r*raw.Stride : r*raw.Stride+na] + for j := i; j < n; j++ { + c := set[j] + if r <= c { + ssub[j] = rsub[c] + } else { + ssub[j] = raw.Data[c*raw.Stride+r] + } + } + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = a.At(set[i], set[j]) + } + } +} + +// SliceSquare returns a new Matrix that shares backing data with the receiver. +// The returned matrix starts at {i,i} of the receiver and extends k-i rows +// and columns. The final row and column in the resulting matrix is k-1. +// SliceSquare panics with ErrIndexOutOfRange if the slice is outside the capacity +// of the receiver. +func (s *SymDense) SliceSquare(i, k int) Matrix { + sz := s.cap + if i < 0 || sz < i || k < i || sz < k { + panic(ErrIndexOutOfRange) + } + v := *s + v.mat.Data = s.mat.Data[i*s.mat.Stride+i : (k-1)*s.mat.Stride+k] + v.mat.N = k - i + v.cap = s.cap - i + return &v +} + +// GrowSquare returns the receiver expanded by n rows and n columns. If the +// dimensions of the expanded matrix are outside the capacity of the receiver +// a new allocation is made, otherwise not. Note that the receiver itself is +// not modified during the call to GrowSquare. +func (s *SymDense) GrowSquare(n int) Matrix { + if n < 0 { + panic(ErrIndexOutOfRange) + } + if n == 0 { + return s + } + var v SymDense + n += s.mat.N + if n > s.cap { + v.mat = blas64.Symmetric{ + N: n, + Stride: n, + Uplo: blas.Upper, + Data: make([]float64, n*n), + } + v.cap = n + // Copy elements, including those not currently visible. Use a temporary + // structure to avoid modifying the receiver. + var tmp SymDense + tmp.mat = blas64.Symmetric{ + N: s.cap, + Stride: s.mat.Stride, + Data: s.mat.Data, + Uplo: s.mat.Uplo, + } + tmp.cap = s.cap + v.CopySym(&tmp) + return &v + } + v.mat = blas64.Symmetric{ + N: n, + Stride: s.mat.Stride, + Uplo: blas.Upper, + Data: s.mat.Data[:(n-1)*s.mat.Stride+n], + } + v.cap = s.cap + return &v +} + +// PowPSD computes a^pow where a is a positive symmetric definite matrix. +// +// PowPSD returns an error if the matrix is not not positive symmetric definite +// or the Eigendecomposition is not successful. +func (s *SymDense) PowPSD(a Symmetric, pow float64) error { + dim := a.Symmetric() + s.reuseAs(dim) + + var eigen EigenSym + ok := eigen.Factorize(a, true) + if !ok { + return ErrFailedEigen + } + values := eigen.Values(nil) + for i, v := range values { + if v <= 0 { + return ErrNotPSD + } + values[i] = math.Pow(v, pow) + } + var u Dense + u.EigenvectorsSym(&eigen) + + s.SymOuterK(values[0], u.ColView(0)) + for i := 1; i < dim; i++ { + s.SymRankOne(s, values[i], u.ColView(i)) + } + return nil +} diff --git a/vendor/gonum.org/v1/gonum/mat/symmetric_example_test.go b/vendor/gonum.org/v1/gonum/mat/symmetric_example_test.go new file mode 100644 index 00000000..2616d6f4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/symmetric_example_test.go @@ -0,0 +1,54 @@ +// Copyright ©2015 The gonum 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 mat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/mat" +) + +func ExampleSymDense_SubsetSym() { + n := 5 + s := mat.NewSymDense(5, nil) + count := 1.0 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.SetSym(i, j, count) + count++ + } + } + fmt.Println("Original matrix:") + fmt.Printf("%0.4v\n\n", mat.Formatted(s)) + + // Take the subset {0, 2, 4} + var sub mat.SymDense + sub.SubsetSym(s, []int{0, 2, 4}) + fmt.Println("Subset {0, 2, 4}") + fmt.Printf("%0.4v\n\n", mat.Formatted(&sub)) + + // Take the subset {0, 0, 4} + sub.SubsetSym(s, []int{0, 0, 4}) + fmt.Println("Subset {0, 0, 4}") + fmt.Printf("%0.4v\n\n", mat.Formatted(&sub)) + + // Output: + // Original matrix: + // ⎡ 1 2 3 4 5⎤ + // ⎢ 2 6 7 8 9⎥ + // ⎢ 3 7 10 11 12⎥ + // ⎢ 4 8 11 13 14⎥ + // ⎣ 5 9 12 14 15⎦ + // + // Subset {0, 2, 4} + // ⎡ 1 3 5⎤ + // ⎢ 3 10 12⎥ + // ⎣ 5 12 15⎦ + // + // Subset {0, 0, 4} + // ⎡ 1 1 5⎤ + // ⎢ 1 1 5⎥ + // ⎣ 5 5 15⎦ +} diff --git a/vendor/gonum.org/v1/gonum/mat/symmetric_test.go b/vendor/gonum.org/v1/gonum/mat/symmetric_test.go new file mode 100644 index 00000000..48210aa4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/symmetric_test.go @@ -0,0 +1,694 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "fmt" + "math/rand" + "os" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +func TestNewSymmetric(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + mat *SymDense + }{ + { + data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + n: 3, + mat: &SymDense{ + mat: blas64.Symmetric{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + cap: 3, + }, + }, + } { + sym := NewSymDense(test.n, test.data) + rows, cols := sym.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(sym, test.mat) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, sym, test.mat) + } + + m := NewDense(test.n, test.n, test.data) + if !reflect.DeepEqual(sym.mat.Data, m.mat.Data) { + t.Errorf("unexpected data slice mismatch for test %d: got: %v want: %v", i, sym.mat.Data, m.mat.Data) + } + } + + panicked, message := panics(func() { NewSymDense(3, []float64{1, 2}) }) + if !panicked || message != ErrShape.Error() { + t.Error("expected panic for invalid data slice length") + } +} + +func TestSymAtSet(t *testing.T) { + sym := &SymDense{ + mat: blas64.Symmetric{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + cap: 3, + } + rows, cols := sym.Dims() + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { sym.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { sym.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { sym.SetSym(row, 0, 1.2) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { sym.SetSym(0, col, 1.2) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + orig, new float64 + }{ + {row: 1, col: 2, orig: 6, new: 15}, + {row: 2, col: 1, orig: 15, new: 12}, + } { + if e := sym.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + if e := sym.At(st.col, st.row); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.col, st.row, e, st.orig) + } + sym.SetSym(st.row, st.col, st.new) + if e := sym.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetSym(%[1]d, %[2]d, %[4]v): got: %[3]v want: %v", st.row, st.col, e, st.new) + } + if e := sym.At(st.col, st.row); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetSym(%[2]d, %[1]d, %[4]v): got: %[3]v want: %v", st.col, st.row, e, st.new) + } + } +} + +func TestSymAdd(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + b := NewSymDense(n, nil) + for i := range a.mat.Data { + b.mat.Data[i] = rand.Float64() + } + var m Dense + m.Add(a, b) + + // Check with new receiver + var s SymDense + s.AddSym(a, b) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + + // Check with equal receiver + s.CopySym(a) + s.AddSym(&s, b) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } + + method := func(receiver, a, b Matrix) { + type addSymer interface { + AddSym(a, b Symmetric) + } + rd := receiver.(addSymer) + rd.AddSym(a.(Symmetric), b.(Symmetric)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Add(a, b) + } + testTwoInput(t, "AddSym", &SymDense{}, method, denseComparison, legalTypesSym, legalSizeSameSquare, 1e-14) +} + +func TestCopy(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + s := NewSymDense(n, nil) + s.CopySym(a) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := a.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } +} + +// TODO(kortschak) Roll this into testOneInput when it exists. +// https://github.com/gonum/matrix/issues/171 +func TestSymCopyPanic(t *testing.T) { + var ( + a SymDense + n int + ) + m := NewSymDense(1, nil) + panicked, message := panics(func() { n = m.CopySym(&a) }) + if panicked { + t.Errorf("unexpected panic: %v", message) + } + if n != 0 { + t.Errorf("unexpected n: got: %d want: 0", n) + } +} + +func TestSymRankOne(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + alpha := 2.0 + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + + xMat := NewDense(n, 1, x) + var m Dense + m.Mul(xMat, xMat.T()) + m.Scale(alpha, &m) + m.Add(&m, a) + + // Check with new receiver + s := NewSymDense(n, nil) + s.SymRankOne(a, alpha, NewVecDense(len(x), x)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + + // Check with reused receiver + copy(s.mat.Data, a.mat.Data) + s.SymRankOne(s, alpha, NewVecDense(len(x), x)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } + + alpha := 3.0 + method := func(receiver, a, b Matrix) { + type SymRankOner interface { + SymRankOne(a Symmetric, alpha float64, x *VecDense) + } + rd := receiver.(SymRankOner) + rd.SymRankOne(a.(Symmetric), alpha, b.(*VecDense)) + } + denseComparison := func(receiver, a, b *Dense) { + var tmp Dense + tmp.Mul(b, b.T()) + tmp.Scale(alpha, &tmp) + receiver.Add(a, &tmp) + } + legalTypes := func(a, b Matrix) bool { + _, ok := a.(Symmetric) + if !ok { + return false + } + _, ok = b.(*VecDense) + return ok + } + legalSize := func(ar, ac, br, bc int) bool { + if ar != ac { + return false + } + return br == ar + } + testTwoInput(t, "SymRankOne", &SymDense{}, method, denseComparison, legalTypes, legalSize, 1e-14) +} + +func TestIssue250SymRankOne(t *testing.T) { + x := NewVecDense(5, []float64{1, 2, 3, 4, 5}) + var s1, s2 SymDense + s1.SymRankOne(NewSymDense(5, nil), 1, x) + s2.SymRankOne(NewSymDense(5, nil), 1, x) + s2.SymRankOne(NewSymDense(5, nil), 1, x) + if !Equal(&s1, &s2) { + t.Error("unexpected result from repeat") + } +} + +func TestRankTwo(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + alpha := 2.0 + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + x := make([]float64, n) + y := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + y[i] = rand.Float64() + } + + xMat := NewDense(n, 1, x) + yMat := NewDense(n, 1, y) + var m Dense + m.Mul(xMat, yMat.T()) + var tmp Dense + tmp.Mul(yMat, xMat.T()) + m.Add(&m, &tmp) + m.Scale(alpha, &m) + m.Add(&m, a) + + // Check with new receiver + s := NewSymDense(n, nil) + s.RankTwo(a, alpha, NewVecDense(len(x), x), NewVecDense(len(y), y)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(s.At(i, j), m.At(i, j), 1e-14, 1e-14) { + t.Errorf("unexpected element value at (%d,%d): got: %f want: %f", i, j, m.At(i, j), s.At(i, j)) + } + } + } + + // Check with reused receiver + copy(s.mat.Data, a.mat.Data) + s.RankTwo(s, alpha, NewVecDense(len(x), x), NewVecDense(len(y), y)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(s.At(i, j), m.At(i, j), 1e-14, 1e-14) { + t.Errorf("unexpected element value at (%d,%d): got: %f want: %f", i, j, m.At(i, j), s.At(i, j)) + } + } + } + } +} + +func TestSymRankK(t *testing.T) { + alpha := 3.0 + method := func(receiver, a, b Matrix) { + type SymRankKer interface { + SymRankK(a Symmetric, alpha float64, x Matrix) + } + rd := receiver.(SymRankKer) + rd.SymRankK(a.(Symmetric), alpha, b) + } + denseComparison := func(receiver, a, b *Dense) { + var tmp Dense + tmp.Mul(b, b.T()) + tmp.Scale(alpha, &tmp) + receiver.Add(a, &tmp) + } + legalTypes := func(a, b Matrix) bool { + _, ok := a.(Symmetric) + return ok + } + legalSize := func(ar, ac, br, bc int) bool { + if ar != ac { + return false + } + return br == ar + } + testTwoInput(t, "SymRankK", &SymDense{}, method, denseComparison, legalTypes, legalSize, 1e-14) +} + +func TestSymOuterK(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, x Matrix) { + type SymOuterKer interface { + SymOuterK(alpha float64, x Matrix) + } + rd := receiver.(SymOuterKer) + rd.SymOuterK(f, x) + } + denseComparison := func(receiver, x *Dense) { + receiver.Mul(x, x.T()) + receiver.Scale(f, receiver) + } + testOneInput(t, "SymOuterK", &SymDense{}, method, denseComparison, isAnyType, isAnySize, 1e-14) + } +} + +func TestIssue250SymOuterK(t *testing.T) { + x := NewVecDense(5, []float64{1, 2, 3, 4, 5}) + var s1, s2 SymDense + s1.SymOuterK(1, x) + s2.SymOuterK(1, x) + s2.SymOuterK(1, x) + if !Equal(&s1, &s2) { + t.Error("unexpected result from repeat") + } +} + +func TestScaleSym(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, a Matrix) { + type ScaleSymer interface { + ScaleSym(f float64, a Symmetric) + } + rd := receiver.(ScaleSymer) + rd.ScaleSym(f, a.(Symmetric)) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(f, a) + } + testOneInput(t, "ScaleSym", &SymDense{}, method, denseComparison, legalTypeSym, isSquare, 1e-14) + } +} + +func TestSubsetSym(t *testing.T) { + for _, test := range []struct { + a *SymDense + dims []int + ans *SymDense + }{ + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{0, 2}, + ans: NewSymDense(2, []float64{ + 1, 3, + 0, 6, + }), + }, + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{2, 0}, + ans: NewSymDense(2, []float64{ + 6, 3, + 0, 1, + }), + }, + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{1, 1, 1}, + ans: NewSymDense(3, []float64{ + 4, 4, 4, + 0, 4, 4, + 0, 0, 4, + }), + }, + } { + var s SymDense + s.SubsetSym(test.a, test.dims) + if !Equal(&s, test.ans) { + t.Errorf("SubsetSym mismatch dims %v\nGot:\n% v\nWant:\n% v\n", test.dims, s, test.ans) + } + } + + dims := []int{0, 2} + maxDim := dims[0] + for _, v := range dims { + if maxDim < v { + maxDim = v + } + } + method := func(receiver, a Matrix) { + type SubsetSymer interface { + SubsetSym(a Symmetric, set []int) + } + rd := receiver.(SubsetSymer) + rd.SubsetSym(a.(Symmetric), dims) + } + denseComparison := func(receiver, a *Dense) { + *receiver = *NewDense(len(dims), len(dims), nil) + sz := len(dims) + for i := 0; i < sz; i++ { + for j := 0; j < sz; j++ { + receiver.Set(i, j, a.At(dims[i], dims[j])) + } + } + } + legalSize := func(ar, ac int) bool { + return ar == ac && ar > maxDim + } + + testOneInput(t, "SubsetSym", &SymDense{}, method, denseComparison, legalTypeSym, legalSize, 0) +} + +func TestViewGrowSquare(t *testing.T) { + // n is the size of the original SymDense. + // The first view uses start1, span1. The second view uses start2, span2 on + // the first view. + for _, test := range []struct { + n, start1, span1, start2, span2 int + }{ + {10, 0, 10, 0, 10}, + {10, 0, 8, 0, 8}, + {10, 2, 8, 0, 6}, + {10, 2, 7, 4, 2}, + {10, 2, 6, 0, 5}, + } { + n := test.n + s := NewSymDense(n, nil) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.SetSym(i, j, float64((i+1)*n+j+1)) + } + } + + // Take a subset and check the view matches. + start1 := test.start1 + span1 := test.span1 + v := s.SliceSquare(start1, start1+span1).(*SymDense) + for i := 0; i < span1; i++ { + for j := i; j < span1; j++ { + if v.At(i, j) != s.At(start1+i, start1+j) { + t.Errorf("View mismatch") + } + } + } + + start2 := test.start2 + span2 := test.span2 + v2 := v.SliceSquare(start2, start2+span2).(*SymDense) + + for i := 0; i < span2; i++ { + for j := i; j < span2; j++ { + if v2.At(i, j) != s.At(start1+start2+i, start1+start2+j) { + t.Errorf("Second view mismatch") + } + } + } + + // Check that a write to the view is reflected in the original. + v2.SetSym(0, 0, 1.2) + if s.At(start1+start2, start1+start2) != 1.2 { + t.Errorf("Write to view not reflected in original") + } + + // Grow the matrix back to the original view + gn := n - start1 - start2 + g := v2.GrowSquare(gn - v2.Symmetric()).(*SymDense) + g.SetSym(1, 1, 2.2) + + for i := 0; i < gn; i++ { + for j := 0; j < gn; j++ { + if g.At(i, j) != s.At(start1+start2+i, start1+start2+j) { + t.Errorf("Grow mismatch") + + fmt.Printf("g=\n% v\n", Formatted(g)) + fmt.Printf("s=\n% v\n", Formatted(s)) + os.Exit(1) + } + } + } + + // View g, then grow it and make sure all the elements were copied. + gv := g.SliceSquare(0, gn-1).(*SymDense) + + gg := gv.GrowSquare(2) + for i := 0; i < gn; i++ { + for j := 0; j < gn; j++ { + if g.At(i, j) != gg.At(i, j) { + t.Errorf("Expand mismatch") + } + } + } + } +} + +func TestPowPSD(t *testing.T) { + for cas, test := range []struct { + a *SymDense + pow float64 + ans *SymDense + }{ + // Comparison with Matlab. + { + a: NewSymDense(2, []float64{10, 5, 5, 12}), + pow: 0.5, + ans: NewSymDense(2, []float64{3.065533767740645, 0.776210486171016, 0.776210486171016, 3.376017962209052}), + }, + { + a: NewSymDense(2, []float64{11, -1, -1, 8}), + pow: 0.5, + ans: NewSymDense(2, []float64{3.312618742210524, -0.162963396980939, -0.162963396980939, 2.823728551267709}), + }, + { + a: NewSymDense(2, []float64{10, 5, 5, 12}), + pow: -0.5, + ans: NewSymDense(2, []float64{0.346372134547712, -0.079637515547296, -0.079637515547296, 0.314517128328794}), + }, + { + a: NewSymDense(3, []float64{15, -1, -3, -1, 8, 6, -3, 6, 14}), + pow: 0.6, + ans: NewSymDense(3, []float64{ + 5.051214323034288, -0.163162161893975, -0.612153996497505, + -0.163162161893976, 3.283474884617009, 1.432842761381493, + -0.612153996497505, 1.432842761381494, 4.695873060862573, + }), + }, + } { + var s SymDense + err := s.PowPSD(test.a, test.pow) + if err != nil { + panic("bad test") + } + if !EqualApprox(&s, test.ans, 1e-10) { + t.Errorf("Case %d, pow mismatch", cas) + fmt.Println(Formatted(&s)) + fmt.Println(Formatted(test.ans)) + } + } + + // Compare with Dense.Pow + rnd := rand.New(rand.NewSource(1)) + for dim := 2; dim < 10; dim++ { + for pow := 2; pow < 6; pow++ { + a := NewDense(dim, dim, nil) + for i := 0; i < dim; i++ { + for j := 0; j < dim; j++ { + a.Set(i, j, rnd.Float64()) + } + } + var mat SymDense + mat.SymOuterK(1, a) + + var sym SymDense + sym.PowPSD(&mat, float64(pow)) + + var dense Dense + dense.Pow(&mat, pow) + + if !EqualApprox(&sym, &dense, 1e-10) { + t.Errorf("Dim %d: pow mismatch", dim) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/triangular.go b/vendor/gonum.org/v1/gonum/mat/triangular.go new file mode 100644 index 00000000..19b15bba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/triangular.go @@ -0,0 +1,540 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" +) + +var ( + triDense *TriDense + _ Matrix = triDense + _ Triangular = triDense + _ RawTriangular = triDense + _ MutableTriangular = triDense + + _ NonZeroDoer = triDense + _ RowNonZeroDoer = triDense + _ ColNonZeroDoer = triDense +) + +const badTriCap = "mat: bad capacity for TriDense" + +// TriDense represents an upper or lower triangular matrix in dense storage +// format. +type TriDense struct { + mat blas64.Triangular + cap int +} + +// Triangular represents a triangular matrix. Triangular matrices are always square. +type Triangular interface { + Matrix + // Triangular returns the number of rows/columns in the matrix and its + // orientation. + Triangle() (n int, kind TriKind) + + // TTri is the equivalent of the T() method in the Matrix interface but + // guarantees the transpose is of triangular type. + TTri() Triangular +} + +// A RawTriangular can return a view of itself as a BLAS Triangular matrix. +type RawTriangular interface { + RawTriangular() blas64.Triangular +} + +// A MutableTriangular can set elements of a triangular matrix. +type MutableTriangular interface { + Triangular + SetTri(i, j int, v float64) +} + +var ( + _ Matrix = TransposeTri{} + _ Triangular = TransposeTri{} + _ UntransposeTrier = TransposeTri{} +) + +// TransposeTri is a type for performing an implicit transpose of a Triangular +// matrix. It implements the Triangular interface, returning values from the +// transpose of the matrix within. +type TransposeTri struct { + Triangular Triangular +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Triangular field. +func (t TransposeTri) At(i, j int) float64 { + return t.Triangular.At(j, i) +} + +// Dims returns the dimensions of the transposed matrix. Triangular matrices are +// square and thus this is the same size as the original Triangular. +func (t TransposeTri) Dims() (r, c int) { + c, r = t.Triangular.Dims() + return r, c +} + +// T performs an implicit transpose by returning the Triangular field. +func (t TransposeTri) T() Matrix { + return t.Triangular +} + +// Triangle returns the number of rows/columns in the matrix and its orientation. +func (t TransposeTri) Triangle() (int, TriKind) { + n, upper := t.Triangular.Triangle() + return n, !upper +} + +// TTri performs an implicit transpose by returning the Triangular field. +func (t TransposeTri) TTri() Triangular { + return t.Triangular +} + +// Untranspose returns the Triangular field. +func (t TransposeTri) Untranspose() Matrix { + return t.Triangular +} + +func (t TransposeTri) UntransposeTri() Triangular { + return t.Triangular +} + +// NewTriDense creates a new Triangular matrix with n rows and columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*n, data is +// used as the backing slice, and changes to the elements of the returned TriDense +// will be reflected in data. If neither of these is true, NewTriDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +// Only the values in the triangular portion corresponding to kind are used. +func NewTriDense(n int, kind TriKind, data []float64) *TriDense { + if n < 0 { + panic("mat: negative dimension") + } + if data != nil && len(data) != n*n { + panic(ErrShape) + } + if data == nil { + data = make([]float64, n*n) + } + uplo := blas.Lower + if kind == Upper { + uplo = blas.Upper + } + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: n, + Data: data, + Uplo: uplo, + Diag: blas.NonUnit, + }, + cap: n, + } +} + +func (t *TriDense) Dims() (r, c int) { + return t.mat.N, t.mat.N +} + +// Triangle returns the dimension of t and its orientation. The returned +// orientation is only valid when n is not zero. +func (t *TriDense) Triangle() (n int, kind TriKind) { + return t.mat.N, TriKind(!t.IsZero()) && t.triKind() +} + +func (t *TriDense) isUpper() bool { + return isUpperUplo(t.mat.Uplo) +} + +func (t *TriDense) triKind() TriKind { + return TriKind(isUpperUplo(t.mat.Uplo)) +} + +func isUpperUplo(u blas.Uplo) bool { + switch u { + case blas.Upper: + return true + case blas.Lower: + return false + default: + panic(badTriangle) + } +} + +// asSymBlas returns the receiver restructured as a blas64.Symmetric with the +// same backing memory. Panics if the receiver is unit. +// This returns a blas64.Symmetric and not a *SymDense because SymDense can only +// be upper triangular. +func (t *TriDense) asSymBlas() blas64.Symmetric { + if t.mat.Diag == blas.Unit { + panic("mat: cannot convert unit TriDense into blas64.Symmetric") + } + return blas64.Symmetric{ + N: t.mat.N, + Stride: t.mat.Stride, + Data: t.mat.Data, + Uplo: t.mat.Uplo, + } +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (t *TriDense) T() Matrix { + return Transpose{t} +} + +// TTri performs an implicit transpose by returning the receiver inside a TransposeTri. +func (t *TriDense) TTri() Triangular { + return TransposeTri{t} +} + +func (t *TriDense) RawTriangular() blas64.Triangular { + return t.mat +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (t *TriDense) Reset() { + // N and Stride must be zeroed in unison. + t.mat.N, t.mat.Stride = 0, 0 + // Defensively zero Uplo to ensure + // it is set correctly later. + t.mat.Uplo = 0 + t.mat.Data = t.mat.Data[:0] +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the +// receiver for size-restricted operations. TriDense matrices can be zeroed using Reset. +func (t *TriDense) IsZero() bool { + // It must be the case that t.Dims() returns + // zeros in this case. See comment in Reset(). + return t.mat.Stride == 0 +} + +// untranspose untransposes a matrix if applicable. If a is an Untransposer, then +// untranspose returns the underlying matrix and true. If it is not, then it returns +// the input matrix and false. +func untransposeTri(a Triangular) (Triangular, bool) { + if ut, ok := a.(UntransposeTrier); ok { + return ut.UntransposeTri(), true + } + return a, false +} + +// reuseAs resizes a zero receiver to an n×n triangular matrix with the given +// orientation. If the receiver is non-zero, reuseAs checks that the receiver +// is the correct size and orientation. +func (t *TriDense) reuseAs(n int, kind TriKind) { + ul := blas.Lower + if kind == Upper { + ul = blas.Upper + } + if t.mat.N > t.cap { + panic(badTriCap) + } + if t.IsZero() { + t.mat = blas64.Triangular{ + N: n, + Stride: n, + Diag: blas.NonUnit, + Data: use(t.mat.Data, n*n), + Uplo: ul, + } + t.cap = n + return + } + if t.mat.N != n { + panic(ErrShape) + } + if t.mat.Uplo != ul { + panic(ErrTriangle) + } +} + +// isolatedWorkspace returns a new TriDense matrix w with the size of a and +// returns a callback to defer which performs cleanup at the return of the call. +// This should be used when a method receiver is the same pointer as an input argument. +func (t *TriDense) isolatedWorkspace(a Triangular) (w *TriDense, restore func()) { + n, kind := a.Triangle() + if n == 0 { + panic("zero size") + } + w = getWorkspaceTri(n, kind, false) + return w, func() { + t.Copy(w) + putWorkspaceTri(w) + } +} + +// Copy makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two matrices and +// returns the number of rows and columns it copied. Only elements within the +// receiver's non-zero triangle are set. +// +// See the Copier interface for more information. +func (t *TriDense) Copy(a Matrix) (r, c int) { + r, c = a.Dims() + r = min(r, t.mat.N) + c = min(c, t.mat.N) + if r == 0 || c == 0 { + return 0, 0 + } + + switch a := a.(type) { + case RawMatrixer: + amat := a.RawMatrix() + if t.isUpper() { + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) + } + } else { + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) + } + } + case RawTriangular: + amat := a.RawTriangular() + aIsUpper := isUpperUplo(amat.Uplo) + tIsUpper := t.isUpper() + switch { + case tIsUpper && aIsUpper: + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) + } + case !tIsUpper && !aIsUpper: + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) + } + default: + for i := 0; i < r; i++ { + t.set(i, i, amat.Data[i*amat.Stride+i]) + } + } + default: + isUpper := t.isUpper() + for i := 0; i < r; i++ { + if isUpper { + for j := i; j < c; j++ { + t.set(i, j, a.At(i, j)) + } + } else { + for j := 0; j <= i; j++ { + t.set(i, j, a.At(i, j)) + } + } + } + } + + return r, c +} + +// InverseTri computes the inverse of the triangular matrix a, storing the result +// into the receiver. If a is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally be +// avoided where possible, for example by using the Solve routines. +func (t *TriDense) InverseTri(a Triangular) error { + if rt, ok := a.(RawTriangular); ok { + t.checkOverlap(rt.RawTriangular()) + } + n, _ := a.Triangle() + t.reuseAs(a.Triangle()) + t.Copy(a) + work := getFloats(3*n, false) + iwork := getInts(n, false) + cond := lapack64.Trcon(CondNorm, t.mat, work, iwork) + putFloats(work) + putInts(iwork) + if math.IsInf(cond, 1) { + return Condition(cond) + } + ok := lapack64.Trtri(t.mat) + if !ok { + return Condition(math.Inf(1)) + } + if cond > ConditionTolerance { + return Condition(cond) + } + return nil +} + +// MulTri takes the product of triangular matrices a and b and places the result +// in the receiver. The size of a and b must match, and they both must have the +// same TriKind, or Mul will panic. +func (t *TriDense) MulTri(a, b Triangular) { + n, kind := a.Triangle() + nb, kindb := b.Triangle() + if n != nb { + panic(ErrShape) + } + if kind != kindb { + panic(ErrTriangle) + } + + aU, _ := untransposeTri(a) + bU, _ := untransposeTri(b) + t.reuseAs(n, kind) + var restore func() + if t == aU { + t, restore = t.isolatedWorkspace(aU) + defer restore() + } else if t == bU { + t, restore = t.isolatedWorkspace(bU) + defer restore() + } + + // TODO(btracey): Improve the set of fast-paths. + if kind == Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + var v float64 + for k := i; k <= j; k++ { + v += a.At(i, k) * b.At(k, j) + } + t.SetTri(i, j, v) + } + } + return + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + var v float64 + for k := j; k <= i; k++ { + v += a.At(i, k) * b.At(k, j) + } + t.SetTri(i, j, v) + } + } +} + +// copySymIntoTriangle copies a symmetric matrix into a TriDense +func copySymIntoTriangle(t *TriDense, s Symmetric) { + n, upper := t.Triangle() + ns := s.Symmetric() + if n != ns { + panic("mat: triangle size mismatch") + } + ts := t.mat.Stride + if rs, ok := s.(RawSymmetricer); ok { + sd := rs.RawSymmetric() + ss := sd.Stride + if upper { + if sd.Uplo == blas.Upper { + for i := 0; i < n; i++ { + copy(t.mat.Data[i*ts+i:i*ts+n], sd.Data[i*ss+i:i*ss+n]) + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + t.mat.Data[i*ts+j] = sd.Data[j*ss+i] + } + } + return + } + if sd.Uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + t.mat.Data[i*ts+j] = sd.Data[j*ss+i] + } + } + return + } + for i := 0; i < n; i++ { + copy(t.mat.Data[i*ts:i*ts+i+1], sd.Data[i*ss:i*ss+i+1]) + } + return + } + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + t.mat.Data[i*ts+j] = s.At(i, j) + } + } + return + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + t.mat.Data[i*ts+j] = s.At(i, j) + } + } +} + +// DoNonZero calls the function fn for each of the non-zero elements of t. The function fn +// takes a row/column index and the element value of t at (i, j). +func (t *TriDense) DoNonZero(fn func(i, j int, v float64)) { + if t.isUpper() { + for i := 0; i < t.mat.N; i++ { + for j := i; j < t.mat.N; j++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } + return + } + for i := 0; i < t.mat.N; i++ { + for j := 0; j <= i; j++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + } +} + +// DoRowNonZero calls the function fn for each of the non-zero elements of row i of t. The function fn +// takes a row/column index and the element value of t at (i, j). +func (t *TriDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { + if i < 0 || t.mat.N <= i { + panic(ErrRowAccess) + } + if t.isUpper() { + for j := i; j < t.mat.N; j++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + return + } + for j := 0; j <= i; j++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } +} + +// DoColNonZero calls the function fn for each of the non-zero elements of column j of t. The function fn +// takes a row/column index and the element value of t at (i, j). +func (t *TriDense) DoColNonZero(j int, fn func(i, j int, v float64)) { + if j < 0 || t.mat.N <= j { + panic(ErrColAccess) + } + if t.isUpper() { + for i := 0; i <= j; i++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } + return + } + for i := j; i < t.mat.N; i++ { + v := t.at(i, j) + if v != 0 { + fn(i, j, v) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/triangular_test.go b/vendor/gonum.org/v1/gonum/mat/triangular_test.go new file mode 100644 index 00000000..883322d7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/triangular_test.go @@ -0,0 +1,438 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +func TestNewTriangular(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + kind TriKind + mat *TriDense + }{ + { + data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + n: 3, + kind: Upper, + mat: &TriDense{ + mat: blas64.Triangular{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + Diag: blas.NonUnit, + }, + cap: 3, + }, + }, + } { + tri := NewTriDense(test.n, test.kind, test.data) + rows, cols := tri.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(tri, test.mat) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, tri, test.mat) + } + } + + for _, kind := range []TriKind{Lower, Upper} { + panicked, message := panics(func() { NewTriDense(3, kind, []float64{1, 2}) }) + if !panicked || message != ErrShape.Error() { + t.Errorf("expected panic for invalid data slice length for upper=%t", kind) + } + } +} + +func TestTriAtSet(t *testing.T) { + tri := &TriDense{ + mat: blas64.Triangular{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + Diag: blas.NonUnit, + }, + cap: 3, + } + + rows, cols := tri.Dims() + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { tri.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { tri.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { tri.SetTri(row, 0, 1.2) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { tri.SetTri(0, col, 1.2) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + uplo blas.Uplo + }{ + {row: 2, col: 1, uplo: blas.Upper}, + {row: 1, col: 2, uplo: blas.Lower}, + } { + tri.mat.Uplo = st.uplo + panicked, message := panics(func() { tri.SetTri(st.row, st.col, 1.2) }) + if !panicked || message != ErrTriangleSet.Error() { + t.Errorf("expected panic for %+v", st) + } + } + + for _, st := range []struct { + row, col int + uplo blas.Uplo + orig, new float64 + }{ + {row: 2, col: 1, uplo: blas.Lower, orig: 8, new: 15}, + {row: 1, col: 2, uplo: blas.Upper, orig: 6, new: 15}, + } { + tri.mat.Uplo = st.uplo + if e := tri.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + tri.SetTri(st.row, st.col, st.new) + if e := tri.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetTri(%[1]d, %d, %v): got: %v want: %[3]v", st.row, st.col, st.new, e) + } + } +} + +func TestTriDenseCopy(t *testing.T) { + for i := 0; i < 100; i++ { + size := rand.Intn(100) + r, err := randDense(size, 0.9, rand.NormFloat64) + if size == 0 { + if err != ErrZeroLength { + t.Fatalf("expected error %v: got: %v", ErrZeroLength, err) + } + continue + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + u := NewTriDense(size, true, nil) + l := NewTriDense(size, false, nil) + + for _, typ := range []Matrix{r, (*basicMatrix)(r)} { + for j := range u.mat.Data { + u.mat.Data[j] = math.NaN() + l.mat.Data[j] = math.NaN() + } + u.Copy(typ) + l.Copy(typ) + for m := 0; m < size; m++ { + for n := 0; n < size; n++ { + want := typ.At(m, n) + switch { + case m < n: // Upper triangular matrix. + if got := u.At(m, n); got != want { + t.Errorf("unexpected upper value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + case m == n: // Diagonal matrix. + if got := u.At(m, n); got != want { + t.Errorf("unexpected upper value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + if got := l.At(m, n); got != want { + t.Errorf("unexpected diagonal value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + case m < n: // Lower triangular matrix. + if got := l.At(m, n); got != want { + t.Errorf("unexpected lower value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + } + } + } + } + } +} + +func TestTriTriDenseCopy(t *testing.T) { + for i := 0; i < 100; i++ { + size := rand.Intn(100) + r, err := randDense(size, 1, rand.NormFloat64) + if size == 0 { + if err != ErrZeroLength { + t.Fatalf("expected error %v: got: %v", ErrZeroLength, err) + } + continue + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + ur := NewTriDense(size, true, nil) + lr := NewTriDense(size, false, nil) + + ur.Copy(r) + lr.Copy(r) + + u := NewTriDense(size, true, nil) + u.Copy(ur) + if !equal(u, ur) { + t.Fatal("unexpected result for U triangle copy of U triangle: not equal") + } + + l := NewTriDense(size, false, nil) + l.Copy(lr) + if !equal(l, lr) { + t.Fatal("unexpected result for L triangle copy of L triangle: not equal") + } + + zero(u.mat.Data) + u.Copy(lr) + if !isDiagonal(u) { + t.Fatal("unexpected result for U triangle copy of L triangle: off diagonal non-zero element") + } + if !equalDiagonal(u, lr) { + t.Fatal("unexpected result for U triangle copy of L triangle: diagonal not equal") + } + + zero(l.mat.Data) + l.Copy(ur) + if !isDiagonal(l) { + t.Fatal("unexpected result for L triangle copy of U triangle: off diagonal non-zero element") + } + if !equalDiagonal(l, ur) { + t.Fatal("unexpected result for L triangle copy of U triangle: diagonal not equal") + } + } +} + +func TestTriInverse(t *testing.T) { + for _, kind := range []TriKind{Upper, Lower} { + for _, n := range []int{1, 3, 5, 9} { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + a := NewTriDense(n, kind, data) + var tr TriDense + err := tr.InverseTri(a) + if err != nil { + t.Errorf("Bad test: %s", err) + } + var d Dense + d.Mul(a, &tr) + if !equalApprox(eye(n), &d, 1e-8, false) { + var diff Dense + diff.Sub(eye(n), &d) + t.Errorf("Tri times inverse is not identity. Norm of difference: %v", Norm(&diff, 2)) + } + } + } +} + +func TestTriMul(t *testing.T) { + method := func(receiver, a, b Matrix) { + type MulTrier interface { + MulTri(a, b Triangular) + } + receiver.(MulTrier).MulTri(a.(Triangular), b.(Triangular)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeTriMul := func(ar, ac, br, bc int) bool { + // Need both to be square and the sizes to be the same + return ar == ac && br == bc && ar == br + } + + // The legal types are triangles with the same TriKind. + // legalTypesTri returns whether both input arguments are Triangular. + legalTypes := func(a, b Matrix) bool { + at, ok := a.(Triangular) + if !ok { + return false + } + bt, ok := b.(Triangular) + if !ok { + return false + } + _, ak := at.Triangle() + _, bk := bt.Triangle() + return ak == bk + } + legalTypesLower := func(a, b Matrix) bool { + legal := legalTypes(a, b) + if !legal { + return false + } + _, kind := a.(Triangular).Triangle() + r := kind == Lower + return r + } + receiver := NewTriDense(3, Lower, nil) + testTwoInput(t, "TriMul", receiver, method, denseComparison, legalTypesLower, legalSizeTriMul, 1e-14) + + legalTypesUpper := func(a, b Matrix) bool { + legal := legalTypes(a, b) + if !legal { + return false + } + _, kind := a.(Triangular).Triangle() + r := kind == Upper + return r + } + receiver = NewTriDense(3, Upper, nil) + testTwoInput(t, "TriMul", receiver, method, denseComparison, legalTypesUpper, legalSizeTriMul, 1e-14) +} + +func TestCopySymIntoTriangle(t *testing.T) { + nan := math.NaN() + for tc, test := range []struct { + n int + sUplo blas.Uplo + s []float64 + + tUplo TriKind + want []float64 + }{ + { + n: 3, + sUplo: blas.Upper, + s: []float64{ + 1, 2, 3, + nan, 4, 5, + nan, nan, 6, + }, + tUplo: Upper, + want: []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }, + }, + { + n: 3, + sUplo: blas.Lower, + s: []float64{ + 1, nan, nan, + 2, 3, nan, + 4, 5, 6, + }, + tUplo: Upper, + want: []float64{ + 1, 2, 4, + 0, 3, 5, + 0, 0, 6, + }, + }, + { + n: 3, + sUplo: blas.Upper, + s: []float64{ + 1, 2, 3, + nan, 4, 5, + nan, nan, 6, + }, + tUplo: Lower, + want: []float64{ + 1, 0, 0, + 2, 4, 0, + 3, 5, 6, + }, + }, + { + n: 3, + sUplo: blas.Lower, + s: []float64{ + 1, nan, nan, + 2, 3, nan, + 4, 5, 6, + }, + tUplo: Lower, + want: []float64{ + 1, 0, 0, + 2, 3, 0, + 4, 5, 6, + }, + }, + } { + n := test.n + s := NewSymDense(n, test.s) + // For the purpose of the test, break the assumption that + // symmetric is stored in the upper triangle (only when S is + // RawSymmetricer). + s.mat.Uplo = test.sUplo + + t1 := NewTriDense(n, test.tUplo, nil) + copySymIntoTriangle(t1, s) + + equal := true + loop1: + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if t1.At(i, j) != test.want[i*n+j] { + equal = false + break loop1 + } + } + } + if !equal { + t.Errorf("Case %v: unexpected T when S is RawSymmetricer", tc) + } + + if test.sUplo == blas.Lower { + continue + } + + sb := (basicSymmetric)(*s) + t2 := NewTriDense(n, test.tUplo, nil) + copySymIntoTriangle(t2, &sb) + equal = true + loop2: + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if t1.At(i, j) != test.want[i*n+j] { + equal = false + break loop2 + } + } + } + if !equal { + t.Errorf("Case %v: unexpected T when S is not RawSymmetricer", tc) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/vector.go b/vendor/gonum.org/v1/gonum/mat/vector.go new file mode 100644 index 00000000..110581ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/vector.go @@ -0,0 +1,484 @@ +// Copyright ©2013 The gonum 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 mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var ( + vector *VecDense + + _ Matrix = vector + _ Vector = vector + _ Reseter = vector +) + +// Vector is a column vector. +type Vector interface { + Matrix + Len() int +} + +// VecDense represents a column vector. +type VecDense struct { + mat blas64.Vector + n int + // A BLAS vector can have a negative increment, but allowing this + // in the mat type complicates a lot of code, and doesn't gain anything. + // VecDense must have positive increment in this package. +} + +// NewVecDense creates a new VecDense of length n. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n, data is +// used as the backing slice, and changes to the elements of the returned VecDense +// will be reflected in data. If neither of these is true, NewVecDense will panic. +func NewVecDense(n int, data []float64) *VecDense { + if len(data) != n && data != nil { + panic(ErrShape) + } + if data == nil { + data = make([]float64, n) + } + return &VecDense{ + mat: blas64.Vector{ + Inc: 1, + Data: data, + }, + n: n, + } +} + +// SliceVec returns a new VecDense that shares backing data with the receiver. +// The returned matrix starts at i of the receiver and extends k-i elements. +// SliceVec panics with ErrIndexOutOfRange if the slice is outside the capacity +// of the receiver. +func (v *VecDense) SliceVec(i, k int) *VecDense { + if i < 0 || k <= i || v.Cap() < k { + panic(ErrIndexOutOfRange) + } + return &VecDense{ + n: k - i, + mat: blas64.Vector{ + Inc: v.mat.Inc, + Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1], + }, + } +} + +// Dims returns the number of rows and columns in the matrix. Columns is always 1 +// for a non-Reset vector. +func (v *VecDense) Dims() (r, c int) { + if v.IsZero() { + return 0, 0 + } + return v.n, 1 +} + +// Caps returns the number of rows and columns in the backing matrix. Columns is always 1 +// for a non-Reset vector. +func (v *VecDense) Caps() (r, c int) { + if v.IsZero() { + return 0, 0 + } + return v.Cap(), 1 +} + +// Len returns the length of the vector. +func (v *VecDense) Len() int { + return v.n +} + +// Cap returns the capacity of the vector. +func (v *VecDense) Cap() int { + if v.IsZero() { + return 0 + } + return (cap(v.mat.Data)-1)/v.mat.Inc + 1 +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (v *VecDense) T() Matrix { + return Transpose{v} +} + +// Reset zeros the length of the vector so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (v *VecDense) Reset() { + // No change of Inc or n to 0 may be + // made unless both are set to 0. + v.mat.Inc = 0 + v.n = 0 + v.mat.Data = v.mat.Data[:0] +} + +// CloneVec makes a copy of a into the receiver, overwriting the previous value +// of the receiver. +func (v *VecDense) CloneVec(a *VecDense) { + if v == a { + return + } + v.n = a.n + v.mat = blas64.Vector{ + Inc: 1, + Data: use(v.mat.Data, v.n), + } + blas64.Copy(v.n, a.mat, v.mat) +} + +func (v *VecDense) RawVector() blas64.Vector { + return v.mat +} + +// CopyVec makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two vectors and +// returns the number of elements it copied. +func (v *VecDense) CopyVec(a *VecDense) int { + n := min(v.Len(), a.Len()) + if v != a { + blas64.Copy(n, a.mat, v.mat) + } + return n +} + +// ScaleVec scales the vector a by alpha, placing the result in the receiver. +func (v *VecDense) ScaleVec(alpha float64, a *VecDense) { + n := a.Len() + if v != a { + v.reuseAs(n) + if v.mat.Inc == 1 && a.mat.Inc == 1 { + f64.ScalUnitaryTo(v.mat.Data, alpha, a.mat.Data) + return + } + f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc), + alpha, a.mat.Data, uintptr(n), uintptr(a.mat.Inc)) + return + } + if v.mat.Inc == 1 { + f64.ScalUnitary(alpha, v.mat.Data) + return + } + f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc)) +} + +// AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver. +func (v *VecDense) AddScaledVec(a *VecDense, alpha float64, b *VecDense) { + if alpha == 1 { + v.AddVec(a, b) + return + } + if alpha == -1 { + v.SubVec(a, b) + return + } + + ar := a.Len() + br := b.Len() + + if ar != br { + panic(ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + switch { + case alpha == 0: // v <- a + v.CopyVec(a) + case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v + blas64.Scal(ar, alpha+1, v.mat) + case v == a && v != b: // v <- v + alpha * b + if v.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, alpha, b.mat.Data, a.mat.Data) + } else { + f64.AxpyInc(alpha, b.mat.Data, v.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(v.mat.Inc), 0, 0) + } + default: // v <- a + alpha * b or v <- a + alpha * v + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, alpha, b.mat.Data, a.mat.Data) + } else { + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + alpha, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) + } + } +} + +// AddVec adds the vectors a and b, placing the result in the receiver. +func (v *VecDense) AddVec(a, b *VecDense) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, 1, b.mat.Data, a.mat.Data) + return + } + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + 1, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) +} + +// SubVec subtracts the vector b from a, placing the result in the receiver. +func (v *VecDense) SubVec(a, b *VecDense) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, -1, b.mat.Data, a.mat.Data) + return + } + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + -1, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) +} + +// MulElemVec performs element-wise multiplication of a and b, placing the result +// in the receiver. +func (v *VecDense) MulElemVec(a, b *VecDense) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + amat, bmat := a.RawVector(), b.RawVector() + for i := 0; i < v.n; i++ { + v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] * bmat.Data[i*bmat.Inc] + } +} + +// DivElemVec performs element-wise division of a by b, placing the result +// in the receiver. +func (v *VecDense) DivElemVec(a, b *VecDense) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + amat, bmat := a.RawVector(), b.RawVector() + for i := 0; i < v.n; i++ { + v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] / bmat.Data[i*bmat.Inc] + } +} + +// MulVec computes a * b. The result is stored into the receiver. +// MulVec panics if the number of columns in a does not equal the number of rows in b. +func (v *VecDense) MulVec(a Matrix, b *VecDense) { + r, c := a.Dims() + br := b.Len() + if c != br { + panic(ErrShape) + } + + if v != b { + v.checkOverlap(b.mat) + } + + a, trans := untranspose(a) + ar, ac := a.Dims() + v.reuseAs(r) + var restore func() + if v == a { + v, restore = v.isolatedWorkspace(a.(*VecDense)) + defer restore() + } else if v == b { + v, restore = v.isolatedWorkspace(b) + defer restore() + } + + switch a := a.(type) { + case *VecDense: + if v != a { + v.checkOverlap(a.mat) + } + + if a.Len() == 1 { + // {1,1} x {1,n} + av := a.At(0, 0) + for i := 0; i < b.Len(); i++ { + v.mat.Data[i*v.mat.Inc] = av * b.mat.Data[i*b.mat.Inc] + } + return + } + if b.Len() == 1 { + // {1,n} x {1,1} + bv := b.At(0, 0) + for i := 0; i < a.Len(); i++ { + v.mat.Data[i*v.mat.Inc] = bv * a.mat.Data[i*a.mat.Inc] + } + return + } + // {n,1} x {1,n} + var sum float64 + for i := 0; i < c; i++ { + sum += a.At(i, 0) * b.At(i, 0) + } + v.SetVec(0, sum) + return + case RawSymmetricer: + amat := a.RawSymmetric() + blas64.Symv(1, amat, b.mat, 0, v.mat) + case RawTriangular: + v.CopyVec(b) + amat := a.RawTriangular() + ta := blas.NoTrans + if trans { + ta = blas.Trans + } + blas64.Trmv(ta, amat, v.mat) + case RawMatrixer: + amat := a.RawMatrix() + // We don't know that a is a *Dense, so make + // a temporary Dense to check overlap. + (&Dense{mat: amat}).checkOverlap(v.asGeneral()) + t := blas.NoTrans + if trans { + t = blas.Trans + } + blas64.Gemv(t, 1, amat, b.mat, 0, v.mat) + default: + if trans { + col := make([]float64, ar) + for c := 0; c < ac; c++ { + for i := range col { + col[i] = a.At(i, c) + } + var f float64 + for i, e := range col { + f += e * b.mat.Data[i*b.mat.Inc] + } + v.mat.Data[c*v.mat.Inc] = f + } + } else { + row := make([]float64, ac) + for r := 0; r < ar; r++ { + for i := range row { + row[i] = a.At(r, i) + } + var f float64 + for i, e := range row { + f += e * b.mat.Data[i*b.mat.Inc] + } + v.mat.Data[r*v.mat.Inc] = f + } + } + } +} + +// reuseAs resizes an empty vector to a r×1 vector, +// or checks that a non-empty matrix is r×1. +func (v *VecDense) reuseAs(r int) { + if v.IsZero() { + v.mat = blas64.Vector{ + Inc: 1, + Data: use(v.mat.Data, r), + } + v.n = r + return + } + if r != v.n { + panic(ErrShape) + } +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized vectors can be the +// receiver for size-restricted operations. VecDenses can be zeroed using Reset. +func (v *VecDense) IsZero() bool { + // It must be the case that v.Dims() returns + // zeros in this case. See comment in Reset(). + return v.mat.Inc == 0 +} + +func (v *VecDense) isolatedWorkspace(a *VecDense) (n *VecDense, restore func()) { + l := a.Len() + n = getWorkspaceVec(l, false) + return n, func() { + v.CopyVec(n) + putWorkspaceVec(n) + } +} + +// asDense returns a Dense representation of the receiver with the same +// underlying data. +func (v *VecDense) asDense() *Dense { + return &Dense{ + mat: v.asGeneral(), + capRows: v.n, + capCols: 1, + } +} + +// asGeneral returns a blas64.General representation of the receiver with the +// same underlying data. +func (v *VecDense) asGeneral() blas64.General { + return blas64.General{ + Rows: v.n, + Cols: 1, + Stride: v.mat.Inc, + Data: v.mat.Data, + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/vector_test.go b/vendor/gonum.org/v1/gonum/mat/vector_test.go new file mode 100644 index 00000000..4f39f71f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/vector_test.go @@ -0,0 +1,530 @@ +// Copyright ©2015 The gonum 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 mat + +import ( + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestNewVecDense(t *testing.T) { + for i, test := range []struct { + n int + data []float64 + vector *VecDense + }{ + { + n: 3, + data: []float64{4, 5, 6}, + vector: &VecDense{ + mat: blas64.Vector{ + Data: []float64{4, 5, 6}, + Inc: 1, + }, + n: 3, + }, + }, + { + n: 3, + data: nil, + vector: &VecDense{ + mat: blas64.Vector{ + Data: []float64{0, 0, 0}, + Inc: 1, + }, + n: 3, + }, + }, + } { + v := NewVecDense(test.n, test.data) + rows, cols := v.Dims() + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != 1 { + t.Errorf("unexpected number of cols for test %d: got: %d want: 1", i, cols) + } + if !reflect.DeepEqual(v, test.vector) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, v, test.vector) + } + } +} + +func TestCap(t *testing.T) { + for i, test := range []struct { + vector *VecDense + want int + }{ + {vector: NewVecDense(3, nil), want: 3}, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: make([]float64, 7, 10), + Inc: 3, + }, + n: 3, + }, + want: 4, + }, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: make([]float64, 10), + Inc: 3, + }, + n: 4, + }, + want: 4, + }, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: make([]float64, 11), + Inc: 3, + }, + n: 4, + }, + want: 4, + }, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: make([]float64, 12), + Inc: 3, + }, + n: 4, + }, + want: 4, + }, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: make([]float64, 13), + Inc: 3, + }, + n: 4, + }, + want: 5, + }, + } { + got := test.vector.Cap() + if got != test.want { + t.Errorf("unexpected capacty for test %d: got: %d want: %d", i, got, test.want) + } + } +} + +func TestVecDenseAtSet(t *testing.T) { + for i, test := range []struct { + vector *VecDense + }{ + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: []float64{0, 1, 2}, + Inc: 1, + }, + n: 3, + }, + }, + { + vector: &VecDense{ + mat: blas64.Vector{ + Data: []float64{0, 10, 10, 1, 10, 10, 2}, + Inc: 3, + }, + n: 3, + }, + }, + } { + v := test.vector + n := test.vector.n + + for _, row := range []int{-1, n} { + panicked, message := panics(func() { v.At(row, 0) }) + if !panicked || message != ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access for test %d n=%d r=%d", i, n, row) + } + } + for _, col := range []int{-1, 1} { + panicked, message := panics(func() { v.At(0, col) }) + if !panicked || message != ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access for test %d n=%d c=%d", i, n, col) + } + } + + for _, row := range []int{0, 1, n - 1} { + if e := v.At(row, 0); e != float64(row) { + t.Errorf("unexpected value for At(%d, 0) for test %d : got: %v want: %v", row, i, e, float64(row)) + } + } + + for _, row := range []int{-1, n} { + panicked, message := panics(func() { v.SetVec(row, 100) }) + if !panicked || message != ErrVectorAccess.Error() { + t.Errorf("expected panic for invalid row access for test %d n=%d r=%d", i, n, row) + } + } + + for inc, row := range []int{0, 2} { + v.SetVec(row, 100+float64(inc)) + if e := v.At(row, 0); e != 100+float64(inc) { + t.Errorf("unexpected value for At(%d, 0) after SetVec(%[1]d, %v) for test %d: got: %v want: %[2]v", row, 100+float64(inc), i, e) + } + } + } +} + +func TestVecDenseMul(t *testing.T) { + method := func(receiver, a, b Matrix) { + type mulVecer interface { + MulVec(a Matrix, b *VecDense) + } + rd := receiver.(mulVecer) + rd.MulVec(a, b.(*VecDense)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeMulVec := func(ar, ac, br, bc int) bool { + var legal bool + if bc != 1 { + legal = false + } else { + legal = ac == br + } + return legal + } + testTwoInput(t, "MulVec", &VecDense{}, method, denseComparison, legalTypesNotVecVec, legalSizeMulVec, 1e-14) +} + +func TestVecDenseScale(t *testing.T) { + for i, test := range []struct { + a *VecDense + alpha float64 + want *VecDense + }{ + { + a: NewVecDense(3, []float64{0, 1, 2}), + alpha: 0, + want: NewVecDense(3, []float64{0, 0, 0}), + }, + { + a: NewVecDense(3, []float64{0, 1, 2}), + alpha: 1, + want: NewVecDense(3, []float64{0, 1, 2}), + }, + { + a: NewVecDense(3, []float64{0, 1, 2}), + alpha: -2, + want: NewVecDense(3, []float64{0, -2, -4}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: 0, + want: NewVecDense(3, []float64{0, 0, 0}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: 1, + want: NewVecDense(3, []float64{0, 1, 2}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: -2, + want: NewVecDense(3, []float64{0, -2, -4}), + }, + { + a: NewDense(3, 3, []float64{ + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, + }).ColView(1), + alpha: -2, + want: NewVecDense(3, []float64{-2, -8, -14}), + }, + } { + var v VecDense + v.ScaleVec(test.alpha, test.a) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("test %d: unexpected result for v = alpha * a: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + + v.CopyVec(test.a) + v.ScaleVec(test.alpha, &v) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("test %d: unexpected result for v = alpha * v: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } + + for _, alpha := range []float64{0, 1, -1, 2.3, -2.3} { + method := func(receiver, a Matrix) { + type scaleVecer interface { + ScaleVec(float64, *VecDense) + } + v := receiver.(scaleVecer) + v.ScaleVec(alpha, a.(*VecDense)) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(alpha, a) + } + testOneInput(t, "ScaleVec", &VecDense{}, method, denseComparison, legalTypeVec, isAnyVecDense, 0) + } +} + +func TestVecDenseAddScaled(t *testing.T) { + for _, alpha := range []float64{0, 1, -1, 2.3, -2.3} { + method := func(receiver, a, b Matrix) { + type addScaledVecer interface { + AddScaledVec(*VecDense, float64, *VecDense) + } + v := receiver.(addScaledVecer) + v.AddScaledVec(a.(*VecDense), alpha, b.(*VecDense)) + } + denseComparison := func(receiver, a, b *Dense) { + var sb Dense + sb.Scale(alpha, b) + receiver.Add(a, &sb) + } + testTwoInput(t, "AddScaledVec", &VecDense{}, method, denseComparison, legalTypesVecVec, legalSizeSameVec, 1e-14) + } +} + +func TestVecDenseAdd(t *testing.T) { + for i, test := range []struct { + a, b *VecDense + want *VecDense + }{ + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewVecDense(3, []float64{0, 2, 3}), + want: NewVecDense(3, []float64{0, 3, 5}), + }, + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVecDense(3, []float64{0, 3, 5}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVecDense(3, []float64{0, 3, 5}), + }, + } { + var v VecDense + v.AddVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVecDenseSub(t *testing.T) { + for i, test := range []struct { + a, b *VecDense + want *VecDense + }{ + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewVecDense(3, []float64{0, 0.5, 1}), + want: NewVecDense(3, []float64{0, 0.5, 1}), + }, + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 0.5, 1}).ColView(0), + want: NewVecDense(3, []float64{0, 0.5, 1}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 0.5, 1}).ColView(0), + want: NewVecDense(3, []float64{0, 0.5, 1}), + }, + } { + var v VecDense + v.SubVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVecDenseMulElem(t *testing.T) { + for i, test := range []struct { + a, b *VecDense + want *VecDense + }{ + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewVecDense(3, []float64{0, 2, 3}), + want: NewVecDense(3, []float64{0, 2, 6}), + }, + { + a: NewVecDense(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVecDense(3, []float64{0, 2, 6}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVecDense(3, []float64{0, 2, 6}), + }, + } { + var v VecDense + v.MulElemVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVecDenseDivElem(t *testing.T) { + for i, test := range []struct { + a, b *VecDense + want *VecDense + }{ + { + a: NewVecDense(3, []float64{0.5, 1, 2}), + b: NewVecDense(3, []float64{0.5, 0.5, 1}), + want: NewVecDense(3, []float64{1, 2, 2}), + }, + { + a: NewVecDense(3, []float64{0.5, 1, 2}), + b: NewDense(3, 1, []float64{0.5, 0.5, 1}).ColView(0), + want: NewVecDense(3, []float64{1, 2, 2}), + }, + { + a: NewDense(3, 1, []float64{0.5, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0.5, 0.5, 1}).ColView(0), + want: NewVecDense(3, []float64{1, 2, 2}), + }, + } { + var v VecDense + v.DivElemVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func BenchmarkAddScaledVec10Inc1(b *testing.B) { addScaledVecBench(b, 10, 1) } +func BenchmarkAddScaledVec100Inc1(b *testing.B) { addScaledVecBench(b, 100, 1) } +func BenchmarkAddScaledVec1000Inc1(b *testing.B) { addScaledVecBench(b, 1000, 1) } +func BenchmarkAddScaledVec10000Inc1(b *testing.B) { addScaledVecBench(b, 10000, 1) } +func BenchmarkAddScaledVec100000Inc1(b *testing.B) { addScaledVecBench(b, 100000, 1) } +func BenchmarkAddScaledVec10Inc2(b *testing.B) { addScaledVecBench(b, 10, 2) } +func BenchmarkAddScaledVec100Inc2(b *testing.B) { addScaledVecBench(b, 100, 2) } +func BenchmarkAddScaledVec1000Inc2(b *testing.B) { addScaledVecBench(b, 1000, 2) } +func BenchmarkAddScaledVec10000Inc2(b *testing.B) { addScaledVecBench(b, 10000, 2) } +func BenchmarkAddScaledVec100000Inc2(b *testing.B) { addScaledVecBench(b, 100000, 2) } +func BenchmarkAddScaledVec10Inc20(b *testing.B) { addScaledVecBench(b, 10, 20) } +func BenchmarkAddScaledVec100Inc20(b *testing.B) { addScaledVecBench(b, 100, 20) } +func BenchmarkAddScaledVec1000Inc20(b *testing.B) { addScaledVecBench(b, 1000, 20) } +func BenchmarkAddScaledVec10000Inc20(b *testing.B) { addScaledVecBench(b, 10000, 20) } +func BenchmarkAddScaledVec100000Inc20(b *testing.B) { addScaledVecBench(b, 100000, 20) } +func addScaledVecBench(b *testing.B, size, inc int) { + x := randVecDense(size, inc, 1, rand.NormFloat64) + y := randVecDense(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v VecDense + for i := 0; i < b.N; i++ { + v.AddScaledVec(y, 2, x) + } +} + +func BenchmarkScaleVec10Inc1(b *testing.B) { scaleVecBench(b, 10, 1) } +func BenchmarkScaleVec100Inc1(b *testing.B) { scaleVecBench(b, 100, 1) } +func BenchmarkScaleVec1000Inc1(b *testing.B) { scaleVecBench(b, 1000, 1) } +func BenchmarkScaleVec10000Inc1(b *testing.B) { scaleVecBench(b, 10000, 1) } +func BenchmarkScaleVec100000Inc1(b *testing.B) { scaleVecBench(b, 100000, 1) } +func BenchmarkScaleVec10Inc2(b *testing.B) { scaleVecBench(b, 10, 2) } +func BenchmarkScaleVec100Inc2(b *testing.B) { scaleVecBench(b, 100, 2) } +func BenchmarkScaleVec1000Inc2(b *testing.B) { scaleVecBench(b, 1000, 2) } +func BenchmarkScaleVec10000Inc2(b *testing.B) { scaleVecBench(b, 10000, 2) } +func BenchmarkScaleVec100000Inc2(b *testing.B) { scaleVecBench(b, 100000, 2) } +func BenchmarkScaleVec10Inc20(b *testing.B) { scaleVecBench(b, 10, 20) } +func BenchmarkScaleVec100Inc20(b *testing.B) { scaleVecBench(b, 100, 20) } +func BenchmarkScaleVec1000Inc20(b *testing.B) { scaleVecBench(b, 1000, 20) } +func BenchmarkScaleVec10000Inc20(b *testing.B) { scaleVecBench(b, 10000, 20) } +func BenchmarkScaleVec100000Inc20(b *testing.B) { scaleVecBench(b, 100000, 20) } +func scaleVecBench(b *testing.B, size, inc int) { + x := randVecDense(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v VecDense + for i := 0; i < b.N; i++ { + v.ScaleVec(2, x) + } +} + +func BenchmarkAddVec10Inc1(b *testing.B) { addVecBench(b, 10, 1) } +func BenchmarkAddVec100Inc1(b *testing.B) { addVecBench(b, 100, 1) } +func BenchmarkAddVec1000Inc1(b *testing.B) { addVecBench(b, 1000, 1) } +func BenchmarkAddVec10000Inc1(b *testing.B) { addVecBench(b, 10000, 1) } +func BenchmarkAddVec100000Inc1(b *testing.B) { addVecBench(b, 100000, 1) } +func BenchmarkAddVec10Inc2(b *testing.B) { addVecBench(b, 10, 2) } +func BenchmarkAddVec100Inc2(b *testing.B) { addVecBench(b, 100, 2) } +func BenchmarkAddVec1000Inc2(b *testing.B) { addVecBench(b, 1000, 2) } +func BenchmarkAddVec10000Inc2(b *testing.B) { addVecBench(b, 10000, 2) } +func BenchmarkAddVec100000Inc2(b *testing.B) { addVecBench(b, 100000, 2) } +func BenchmarkAddVec10Inc20(b *testing.B) { addVecBench(b, 10, 20) } +func BenchmarkAddVec100Inc20(b *testing.B) { addVecBench(b, 100, 20) } +func BenchmarkAddVec1000Inc20(b *testing.B) { addVecBench(b, 1000, 20) } +func BenchmarkAddVec10000Inc20(b *testing.B) { addVecBench(b, 10000, 20) } +func BenchmarkAddVec100000Inc20(b *testing.B) { addVecBench(b, 100000, 20) } +func addVecBench(b *testing.B, size, inc int) { + x := randVecDense(size, inc, 1, rand.NormFloat64) + y := randVecDense(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v VecDense + for i := 0; i < b.N; i++ { + v.AddVec(x, y) + } +} + +func BenchmarkSubVec10Inc1(b *testing.B) { subVecBench(b, 10, 1) } +func BenchmarkSubVec100Inc1(b *testing.B) { subVecBench(b, 100, 1) } +func BenchmarkSubVec1000Inc1(b *testing.B) { subVecBench(b, 1000, 1) } +func BenchmarkSubVec10000Inc1(b *testing.B) { subVecBench(b, 10000, 1) } +func BenchmarkSubVec100000Inc1(b *testing.B) { subVecBench(b, 100000, 1) } +func BenchmarkSubVec10Inc2(b *testing.B) { subVecBench(b, 10, 2) } +func BenchmarkSubVec100Inc2(b *testing.B) { subVecBench(b, 100, 2) } +func BenchmarkSubVec1000Inc2(b *testing.B) { subVecBench(b, 1000, 2) } +func BenchmarkSubVec10000Inc2(b *testing.B) { subVecBench(b, 10000, 2) } +func BenchmarkSubVec100000Inc2(b *testing.B) { subVecBench(b, 100000, 2) } +func BenchmarkSubVec10Inc20(b *testing.B) { subVecBench(b, 10, 20) } +func BenchmarkSubVec100Inc20(b *testing.B) { subVecBench(b, 100, 20) } +func BenchmarkSubVec1000Inc20(b *testing.B) { subVecBench(b, 1000, 20) } +func BenchmarkSubVec10000Inc20(b *testing.B) { subVecBench(b, 10000, 20) } +func BenchmarkSubVec100000Inc20(b *testing.B) { subVecBench(b, 100000, 20) } +func subVecBench(b *testing.B, size, inc int) { + x := randVecDense(size, inc, 1, rand.NormFloat64) + y := randVecDense(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v VecDense + for i := 0; i < b.N; i++ { + v.SubVec(x, y) + } +} + +func randVecDense(size, inc int, rho float64, rnd func() float64) *VecDense { + if size <= 0 { + panic("bad vector size") + } + data := make([]float64, size*inc) + for i := range data { + if rand.Float64() < rho { + data[i] = rnd() + } + } + return &VecDense{ + mat: blas64.Vector{ + Inc: inc, + Data: data, + }, + n: size, + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/README.md b/vendor/gonum.org/v1/gonum/mathext/README.md new file mode 100644 index 00000000..b3bc6442 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/README.md @@ -0,0 +1,3 @@ +# mathext [![GoDoc](https://godoc.org/gonum.org/v1/gonum/mathext?status.svg)](https://godoc.org/gonum.org/v1/gonum/mathext) + +Package mathext implements basic elementary functions not included in the Go standard library. diff --git a/vendor/gonum.org/v1/gonum/mathext/airy.go b/vendor/gonum.org/v1/gonum/mathext/airy.go new file mode 100644 index 00000000..1022e938 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/airy.go @@ -0,0 +1,37 @@ +// Copyright ©2016 The gonum 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 mathext + +import "gonum.org/v1/gonum/mathext/internal/amos" + +// AiryAi returns the value of the Airy function at z. The Airy function here, +// Ai(z), is one of the two linearly independent solutions to +// y'' - y*z = 0. +// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. +func AiryAi(z complex128) complex128 { + // id specifies the order of the derivative to compute, + // 0 for the function itself and 1 for the derivative. + // kode specifies the scaling option. See the function + // documentation for the exact behavior. + id := 0 + kode := 1 + air, aii, _ := amos.Zairy(real(z), imag(z), id, kode) + return complex(air, aii) +} + +// AiryAiDeriv returns the value of the derivative of the Airy function at z. The +// Airy function here, Ai(z), is one of the two linearly independent solutions to +// y'' - y*z = 0. +// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. +func AiryAiDeriv(z complex128) complex128 { + // id specifies the order of the derivative to compute, + // 0 for the function itself and 1 for the derivative. + // kode specifies the scaling option. See the function + // documentation for the exact behavior. + id := 1 + kode := 1 + air, aii, _ := amos.Zairy(real(z), imag(z), id, kode) + return complex(air, aii) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/airy_test.go b/vendor/gonum.org/v1/gonum/mathext/airy_test.go new file mode 100644 index 00000000..4359abd5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/airy_test.go @@ -0,0 +1,28 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" + "testing" +) + +func TestAiry(t *testing.T) { + for _, test := range []struct { + z, ans complex128 + }{ + // Results computed using Octave. + {5, 1.08344428136074e-04}, + {5i, 29.9014823980070 + 21.6778315987835i}, + } { + ans := AiryAi(test.z) + if math.Abs(real(ans)-real(test.ans)) > 1e-10 { + t.Errorf("Real part mismatch. Got %v, want %v", real(ans), real(test.ans)) + } + if math.Abs(imag(ans)-imag(test.ans)) > 1e-10 { + t.Errorf("Imaginary part mismatch. Got %v, want %v", imag(ans), imag(test.ans)) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/beta.go b/vendor/gonum.org/v1/gonum/mathext/beta.go new file mode 100644 index 00000000..03f53f09 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/beta.go @@ -0,0 +1,34 @@ +// Copyright ©2016 The gonum 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 mathext + +import "gonum.org/v1/gonum/mathext/internal/gonum" + +// Beta returns the value of the complete beta function B(a, b). It is defined as +// Γ(a)Γ(b) / Γ(a+b) +// Special cases are: +// B(a,b) returns NaN if a or b is Inf +// B(a,b) returns NaN if a and b are 0 +// B(a,b) returns NaN if a or b is NaN +// B(a,b) returns NaN if a or b is < 0 +// B(a,b) returns +Inf if a xor b is 0. +// +// See http://mathworld.wolfram.com/BetaFunction.html for more detailed informations. +func Beta(a, b float64) float64 { + return gonum.Beta(a, b) +} + +// Lbeta returns the natural logarithm of the complete beta function B(a,b). +// Lbeta is defined as: +// Ln(Γ(a)Γ(b)/Γ(a+b)) +// Special cases are: +// Lbeta(a,b) returns NaN if a or b is Inf +// Lbeta(a,b) returns NaN if a and b are 0 +// Lbeta(a,b) returns NaN if a or b is NaN +// Lbeta(a,b) returns NaN if a or b is < 0 +// Lbeta(a,b) returns +Inf if a xor b is 0. +func Lbeta(a, b float64) float64 { + return gonum.Lbeta(a, b) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/beta_test.go b/vendor/gonum.org/v1/gonum/mathext/beta_test.go new file mode 100644 index 00000000..7e0cd4c8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/beta_test.go @@ -0,0 +1,177 @@ +// Copyright ©2016 The gonum 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 mathext_test + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" +) + +var betaTests = []struct { + p, q float64 + want float64 +}{ + { + p: 1, + q: 2, + want: 0.5, // obtained from scipy.special.beta(1,2) (version=0.18.0) + }, + { + p: 10, + q: 20, + want: 4.9925087406346778e-09, // obtained from scipy.special.beta(10,20) (version=0.18.0) + }, + { + p: +0, + q: 10, + want: math.Inf(+1), + }, + { + p: -0, + q: 10, + want: math.Inf(+1), + }, + { + p: 0, + q: 0, + want: math.NaN(), + }, + { + p: 0, + q: math.Inf(-1), + want: math.NaN(), + }, + { + p: 10, + q: math.Inf(-1), + want: math.NaN(), + }, + { + p: 0, + q: math.Inf(+1), + want: math.NaN(), + }, + { + p: 10, + q: math.Inf(+1), + want: math.NaN(), + }, + { + p: math.NaN(), + q: 10, + want: math.NaN(), + }, + { + p: math.NaN(), + q: 0, + want: math.NaN(), + }, + { + p: -1, + q: 0, + want: math.NaN(), + }, + { + p: -1, + q: +1, + want: math.NaN(), + }, +} + +func TestBeta(t *testing.T) { + for i, test := range betaTests { + v := mathext.Beta(test.p, test.q) + testOK := func(x float64) bool { + return floats.EqualWithinAbsOrRel(x, test.want, 1e-15, 1e-15) || (math.IsNaN(test.want) && math.IsNaN(x)) + } + if !testOK(v) { + t.Errorf("test #%d: Beta(%v, %v)=%v. want=%v\n", + i, test.p, test.q, v, test.want, + ) + } + + u := mathext.Beta(test.q, test.p) + if !testOK(u) { + t.Errorf("test #%[1]d: Beta(%[2]v, %[3]v)=%[4]v != Beta(%[3]v, %[2]v)=%[5]v)\n", + i, test.p, test.q, v, u, + ) + } + + if math.IsInf(v, +1) || math.IsNaN(v) { + continue + } + + vv := mathext.Beta(test.p, test.q+1) + uu := mathext.Beta(test.p+1, test.q) + if !floats.EqualWithinAbsOrRel(v, vv+uu, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Beta(%[2]v, %[3]v)=%[4]v != Beta(%[2]v+1, %[3]v) + Beta(%[2]v, %[3]v+1) (=%[5]v + %[6]v = %[7]v)\n", + i, test.p, test.q, v, uu, vv, uu+vv, + ) + } + + vbeta2 := beta2(test.p, test.q) + if !floats.EqualWithinAbsOrRel(v, vbeta2, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Beta(%[2]v, %[3]v) != Γ(p)Γ(q) / Γ(p+q) (v=%[4]v u=%[5]v)\n", + i, test.p, test.q, v, vbeta2, + ) + } + } +} + +func beta2(x, y float64) float64 { + return math.Gamma(x) * math.Gamma(y) / math.Gamma(x+y) +} + +func BenchmarkBeta(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = mathext.Beta(10, 20) + } +} + +func BenchmarkBeta2(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = math.Gamma(10) * math.Gamma(20) / math.Gamma(10+20) + } +} + +func TestLbeta(t *testing.T) { + for i, test := range betaTests { + want := math.Log(test.want) + v := mathext.Lbeta(test.p, test.q) + + testOK := func(x float64) bool { + return floats.EqualWithinAbsOrRel(x, want, 1e-15, 1e-15) || (math.IsNaN(want) && math.IsNaN(x)) + } + if !testOK(v) { + t.Errorf("test #%d: Lbeta(%v, %v)=%v. want=%v\n", + i, test.p, test.q, v, want, + ) + } + + u := mathext.Lbeta(test.q, test.p) + if !testOK(u) { + t.Errorf("test #%[1]d: Lbeta(%[2]v, %[3]v)=%[4]v != Lbeta(%[3]v, %[2]v)=%[5]v)\n", + i, test.p, test.q, v, u, + ) + } + + if math.IsInf(v, +1) || math.IsNaN(v) { + continue + } + + vbeta2 := math.Log(beta2(test.p, test.q)) + if !floats.EqualWithinAbsOrRel(v, vbeta2, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Lbeta(%[2]v, %[3]v) != Log(Γ(p)Γ(q) / Γ(p+q)) (v=%[4]v u=%[5]v)\n", + i, test.p, test.q, v, vbeta2, + ) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/betainc.go b/vendor/gonum.org/v1/gonum/mathext/betainc.go new file mode 100644 index 00000000..77791ce9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/betainc.go @@ -0,0 +1,29 @@ +// Copyright ©2016 The gonum 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 mathext + +import "gonum.org/v1/gonum/mathext/internal/cephes" + +// RegIncBeta returns the value of the regularized incomplete beta function +// I(x;a,b). It is defined as +// I(x;a,b) = B(x;a,b) / B(a,b) +// = Γ(a+b) / (Γ(a)*Γ(b)) * int_0^x u^(a-1) * (1-u)^(b-1) du. +// The domain of definition is 0 <= x <= 1, and the parameters a and b must be positive. +// For other values of x, a, and b RegIncBeta will panic. +func RegIncBeta(a, b float64, x float64) float64 { + return cephes.Incbet(a, b, x) +} + +// InvRegIncBeta computes the inverse of the regularized incomplete beta function. +// It returns the x for which +// y = I(x;a,b) +// The domain of definition is 0 <= y <= 1, and the parameters a and b must be +// positive. For other values of x, a, and b InvRegIncBeta will panic. +func InvRegIncBeta(a, b float64, y float64) float64 { + if y < 0 || y > 1 { + panic("mathext: parameter out of range") + } + return cephes.Incbi(a, b, y) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/betainc_test.go b/vendor/gonum.org/v1/gonum/mathext/betainc_test.go new file mode 100644 index 00000000..f1e0c950 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/betainc_test.go @@ -0,0 +1,75 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestIncBeta(t *testing.T) { + tol := 1e-14 + tol2 := 1e-10 + // Test against values from scipy + for i, test := range []struct { + a, b, x, ans float64 + }{ + {1, 1, 0.8, 0.8}, + {1, 5, 0.8, 0.99968000000000001}, + {10, 10, 0.8, 0.99842087945083291}, + {10, 10, 0.1, 3.929882327128003e-06}, + {10, 2, 0.4, 0.00073400320000000028}, + {0.1, 0.2, 0.6, 0.69285678232066683}, + {1, 10, 0.7489, 0.99999900352334858}, + } { + y := RegIncBeta(test.a, test.b, test.x) + if !floats.EqualWithinAbsOrRel(y, test.ans, tol, tol) { + t.Errorf("Incomplete beta mismatch. Case %v: Got %v, want %v", i, y, test.ans) + } + + yc := 1 - RegIncBeta(test.b, test.a, 1-test.x) + if !floats.EqualWithinAbsOrRel(y, yc, tol, tol) { + t.Errorf("Incomplete beta complementary mismatch. Case %v: Got %v, want %v", i, y, yc) + } + + x := InvRegIncBeta(test.a, test.b, y) + if !floats.EqualWithinAbsOrRel(x, test.x, tol2, tol2) { + t.Errorf("Inverse incomplete beta mismatch. Case %v: Got %v, want %v", i, x, test.x) + } + } + + // Confirm that Invincbeta and Incbeta agree. Sweep over a variety of + // a, b, and y values. + tol = 1e-6 + steps := 201 + ints := make([]float64, steps) + floats.Span(ints, 0, 1) + + sz := 51 + min := 1e-2 + max := 1e2 + as := make([]float64, sz) + floats.LogSpan(as, min, max) + bs := make([]float64, sz) + floats.LogSpan(bs, min, max) + + for _, a := range as { + for _, b := range bs { + for _, yr := range ints { + x := InvRegIncBeta(a, b, yr) + if x > 1-1e-6 { + // Numerical error too large + continue + } + y := RegIncBeta(a, b, x) + if !floats.EqualWithinAbsOrRel(yr, y, tol, tol) { + t.Errorf("Mismatch between inv inc beta and inc beta. a = %v, b = %v, x = %v, got %v, want %v.", a, b, x, y, yr) + break + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/digamma.go b/vendor/gonum.org/v1/gonum/mathext/digamma.go new file mode 100644 index 00000000..81132dd1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/digamma.go @@ -0,0 +1,28 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" +) + +// Digamma returns the logorithmic derivative of the gamma function at x. +// ψ(x) = d/dx (Ln (Γ(x)). +// Note that if x is a negative integer in [-7, 0] this function will return +// negative Inf. +func Digamma(x float64) float64 { + // This is adapted from + // http://web.science.mq.edu.au/~mjohnson/code/digamma.c + var result float64 + for ; x < 7.0; x++ { + result -= 1 / x + } + x -= 1.0 / 2.0 + xx := 1.0 / x + xx2 := xx * xx + xx4 := xx2 * xx2 + result += math.Log(x) + (1./24.)*xx2 - (7.0/960.0)*xx4 + (31.0/8064.0)*xx4*xx2 - (127.0/30720.0)*xx4*xx4 + return result +} diff --git a/vendor/gonum.org/v1/gonum/mathext/digamma_test.go b/vendor/gonum.org/v1/gonum/mathext/digamma_test.go new file mode 100644 index 00000000..0e113ed1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/digamma_test.go @@ -0,0 +1,27 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" + "testing" +) + +func TestDigamma(t *testing.T) { + for i, test := range []struct { + x, want float64 + }{ + // Results computed using WolframAlpha. + {-100.5, 4.615124601338064117341315601525112558522917517910505881343}, + {.5, -1.96351002602142347944097633299875556719315960466043}, + {10, 2.251752589066721107647456163885851537211808918028330369448}, + {math.Pow10(20), 46.05170185988091368035482909368728415202202143924212618733}, + } { + + if got := Digamma(test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d Digamma(%g) failed: got %g want %g", i, test.x, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/doc.go b/vendor/gonum.org/v1/gonum/mathext/doc.go new file mode 100644 index 00000000..b1c350ee --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 mathext implements special math functions not implemented by the +// Go standard library. +package mathext // import "gonum.org/v1/gonum/mathext" diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go b/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go new file mode 100644 index 00000000..159f0a9e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go @@ -0,0 +1,156 @@ +// Copyright ©2017 The gonum 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 mathext + +import ( + "math" +) + +// EllipticRF computes the symmetric elliptic integral R_F(x,y,z): +// R_F(x,y,z) = (1/2)\int_{0}^{\infty}{1/s(t)} dt, +// s(t) = \sqrt{(t+x)(t+y)(t+z)}. +// +// The arguments x, y, z must satisfy the following conditions, otherwise the function returns math.NaN(): +// 0 ≤ x,y,z ≤ upper, +// lower ≤ x+y,y+z,z+x, +// where: +// lower = 5/(2^1022) = 1.112536929253601e-307, +// upper = (2^1022)/5 = 8.988465674311580e+306. +// +// The definition of the symmetric elliptic integral R_F can be found in NIST +// Digital Library of Mathematical Functions (http://dlmf.nist.gov/19.16.E1). +func EllipticRF(x, y, z float64) float64 { + // The original Fortran code was published as Algorithm 577 in ACM TOMS (http://doi.org/10.1145/355958.355970). + // This code is also available as a part of SLATEC Common Mathematical Library (http://netlib.org/slatec/index.html). Later, Carlson described + // an improved version in http://dx.doi.org/10.1007/BF02198293 (also available at https://arxiv.org/abs/math/9409227). + const ( + lower = 5.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) // 5*2^-1022 + upper = 1 / lower + tol = 1.2674918778210762260320167734407048051023273568443e-02 // (3ε)^(1/8) + ) + if x < 0 || y < 0 || z < 0 || math.IsNaN(x) || math.IsNaN(y) || math.IsNaN(z) { + return math.NaN() + } + if upper < x || upper < y || upper < z { + return math.NaN() + } + if x+y < lower || y+z < lower || z+x < lower { + return math.NaN() + } + + A0 := (x + y + z) / 3 + An := A0 + Q := math.Max(math.Max(math.Abs(A0-x), math.Abs(A0-y)), math.Abs(A0-z)) / tol + xn, yn, zn := x, y, z + mul := 1.0 + + for Q >= mul*math.Abs(An) { + xnsqrt, ynsqrt, znsqrt := math.Sqrt(xn), math.Sqrt(yn), math.Sqrt(zn) + lambda := xnsqrt*ynsqrt + ynsqrt*znsqrt + znsqrt*xnsqrt + An = (An + lambda) * 0.25 + xn = (xn + lambda) * 0.25 + yn = (yn + lambda) * 0.25 + zn = (zn + lambda) * 0.25 + mul *= 4 + } + + X := (A0 - x) / (mul * An) + Y := (A0 - y) / (mul * An) + Z := -(X + Y) + E2 := X*Y - Z*Z + E3 := X * Y * Z + + // http://dlmf.nist.gov/19.36.E1 + return (1 - 1/10.0*E2 + 1/14.0*E3 + 1/24.0*E2*E2 - 3/44.0*E2*E3 - 5/208.0*E2*E2*E2 + 3/104.0*E3*E3 + 1/16.0*E2*E2*E3) / math.Sqrt(An) +} + +// EllipticRD computes the symmetric elliptic integral R_D(x,y,z): +// R_D(x,y,z) = (1/2)\int_{0}^{\infty}{1/(s(t)(t+z))} dt, +// s(t) = \sqrt{(t+x)(t+y)(t+z)}. +// +// The arguments x, y, z must satisfy the following conditions, otherwise the function returns math.NaN(): +// 0 ≤ x,y ≤ upper, +// lower ≤ z ≤ upper, +// lower ≤ x+y, +// where: +// lower = (5/(2^1022))^(1/3) = 4.809554074311679e-103, +// upper = ((2^1022)/5)^(1/3) = 2.079194837087086e+102. +// +// The definition of the symmetric elliptic integral R_D can be found in NIST +// Digital Library of Mathematical Functions (http://dlmf.nist.gov/19.16.E5). +func EllipticRD(x, y, z float64) float64 { + // The original Fortran code was published as Algorithm 577 in ACM TOMS (http://doi.org/10.1145/355958.355970). + // This code is also available as a part of SLATEC Common Mathematical Library (http://netlib.org/slatec/index.html). Later, Carlson described + // an improved version in http://dx.doi.org/10.1007/BF02198293 (also available at https://arxiv.org/abs/math/9409227). + const ( + lower = 4.8095540743116787026618007863123676393525016818363e-103 // (5*2^-1022)^(1/3) + upper = 1 / lower + tol = 9.0351169339315770474760122547068324993857488849382e-03 // (ε/5)^(1/8) + ) + if x < 0 || y < 0 || math.IsNaN(x) || math.IsNaN(y) || math.IsNaN(z) { + return math.NaN() + } + if upper < x || upper < y || upper < z { + return math.NaN() + } + if x+y < lower || z < lower { + return math.NaN() + } + + A0 := (x + y + 3*z) / 5 + An := A0 + Q := math.Max(math.Max(math.Abs(A0-x), math.Abs(A0-y)), math.Abs(A0-z)) / tol + xn, yn, zn := x, y, z + mul, s := 1.0, 0.0 + + for Q >= mul*math.Abs(An) { + xnsqrt, ynsqrt, znsqrt := math.Sqrt(xn), math.Sqrt(yn), math.Sqrt(zn) + lambda := xnsqrt*ynsqrt + ynsqrt*znsqrt + znsqrt*xnsqrt + s += 1 / (mul * znsqrt * (zn + lambda)) + An = (An + lambda) * 0.25 + xn = (xn + lambda) * 0.25 + yn = (yn + lambda) * 0.25 + zn = (zn + lambda) * 0.25 + mul *= 4 + } + + X := (A0 - x) / (mul * An) + Y := (A0 - y) / (mul * An) + Z := -(X + Y) / 3 + E2 := X*Y - 6*Z*Z + E3 := (3*X*Y - 8*Z*Z) * Z + E4 := 3 * (X*Y - Z*Z) * Z * Z + E5 := X * Y * Z * Z * Z + + // http://dlmf.nist.gov/19.36.E2 + return (1-3/14.0*E2+1/6.0*E3+9/88.0*E2*E2-3/22.0*E4-9/52.0*E2*E3+3/26.0*E5-1/16.0*E2*E2*E2+3/40.0*E3*E3+3/20.0*E2*E4+45/272.0*E2*E2*E3-9/68.0*(E3*E4+E2*E5))/(mul*An*math.Sqrt(An)) + 3*s +} + +// EllipticF computes the Legendre's elliptic integral of the 1st kind F(phi,m), 0≤m<1: +// F(\phi,m) = \int_{0}^{\phi} 1 / \sqrt{1-m\sin^2(\theta)} d\theta +// +// Legendre's elliptic integrals can be expressed as symmetric elliptic integrals, in this case: +// F(\phi,m) = \sin\phi R_F(\cos^2\phi,1-m\sin^2\phi,1) +// +// The definition of F(phi,k) where k=sqrt(m) can be found in NIST Digital Library of Mathematical +// Functions (http://dlmf.nist.gov/19.2.E4). +func EllipticF(phi, m float64) float64 { + s, c := math.Sincos(phi) + return s * EllipticRF(c*c, 1-m*s*s, 1) +} + +// EllipticE computes the Legendre's elliptic integral of the 2nd kind E(phi,m), 0≤m<1: +// E(\phi,m) = \int_{0}^{\phi} \sqrt{1-m\sin^2(\theta)} d\theta +// +// Legendre's elliptic integrals can be expressed as symmetric elliptic integrals, in this case: +// E(\phi,m) = \sin\phi R_F(\cos^2\phi,1-m\sin^2\phi,1)-(m/3)\sin^3\phi R_D(\cos^2\phi,1-m\sin^2\phi,1) +// +// The definition of E(phi,k) where k=sqrt(m) can be found in NIST Digital Library of Mathematical +// Functions (http://dlmf.nist.gov/19.2.E5). +func EllipticE(phi, m float64) float64 { + s, c := math.Sincos(phi) + x, y := c*c, 1-m*s*s + return s * (EllipticRF(x, y, 1) - (m/3)*s*s*EllipticRD(x, y, 1)) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_carlson_test.go b/vendor/gonum.org/v1/gonum/mathext/ell_carlson_test.go new file mode 100644 index 00000000..4018bc1c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/ell_carlson_test.go @@ -0,0 +1,103 @@ +// Copyright ©2017 The gonum 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 mathext + +import ( + "math" + "math/rand" + "testing" +) + +// Testing EllipticF (and EllipticRF) using the addition theorems from http://dlmf.nist.gov/19.11.i +func TestEllipticF(t *testing.T) { + const tol = 1.0e-14 + rnd := rand.New(rand.NewSource(1)) + + // The following EllipticF(pi/3,m), m=0.1(0.1)0.9 was computed in Maxima 5.38.0 using Bigfloat arithmetic. + vF := [...]float64{ + 1.0631390181954904767742338285104637431858016483079, + 1.0803778062523490005579242592072579594037132891908, + 1.0991352230920430074586978843452269008747645822123, + 1.1196949183404746257742176145632376703505764745654, + 1.1424290580457772555013955266260457822322036529624, + 1.1678400583161860445148860686430780757517286094732, + 1.1966306515644649360767197589467723191317720122309, + 1.2298294422249382706933871574135731278765534034979, + 1.2690359140762658660446752406901433173504503955036, + } + phi := math.Pi / 3 + for m := 1; m <= 9; m++ { + mf := float64(m) / 10 + delta := math.Abs(EllipticF(phi, mf) - vF[m-1]) + if delta > tol { + t.Fatalf("EllipticF(pi/3,m) test fail for m=%v", mf) + } + } + + for test := 0; test < 100; test++ { + alpha := rnd.Float64() * math.Pi / 4 + beta := rnd.Float64() * math.Pi / 4 + for mi := 0; mi < 9999; mi++ { + m := float64(mi) / 10000 + Fa := EllipticF(alpha, m) + Fb := EllipticF(beta, m) + sina, cosa := math.Sincos(alpha) + sinb, cosb := math.Sincos(beta) + tan := (sina*math.Sqrt(1-m*sinb*sinb) + sinb*math.Sqrt(1-m*sina*sina)) / (cosa + cosb) + gamma := 2 * math.Atan(tan) + Fg := EllipticF(gamma, m) + delta := math.Abs(Fa + Fb - Fg) + if delta > tol { + t.Fatalf("EllipticF test fail for m=%v, alpha=%v, beta=%v", m, alpha, beta) + } + } + } +} + +// Testing EllipticE (and EllipticRF, EllipticRD) using the addition theorems from http://dlmf.nist.gov/19.11.i +func TestEllipticE(t *testing.T) { + const tol = 1.0e-14 + rnd := rand.New(rand.NewSource(1)) + + // The following EllipticE(pi/3,m), m=0.1(0.1)0.9 was computed in Maxima 5.38.0 using Bigfloat arithmetic. + vE := [...]float64{ + 1.0316510822817691068014397636905610074934300946730, + 1.0156973658341766636288643556414001451527597364432, + 9.9929636467826398814855428365155224243586391115108e-1, + 9.8240033979859736941287149003648737502960015189033e-1, + 9.6495145764299257550956863602992167490195750321518e-1, + 9.4687829659158090935158610908054896203271861698355e-1, + 9.2809053417715769009517654522979827392794124845027e-1, + 9.0847044378047233264777277954768245721857017157916e-1, + 8.8785835036531301307661603341327881634688308777383e-1, + } + phi := math.Pi / 3 + for m := 1; m <= 9; m++ { + mf := float64(m) / 10 + delta := math.Abs(EllipticE(phi, mf) - vE[m-1]) + if delta > tol { + t.Fatalf("EllipticE(pi/3,m) test fail for m=%v", mf) + } + } + + for test := 0; test < 100; test++ { + alpha := rnd.Float64() * math.Pi / 4 + beta := rnd.Float64() * math.Pi / 4 + for mi := 0; mi < 9999; mi++ { + m := float64(mi) / 10000 + Ea := EllipticE(alpha, m) + Eb := EllipticE(beta, m) + sina, cosa := math.Sincos(alpha) + sinb, cosb := math.Sincos(beta) + tan := (sina*math.Sqrt(1-m*sinb*sinb) + sinb*math.Sqrt(1-m*sina*sina)) / (cosa + cosb) + gamma := 2 * math.Atan(tan) + Eg := EllipticE(gamma, m) + delta := math.Abs(Ea + Eb - Eg - m*sina*sinb*math.Sin(gamma)) + if delta > tol { + t.Fatalf("EllipticE test fail for m=%v, alpha=%v, beta=%v", m, alpha, beta) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_complete.go b/vendor/gonum.org/v1/gonum/mathext/ell_complete.go new file mode 100644 index 00000000..08586ec0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/ell_complete.go @@ -0,0 +1,157 @@ +// Copyright ©2017 The gonum 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 mathext + +import ( + "math" +) + +// CompleteK computes the complete elliptic integral of the 1st kind, 0≤m≤1. +// It returns math.NaN() if m is not in [0,1]. +// +// K(m) = \int_{0}^{\pi/2} 1 / {\sqrt{1-m{\sin^2\theta}}} d\theta +// +// See: http://dx.doi.org/10.1016/j.cam.2014.12.038 for the computation method. +func CompleteK(m float64) float64 { + if m < 0 || 1 < m || math.IsNaN(m) { + return math.NaN() + } + + mc := 1 - m + + if mc > 0.592990 { + t := 2.45694208987494165*mc - 1.45694208987494165 + p := 3703.75266375099019 + t*(5462.47093231923466+t*(2744.82029097576810+t*(543.839017382099411+t*(36.2381612593459565+t*0.393188651542789784)))) + q := 2077.94377067058435 + t*(3398.00069767755460+t*(1959.05960044399275+t*(472.794455487539279+t*(43.5464368440078942+t)))) + return p / q + } + if mc > 0.350756 { + t := 4.12823963605439369*mc - 1.44800482178389491 + p := 4264.28203103974630 + t*(6341.90978213264024+t*(3214.59187442783167+t*(642.790566685354573+t*(43.2589626155454993+t*0.475223892294445943)))) + q := 2125.06914237062279 + t*(3479.95663350926514+t*(2006.03187933518870+t*(482.900172581418890+t*(44.1848041560412224+t)))) + return p / q + } + if mc > 0.206924 { + t := 6.95255575949719117*mc - 1.43865064797819679 + p := 4870.25402224986382 + t*(7307.18826377416591+t*(3738.29369283392307+t*(754.928587580583704+t*(51.3609902253065926+t*0.571948962277566451)))) + q := 2172.51745704102287 + t*(3565.04737778032566+t*(2056.13612019430497+t*(493.962405117599400+t*(44.9026847057686146+t)))) + return p / q + } + if mc > 0.121734 { + t := 11.7384669562155183*mc - 1.42897053644793990 + p := 5514.8512729127464 + t*(8350.4595896779631+t*(4313.60788246750934+t*(880.27903031894216+t*(60.598720224393536+t*0.68504458747933773)))) + q := 2218.41682813309737 + t*(3650.41829123846319+t*(2107.97379949034285+t*(505.74295207655096+t*(45.6911096775045314+t)))) + return p / q + } + if mc > 0.071412 { + t := 19.8720241643813839*mc - 1.41910098962680339 + p := 6188.8743957372448 + t*(9459.3331440432847+t*(4935.41351498551527+t*(1018.21910476032105+t*(70.981049144472361+t*0.81599895108245948)))) + q := 2260.73112539748448 + t*(3732.66955095581621+t*(2159.68721749761492+t*(517.86964191812384+t*(46.5298955058476510+t)))) + return p / q + } + if mc > 0.041770 { + t := 33.7359152553808785*mc - 1.40914918021725929 + p := 6879.5170681289562 + t*(10615.0836403687221+t*(5594.8381504799829+t*(1167.26108955935542+t*(82.452856129147838+t*0.96592719058503951)))) + q := 2296.88303450660439 + t*(3807.37745652028212+t*(2208.74949754945558+t*(529.79651353072921+t*(47.3844470709989137+t)))) + return p / q + } + if mc > 0.024360 { + t := 57.4382538770821367*mc - 1.39919586444572085 + p := 7570.6827538712100 + t*(11792.9392624454532+t*(6279.2661370014890+t*(1325.01058966228180+t*(94.886883830605940+t*1.13537029594409690)))) + q := 2324.04824540459984 + t*(3869.56755306385732+t*(2252.22250562615338+t*(540.85752251676412+t*(48.2089280211559345+t)))) + return p / q + } + if mc > 0.014165 { + t := 98.0872976949485042*mc - 1.38940657184894556 + p := 8247.2601660137746 + t*(12967.7060124572914+t*(6974.7495213178613+t*(1488.54008220335966+t*(108.098282908839979+t*1.32411616748380686)))) + q := 2340.47337508405427 + t*(3915.63324533769906+t*(2287.70677154700516+t*(550.45072377717361+t*(48.9575432570382154+t)))) + return p / q + } + if mc > 0.008213 { + t := 168.010752688172043*mc - 1.37987231182795699 + p := 8894.2961573611293 + t*(14113.7038749808951+t*(7666.5611739483371+t*(1654.60731579994159+t*(121.863474964652041+t*1.53112170837206117)))) + q := 2344.88618943372377 + t*(3942.81065054556536+t*(2313.28396270968662+t*(558.07615380622169+t*(49.5906602613891184+t)))) + return p / q + } + if mc > 0 { + t := 1.0 - 121.758188238159016*mc + p := -math.Log(mc*0.0625) * (34813.4518336350547 + t*(235.767716637974271+t*0.199792723884069485)) / (69483.5736412906324 + t*(614.265044703187382+t)) + q := -mc * (9382.53386835986099 + t*(51.6478985993381223+t*0.00410754154682816898)) / (37327.7262507318317 + t*(408.017247271148538+t)) + return p + q + } + + return math.Inf(1) +} + +// CompleteE computes the complete elliptic integral of the 2nd kind, 0≤m≤1. +// It returns math.NaN() if m is not in [0,1]. +// +// E(m) = \int_{0}^{\pi/2} {\sqrt{1-m{\sin^2\theta}}} d\theta +// +// See: http://dx.doi.org/10.1016/j.cam.2014.12.038 for the computation method. +func CompleteE(m float64) float64 { + if m < 0 || 1 < m || math.IsNaN(m) { + return math.NaN() + } + + mc := 1 - m + + if mc > 0.566638 { + t := 2.30753965506897236*mc - 1.30753965506897236 + p := 19702.2363352671642 + t*(31904.1559574281609+t*(18177.1879313824040+t*(4362.94760768571862+t*(409.975559128654710+t*10.3244775335024885)))) + q := 14241.2135819448616 + t*(20909.9899599927367+t*(10266.4884503526076+t*(1934.86289070792954+t*(117.162100771599098+t)))) + return p / q + } + if mc > 0.315153 { + t := 3.97638030101198879*mc - 1.25316818100483130 + p := 16317.0721393008221 + t*(26627.8852140835023+t*(15129.4009798463159+t*(3574.15857605556033+t*(326.113727011739428+t*7.93163724081373477)))) + q := 13047.1505096551210 + t*(19753.5762165922376+t*(9964.25173735060361+t*(1918.72232033637537+t*(117.670514069579649+t)))) + return p / q + } + if mc > 0.171355 { + t := 6.95419964116329852*mc - 1.19163687951153702 + p := 13577.3850240991520 + t*(22545.4744699553993+t*(12871.9137872656293+t*(3000.74575264868572+t*(263.964361648520708+t*6.08522443139677663)))) + q := 11717.3306408059832 + t*(18431.1264424290258+t*(9619.40382323874064+t*(1904.06010727307491+t*(118.690522739531267+t)))) + return p / q + } + if mc > 0.090670 { + t := 12.3938774245522712*mc - 1.12375286608415443 + p := 11307.9485341543712 + t*(19328.6173704569489+t*(11208.6068472959372+t*(2596.54874477084334+t*(219.253495956962613+t*4.66931143174036616)))) + q := 10307.6837501971393 + t*(16982.2450249024383+t*(9241.7604666150102+t*(1893.41905403040679+t*(120.498555754227847+t)))) + return p / q + } + if mc > 0.046453 { + t := 22.6157360291290680*mc - 1.05056878576113260 + p := 9383.1490856819874 + t*(16718.9730458676860+t*(9977.2498973537718+t*(2323.49987246555537+t*(188.618148076418837+t*3.59313532204509922)))) + q := 8877.1964704758383 + t*(15450.0537230364062+t*(8840.2771293410661+t*(1889.13672102820913+t*(123.422125687316355+t)))) + return p / q + } + if mc > 0.022912 { + t := 42.4790790535661187*mc - 0.973280659275306911 + p := 7719.1171817802054 + t*(14521.7363804934985+t*(9045.3996063894006+t*(2149.92068078627829+t*(169.386557799782496+t*2.78515570453129137)))) + q := 7479.7539074698012 + t*(13874.4978011497847+t*(8420.3848818926324+t*(1892.69753150329759+t*(127.802109608726363+t)))) + return p / q + } + if mc > 0.010809 { + t := 82.6241427745187144*mc - 0.893084359249772784 + p := 6261.6095608987273 + t*(12593.0874916293982+t*(8304.3265605809870+t*(2048.68391263416822+t*(159.371262600702237+t*2.18867046462858104)))) + q := 6156.4532048239501 + t*(12283.8373999680518+t*(7979.7435857665227+t*(1903.60556312663537+t*(133.911640385965187+t)))) + return p / q + } + if mc > 0.004841 { + t := 167.560321715817694*mc - 0.811159517426273458 + p := 4978.06146583586728 + t*(10831.7178150656694+t*(7664.6703673290453+t*(1995.66437151562090+t*(156.689647694892782+t*1.75859085945198570)))) + q := 4935.56743322938333 + t*(10694.5510113880077+t*(7506.8028283118051+t*(1918.38517009740321+t*(141.854303920116856+t)))) + return p / q + } + if mc > 0 { + t := 1.0 - 206.568890725056806*mc + p := -mc * math.Log(mc*0.0625) * (41566.6612602868736 + t*(154.034981522913482+t*0.0618072471798575991)) / (165964.442527585615 + t*(917.589668642251803+t)) + q := (132232.803956682877 + t*(353.375480007017643-t*1.40105837312528026)) / (132393.665743088043 + t*(192.112635228732532-t)) + return p + q + } + + return 1 +} diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_complete_test.go b/vendor/gonum.org/v1/gonum/mathext/ell_complete_test.go new file mode 100644 index 00000000..54840c58 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/ell_complete_test.go @@ -0,0 +1,27 @@ +// Copyright ©2017 The gonum 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 mathext + +import ( + "math" + "testing" +) + +// TestCompleteKE checks if the Legendre's relation for m=0.0001(0.0001)0.9999 +// is satisfied with accuracy 1e-14. +func TestCompleteKE(t *testing.T) { + const tol = 1.0e-14 + + for m := 1; m <= 9999; m++ { + mf := float64(m) / 10000 + mp := 1 - mf + K, Kp := CompleteK(mf), CompleteK(mp) + E, Ep := CompleteE(mf), CompleteE(mp) + legendre := math.Abs(E*Kp + Ep*K - K*Kp - math.Pi/2) + if legendre > tol { + t.Fatalf("legendre > tol: m=%v, legendre=%v, tol=%v", mf, legendre, tol) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/erf.go b/vendor/gonum.org/v1/gonum/mathext/erf.go new file mode 100644 index 00000000..cee4dbc2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/erf.go @@ -0,0 +1,91 @@ +// Copyright ©2017 The gonum 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 mathext + +import "math" + +/* +Copyright (c) 2012 The Probab Authors. 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 Google Inc. 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 +OWNER 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. +*/ + +// NormalQuantile computes the quantile function (inverse CDF) of the standard +// normal. NormalQuantile panics if the input p is less than 0 or greater than 1. +func NormalQuantile(p float64) float64 { + switch { + case p < 0 || 1 < p: + panic("mathext: quantile out of bounds") + case p == 1: + return math.Inf(1) + case p == 0: + return math.Inf(-1) + } + // Compute rational approximation based on the value of p. + + dp := p - 0.5 + if math.Abs(dp) <= 0.425 { + z := 0.180625 - dp*dp + z1 := ((((((zQSA[0]*z+zQSA[1])*z+zQSA[2])*z+zQSA[3])*z+zQSA[4])*z+zQSA[5])*z+zQSA[6])*z + zQSA[7] + z2 := ((((((zQSB[0]*z+zQSB[1])*z+zQSB[2])*z+zQSB[3])*z+zQSB[4])*z+zQSB[5])*z+zQSB[6])*z + zQSB[7] + return dp * z1 / z2 + } + + if p < 0.5 { + r := math.Sqrt(-math.Log(p)) + if r <= 5.0 { + z := r - 1.6 + z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] + z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] + return -z1 / z2 + } + z := r - 5 + z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] + z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] + return -z1 / z2 + } + r := math.Sqrt(-math.Log(1 - p)) + if r <= 5.0 { + z := r - 1.6 + z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] + z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] + return z1 / z2 + } + + z := r - 5 + z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] + z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] + return z1 / z2 +} + +var ( + zQSA = [...]float64{2509.0809287301226727, 33430.575583588128105, 67265.770927008700853, 45921.953931549871457, 13731.693765509461125, 1971.5909503065514427, 133.14166789178437745, 3.387132872796366608} + zQSB = [...]float64{5226.495278852854561, 28729.085735721942674, 39307.89580009271061, 21213.794301586595867, 5394.1960214247511077, 687.1870074920579083, 42.313330701600911252, 1.0} + zQIA = [...]float64{7.7454501427834140764e-4, 0.0227238449892691845833, 0.24178072517745061177, 1.27045825245236838258, 3.64784832476320460504, 5.7694972214606914055, 4.6303378461565452959, 1.42343711074968357734} + zQIB = [...]float64{1.05075007164441684324e-9, 5.475938084995344946e-4, 0.0151986665636164571966, 0.14810397642748007459, 0.68976733498510000455, 1.6763848301838038494, 2.05319162663775882187, 1.0} + zQTA = [...]float64{2.01033439929228813265e-7, 2.71155556874348757815e-5, 0.0012426609473880784386, 0.026532189526576123093, 0.29656057182850489123, 1.7848265399172913358, 5.4637849111641143699, 6.6579046435011037772} + zQTB = [...]float64{2.04426310338993978564e-15, 1.4215117583164458887e-7, 1.8463183175100546818e-5, 7.868691311456132591e-4, 0.0148753612908506148525, 0.13692988092273580531, 0.59983220655588793769, 1.0} +) diff --git a/vendor/gonum.org/v1/gonum/mathext/erf_test.go b/vendor/gonum.org/v1/gonum/mathext/erf_test.go new file mode 100644 index 00000000..f698e51e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/erf_test.go @@ -0,0 +1,69 @@ +// Copyright ©2017 The gonum 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 mathext + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestNormalQuantile(t *testing.T) { + // Values from https://www.johndcook.com/blog/normal_cdf_inverse/ + p := []float64{ + 0.0000001, + 0.00001, + 0.001, + 0.05, + 0.15, + 0.25, + 0.35, + 0.45, + 0.55, + 0.65, + 0.75, + 0.85, + 0.95, + 0.999, + 0.99999, + 0.9999999, + } + ans := []float64{ + -5.199337582187471, + -4.264890793922602, + -3.090232306167813, + -1.6448536269514729, + -1.0364333894937896, + -0.6744897501960817, + -0.38532046640756773, + -0.12566134685507402, + 0.12566134685507402, + 0.38532046640756773, + 0.6744897501960817, + 1.0364333894937896, + 1.6448536269514729, + 3.090232306167813, + 4.264890793922602, + 5.199337582187471, + } + for i, v := range p { + got := NormalQuantile(v) + if !floats.EqualWithinAbsOrRel(got, ans[i], 1e-10, 1e-10) { + t.Errorf("Quantile mismatch. Case %d, want: %v, got: %v", i, ans[i], got) + } + } +} + +var nqtmp float64 + +func BenchmarkNormalQuantile(b *testing.B) { + ps := make([]float64, 1000) // ensure there are small values + floats.Span(ps, 0, 1) + for i := 0; i < b.N; i++ { + for _, v := range ps { + nqtmp = NormalQuantile(v) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go b/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go new file mode 100644 index 00000000..db16dad9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go @@ -0,0 +1,50 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "gonum.org/v1/gonum/mathext/internal/cephes" +) + +// GammaInc computes the incomplete Gamma integral. +// GammaInc(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or GammaInc +// will panic. +// +// See http://mathworld.wolfram.com/IncompleteGammaFunction.html +// or https://en.wikipedia.org/wiki/Incomplete_gamma_function for more detailed +// information. +func GammaInc(a, x float64) float64 { + return cephes.Igam(a, x) +} + +// GammaIncComp computes the complemented incomplete Gamma integral. +// GammaIncComp(a,x) = 1 - GammaInc(a,x) +// = (1/ Γ(a)) \int_0^\infty e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or +// GammaIncComp will panic. +func GammaIncComp(a, x float64) float64 { + return cephes.IgamC(a, x) +} + +// GammaIncInv computes the inverse of the incomplete Gamma integral. That is, +// it returns the x such that: +// GammaInc(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or GammaIncInv will panic. GammaIncInv should return a positive +// number, but can return NaN if there is a failure to converge. +func GammaIncInv(a, y float64) float64 { + return gammaIncInv(a, y) +} + +// GammaIncCompInv computes the inverse of the complemented incomplete Gamma +// integral. That is, it returns the x such that: +// GammaIncComp(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or GammaIncCompInv will panic. GammaIncCompInv should return a +// positive number, but can return 0 even with non-zero y due to underflow. +func GammaIncCompInv(a, y float64) float64 { + return cephes.IgamI(a, y) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go b/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go new file mode 100644 index 00000000..650717b0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go @@ -0,0 +1,56 @@ +// Derived from SciPy's special/c_misc/gammaincinv.c +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/gammaincinv.c + +// Copyright ©2017 The gonum 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 mathext + +import ( + "math" + + "gonum.org/v1/gonum/mathext/internal/cephes" +) + +const ( + allowedATol = 1e-306 + allowedRTol = 1e-6 +) + +func gammaInc(x float64, params []float64) float64 { + return cephes.Igam(params[0], x) - params[1] +} + +// gammaIncInv is the inverse of the incomplete Gamma integral. That is, it +// returns x such that: +// Igam(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or gammaIncInv will panic. gammaIncInv should return a +// positive number, but can return NaN if there is a failure to converge. +func gammaIncInv(a, y float64) float64 { + // For y not small, we just use + // IgamI(a, 1-y) + // (inverse of the complemented incomplete Gamma integral). For y small, + // however, 1-y is about 1, and we lose digits. + if a <= 0 || y <= 0 || y >= 0.25 { + return cephes.IgamI(a, 1-y) + } + + lo := 0.0 + flo := -y + hi := cephes.IgamI(a, 0.75) + fhi := 0.25 - y + + params := []float64{a, y} + + // Also, after we generate a small interval by bisection above, false + // position will do a large step from an interval of width ~1e-4 to ~1e-14 + // in one step (a=10, x=0.05, but similar for other values). + result, bestX, _, errEst := falsePosition(lo, hi, flo, fhi, 2*machEp, 2*machEp, 1e-2*a, gammaInc, params) + if result == fSolveMaxIterations && errEst > allowedATol+allowedRTol*math.Abs(bestX) { + bestX = math.NaN() + } + + return bestX +} diff --git a/vendor/gonum.org/v1/gonum/mathext/gamma_inc_test.go b/vendor/gonum.org/v1/gonum/mathext/gamma_inc_test.go new file mode 100644 index 00000000..03d5f014 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/gamma_inc_test.go @@ -0,0 +1,138 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" + "testing" +) + +func TestGammaInc(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gamminc + {0, 0, 0}, + {0.0001, 1, 0.99997805936186279}, + {0.001, 0.005, 0.99528424172333985}, + {0.01, 10, 0.99999995718295021}, + {0.1, 10, 0.99999944520142825}, + {0.25, 0.75, 0.89993651328449831}, + {0.5, 0.5, 0.68268949213708596}, + {0.5, 2, 0.95449973610364147}, + {0.75, 2.5, 0.95053039734695643}, + {1, 0.5, 0.39346934028736652}, + {1, 1, 0.63212055882855778}, + {1.5, 0.75, 0.31772966966378746}, + {2.5, 1, 0.15085496391539038}, + {3, 0.05, 2.0067493624397931e-05}, + {3, 20, 0.99999954448504946}, + {5, 50, 1}, + {7, 10, 0.86985857911751696}, + {10, 0.9, 4.2519575433351128e-08}, + {10, 5, 0.031828057306204811}, + {25, 10, 4.6949381426799868e-05}, + } { + if got := GammaInc(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaInc(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncComp(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gammincc + {0.00001, 0.075, 2.0866541002417804e-05}, + {0.0001, 1, 2.1940638138146658e-05}, + {0.001, 0.005, 0.0047157582766601536}, + {0.01, 0.9, 0.0026263432520514662}, + {0.25, 0.75, 0.10006348671550169}, + {0.5, 0.5, 0.31731050786291404}, + {0.75, 0.25, 0.65343980284081038}, + {0.9, 0.01, 0.98359881081593148}, + {1, 0, 1}, + {1, 0.075, 0.92774348632855297}, + {1, 1, 0.36787944117144233}, + {1, 10, 4.5399929762484861e-05}, + {1, math.Inf(1), 0}, + {3, 20, 4.5551495055892125e-07}, + {5, 10, 0.029252688076961127}, + {10, 3, 0.99889751186988451}, + {50, 25, 0.99999304669475242}, + {100, 10, 1}, + {500, 500, 0.49405285382921321}, + {500, 550, 0.014614408126291296}, + } { + if got := GammaIncComp(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncComp(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncInv(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gammincinv + {0.001, 0.99, 2.4259428385570885e-05}, + {0.01, 0.99, 0.26505255025157959}, + {0.1, 0.5, 0.00059339110446022798}, + {0.2, 0.8, 0.26354363204872067}, + {0.25, 0.5, 0.043673802352873381}, + {0.5, 0.25, 0.050765522133810789}, + {0.5, 0.5, 0.22746821155978625}, + {0.75, 0.25, 0.15340752707472377}, + {1, 0, 0}, + {1, 0.075, 0.077961541469711862}, + {1, 1, math.Inf(1)}, + {2.5, 0.99, 7.5431362346944937}, + {10, 0.5, 9.6687146147141299}, + {25, 0.01, 14.853341349420646}, + {25, 0.99, 38.076945624506337}, + {50, 0.75, 54.570620535040511}, + {100, 0.25, 93.08583383712174}, + {1000, 0.01, 927.90815979664251}, + {1000, 0.99, 1075.0328320864389}, + {10000, 0.5, 9999.6666686420485}, + } { + if got := GammaIncInv(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncInv(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncCompInv(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gamminccinv + {0.001, 0.01, 2.4259428385570885e-05}, + {0.01, 0.01, 0.26505255025158292}, + {0.03, 0.4, 2.316980536227699e-08}, + {0.1, 0.5, 0.00059339110446022798}, + {0.1, 0.75, 5.7917132949696076e-07}, + {0.25, 0.25, 0.26062600197823282}, + {0.5, 0.1, 1.3527717270477047}, + {0.5, 0.5, 0.22746821155978625}, + {0.75, 0.25, 1.0340914067758025}, + {1, 0, math.Inf(1)}, + {1, 0.5, 0.69314718055994529}, + {1, 1, 0}, + {3, 0.75, 1.727299417860519}, + {25, 0.4, 25.945791937289371}, + {25, 0.7, 22.156653488661991}, + {10, 0.5, 9.6687146147141299}, + {100, 0.25, 106.5510925269767}, + {1000, 0.01, 1075.0328320864389}, + {1000, 0.99, 927.90815979664251}, + {10000, 0.5, 9999.6666686420485}, + } { + if got := GammaIncCompInv(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncCompInv(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go new file mode 100644 index 00000000..2bd74d43 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go @@ -0,0 +1,2154 @@ +// Copyright ©2016 The gonum 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 amos + +import ( + "math" + "math/cmplx" +) + +/* +The AMOS functions are included in SLATEC, and the SLATEC guide (http://www.netlib.org/slatec/guide) explicitly states: +"The Library is in the public domain and distributed by the Energy +Science and Technology Software Center." +Mention of AMOS's inclusion in SLATEC goes back at least to this 1985 technical report from Sandia National Labs: http://infoserve.sandia.gov/sand_doc/1985/851018.pdf +*/ + +// math.NaN() are for padding to keep indexing easy. +var imach = []int{-0, 5, 6, 0, 0, 32, 4, 2, 31, 2147483647, 2, 24, -125, 127, 53, -1021, 1023} + +var dmach = []float64{math.NaN(), 2.23E-308, 1.79E-308, 1.11E-16, 2.22E-16, 0.30103000998497009} + +func abs(a int) int { + if a >= 0 { + return a + } + return -a +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func Zairy(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + // zairy is adapted from the original Netlib code by Donald Amos. + // http://www.netlib.no/netlib/amos/zairy.f + + // Original comment: + /* + C***BEGIN PROLOGUE ZAIRY + C***DATE WRITTEN 830501 (YYMMDD) + C***REVISION DATE 890801 (YYMMDD) + C***CATEGORY NO. B5K + C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD + C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES + C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z + C***DESCRIPTION + C + C ***A DOUBLE PRECISION ROUTINE*** + C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR + C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON + C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* + C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN + C -PI/31.0 FROM THE K BESSEL + C FUNCTIONS BY + C + C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) + C C=1.0/(PI*SQRT(3.0)) + C ZTA=(2/3)*Z**(3/2) + C + C WITH THE POWER SERIES FOR CABS(Z)<=1.0. + C + C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- + C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES + C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF + C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), + C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR + C FLAG IERR=3 IS TRIGGERED WHERE UR=math.Max(dmach[4),1.0D-18) IS + C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. + C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN + C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT + C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE + C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA + C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, + C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE + C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE + C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- + C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- + C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN + C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN + C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, + C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE + C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER + C MACHINES. + C + C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX + C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT + C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- + C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE + C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), + C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF + C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY + C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN + C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY + C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER + C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, + C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS + C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER + C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY + C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER + C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE + C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, + C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, + C OR -PI/2+P. + C + C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ + C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF + C COMMERCE, 1955. + C + C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT + C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 + C + C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- + C 1018, MAY, 1985 + C + C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. + C MATH. SOFTWARE, 1986 + */ + var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128 + var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, + CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG, + DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64 + var IERR, IFLAG, K, K1, K2, MR, NN int + var tmp complex128 + + // Extra element for padding. + CYR := []float64{math.NaN(), 0} + CYI := []float64{math.NaN(), 0} + + _ = AI + _ = CONE + _ = CSQ + _ = CY + _ = S1 + _ = S2 + _ = TRM1 + _ = TRM2 + _ = Z + _ = ZTA + _ = Z3 + + TTH = 6.66666666666666667E-01 + C1 = 3.55028053887817240E-01 + C2 = 2.58819403792806799E-01 + COEF = 1.83776298473930683E-01 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + if ID < 0 || ID > 1 { + IERR = 1 + } + if KODE < 1 || KODE > 2 { + IERR = 1 + } + if IERR != 0 { + return + } + AZ = cmplx.Abs(complex(ZR, ZI)) + TOL = math.Max(dmach[4], 1.0E-18) + FID = float64(ID) + if AZ > 1.0E0 { + goto Seventy + } + + // POWER SERIES FOR CABS(Z)<=1. + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + if AZ < TOL { + goto OneSeventy + } + AA = AZ * AZ + if AA < TOL/AZ { + goto Forty + } + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0E0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ * AA + AK = 2.0E0 + FID + BK = 3.0E0 - FID - FID + CK = 4.0E0 - FID + DK = 3.0E0 + FID + FID + D1 = AK * DK + D2 = BK * CK + AD = math.Min(D1, D2) + AK = 24.0E0 + 9.0E0*FID + BK = 30.0E0 - 9.0E0*FID + for K = 1; K <= 25; K++ { + STR = (TRM1R*Z3R - TRM1I*Z3I) / D1 + TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R - TRM2I*Z3I) / D2 + TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM * AZ3 / AD + D1 = D1 + AK + D2 = D2 + BK + AD = math.Min(D1, D2) + if ATRM < TOL*AD { + goto Forty + } + AK = AK + 18.0E0 + BK = BK + 18.0E0 + } +Forty: + if ID == 1 { + goto Fifty + } + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + if KODE == 1 { + return + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = cmplx.Exp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + return + +Fifty: + AIR = -S2R * C2 + AII = -S2I * C2 + if AZ <= TOL { + goto Sixty + } + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1 / (1.0E0 + FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + +Sixty: + if KODE == 1 { + return + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = cmplx.Exp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + return + + // CASE FOR CABS(Z)>1.0. +Seventy: + FNU = (1.0E0 + FID) / 3.0E0 + + /* + SET PARAMETERS RELATED TO MACHINE CONSTANTS. + TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. + ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT. + EXP(-ELIM)EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR + UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. + RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z. + DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). + */ + K1 = imach[15] + K2 = imach[16] + R1M5 = dmach[5] + + K = min(abs(K1), abs(K2)) + ELIM = 2.303E0 * (float64(K)*R1M5 - 3.0E0) + K1 = imach[14] - 1 + AA = R1M5 * float64(K1) + DIG = math.Min(AA, 18.0E0) + AA = AA * 2.303E0 + ALIM = ELIM + math.Max(-AA, -41.45E0) + RL = 1.2E0*DIG + 3.0E0 + ALAZ = math.Log(AZ) + + // TEST FOR PROPER RANGE. + AA = 0.5E0 / TOL + BB = float64(float32(imach[9])) * 0.5E0 + AA = math.Min(AA, BB) + AA = math.Pow(AA, TTH) + if AZ > AA { + goto TwoSixty + } + AA = math.Sqrt(AA) + if AZ > AA { + IERR = 3 + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + CSQR = real(tmp) + CSQI = imag(tmp) + ZTAR = TTH * (ZR*CSQR - ZI*CSQI) + ZTAI = TTH * (ZR*CSQI + ZI*CSQR) + + // RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL. + IFLAG = 0 + SFAC = 1.0E0 + AK = ZTAI + if ZR >= 0.0E0 { + goto Eighty + } + BK = ZTAR + CK = -math.Abs(BK) + ZTAR = CK + ZTAI = AK + +Eighty: + if ZI != 0.0E0 { + goto Ninety + } + if ZR > 0.0E0 { + goto Ninety + } + ZTAR = 0.0E0 + ZTAI = AK +Ninety: + AA = ZTAR + if AA >= 0.0E0 && ZR > 0.0E0 { + goto OneTen + } + if KODE == 2 { + goto OneHundred + } + + // OVERFLOW TEST. + if AA > (-ALIM) { + goto OneHundred + } + AA = -AA + 0.25E0*ALAZ + IFLAG = 1 + SFAC = TOL + if AA > ELIM { + goto TwoSeventy + } + +OneHundred: + // CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2. + MR = 1 + if ZI < 0.0E0 { + MR = -1 + } + ZTAR, ZTAI, FNU, KODE, MR, _, CYR, CYI, NN, RL, TOL, ELIM, ALIM = Zacai(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, ELIM, ALIM) + if NN < 0 { + goto TwoEighty + } + NZ = NZ + NN + goto OneThirty + +OneTen: + if KODE == 2 { + goto OneTwenty + } + + // UNDERFLOW TEST. + if AA < ALIM { + goto OneTwenty + } + AA = -AA - 0.25E0*ALAZ + IFLAG = 2 + SFAC = 1.0E0 / TOL + if AA < (-ELIM) { + goto TwoTen + } +OneTwenty: + ZTAR, ZTAI, FNU, KODE, _, CYR, CYI, NZ, TOL, ELIM, ALIM = Zbknu(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, ALIM) + +OneThirty: + S1R = CYR[1] * COEF + S1I = CYI[1] * COEF + if IFLAG != 0 { + goto OneFifty + } + if ID == 1 { + goto OneFourty + } + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + return +OneFourty: + AIR = -(ZR*S1R - ZI*S1I) + AII = -(ZR*S1I + ZI*S1R) + return +OneFifty: + S1R = S1R * SFAC + S1I = S1I * SFAC + if ID == 1 { + goto OneSixty + } + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSixty: + STR = -(S1R*ZR - S1I*ZI) + S1I = -(S1R*ZI + S1I*ZR) + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSeventy: + AA = 1.0E+3 * dmach[1] + S1R = ZEROR + S1I = ZEROI + if ID == 1 { + goto OneNinety + } + if AZ <= AA { + goto OneEighty + } + S1R = C2 * ZR + S1I = C2 * ZI +OneEighty: + AIR = C1 - S1R + AII = -S1I + return +OneNinety: + AIR = -C2 + AII = 0.0E0 + AA = math.Sqrt(AA) + if AZ <= AA { + goto TwoHundred + } + S1R = 0.5E0 * (ZR*ZR - ZI*ZI) + S1I = ZR * ZI +TwoHundred: + AIR = AIR + C1*S1R + AII = AII + C1*S1I + return +TwoTen: + NZ = 1 + AIR = ZEROR + AII = ZEROI + return +TwoSeventy: + NZ = 0 + IERR = 2 + return +TwoEighty: + if NN == (-1) { + goto TwoSeventy + } + NZ = 0 + IERR = 5 + return +TwoSixty: + IERR = 4 + NZ = 0 + return +} + +// sbknu computes the k bessel function in the right half z plane. +func Zbknu(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + /* Old dimension comment. + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) + */ + + // TODO(btracey): Find which of these are inputs/outputs/both and clean up + // the function call. + // YR and YI have length n (but n+1 with better indexing) + var AA, AK, ASCLE, A1, A2, BB, BK, CAZ, + CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR, + CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS, + FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI, + PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64 + + var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int + + var sinh, cosh complex128 + //var sin, cos float64 + + var tmp, p complex128 + var CSSR, CSRR, BRY [4]float64 + var CYR, CYI [3]float64 + + KMAX = 30 + CZEROR = 0 + CZEROI = 0 + CONER = 1 + CONEI = 0 + CTWOR = 2 + R1 = 2 + + DPI = 3.14159265358979324E0 + RTHPI = 1.25331413731550025E0 + SPI = 1.90985931710274403E0 + HPI = 1.57079632679489662E0 + FPI = 1.89769999331517738E0 + TTH = 6.66666666666666666E-01 + + CC := [9]float64{math.NaN(), 5.77215664901532861E-01, -4.20026350340952355E-02, + -4.21977345555443367E-02, 7.21894324666309954E-03, + -2.15241674114950973E-04, -2.01348547807882387E-05, + 1.13302723198169588E-06, 6.11609510448141582E-09} + + CAZ = cmplx.Abs(complex(ZR, ZI)) + CSCLR = 1.0E0 / TOL + CRSCR = TOL + CSSR[1] = CSCLR + CSSR[2] = 1.0E0 + CSSR[3] = CRSCR + CSRR[1] = CRSCR + CSRR[2] = 1.0E0 + CSRR[3] = CSCLR + BRY[1] = 1.0E+3 * dmach[1] / TOL + BRY[2] = 1.0E0 / BRY[1] + BRY[3] = dmach[2] + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0E0 / CAZ + STR = ZR * RCAZ + STI = -ZI * RCAZ + RZR = (STR + STR) * RCAZ + RZI = (STI + STI) * RCAZ + INU = int(float32(FNU + 0.5)) + DNU = FNU - float64(INU) + if math.Abs(DNU) == 0.5E0 { + goto OneTen + } + DNU2 = 0.0E0 + if math.Abs(DNU) > TOL { + DNU2 = DNU * DNU + } + if CAZ > R1 { + goto OneTen + } + + // SERIES FOR CABS(Z)<=R1. + FC = 1.0E0 + tmp = cmplx.Log(complex(RZR, RZI)) + SMUR = real(tmp) + SMUI = imag(tmp) + FMUR = SMUR * DNU + FMUI = SMUI * DNU + tmp = complex(FMUR, FMUI) + sinh = cmplx.Sinh(tmp) + cosh = cmplx.Cosh(tmp) + CSHR = real(sinh) + CSHI = imag(sinh) + CCHR = real(cosh) + CCHI = imag(cosh) + if DNU == 0.0E0 { + goto Ten + } + FC = DNU * DPI + FC = FC / math.Sin(FC) + SMUR = CSHR / DNU + SMUI = CSHI / DNU +Ten: + A2 = 1.0E0 + DNU + + // GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU). + T2 = math.Exp(-dgamln(A2, IDUM)) + T1 = 1.0E0 / (T2 * FC) + if math.Abs(DNU) > 0.1E0 { + goto Forty + } + + // SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU). + AK = 1.0E0 + S = CC[1] + for K = 2; K <= 8; K++ { + AK = AK * DNU2 + TM = CC[K] * AK + S = S + TM + if math.Abs(TM) < TOL { + goto Thirty + } + } +Thirty: + G1 = -S + goto Fifty +Forty: + G1 = (T1 - T2) / (DNU + DNU) +Fifty: + G2 = (T1 + T2) * 0.5E0 + FR = FC * (CCHR*G1 + SMUR*G2) + FI = FC * (CCHI*G1 + SMUI*G2) + tmp = cmplx.Exp(complex(FMUR, FMUI)) + STR = real(tmp) + STI = imag(tmp) + PR = 0.5E0 * STR / T2 + PI = 0.5E0 * STI / T2 + tmp = complex(0.5, 0) / complex(STR, STI) + PTR = real(tmp) + PTI = imag(tmp) + QR = PTR / T1 + QI = PTI / T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0E0 + A1 = 1.0E0 + CKR = CONER + CKI = CONEI + BK = 1.0E0 - DNU2 + if INU > 0 || N > 1 { + goto Eighty + } + + // GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1. + if CAZ < TOL { + goto Seventy + } + tmp = complex(ZR, ZI) * complex(ZR, ZI) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Sixty: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Sixty + } +Seventy: + YR[1] = S1R + YI[1] = S1I + if KODED == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + tmp = cmplx.Exp(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(S1R, S1I) * complex(STR, STI) + YR[1] = real(tmp) + YI[1] = imag(tmp) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE. +Eighty: + if CAZ < TOL { + goto OneHundred + } + tmp = complex(ZR, ZI) * complex(ZR, ZI) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Ninety: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Ninety + } +OneHundred: + KFLAG = 2 + A1 = FNU + 1.0E0 + AK = A1 * math.Abs(SMUR) + if AK > ALIM { + KFLAG = 3 + } + STR = CSSR[KFLAG] + P2R = S2R * STR + P2I = S2I * STR + tmp = complex(P2R, P2I) * complex(RZR, RZI) + S2R = real(tmp) + S2I = imag(tmp) + S1R = S1R * STR + S1I = S1I * STR + if KODED == 1 { + goto TwoTen + } + tmp = cmplx.Exp(complex(ZR, ZI)) + FR = real(tmp) + FI = imag(tmp) + tmp = complex(S1R, S1I) * complex(FR, FI) + S1R = real(tmp) + S1I = imag(tmp) + tmp = complex(S2R, S2I) * complex(FR, FI) + S2R = real(tmp) + S2I = imag(tmp) + goto TwoTen + + // IFLAG=0 MEANS NO UNDERFLOW OCCURRED + // IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH + // KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION +OneTen: + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(RTHPI, CZEROI) / complex(STR, STI) + COEFR = real(tmp) + COEFI = imag(tmp) + KFLAG = 2 + if KODED == 2 { + goto OneTwenty + } + if ZR > ALIM { + goto TwoNinety + } + + STR = math.Exp(-ZR) * CSSR[KFLAG] + //sin, cos = math.Sincos(ZI) + STI = -STR * math.Sin(ZI) + STR = STR * math.Cos(ZI) + tmp = complex(COEFR, COEFI) * complex(STR, STI) + COEFR = real(tmp) + COEFI = imag(tmp) +OneTwenty: + if math.Abs(DNU) == 0.5E0 { + goto ThreeHundred + } + // MILLER ALGORITHM FOR CABS(Z)>R1. + AK = math.Cos(DPI * DNU) + AK = math.Abs(AK) + if AK == CZEROR { + goto ThreeHundred + } + FHS = math.Abs(0.25E0 - DNU2) + if FHS == CZEROR { + goto ThreeHundred + } + + // COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO + // DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON + // 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= + // TOL WHERE B IS THE BASE OF THE ARITHMETIC. + T1 = float64(imach[14] - 1) + T1 = T1 * dmach[5] * 3.321928094E0 + T1 = math.Max(T1, 12.0E0) + T1 = math.Min(T1, 60.0E0) + T2 = TTH*T1 - 6.0E0 + if ZR != 0.0E0 { + goto OneThirty + } + T1 = HPI + goto OneFourty +OneThirty: + T1 = math.Atan(ZI / ZR) + T1 = math.Abs(T1) +OneFourty: + if T2 > CAZ { + goto OneSeventy + } + // FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2. + ETEST = AK / (DPI * CAZ * TOL) + FK = CONER + if ETEST < CONER { + goto OneEighty + } + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + for I = 1; I <= KMAX; I++ { + AK = FHS / FKS + CBR = CKR / (FK + CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = math.Abs(P2R) * FK + if ETEST < STR { + goto OneSixty + } + } + goto ThreeTen +OneSixty: + FK = FK + SPI*T1*math.Sqrt(T2/CAZ) + FHS = math.Abs(0.25 - DNU2) + goto OneEighty +OneSeventy: + // COMPUTE BACKWARD INDEX K FOR CABS(Z) 0 || N > 1 { + goto TwoHundred + } + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoHundred: + // COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING. + TM = cmplx.Abs(complex(P2R, P2I)) + PTR = 1.0E0 / TM + P1R = P1R * PTR + P1I = P1I * PTR + P2R = P2R * PTR + P2I = -P2I * PTR + tmp = complex(P1R, P1I) * complex(P2R, P2I) + PTR = real(tmp) + PTI = imag(tmp) + STR = DNU + 0.5E0 - PTR + STI = -PTI + tmp = complex(STR, STI) / complex(ZR, ZI) + STR = real(tmp) + STI = imag(tmp) + STR = STR + 1.0E0 + tmp = complex(STR, STI) * complex(S1R, S1I) + S2R = real(tmp) + S2I = imag(tmp) + + // FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH + // SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +TwoTen: + STR = DNU + 1.0E0 + CKR = STR * RZR + CKI = STR * RZI + if N == 1 { + INU = INU - 1 + } + if INU > 0 { + goto TwoTwenty + } + if N > 1 { + goto TwoFifteen + } + S1R = S2R + S1I = S2I +TwoFifteen: + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoTwenty: + INUB = 1 + if IFLAG == 1 { + goto TwoSixtyOne + } +TwoTwentyFive: + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = INUB; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + if KFLAG >= 3 { + continue + } + P2R = S2R * P1R + P2I = S2I * P1R + STR = math.Abs(P2R) + STI = math.Abs(P2I) + P2M = math.Max(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I +TwoFourty: + STR = CSRR[KFLAG] + YR[1] = S1R * STR + YI[1] = S1I * STR + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + YR[2] = S2R * STR + YI[2] = S2I * STR + if N == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = 2 +TwoFifty: + KK = KK + 1 + if KK > N { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = KK; I <= N; I++ { + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R * P1R + P2I = S2I * P1R + YR[I] = P2R + YI[I] = P2I + if KFLAG >= 3 { + continue + } + STR = math.Abs(P2R) + STI = math.Abs(P2I) + P2M = math.Max(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW. +TwoSixtyOne: + HELIM = 0.5E0 * ELIM + ELM = math.Exp(-ELIM) + CELMR = ELM + ASCLE = BRY[1] + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + for I = 1; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = STR*CKR - STI*CKI + S1R + S2I = STI*CKR + STR*CKI + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + AS = cmplx.Abs(complex(S2R, S2I)) + ALAS = math.Log(AS) + P2R = -ZDR + ALAS + if P2R < (-ELIM) { + goto TwoSixtyThree + } + tmp = cmplx.Log(complex(S2R, S2I)) + STR = real(tmp) + STI = imag(tmp) + P2R = -ZDR + STR + P2I = -ZDI + STI + P2M = math.Exp(P2R) / TOL + // sin, cos = math.Sincos(P2I) + P1R = P2M * math.Cos(P2I) + P1I = P2M * math.Sin(P2I) + p = complex(P1R, P1I) + NW = Zuchk(p, ASCLE, TOL) + if NW != 0 { + goto TwoSixtyThree + } + J = 3 - J + CYR[J] = P1R + CYI[J] = P1I + if IC == (I - 1) { + goto TwoSixtyFour + } + IC = I + continue + TwoSixtyThree: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + if N != 1 { + goto TwoSeventy + } + S1R = S2R + S1I = S2I + goto TwoSeventy +TwoSixtyFour: + KFLAG = 1 + INUB = I + 1 + S2R = CYR[J] + S2I = CYI[J] + J = 3 - J + S1R = CYR[J] + S1I = CYI[J] + if INUB <= INU { + goto TwoTwentyFive + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I + goto TwoFourty +TwoSeventy: + YR[1] = S1R + YI[1] = S1I + if N == 1 { + goto TwoEighty + } + YR[2] = S2R + YI[2] = S2I +TwoEighty: + ASCLE = BRY[1] + ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM = Zkscl(ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM) + INU = N - NZ + if INU <= 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 1 + S1R = YR[KK] + S1I = YI[KK] + YR[KK] = S1R * CSRR[1] + YI[KK] = S1I * CSRR[1] + if INU == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 2 + S2R = YR[KK] + S2I = YI[KK] + YR[KK] = S2R * CSRR[1] + YI[KK] = S2I * CSRR[1] + if INU == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + T2 = FNU + float64(float32(KK-1)) + CKR = T2 * RZR + CKI = T2 * RZI + KFLAG = 1 + goto TwoFifty +TwoNinety: + + // SCALE BY math.Exp(Z), IFLAG = 1 CASES. + + KODED = 2 + IFLAG = 1 + KFLAG = 2 + goto OneTwenty + + // FNU=HALF ODD INTEGER CASE, DNU=-0.5 +ThreeHundred: + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + goto TwoTen + +ThreeTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +func Zkscl(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I, + S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64 + + var I, IC, KK, NN, NW int + var tmp, c complex128 + var CYR, CYI [3]float64 + var sin, cos float64 + + // DIMENSION YR(N), YI(N), CYR(2), CYI(2) + ZEROR = 0 + ZEROI = 0 + NZ = 0 + IC = 0 + NN = min(2, N) + for I = 1; I <= NN; I++ { + S1R = YR[I] + S1I = YI[I] + CYR[I] = S1R + CYI[I] = S1I + AS = cmplx.Abs(complex(S1R, S1I)) + ACS = -ZRR + math.Log(AS) + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + continue + } + + tmp = cmplx.Log(complex(S1R, S1I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = math.Exp(CSR) / TOL + // sin, cos = math.Sincos(CSI) + CSR = STR * math.Cos(CSI) + CSI = STR * math.Sin(CSI) + c = complex(CSR, CSI) + NW = Zuchk(c, ASCLE, TOL) + if NW != 0 { + continue + } + YR[I] = CSR + YI[I] = CSI + IC = I + NZ = NZ - 1 + } + if N == 1 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if IC > 1 { + goto Twenty + } + YR[1] = ZEROR + YI[1] = ZEROI + NZ = 2 +Twenty: + if N == 2 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if NZ == 0 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + FN = FNU + 1.0E0 + CKR = FN * RZR + CKI = FN * RZI + S1R = CYR[1] + S1I = CYI[1] + S2R = CYR[2] + S2I = CYI[2] + HELIM = 0.5E0 * ELIM + ELM = math.Exp(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI + + // FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF + // S2 GETS LARGER THAN EXP(ELIM/2) + for I = 3; I <= N; I++ { + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = cmplx.Abs(complex(S2R, S2I)) + ALAS = math.Log(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + goto TwentyFive + } + tmp = cmplx.Log(complex(S2R, S2I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = math.Exp(CSR) / TOL + sin, cos = math.Sincos(CSI) + CSR = STR * cos + CSI = STR * sin + c = complex(CSR, CSI) + NW = Zuchk(c, ASCLE, TOL) + if NW != 0 { + goto TwentyFive + } + YR[I] = CSR + YI[I] = CSI + NZ = NZ - 1 + if IC == KK-1 { + goto Forty + } + IC = KK + continue + TwentyFive: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + NZ = N + if IC == N { + NZ = N - 1 + } + goto FourtyFive +Forty: + NZ = KK - 2 +FourtyFive: + for I = 1; I <= NZ; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +// Zuchk tests whether the magnitude of the real or imaginary part would +// underflow when y is scaled by tol. +// +// y enters as a scaled quantity whose magnitude is greater than +// 1e3 + 3*dmach(1)/tol +// y is accepted if the underflow is at least one precision below the magnitude +// of the largest component. Otherwise an underflow is assumed as the phase angle +// does not have sufficient accuracy. +func Zuchk(y complex128, scale, tol float64) int { + absR := math.Abs(real(y)) + absI := math.Abs(imag(y)) + minAbs := math.Min(absR, absI) + if minAbs > scale { + return 0 + } + maxAbs := math.Max(absR, absI) + minAbs /= tol + if maxAbs < minAbs { + return 1 + } + return 0 +} + +// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +// +// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +// MP=PI*MR*CMPLX(0.0,1.0) +// +// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON +// IS CALLED FROM ZAIRY. +func Zacai(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI, + SGN, YY, ZNR, ZNI float64 + var INU, IUF, NN, NW int + var zn, c1, c2, z complex128 + var y []complex128 + //var sin, cos float64 + + CYR := []float64{math.NaN(), 0, 0} + CYI := []float64{math.NaN(), 0, 0} + + PI = math.Pi + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = cmplx.Abs(complex(ZR, ZI)) + NN = N + DFNU = FNU + float64(float32(N-1)) + if AZ <= 2.0E0 { + goto Ten + } + if AZ*AZ*0.25 > DFNU+1.0E0 { + goto Twenty + } +Ten: + // POWER SERIES FOR THE I FUNCTION. + z = complex(ZNR, ZNI) + y = make([]complex128, len(YR)) + for i, v := range YR { + y[i] = complex(v, YI[i]) + } + NW = Zseri(z, FNU, KODE, NN, y[1:], TOL, ELIM, ALIM) + for i, v := range y { + YR[i] = real(v) + YI[i] = imag(v) + } + goto Forty +Twenty: + if AZ < RL { + goto Thirty + } + // ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM = Zasyi(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM) + if NW < 0 { + goto Eighty + } + goto Forty +Thirty: + // MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL = Zmlri(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + if NW < 0 { + goto Eighty + } +Forty: + // ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION. + ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = Zbknu(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + if NW != 0 { + goto Eighty + } + FMR = float64(float32(MR)) + SGN = -math.Copysign(PI, FMR) + CSGNR = 0.0E0 + CSGNI = SGN + if KODE == 1 { + goto Fifty + } + YY = -ZNI + //sin, cos = math.Sincos(YY) + CSGNR = -CSGNI * math.Sin(YY) + CSGNI = CSGNI * math.Cos(YY) +Fifty: + // CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE + // WHEN FNU IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * SGN + //sin, cos = math.Sincos(ARG) + CSPNR = math.Cos(ARG) + CSPNI = math.Sin(ARG) + if INU%2 == 0 { + goto Sixty + } + CSPNR = -CSPNR + CSPNI = -CSPNI +Sixty: + C1R = CYR[1] + C1I = CYI[1] + C2R = YR[1] + C2I = YI[1] + if KODE == 1 { + goto Seventy + } + IUF = 0 + ASCLE = 1.0E+3 * dmach[1] / TOL + zn = complex(ZNR, ZNI) + c1 = complex(C1R, C1I) + c2 = complex(C2R, C2I) + c1, c2, NW, IUF = Zs1s2(zn, c1, c2, ASCLE, ALIM, IUF) + C1R = real(c1) + C1I = imag(c1) + C2R = real(c2) + C2I = imag(c2) + NZ = NZ + NW +Seventy: + YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +Eighty: + NZ = -1 + if NW == -2 { + NZ = -2 + } + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return. +// NZ<0 INDICATES AN OVERFLOW ON KODE=1. +func Zasyi(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL, + AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I, + P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + S2R, TZI, TZR, ZEROI, ZEROR float64 + + var I, IB, IL, INU, J, JL, K, KODED, M, NN int + var tmp complex128 + // var sin, cos float64 + + PI = math.Pi + RTPI = 0.159154943091895336E0 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + AZ = cmplx.Abs(complex(ZR, ZI)) + ARM = 1.0E3 * dmach[1] + RTR1 = math.Sqrt(ARM) + IL = min(2, N) + DFNU = FNU + float64(float32(N-IL)) + + // OVERFLOW TEST + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + AK1R = RTPI * STR * RAZ + AK1I = RTPI * STI * RAZ + tmp = cmplx.Sqrt(complex(AK1R, AK1I)) + AK1R = real(tmp) + AK1I = imag(tmp) + CZR = ZR + CZI = ZI + if KODE != 2 { + goto Ten + } + CZR = ZEROR + CZI = ZI +Ten: + if math.Abs(CZR) > ELIM { + goto OneHundred + } + DNU2 = DFNU + DFNU + KODED = 1 + if (math.Abs(CZR) > ALIM) && (N > 2) { + goto Twenty + } + KODED = 0 + tmp = cmplx.Exp(complex(CZR, CZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(AK1R, AK1I) * complex(STR, STI) + AK1R = real(tmp) + AK1I = imag(tmp) +Twenty: + FDN = 0.0E0 + if DNU2 > RTR1 { + FDN = DNU2 * DNU2 + } + EZR = ZR * 8.0E0 + EZI = ZI * 8.0E0 + + // WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE + // FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE + // EXPANSION FOR THE IMAGINARY PART. + AEZ = 8.0E0 * AZ + S = TOL / AEZ + JL = int(float32(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + if ZI == 0.0E0 { + goto Thirty + } + + // CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF + // SIGNIFICANCE WHEN FNU OR N IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * PI + INU = INU + N - IL + //sin, cos = math.Sincos(ARG) + AK = -math.Sin(ARG) + BK = math.Cos(ARG) + if ZI < 0.0E0 { + BK = -BK + } + P1R = AK + P1I = BK + if INU%2 == 0 { + goto Thirty + } + P1R = -P1R + P1I = -P1I +Thirty: + for K = 1; K <= IL; K++ { + SQK = FDN - 1.0E0 + ATOL = S * math.Abs(SQK) + SGN = 1.0E0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0E0 + AA = 1.0E0 + BB = AEZ + DKR = EZR + DKI = EZI + // TODO(btracey): This loop is executed tens of thousands of times. Why? + // is that really necessary? + for J = 1; J <= JL; J++ { + tmp = complex(CKR, CKI) / complex(DKR, DKI) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * SQK + CKI = STI * SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA * math.Abs(SQK) / BB + BB = BB + AEZ + AK = AK + 8.0E0 + SQK = SQK - AK + if AA <= ATOL { + goto Fifty + } + } + goto OneTen + Fifty: + S2R = CS1R + S2I = CS1I + if ZR+ZR >= ELIM { + goto Sixty + } + TZR = ZR + ZR + TZI = ZI + ZI + tmp = cmplx.Exp(complex(-TZR, -TZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(STR, STI) * complex(P1R, P1I) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(STR, STI) * complex(CS2R, CS2I) + STR = real(tmp) + STI = imag(tmp) + S2R = S2R + STR + S2I = S2I + STI + Sixty: + FDN = FDN + 8.0E0*DFNU + 4.0E0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR[M] = S2R*AK1R - S2I*AK1I + YI[M] = S2R*AK1I + S2I*AK1R + } + if N <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + NN = N + K = NN - 2 + AK = float64(float32(K)) + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + IB = 3 + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + if KODED == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + tmp = cmplx.Exp(complex(CZR, CZI)) + CKR = real(tmp) + CKI = imag(tmp) + for I = 1; I <= NN; I++ { + STR = YR[I]*CKR - YI[I]*CKI + YI[I] = YR[I]*CKI + YI[I]*CKR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneHundred: + NZ = -1 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE +// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +func Zmlri(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I, + P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + SUMR, TFNF, TST, ZEROI, ZEROR float64 + var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int + var tmp complex128 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + SCLE = dmach[1] / TOL + NZ = 0 + AZ = cmplx.Abs(complex(ZR, ZI)) + IAZ = int(float32(AZ)) + IFNU = int(float32(FNU)) + INU = IFNU + N - 1 + AT = float64(float32(IAZ)) + 1.0E0 + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT + 1.0E0) * RAZ + RHO = ACK + math.Sqrt(ACK*ACK-1.0E0) + RHO2 = RHO * RHO + TST = (RHO2 + RHO2) / ((RHO2 - 1.0E0) * (RHO - 1.0E0)) + TST = TST / TOL + + // COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES. + //fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK) + AK = AT + for I = 1; I <= 80; I++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKI*PTR + CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = cmplx.Abs(complex(P2R, P2I)) + if AP > TST*AK*AK { + goto Twenty + } + AK = AK + 1.0E0 + } + goto OneTen +Twenty: + I = I + 1 + K = 0 + if INU < IAZ { + goto Forty + } + // COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS. + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = float64(float32(INU)) + 1.0E0 + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + ACK = AT * RAZ + TST = math.Sqrt(ACK / TOL) + ITIME = 1 + for K = 1; K <= 80; K++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKR*PTI + CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = cmplx.Abs(complex(P2R, P2I)) + if AP < TST { + continue + } + if ITIME == 2 { + goto Forty + } + ACK = cmplx.Abs(complex(CKR, CKI)) + FLAM = ACK + math.Sqrt(ACK*ACK-1.0E0) + FKAP = AP / cmplx.Abs(complex(P1R, P1I)) + RHO = math.Min(FLAM, FKAP) + TST = TST * math.Sqrt(RHO/(RHO*RHO-1.0E0)) + ITIME = 2 + } + goto OneTen +Forty: + // BACKWARD RECURRENCE AND SUM NORMALIZING RELATION. + K = K + 1 + KK = max(I+IAZ, K+INU) + FKK = float64(float32(KK)) + P1R = ZEROR + P1I = ZEROI + + // SCALE P2 AND SUM BY SCLE. + P2R = SCLE + P2I = ZEROI + FNF = FNU - float64(float32(IFNU)) + TFNF = FNF + FNF + BK = dgamln(FKK+TFNF+1.0E0, IDUM) - dgamln(FKK+1.0E0, IDUM) - dgamln(TFNF+1.0E0, IDUM) + BK = math.Exp(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + for I = 1; I <= KM; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } + YR[N] = P2R + YI[N] = P2I + if N == 1 { + goto Seventy + } + for I = 2; I <= N; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + M = N - I + 1 + YR[M] = P2R + YI[M] = P2I + } +Seventy: + if IFNU <= 0 { + goto Ninety + } + for I = 1; I <= IFNU; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } +Ninety: + PTR = ZR + PTI = ZI + if KODE == 2 { + PTR = ZEROR + } + tmp = cmplx.Log(complex(RZR, RZI)) + STR = real(tmp) + STI = imag(tmp) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = dgamln(1.0E0+FNF, IDUM) + PTR = P1R - AP + PTI = P1I + + // THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW + // IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES. + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = cmplx.Abs(complex(P2R, P2I)) + P1R = 1.0E0 / AP + tmp = cmplx.Exp(complex(PTR, PTI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * P1R + CKI = STI * P1R + PTR = P2R * P1R + PTI = -P2I * P1R + tmp = complex(CKR, CKI) * complex(PTR, PTI) + CNORMR = real(tmp) + CNORMI = imag(tmp) + for I = 1; I <= N; I++ { + STR = YR[I]*CNORMR - YI[I]*CNORMI + YI[I] = YR[I]*CNORMI + YI[I]*CNORMR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} + +// Zseri computes the I bessel function for real(z) >= 0 by means of the power +// series for large |z| in the region |z| <= 2*sqrt(fnu+1). +// +// nz = 0 is a normal return. nz > 0 means that the last nz components were set +// to zero due to underflow. nz < 0 means that underflow occurred, but the +// condition |z| <= 2*sqrt(fnu+1) was violated and the computation must be +// completed in another routine with n -= abs(nz). +func Zseri(z complex128, fnu float64, kode, n int, y []complex128, tol, elim, alim float64) (nz int) { + // TODO(btracey): The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran + // this is interpreted as one to the power of +3*D1MACH(1). While it is possible + // this was intentional, it seems unlikely. + arm := 1000 * dmach[1] + az := cmplx.Abs(z) + if az < arm { + for i := 0; i < n; i++ { + y[i] = 0 + } + if fnu == 0 { + y[0] = 1 + n-- + } + if az == 0 { + return 0 + } + return n + } + hz := 0.5 * z + var cz complex128 + var acz float64 + if az > math.Sqrt(arm) { + cz = hz * hz + acz = cmplx.Abs(cz) + } + NN := n + ck := cmplx.Log(hz) + var ak1 complex128 + for { + dfnu := fnu + float64(NN-1) + // Underflow test. + ak1 = ck * complex(dfnu, 0) + ak := dgamln(dfnu+1, 0) + ak1 -= complex(ak, 0) + if kode == 2 { + ak1 -= complex(real(z), 0) + } + if real(ak1) > -elim { + break + } + nz++ + y[NN-1] = 0 + if acz > dfnu { + // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation + // in cbinu with n = n - abs(nz). + nz *= -1 + return nz + } + NN-- + if NN == 0 { + return nz + } + } + crscr := 1.0 + var flag int + var scale float64 + aa := real(ak1) + if aa <= -alim { + flag = 1 + crscr = tol + scale = arm / tol + aa -= math.Log(tol) + } + var w [2]complex128 + for { + coef := cmplx.Exp(complex(aa, imag(ak1))) + atol := tol * acz / (fnu + float64(NN)) + for i := 0; i < min(2, NN); i++ { + FNUP := fnu + float64(NN-i) + s1 := 1 + 0i + if acz >= tol*FNUP { + ak2 := 1 + 0i + ak := FNUP + 2 + S := FNUP + scl := 2.0 + first := true + for first || scl > atol { + ak2 = ak2 * cz * complex(1/S, 0) + scl *= acz / S + s1 += ak2 + S += ak + ak += 2 + first = false + } + } + s2 := s1 * coef + w[i] = s2 + if flag == 1 { + if Zuchk(s2, scale, tol) != 0 { + var full bool + var dfnu float64 + // This code is similar to the code that exists above. The + // code copying is here because the original Fortran used + // a goto to solve the loop-and-a-half problem. Removing the + // goto makes the behavior of the function and variable scoping + // much clearer, but requires copying this code due to Go's + // goto rules. + for { + if full { + dfnu = fnu + float64(NN-1) + // Underflow test. + ak1 = ck * complex(dfnu, 0) + ak1 -= complex(dgamln(dfnu+1, 0), 0) + if kode == 2 { + ak1 -= complex(real(z), 0) + } + if real(ak1) > -elim { + break + } + } else { + full = true + } + nz++ + y[NN-1] = 0 + if acz > dfnu { + // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation + // in cbinu with n = n - abs(nz). + nz *= -1 + return nz + } + NN-- + if NN == 0 { + return nz + } + } + continue + } + } + y[NN-i-1] = s2 * complex(crscr, 0) + coef /= hz + coef *= complex(FNUP-1, 0) + } + break + } + if NN <= 2 { + return nz + } + rz := complex(2*real(z)/(az*az), -2*imag(z)/(az*az)) + if flag == 0 { + for i := NN - 3; i >= 0; i-- { + y[i] = complex(float64(i+1)+fnu, 0)*rz*y[i+1] + y[i+2] + } + return nz + } + + // exp(-alim)=exp(-elim)/tol=approximately one digit of precision above the + // underflow limit, which equals scale = dmach[1)*SS*1e3. + s1 := w[0] + s2 := w[1] + for K := NN - 3; K >= 0; K-- { + s1, s2 = s2, s1+complex(float64(K+1)+fnu, 0)*(rz*s2) + ck := s2 * complex(crscr, 0) + y[K] = ck + if cmplx.Abs(ck) > scale { + for ; K >= 0; K-- { + y[K] = complex(float64(K+1)+fnu, 0)*rz*y[K+1] + y[K+2] + } + return nz + } + } + return nz +} + +// Zs1s2 tests for a possible underflow resulting from the addition of the I and +// K functions in the analytic continuation formula where s1 == K function and +// s2 == I function. +// +// When kode == 1, the I and K functions are different orders of magnitude. +// +// When kode == 2, they may both be of the same order of magnitude, but the maximum +// must be at least one precision above the underflow limit. +func Zs1s2(zr, s1, s2 complex128, scale, lim float64, iuf int) (s1o, s2o complex128, nz, iufo int) { + if s1 == 0 || math.Log(cmplx.Abs(s1))-2*real(zr) < -lim { + if cmplx.Abs(s2) > scale { + return 0, s2, 0, iuf + } + return 0, 0, 1, 0 + } + // TODO(btracey): Written like this for numerical rounding reasons. + // Fix once we're sure other changes are correct. + s1 = cmplx.Exp(cmplx.Log(s1) - zr - zr) + if math.Max(cmplx.Abs(s1), cmplx.Abs(s2)) > scale { + return s1, s2, 0, iuf + 1 + } + return 0, 0, 1, 0 +} + +func dgamln(z float64, ierr int) float64 { + //return amoslib.DgamlnFort(z) + // Go implementation. + if z < 0 { + return 0 + } + a2, _ := math.Lgamma(z) + return a2 +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos_test.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos_test.go new file mode 100644 index 00000000..59cdfa4f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos_test.go @@ -0,0 +1,521 @@ +// Copyright ©2016 The gonum 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 amos + +import ( + "math" + "math/rand" + "strconv" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type input struct { + x []float64 + is []int + kode int + id int + yr []float64 + yi []float64 + n int + tol float64 +} + +func randnum(rnd *rand.Rand) float64 { + r := 2e2 // Fortran has infinite loop if this is set higher than 2e3 + if rnd.Float64() > 0.99 { + return 0 + } + return rnd.Float64()*r - r/2 +} + +func randInput(rnd *rand.Rand) input { + x := make([]float64, 8) + for j := range x { + x[j] = randnum(rnd) + } + is := make([]int, 3) + for j := range is { + is[j] = rand.Intn(1000) + } + kode := rand.Intn(2) + 1 + id := rand.Intn(2) + n := rand.Intn(5) + 1 + yr := make([]float64, n+1) + yi := make([]float64, n+1) + for j := range yr { + yr[j] = randnum(rnd) + yi[j] = randnum(rnd) + } + tol := 1e-14 + + return input{ + x, is, kode, id, yr, yi, n, tol, + } +} + +const nInputs = 100000 + +func TestAiry(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zairytest(t, in.x, in.kode, in.id) + } +} + +func TestZacai(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zacaitest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZbknu(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zbknutest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZasyi(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zasyitest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZseri(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zseritest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZmlri(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zmlritest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZkscl(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zkscltest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi) + } +} + +func TestZuchk(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zuchktest(t, in.x, in.is, in.tol) + } +} + +func TestZs1s2(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zs1s2test(t, in.x, in.is) + } +} + +func zs1s2test(t *testing.T, x []float64, is []int) { + + type data struct { + ZRR, ZRI, S1R, S1I, S2R, S2I float64 + NZ int + ASCLE, ALIM float64 + IUF int + } + + input := data{ + x[0], x[1], x[2], x[3], x[4], x[5], + is[0], + x[6], x[7], + is[1], + } + + zr := complex(input.ZRR, input.ZRI) + s1 := complex(input.S1R, input.S1I) + s2 := complex(input.S2R, input.S2I) + impl := func(input data) data { + s1, s2, nz, iuf := Zs1s2(zr, s1, s2, input.ASCLE, input.ALIM, input.IUF) + zrr := real(zr) + zri := imag(zr) + s1r := real(s1) + s1i := imag(s1) + s2r := real(s2) + s2i := imag(s2) + alim := input.ALIM + ascle := input.ASCLE + return data{zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf} + } + + comp := func(input data) data { + zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf := + zs1s2Orig(input.ZRR, input.ZRI, input.S1R, input.S1I, input.S2R, input.S2I, input.NZ, input.ASCLE, input.ALIM, input.IUF) + return data{zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf} + } + + oi := impl(input) + oc := comp(input) + + sameF64(t, "zs1s2 zrr", oc.ZRR, oi.ZRR) + sameF64(t, "zs1s2 zri", oc.ZRI, oi.ZRI) + sameF64(t, "zs1s2 s1r", oc.S1R, oi.S1R) + sameF64(t, "zs1s2 s1i", oc.S1I, oi.S1I) + sameF64(t, "zs1s2 s2r", oc.S2R, oi.S2R) + sameF64(t, "zs1s2 s2i", oc.S2I, oi.S2I) + sameF64(t, "zs1s2 ascle", oc.ASCLE, oi.ASCLE) + sameF64(t, "zs1s2 alim", oc.ALIM, oi.ALIM) + sameInt(t, "iuf", oc.IUF, oi.IUF) + sameInt(t, "nz", oc.NZ, oi.NZ) +} + +func zuchktest(t *testing.T, x []float64, is []int, tol float64) { + YR := x[0] + YI := x[1] + NZ := is[0] + ASCLE := x[2] + TOL := tol + + YRfort, YIfort, NZfort, ASCLEfort, TOLfort := zuchkOrig(YR, YI, NZ, ASCLE, TOL) + y := complex(YR, YI) + NZamos := Zuchk(y, ASCLE, TOL) + YRamos := real(y) + YIamos := imag(y) + ASCLEamos := ASCLE + TOLamos := TOL + + sameF64(t, "zuchk yr", YRfort, YRamos) + sameF64(t, "zuchk yi", YIfort, YIamos) + sameInt(t, "zuchk nz", NZfort, NZamos) + sameF64(t, "zuchk ascle", ASCLEfort, ASCLEamos) + sameF64(t, "zuchk tol", TOLfort, TOLamos) +} + +func zkscltest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64) { + ZRR := x[0] + ZRI := x[1] + FNU := x[2] + NZ := is[1] + ELIM := x[3] + ASCLE := x[4] + RZR := x[6] + RZI := x[7] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRRfort, ZRIfort, FNUfort, Nfort, YRfort, YIfort, NZfort, RZRfort, RZIfort, ASCLEfort, TOLfort, ELIMfort := + zksclOrig(ZRR, ZRI, FNU, n, yrfort, yifort, NZ, RZR, RZI, ASCLE, tol, ELIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRRamos, ZRIamos, FNUamos, Namos, YRamos, YIamos, NZamos, RZRamos, RZIamos, ASCLEamos, TOLamos, ELIMamos := + Zkscl(ZRR, ZRI, FNU, n, yramos, yiamos, NZ, RZR, RZI, ASCLE, tol, ELIM) + + sameF64(t, "zkscl zrr", ZRRfort, ZRRamos) + sameF64(t, "zkscl zri", ZRIfort, ZRIamos) + sameF64(t, "zkscl fnu", FNUfort, FNUamos) + sameInt(t, "zkscl n", Nfort, Namos) + sameInt(t, "zkscl nz", NZfort, NZamos) + sameF64(t, "zkscl rzr", RZRfort, RZRamos) + sameF64(t, "zkscl rzi", RZIfort, RZIamos) + sameF64(t, "zkscl ascle", ASCLEfort, ASCLEamos) + sameF64(t, "zkscl tol", TOLfort, TOLamos) + sameF64(t, "zkscl elim", ELIMfort, ELIMamos) + + sameF64SApprox(t, "zkscl yr", YRfort, YRamos, 1e-14) + sameF64SApprox(t, "zkscl yi", YIfort, YIamos, 1e-14) +} + +func zmlritest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort := + zmlriOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, TOLamos := + Zmlri(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, tol) + + sameF64(t, "zmlri zr", ZRfort, ZRamos) + sameF64(t, "zmlri zi", ZIfort, ZIamos) + sameF64(t, "zmlri fnu", FNUfort, FNUamos) + sameInt(t, "zmlri kode", KODEfort, KODEamos) + sameInt(t, "zmlri n", Nfort, Namos) + sameInt(t, "zmlri nz", NZfort, NZamos) + sameF64(t, "zmlri tol", TOLfort, TOLamos) + + sameF64S(t, "zmlri yr", YRfort, YRamos) + sameF64S(t, "zmlri yi", YIfort, YIamos) +} + +func zseritest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort, ELIMfort, ALIMfort := + zseriOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + y := make([]complex128, len(yramos)) + for i, v := range yramos { + y[i] = complex(v, yiamos[i]) + } + z := complex(ZR, ZI) + + NZamos := Zseri(z, FNU, KODE, n, y[1:], tol, ELIM, ALIM) + + ZRamos := real(z) + ZIamos := imag(z) + FNUamos := FNU + KODEamos := KODE + Namos := n + TOLamos := tol + ELIMamos := ELIM + ALIMamos := ALIM + YRamos := make([]float64, len(y)) + YIamos := make([]float64, len(y)) + for i, v := range y { + YRamos[i] = real(v) + YIamos[i] = imag(v) + } + + sameF64(t, "zseri zr", ZRfort, ZRamos) + sameF64(t, "zseri zi", ZIfort, ZIamos) + sameF64(t, "zseri fnu", FNUfort, FNUamos) + sameInt(t, "zseri kode", KODEfort, KODEamos) + sameInt(t, "zseri n", Nfort, Namos) + sameInt(t, "zseri nz", NZfort, NZamos) + sameF64(t, "zseri tol", TOLfort, TOLamos) + sameF64(t, "zseri elim", ELIMfort, ELIMamos) + sameF64(t, "zseri elim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zseri yr", YRfort, YRamos, 1e-10) + sameF64SApprox(t, "zseri yi", YIfort, YIamos, 1e-10) +} + +func zasyitest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + RL := x[5] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, RLfort, TOLfort, ELIMfort, ALIMfort := + zasyiOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, RL, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, RLamos, TOLamos, ELIMamos, ALIMamos := + Zasyi(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, RL, tol, ELIM, ALIM) + + sameF64(t, "zasyi zr", ZRfort, ZRamos) + sameF64(t, "zasyi zr", ZIfort, ZIamos) + sameF64(t, "zasyi fnu", FNUfort, FNUamos) + sameInt(t, "zasyi kode", KODEfort, KODEamos) + sameInt(t, "zasyi n", Nfort, Namos) + sameInt(t, "zasyi nz", NZfort, NZamos) + sameF64(t, "zasyi rl", RLfort, RLamos) + sameF64(t, "zasyi tol", TOLfort, TOLamos) + sameF64(t, "zasyi elim", ELIMfort, ELIMamos) + sameF64(t, "zasyi alim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zasyi yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zasyi yi", YIfort, YIamos, 1e-12) +} + +func zbknutest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort, ELIMfort, ALIMfort := + zbknuOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, TOLamos, ELIMamos, ALIMamos := + Zbknu(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, tol, ELIM, ALIM) + + sameF64(t, "zbknu zr", ZRfort, ZRamos) + sameF64(t, "zbknu zr", ZIfort, ZIamos) + sameF64(t, "zbknu fnu", FNUfort, FNUamos) + sameInt(t, "zbknu kode", KODEfort, KODEamos) + sameInt(t, "zbknu n", Nfort, Namos) + sameInt(t, "zbknu nz", NZfort, NZamos) + sameF64(t, "zbknu tol", TOLfort, TOLamos) + sameF64(t, "zbknu elim", ELIMfort, ELIMamos) + sameF64(t, "zbknu alim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zbknu yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zbknu yi", YIfort, YIamos, 1e-12) +} + +func zairytest(t *testing.T, x []float64, kode, id int) { + ZR := x[0] + ZI := x[1] + KODE := kode + ID := id + + AIRfort, AIIfort, NZfort := zairyOrig(ZR, ZI, ID, KODE) + AIRamos, AIIamos, NZamos := Zairy(ZR, ZI, ID, KODE) + + sameF64Approx(t, "zairy air", AIRfort, AIRamos, 1e-12) + sameF64Approx(t, "zairy aii", AIIfort, AIIamos, 1e-12) + sameInt(t, "zairy nz", NZfort, NZamos) +} + +func zacaitest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + MR := is[2] + ELIM := x[3] + ALIM := x[4] + RL := x[5] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, MRfort, Nfort, YRfort, YIfort, NZfort, RLfort, TOLfort, ELIMfort, ALIMfort := + zacaiOrig(ZR, ZI, FNU, KODE, MR, n, yrfort, yifort, NZ, RL, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, MRamos, Namos, YRamos, YIamos, NZamos, RLamos, TOLamos, ELIMamos, ALIMamos := + Zacai(ZR, ZI, FNU, KODE, MR, n, yramos, yiamos, NZ, RL, tol, ELIM, ALIM) + + sameF64(t, "zacai zr", ZRfort, ZRamos) + sameF64(t, "zacai zi", ZIfort, ZIamos) + sameF64(t, "zacai fnu", FNUfort, FNUamos) + sameInt(t, "zacai kode", KODEfort, KODEamos) + sameInt(t, "zacai mr", MRfort, MRamos) + sameInt(t, "zacai n", Nfort, Namos) + sameInt(t, "zacai nz", NZfort, NZamos) + sameF64(t, "zacai rl", RLfort, RLamos) + sameF64(t, "zacai tol", TOLfort, TOLamos) + sameF64(t, "zacai elim", ELIMfort, ELIMamos) + sameF64(t, "zacai elim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zacai yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zacai yi", YIfort, YIamos, 1e-12) +} + +func sameF64(t *testing.T, str string, c, native float64) { + if math.IsNaN(c) && math.IsNaN(native) { + return + } + if c == native { + return + } + cb := math.Float64bits(c) + nb := math.Float64bits(native) + t.Errorf("Case %s: Float64 mismatch. c = %v, native = %v\n cb: %v, nb: %v\n", str, c, native, cb, nb) +} + +func sameF64Approx(t *testing.T, str string, c, native, tol float64) { + if math.IsNaN(c) && math.IsNaN(native) { + return + } + if floats.EqualWithinAbsOrRel(c, native, tol, tol) { + return + } + // Have a much looser tolerance for correctness when the values are large. + // Floating point noise makes the relative tolerance difference greater for + // higher values. + if c > 1e200 && floats.EqualWithinAbsOrRel(c, native, 10, 10) { + return + } + cb := math.Float64bits(c) + nb := math.Float64bits(native) + t.Errorf("Case %s: Float64 mismatch. c = %v, native = %v\n cb: %v, nb: %v\n", str, c, native, cb, nb) +} + +func sameInt(t *testing.T, str string, c, native int) { + if c != native { + t.Errorf("Case %s: Int mismatch. c = %v, native = %v.", str, c, native) + } +} + +func sameF64S(t *testing.T, str string, c, native []float64) { + if len(c) != len(native) { + panic(str) + } + for i, v := range c { + sameF64(t, str+"_idx_"+strconv.Itoa(i), v, native[i]) + } +} + +func sameF64SApprox(t *testing.T, str string, c, native []float64, tol float64) { + if len(c) != len(native) { + panic(str) + } + for i, v := range c { + sameF64Approx(t, str+"_idx_"+strconv.Itoa(i), v, native[i], tol) + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/Make.files b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/Make.files new file mode 100644 index 00000000..81c7c715 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/Make.files @@ -0,0 +1,5 @@ +$(CUR_SRCS) += d1mach.f zabs.f zasyi.f zbesk.f zbknu.f zexp.f zmlt.f zshch.f zuni1.f zunk2.f \ + dgamln.f zacai.f zbesh.f zbesy.f zbuni.f zkscl.f zrati.f zsqrt.f zuni2.f zuoik.f \ + i1mach.f zacon.f zbesi.f zbinu.f zbunk.f zlog.f zs1s2.f zuchk.f zunik.f zwrsk.f \ + xerror.f zairy.f zbesj.f zbiry.f zdiv.f zmlri.f zseri.f zunhj.f zunk1.f + diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/d1mach.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/d1mach.f new file mode 100644 index 00000000..0d344def --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/d1mach.f @@ -0,0 +1,97 @@ +*DECK D1MACH + DOUBLE PRECISION FUNCTION D1MACH(I) +C***BEGIN PROLOGUE D1MACH +C***DATE WRITTEN 750101 (YYMMDD) +C***REVISION DATE 890213 (YYMMDD) +C***CATEGORY NO. R1 +C***KEYWORDS LIBRARY=SLATEC,TYPE=DOUBLE PRECISION(R1MACH-S D1MACH-D), +C MACHINE CONSTANTS +C***AUTHOR FOX, P. A., (BELL LABS) +C HALL, A. D., (BELL LABS) +C SCHRYER, N. L., (BELL LABS) +C***PURPOSE Returns double precision machine dependent constants +C***DESCRIPTION +C +C D1MACH can be used to obtain machine-dependent parameters +C for the local machine environment. It is a function +C subprogram with one (input) argument, and can be called +C as follows, for example +C +C D = D1MACH(I) +C +C where I=1,...,5. The (output) value of D above is +C determined by the (input) value of I. The results for +C various values of I are discussed below. +C +C D1MACH( 1) = B**(EMIN-1), the smallest positive magnitude. +C D1MACH( 2) = B**EMAX*(1 - B**(-T)), the largest magnitude. +C D1MACH( 3) = B**(-T), the smallest relative spacing. +C D1MACH( 4) = B**(1-T), the largest relative spacing. +C D1MACH( 5) = LOG10(B) +C +C Assume double precision numbers are represented in the T-digit, +C base-B form +C +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, 0 .LT. X(1), and +C EMIN .LE. E .LE. EMAX. +C +C The values of B, T, EMIN and EMAX are provided in I1MACH as +C follows: +C I1MACH(10) = B, the base. +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, +C the desired set of DATA statements should be activated by +C removing the C from column 1. Also, the values of +C D1MACH(1) - D1MACH(4) should be checked for consistency +C with the local operating system. +C +C***REFERENCES FOX P.A., HALL A.D., SCHRYER N.L.,*FRAMEWORK FOR A +C PORTABLE LIBRARY*, ACM TRANSACTIONS ON MATHEMATICAL +C SOFTWARE, VOL. 4, NO. 2, JUNE 1978, PP. 177-188. +C***ROUTINES CALLED XERROR +C***END PROLOGUE D1MACH +C + INTEGER SMALL(4) + INTEGER LARGE(4) + INTEGER RIGHT(4) + INTEGER DIVER(4) + INTEGER LOG10(4) +C + DOUBLE PRECISION DMACH(5) + SAVE DMACH +C +C EQUIVALENCE (DMACH(1),SMALL(1)) +C EQUIVALENCE (DMACH(2),LARGE(1)) +C EQUIVALENCE (DMACH(3),RIGHT(1)) +C EQUIVALENCE (DMACH(4),DIVER(1)) +C EQUIVALENCE (DMACH(5),LOG10(1)) +C +C MACHINE CONSTANTS FOR THE IBM PC +C ASSUMES THAT ALL ARITHMETIC IS DONE IN DOUBLE PRECISION +C ON 8088, I.E., NOT IN 80 BIT FORM FOR THE 8087. +C + DATA DMACH(1) / 2.23D-308 / +C DATA SMALL(1),SMALL(2) / 2002288515, 1050897 / + DATA DMACH(2) / 1.79D-308 / +C DATA LARGE(1),LARGE(2) / 1487780761, 2146426097 / + DATA DMACH(3) / 1.11D-16 / +C DATA RIGHT(1),RIGHT(2) / -1209488034, 1017118298 / + DATA DMACH(4) / 2.22D-16 / +C DATA DIVER(1),DIVER(2) / -1209488034, 1018166874 / + DATA DMACH(5) / 0.3010299956639812 / +C DATA LOG10(1),LOG10(2) / 1352628735, 1070810131 / +C +C +C***FIRST EXECUTABLE STATEMENT D1MACH + IF (I .LT. 1 .OR. I .GT. 5) + 1 CALL XERROR ('D1MACH -- I OUT OF BOUNDS', 25, 1, 2) +C + D1MACH = DMACH(I) + RETURN +C + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/dgamln.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/dgamln.f new file mode 100644 index 00000000..792014be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/dgamln.f @@ -0,0 +1,189 @@ + DOUBLE PRECISION FUNCTION DGAMLN(Z,IERR) +C***BEGIN PROLOGUE DGAMLN +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 830501 (YYMMDD) +C***CATEGORY NO. B5F +C***KEYWORDS GAMMA FUNCTION,LOGARITHM OF GAMMA FUNCTION +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE LOGARITHM OF THE GAMMA FUNCTION +C***DESCRIPTION +C +C **** A DOUBLE PRECISION ROUTINE **** +C DGAMLN COMPUTES THE NATURAL LOG OF THE GAMMA FUNCTION FOR +C Z.GT.0. THE ASYMPTOTIC EXPANSION IS USED TO GENERATE VALUES +C GREATER THAN ZMIN WHICH ARE ADJUSTED BY THE RECURSION +C G(Z+1)=Z*G(Z) FOR Z.LE.ZMIN. THE FUNCTION WAS MADE AS +C PORTABLE AS POSSIBLE BY COMPUTIMG ZMIN FROM THE NUMBER OF BASE +C 10 DIGITS IN A WORD, RLN=AMAX1(-ALOG10(R1MACH(4)),0.5E-18) +C LIMITED TO 18 DIGITS OF (RELATIVE) ACCURACY. +C +C SINCE INTEGER ARGUMENTS ARE COMMON, A TABLE LOOK UP ON 100 +C VALUES IS USED FOR SPEED OF EXECUTION. +C +C DESCRIPTION OF ARGUMENTS +C +C INPUT Z IS D0UBLE PRECISION +C Z - ARGUMENT, Z.GT.0.0D0 +C +C OUTPUT DGAMLN IS DOUBLE PRECISION +C DGAMLN - NATURAL LOG OF THE GAMMA FUNCTION AT Z.NE.0.0D0 +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN, COMPUTATION COMPLETED +C IERR=1, Z.LE.0.0D0, NO COMPUTATION +C +C +C***REFERENCES COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C***ROUTINES CALLED I1MACH,D1MACH +C***END PROLOGUE DGAMLN + DOUBLE PRECISION CF, CON, FLN, FZ, GLN, RLN, S, TLG, TRM, TST, + * T1, WDTOL, Z, ZDMY, ZINC, ZM, ZMIN, ZP, ZSQ, D1MACH + INTEGER I, IERR, I1M, K, MZ, NZ, I1MACH + DIMENSION CF(22), GLN(100) +C LNGAMMA(N), N=1,100 + DATA GLN(1), GLN(2), GLN(3), GLN(4), GLN(5), GLN(6), GLN(7), + 1 GLN(8), GLN(9), GLN(10), GLN(11), GLN(12), GLN(13), GLN(14), + 2 GLN(15), GLN(16), GLN(17), GLN(18), GLN(19), GLN(20), + 3 GLN(21), GLN(22)/ + 4 0.00000000000000000D+00, 0.00000000000000000D+00, + 5 6.93147180559945309D-01, 1.79175946922805500D+00, + 6 3.17805383034794562D+00, 4.78749174278204599D+00, + 7 6.57925121201010100D+00, 8.52516136106541430D+00, + 8 1.06046029027452502D+01, 1.28018274800814696D+01, + 9 1.51044125730755153D+01, 1.75023078458738858D+01, + A 1.99872144956618861D+01, 2.25521638531234229D+01, + B 2.51912211827386815D+01, 2.78992713838408916D+01, + C 3.06718601060806728D+01, 3.35050734501368889D+01, + D 3.63954452080330536D+01, 3.93398841871994940D+01, + E 4.23356164607534850D+01, 4.53801388984769080D+01/ + DATA GLN(23), GLN(24), GLN(25), GLN(26), GLN(27), GLN(28), + 1 GLN(29), GLN(30), GLN(31), GLN(32), GLN(33), GLN(34), + 2 GLN(35), GLN(36), GLN(37), GLN(38), GLN(39), GLN(40), + 3 GLN(41), GLN(42), GLN(43), GLN(44)/ + 4 4.84711813518352239D+01, 5.16066755677643736D+01, + 5 5.47847293981123192D+01, 5.80036052229805199D+01, + 6 6.12617017610020020D+01, 6.45575386270063311D+01, + 7 6.78897431371815350D+01, 7.12570389671680090D+01, + 8 7.46582363488301644D+01, 7.80922235533153106D+01, + 9 8.15579594561150372D+01, 8.50544670175815174D+01, + A 8.85808275421976788D+01, 9.21361756036870925D+01, + B 9.57196945421432025D+01, 9.93306124547874269D+01, + C 1.02968198614513813D+02, 1.06631760260643459D+02, + D 1.10320639714757395D+02, 1.14034211781461703D+02, + E 1.17771881399745072D+02, 1.21533081515438634D+02/ + DATA GLN(45), GLN(46), GLN(47), GLN(48), GLN(49), GLN(50), + 1 GLN(51), GLN(52), GLN(53), GLN(54), GLN(55), GLN(56), + 2 GLN(57), GLN(58), GLN(59), GLN(60), GLN(61), GLN(62), + 3 GLN(63), GLN(64), GLN(65), GLN(66)/ + 4 1.25317271149356895D+02, 1.29123933639127215D+02, + 5 1.32952575035616310D+02, 1.36802722637326368D+02, + 6 1.40673923648234259D+02, 1.44565743946344886D+02, + 7 1.48477766951773032D+02, 1.52409592584497358D+02, + 8 1.56360836303078785D+02, 1.60331128216630907D+02, + 9 1.64320112263195181D+02, 1.68327445448427652D+02, + A 1.72352797139162802D+02, 1.76395848406997352D+02, + B 1.80456291417543771D+02, 1.84533828861449491D+02, + C 1.88628173423671591D+02, 1.92739047287844902D+02, + D 1.96866181672889994D+02, 2.01009316399281527D+02, + E 2.05168199482641199D+02, 2.09342586752536836D+02/ + DATA GLN(67), GLN(68), GLN(69), GLN(70), GLN(71), GLN(72), + 1 GLN(73), GLN(74), GLN(75), GLN(76), GLN(77), GLN(78), + 2 GLN(79), GLN(80), GLN(81), GLN(82), GLN(83), GLN(84), + 3 GLN(85), GLN(86), GLN(87), GLN(88)/ + 4 2.13532241494563261D+02, 2.17736934113954227D+02, + 5 2.21956441819130334D+02, 2.26190548323727593D+02, + 6 2.30439043565776952D+02, 2.34701723442818268D+02, + 7 2.38978389561834323D+02, 2.43268849002982714D+02, + 8 2.47572914096186884D+02, 2.51890402209723194D+02, + 9 2.56221135550009525D+02, 2.60564940971863209D+02, + A 2.64921649798552801D+02, 2.69291097651019823D+02, + B 2.73673124285693704D+02, 2.78067573440366143D+02, + C 2.82474292687630396D+02, 2.86893133295426994D+02, + D 2.91323950094270308D+02, 2.95766601350760624D+02, + E 3.00220948647014132D+02, 3.04686856765668715D+02/ + DATA GLN(89), GLN(90), GLN(91), GLN(92), GLN(93), GLN(94), + 1 GLN(95), GLN(96), GLN(97), GLN(98), GLN(99), GLN(100)/ + 2 3.09164193580146922D+02, 3.13652829949879062D+02, + 3 3.18152639620209327D+02, 3.22663499126726177D+02, + 4 3.27185287703775217D+02, 3.31717887196928473D+02, + 5 3.36261181979198477D+02, 3.40815058870799018D+02, + 6 3.45379407062266854D+02, 3.49954118040770237D+02, + 7 3.54539085519440809D+02, 3.59134205369575399D+02/ +C COEFFICIENTS OF ASYMPTOTIC EXPANSION + DATA CF(1), CF(2), CF(3), CF(4), CF(5), CF(6), CF(7), CF(8), + 1 CF(9), CF(10), CF(11), CF(12), CF(13), CF(14), CF(15), + 2 CF(16), CF(17), CF(18), CF(19), CF(20), CF(21), CF(22)/ + 3 8.33333333333333333D-02, -2.77777777777777778D-03, + 4 7.93650793650793651D-04, -5.95238095238095238D-04, + 5 8.41750841750841751D-04, -1.91752691752691753D-03, + 6 6.41025641025641026D-03, -2.95506535947712418D-02, + 7 1.79644372368830573D-01, -1.39243221690590112D+00, + 8 1.34028640441683920D+01, -1.56848284626002017D+02, + 9 2.19310333333333333D+03, -3.61087712537249894D+04, + A 6.91472268851313067D+05, -1.52382215394074162D+07, + B 3.82900751391414141D+08, -1.08822660357843911D+10, + C 3.47320283765002252D+11, -1.23696021422692745D+13, + D 4.88788064793079335D+14, -2.13203339609193739D+16/ +C +C LN(2*PI) + DATA CON / 1.83787706640934548D+00/ +C +C***FIRST EXECUTABLE STATEMENT DGAMLN + IERR=0 + IF (Z.LE.0.0D0) GO TO 70 + IF (Z.GT.101.0D0) GO TO 10 + NZ = INT(SNGL(Z)) + FZ = Z - FLOAT(NZ) + IF (FZ.GT.0.0D0) GO TO 10 + IF (NZ.GT.100) GO TO 10 + DGAMLN = GLN(NZ) + RETURN + 10 CONTINUE + WDTOL = D1MACH(4) + WDTOL = DMAX1(WDTOL,0.5D-18) + I1M = I1MACH(14) + RLN = D1MACH(5)*FLOAT(I1M) + FLN = DMIN1(RLN,20.0D0) + FLN = DMAX1(FLN,3.0D0) + FLN = FLN - 3.0D0 + ZM = 1.8000D0 + 0.3875D0*FLN + MZ = INT(SNGL(ZM)) + 1 + ZMIN = FLOAT(MZ) + ZDMY = Z + ZINC = 0.0D0 + IF (Z.GE.ZMIN) GO TO 20 + ZINC = ZMIN - FLOAT(NZ) + ZDMY = Z + ZINC + 20 CONTINUE + ZP = 1.0D0/ZDMY + T1 = CF(1)*ZP + S = T1 + IF (ZP.LT.WDTOL) GO TO 40 + ZSQ = ZP*ZP + TST = T1*WDTOL + DO 30 K=2,22 + ZP = ZP*ZSQ + TRM = CF(K)*ZP + IF (DABS(TRM).LT.TST) GO TO 40 + S = S + TRM + 30 CONTINUE + 40 CONTINUE + IF (ZINC.NE.0.0D0) GO TO 50 + TLG = DLOG(Z) + DGAMLN = Z*(TLG-1.0D0) + 0.5D0*(CON-TLG) + S + RETURN + 50 CONTINUE + ZP = 1.0D0 + NZ = INT(SNGL(ZINC)) + DO 60 I=1,NZ + ZP = ZP*(Z+FLOAT(I-1)) + 60 CONTINUE + TLG = DLOG(ZDMY) + DGAMLN = ZDMY*(TLG-1.0D0) - DLOG(ZP) + 0.5D0*(CON-TLG) + S + RETURN +C +C + 70 CONTINUE + IERR=1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/fortran.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/fortran.go new file mode 100644 index 00000000..52e17e1f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/fortran.go @@ -0,0 +1,366 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build fortran +// TODO(jonlawlor): remove fortran build tag when gonum only supports go 1.7+. + +package amoslib + +/* +double mzabs_(double * ar, double * ai); +void zs1s2_(double * ZRR, double * ZRI, double * S1R, double * S1I, double * S2R, double * S2I, int* NZ, double *ASCLE, double * ALIM, int * IUF); +void zacai_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, int * MR, double * YR, double * YI, int * NZ, double * RL, double * tol, double * elim, double * alim); +void zseri_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol, double * elim, double * alim); +void zmlri_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol); +void zbknu_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol, double * elim, double * alim); +void zasyi_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ,double * RL, double * tol, double * elim, double * alim); +void zkscl_(double * ZRR, double * ZRI, double * FNU, int * N, double * YR, double * YI, int * NZ, double * RZR, double * RZI, double * ASCLE, double * tol, double * elim); +void zuchk_(double * YR, double * YI, int * NZ, double * ASCLE, double * TOL); +void zairy_(double * ZR, double * ZI, int * ID, int * KODE, double * AIR, double * AII, int * NZ, int * IERR); +void zlog_(double * ar, double * ai, double * br, double * bi, int * ierr); +void zexp_(double * ar, double * ai, double * br, double * bi); +void zsqrt_(double * ar, double * ai, double * br, double * bi); +void zdiv_(double * ar, double * ai, double * br, double * bi, double * cr, double * ci); +void zmlt_(double * ar, double * ai, double * br, double * bi, double * cr, double * ci); +double dgamln_(double *z, int * ierr); +void zshch_(double * zr, double * zi, double * cshr, double * cshi, double * cchr, double * cchi); +double mysqrt_(double * A); +double myexp_(double * A); +double mycos_(double * A); +double mysin_(double * A); +double mylog_(double * A); +double mytan_(double * A); +double myatan_(double * A); +double myabs_(double * A); +double mymin_(double * A, double * B); +double mymax_(double * A, double * B); +*/ +import "C" +import "unsafe" + +func MinFort(a, b float64) float64 { + ans := C.mymin_((*C.double)(&a), (*C.double)(&b)) + return float64(ans) +} + +func MaxFort(a, b float64) float64 { + ans := C.mymax_((*C.double)(&a), (*C.double)(&b)) + return float64(ans) +} + +func AbsFort(a float64) float64 { + ans := C.myabs_((*C.double)(&a)) + return float64(ans) +} + +func AtanFort(a float64) float64 { + ans := C.myatan_((*C.double)(&a)) + return float64(ans) +} + +func TanFort(a float64) float64 { + ans := C.mytan_((*C.double)(&a)) + return float64(ans) +} + +func LogFort(a float64) float64 { + ans := C.mylog_((*C.double)(&a)) + return float64(ans) +} + +func SinFort(a float64) float64 { + ans := C.mysin_((*C.double)(&a)) + return float64(ans) +} + +func CosFort(a float64) float64 { + ans := C.mycos_((*C.double)(&a)) + return float64(ans) +} + +func ExpFort(a float64) float64 { + ans := C.myexp_((*C.double)(&a)) + return float64(ans) +} + +func SqrtFort(a float64) float64 { + ans := C.mysqrt_((*C.double)(&a)) + return float64(ans) +} + +func DgamlnFort(a float64) float64 { + var ierr int + pierr := (*C.int)(unsafe.Pointer(&ierr)) + pa := (*C.double)(&a) + ans := C.dgamln_(pa, pierr) + return (float64)(ans) +} + +func ZmltFort(a, b complex128) complex128 { + ar := real(a) + ai := imag(a) + br := real(b) + bi := imag(b) + var cr, ci float64 + C.zmlt_( + (*C.double)(&ar), (*C.double)(&ai), + (*C.double)(&br), (*C.double)(&bi), + (*C.double)(&cr), (*C.double)(&ci), + ) + return complex(cr, ci) +} + +func ZdivFort(a, b complex128) complex128 { + ar := real(a) + ai := imag(a) + br := real(b) + bi := imag(b) + var cr, ci float64 + C.zdiv_( + (*C.double)(&ar), (*C.double)(&ai), + (*C.double)(&br), (*C.double)(&bi), + (*C.double)(&cr), (*C.double)(&ci), + ) + return complex(cr, ci) +} + +func ZabsFort(a complex128) float64 { + ar := real(a) + ai := imag(a) + return float64(C.mzabs_((*C.double)(&ar), (*C.double)(&ai))) +} + +func ZsqrtFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + + C.zsqrt_(par, pai, pbr, pbi) + return complex(br, bi) +} + +func ZexpFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + + C.zexp_(par, pai, pbr, pbi) + return complex(br, bi) +} + +func ZlogFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + var ierr int + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + pierr := (*C.int)(unsafe.Pointer(&ierr)) + C.zlog_(par, pai, pbr, pbi, pierr) + return complex(br, bi) +} + +func Zshch(ZR, ZI, CSHR, CSHI, CCHR, CCHI float64) (ZRout, ZIout, CSHRout, CSHIout, CCHRout, CCHIout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pcshr := (*C.double)(&CSHR) + pcshi := (*C.double)(&CSHI) + pcchr := (*C.double)(&CCHR) + pcchi := (*C.double)(&CCHI) + + C.zshch_(pzr, pzi, pcshr, pcshi, pcchr, pcchi) + return ZR, ZI, CSHR, CSHI, CCHR, CCHI +} + +func ZairyFort(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + var IERR int + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pid := (*C.int)(unsafe.Pointer(&ID)) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + + pair := (*C.double)(&AIR) + paii := (*C.double)(&AII) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pierr := (*C.int)(unsafe.Pointer(&IERR)) + C.zairy_(pzr, pzi, pid, pkode, pair, paii, pnz, pierr) + + NZ = int(*pnz) + return AIR, AII, NZ +} + +func ZksclFort(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRout, ZIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + + pzrr := (*C.double)(&ZRR) + pzri := (*C.double)(&ZRI) + pfnu := (*C.double)(&FNU) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + przr := (*C.double)(&RZR) + przi := (*C.double)(&RZI) + pascle := (*C.double)(&ASCLE) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + + C.zkscl_(pzrr, pzri, pfnu, pn, pyr, pyi, pnz, przr, przi, pascle, ptol, pelim) + N = int(*pn) + NZ = int(*pnz) + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +func ZbknuFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zbknu_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +func ZasyiFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + prl := (*C.double)(&RL) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zasyi_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, prl, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +func ZuchkFort(YR, YI float64, NZ int, ASCLE, TOL float64) (YRout, YIout float64, NZout int, ASCLEout, TOLout float64) { + pyr := (*C.double)(&YR) + pyi := (*C.double)(&YI) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pascle := (*C.double)(&ASCLE) + ptol := (*C.double)(&TOL) + + C.zuchk_(pyr, pyi, pnz, pascle, ptol) + return YR, YI, NZ, ASCLE, TOL +} + +func Zs1s2Fort(ZRR, ZRI, S1R, S1I, S2R, S2I float64, NZ int, ASCLE, ALIM float64, IUF int) ( + ZRRout, ZRIout, S1Rout, S1Iout, S2Rout, S2Iout float64, NZout int, ASCLEout, ALIMout float64, IUFout int) { + + pzrr := (*C.double)(&ZRR) + pzri := (*C.double)(&ZRI) + ps1r := (*C.double)(&S1R) + ps1i := (*C.double)(&S1I) + ps2r := (*C.double)(&S2R) + ps2i := (*C.double)(&S2I) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pascle := (*C.double)(&ASCLE) + palim := (*C.double)(&ALIM) + piuf := (*C.int)(unsafe.Pointer(&IUF)) + + C.zs1s2_(pzrr, pzri, ps1r, ps1i, ps2r, ps2i, pnz, pascle, palim, piuf) + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF +} + +func ZacaiFort(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pmr := (*C.int)(unsafe.Pointer(&MR)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + prl := (*C.double)(&RL) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zacai_(pzr, pzi, pfnu, pkode, pmr, pn, pyr, pyi, pnz, prl, ptol, pelim, palim) + KODE = int(*pkode) + MR = int(*pmr) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +func ZseriFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zseri_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +func ZmlriFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + + C.zmlri_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/i1mach.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/i1mach.f new file mode 100644 index 00000000..b9683336 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/i1mach.f @@ -0,0 +1,113 @@ +*DECK I1MACH + INTEGER FUNCTION I1MACH(I) +C***BEGIN PROLOGUE I1MACH +C***DATE WRITTEN 750101 (YYMMDD) +C***REVISION DATE 890213 (YYMMDD) +C***CATEGORY NO. R1 +C***KEYWORDS LIBRARY=SLATEC,TYPE=INTEGER(I1MACH-I),MACHINE CONSTANTS +C***AUTHOR FOX, P. A., (BELL LABS) +C HALL, A. D., (BELL LABS) +C SCHRYER, N. L., (BELL LABS) +C***PURPOSE Returns integer machine dependent constants +C***DESCRIPTION +C +C I1MACH can be used to obtain machine-dependent parameters +C for the local machine environment. It is a function +C subroutine with one (input) argument, and can be called +C as follows, for example +C +C K = I1MACH(I) +C +C where I=1,...,16. The (output) value of K above is +C determined by the (input) value of I. The results for +C various values of I are discussed below. +C +C I/O unit numbers. +C I1MACH( 1) = the standard input unit. +C I1MACH( 2) = the standard output unit. +C I1MACH( 3) = the standard punch unit. +C I1MACH( 4) = the standard error message unit. +C +C Words. +C I1MACH( 5) = the number of bits per integer storage unit. +C I1MACH( 6) = the number of characters per integer storage unit. +C +C Integers. +C assume integers are represented in the S-digit, base-A form +C +C sign ( X(S-1)*A**(S-1) + ... + X(1)*A + X(0) ) +C +C where 0 .LE. X(I) .LT. A for I=0,...,S-1. +C I1MACH( 7) = A, the base. +C I1MACH( 8) = S, the number of base-A digits. +C I1MACH( 9) = A**S - 1, the largest magnitude. +C +C Floating-Point Numbers. +C Assume floating-point numbers are represented in the T-digit, +C base-B form +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, +C 0 .LT. X(1), and EMIN .LE. E .LE. EMAX. +C I1MACH(10) = B, the base. +C +C Single-Precision +C I1MACH(11) = T, the number of base-B digits. +C I1MACH(12) = EMIN, the smallest exponent E. +C I1MACH(13) = EMAX, the largest exponent E. +C +C Double-Precision +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, +C the desired set of DATA statements should be activated by +C removing the C from column 1. Also, the values of +C I1MACH(1) - I1MACH(4) should be checked for consistency +C with the local operating system. +C +C***REFERENCES FOX P.A., HALL A.D., SCHRYER N.L.,*FRAMEWORK FOR A +C PORTABLE LIBRARY*, ACM TRANSACTIONS ON MATHEMATICAL +C SOFTWARE, VOL. 4, NO. 2, JUNE 1978, PP. 177-188. +C***ROUTINES CALLED (NONE) +C***END PROLOGUE I1MACH +C + INTEGER IMACH(16),OUTPUT + SAVE IMACH + EQUIVALENCE (IMACH(4),OUTPUT) +C +C MACHINE CONSTANTS FOR THE IBM PC +C + DATA IMACH( 1) / 5 / + DATA IMACH( 2) / 6 / + DATA IMACH( 3) / 0 / + DATA IMACH( 4) / 0 / + DATA IMACH( 5) / 32 / + DATA IMACH( 6) / 4 / + DATA IMACH( 7) / 2 / + DATA IMACH( 8) / 31 / + DATA IMACH( 9) / 2147483647 / + DATA IMACH(10) / 2 / + DATA IMACH(11) / 24 / + DATA IMACH(12) / -125 / + DATA IMACH(13) / 127 / + DATA IMACH(14) / 53 / + DATA IMACH(15) / -1021 / + DATA IMACH(16) / 1023 / +C +C***FIRST EXECUTABLE STATEMENT I1MACH + IF (I .LT. 1 .OR. I .GT. 16) GO TO 10 +C + I1MACH = IMACH(I) + RETURN +C + 10 CONTINUE + WRITE (UNIT = OUTPUT, FMT = 9000) + 9000 FORMAT ('1ERROR 1 IN I1MACH - I OUT OF BOUNDS') +C +C CALL FDUMP +C +C + STOP + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myabs.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myabs.f new file mode 100644 index 00000000..5060195c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myabs.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYABS(A) + DOUBLE PRECISION A + MYABS = DABS(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myatan.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myatan.f new file mode 100644 index 00000000..0887fdae --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myatan.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYATAN(A) + DOUBLE PRECISION A + MYATAN = DATAN(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mycos.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mycos.f new file mode 100644 index 00000000..c39e46df --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mycos.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYCOS(A) + DOUBLE PRECISION A + MYCOS = DCOS(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myexp.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myexp.f new file mode 100644 index 00000000..44a2a80b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/myexp.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYEXP(A) + DOUBLE PRECISION A + MYEXP = DEXP(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mylog.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mylog.f new file mode 100644 index 00000000..ac7e3a34 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mylog.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYLOG(A) + DOUBLE PRECISION A + MYLOG = DLOG(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymax.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymax.f new file mode 100644 index 00000000..0438eb46 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymax.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYMAX(A, B) + DOUBLE PRECISION A, B + MYMAX = DMAX1(A,B) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymin.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymin.f new file mode 100644 index 00000000..950606c6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mymin.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYMIN(A, B) + DOUBLE PRECISION A, B + MYMIN = DMIN1(A,B) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysin.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysin.f new file mode 100644 index 00000000..1663ed56 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysin.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYSIN(A) + DOUBLE PRECISION A + MYSIN = DSIN(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysqrt.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysqrt.f new file mode 100644 index 00000000..a3998389 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mysqrt.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYSQRT(A) + DOUBLE PRECISION A + MYSQRT = SQRT(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mytan.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mytan.f new file mode 100644 index 00000000..239aa682 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/mytan.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYTAN(A) + DOUBLE PRECISION A + MYTAN = DTAN(A) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/xerror.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/xerror.f new file mode 100644 index 00000000..baa55067 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/xerror.f @@ -0,0 +1,22 @@ + SUBROUTINE XERROR(MESS,NMESS,L1,L2) +C +C THIS IS A DUMMY XERROR ROUTINE TO PRINT ERROR MESSAGES WITH NMESS +C CHARACTERS. L1 AND L2 ARE DUMMY PARAMETERS TO MAKE THIS CALL +C COMPATIBLE WITH THE SLATEC XERROR ROUTINE. THIS IS A FORTRAN 77 +C ROUTINE. +C + CHARACTER*(*) MESS + NN=NMESS/70 + NR=NMESS-70*NN + IF(NR.NE.0) NN=NN+1 + K=1 + PRINT 900 + 900 FORMAT(/) + DO 10 I=1,NN + KMIN=MIN0(K+69,NMESS) + PRINT *, MESS(K:KMIN) + K=K+70 + 10 CONTINUE + PRINT 900 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zabs.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zabs.f new file mode 100644 index 00000000..23e00a64 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zabs.f @@ -0,0 +1,34 @@ + DOUBLE PRECISION FUNCTION MZABS(ZR, ZI) +C***BEGIN PROLOGUE ZABS +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C ZABS COMPUTES THE ABSOLUTE VALUE OR MAGNITUDE OF A DOUBLE +C PRECISION COMPLEX VARIABLE CMPLX(ZR,ZI) +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZABS + DOUBLE PRECISION ZR, ZI, U, V, Q, S + + MZABS = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + RETURN + END + +c U = DABS(ZR) +c V = DABS(ZI) +c S = U + V +C----------------------------------------------------------------------- +C S*1.0D0 MAKES AN UNNORMALIZED UNDERFLOW ON CDC MACHINES INTO A +C TRUE FLOATING ZERO +C----------------------------------------------------------------------- +c S = S*1.0D+0 +c IF (S.EQ.0.0D+0) GO TO 20 +c IF (U.GT.V) GO TO 10 +c Q = U/V +c ZABS = V*DSQRT(1.D+0+Q*Q) +c RETURN +c 10 Q = V/U +c ZABS = U*DSQRT(1.D+0+Q*Q) +c RETURN +c 20 ZABS = 0.0D+0 +c RETURN +c END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacai.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacai.f new file mode 100644 index 00000000..aa05a5c7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacai.f @@ -0,0 +1,99 @@ + SUBROUTINE ZACAI(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, + * ELIM, ALIM) +C***BEGIN PROLOGUE ZACAI +C***REFER TO ZAIRY +C +C ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +C +C K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +C MP=PI*MR*CMPLX(0.0,1.0) +C +C TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +C HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +C ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +C RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT IF ZACON +C IS CALLED FROM ZAIRY. +C +C***ROUTINES CALLED ZASYI,ZBKNU,ZMLRI,ZSERI,ZS1S2,D1MACH,ZABS +C***END PROLOGUE ZACAI +C COMPLEX CSGN,CSPN,C1,C2,Y,Z,ZN,CY + DOUBLE PRECISION ALIM, ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + * CSPNI, C1R, C1I, C2R, C2I, CYR, CYI, DFNU, ELIM, FMR, FNU, PI, + * RL, SGN, TOL, YY, YR, YI, ZR, ZI, ZNR, ZNI, D1MACH, ZABS + INTEGER INU, IUF, KODE, MR, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2) + DATA PI / 3.14159265358979324D0 / + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + NN = N + DFNU = FNU + DBLE(FLOAT(N-1)) + IF (AZ.LE.2.0D0) GO TO 10 + IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C POWER SERIES FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZSERI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM) + GO TO 40 + 20 CONTINUE + IF (AZ.LT.RL) GO TO 30 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZASYI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 80 + GO TO 40 + 30 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZMLRI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + IF(NW.LT.0) GO TO 80 + 40 CONTINUE +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION +C----------------------------------------------------------------------- + CALL ZBKNU(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 80 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) + CSGNR = 0.0D0 + CSGNI = SGN + IF (KODE.EQ.1) GO TO 50 + YY = -ZNI + CSGNR = -CSGNI*DSIN(YY) + CSGNI = CSGNI*DCOS(YY) + 50 CONTINUE +C----------------------------------------------------------------------- +C CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*SGN + CSPNR = DCOS(ARG) + CSPNI = DSIN(ARG) + IF (MOD(INU,2).EQ.0) GO TO 60 + CSPNR = -CSPNR + CSPNI = -CSPNI + 60 CONTINUE + C1R = CYR(1) + C1I = CYI(1) + C2R = YR(1) + C2I = YI(1) + IF (KODE.EQ.1) GO TO 70 + IUF = 0 + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + 70 CONTINUE + YR(1) = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI(1) = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + RETURN + 80 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacon.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacon.f new file mode 100644 index 00000000..ba593590 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zacon.f @@ -0,0 +1,203 @@ + SUBROUTINE ZACON(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZACON +C***REFER TO ZBESK,ZBESH +C +C ZACON APPLIES THE ANALYTIC CONTINUATION FORMULA +C +C K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +C MP=PI*MR*CMPLX(0.0,1.0) +C +C TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +C HALF Z PLANE +C +C***ROUTINES CALLED ZBINU,ZBKNU,ZS1S2,D1MACH,ZABS,ZMLT +C***END PROLOGUE ZACON +C COMPLEX CK,CONE,CSCL,CSCR,CSGN,CSPN,CY,CZERO,C1,C2,RZ,SC1,SC2,ST, +C *S1,S2,Y,Z,ZN + DOUBLE PRECISION ALIM, ARG, ASCLE, AS2, AZN, BRY, BSCLE, CKI, + * CKR, CONER, CPN, CSCL, CSCR, CSGNI, CSGNR, CSPNI, CSPNR, + * CSR, CSRR, CSSR, CYI, CYR, C1I, C1M, C1R, C2I, C2R, ELIM, FMR, + * FN, FNU, FNUL, PI, PTI, PTR, RAZN, RL, RZI, RZR, SC1I, SC1R, + * SC2I, SC2R, SGN, SPN, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, + * YY, ZEROR, ZI, ZNI, ZNR, ZR, D1MACH, ZABS + INTEGER I, INU, IUF, KFLAG, KODE, MR, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2), CSSR(3), CSRR(3), BRY(3) + DATA PI / 3.14159265358979324D0 / + DATA ZEROR,CONER / 0.0D0,1.0D0 / + NZ = 0 + ZNR = -ZR + ZNI = -ZI + NN = N + CALL ZBINU(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NW.LT.0) GO TO 90 +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION +C----------------------------------------------------------------------- + NN = MIN0(2,N) + CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 90 + S1R = CYR(1) + S1I = CYI(1) + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) + CSGNR = ZEROR + CSGNI = SGN + IF (KODE.EQ.1) GO TO 10 + YY = -ZNI + CPN = DCOS(YY) + SPN = DSIN(YY) + CALL ZMLT(CSGNR, CSGNI, CPN, SPN, CSGNR, CSGNI) + 10 CONTINUE +C----------------------------------------------------------------------- +C CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*SGN + CPN = DCOS(ARG) + SPN = DSIN(ARG) + CSPNR = CPN + CSPNI = SPN + IF (MOD(INU,2).EQ.0) GO TO 20 + CSPNR = -CSPNR + CSPNI = -CSPNI + 20 CONTINUE + IUF = 0 + C1R = S1R + C1I = S1I + C2R = YR(1) + C2I = YI(1) + ASCLE = 1.0D+3*D1MACH(1)/TOL + IF (KODE.EQ.1) GO TO 30 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC1R = C1R + SC1I = C1I + 30 CONTINUE + CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI) + CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI) + YR(1) = STR + PTR + YI(1) = STI + PTI + IF (N.EQ.1) RETURN + CSPNR = -CSPNR + CSPNI = -CSPNI + S2R = CYR(2) + S2I = CYI(2) + C1R = S2R + C1I = S2I + C2R = YR(2) + C2I = YI(2) + IF (KODE.EQ.1) GO TO 40 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC2R = C1R + SC2I = C1I + 40 CONTINUE + CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI) + CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI) + YR(2) = STR + PTR + YI(2) = STI + PTI + IF (N.EQ.2) RETURN + CSPNR = -CSPNR + CSPNI = -CSPNI + AZN = ZABS(CMPLX(ZNR,ZNI,kind=KIND(1.0D0))) + RAZN = 1.0D0/AZN + STR = ZNR*RAZN + STI = -ZNI*RAZN + RZR = (STR+STR)*RAZN + RZI = (STI+STI)*RAZN + FN = FNU + 1.0D0 + CKR = FN*RZR + CKI = FN*RZI +C----------------------------------------------------------------------- +C SCALE NEAR EXPONENT EXTREMES DURING RECURRENCE ON K FUNCTIONS +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CSCR = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CSCR + CSRR(1) = CSCR + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = ASCLE + BRY(2) = 1.0D0/ASCLE + BRY(3) = D1MACH(2) + AS2 = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + KFLAG = 2 + IF (AS2.GT.BRY(1)) GO TO 50 + KFLAG = 1 + GO TO 60 + 50 CONTINUE + IF (AS2.LT.BRY(2)) GO TO 60 + KFLAG = 3 + 60 CONTINUE + BSCLE = BRY(KFLAG) + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + CSR = CSRR(KFLAG) + DO 80 I=3,N + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + C1R = S2R*CSR + C1I = S2I*CSR + STR = C1R + STI = C1I + C2R = YR(I) + C2I = YI(I) + IF (KODE.EQ.1) GO TO 70 + IF (IUF.LT.0) GO TO 70 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC1R = SC2R + SC1I = SC2I + SC2R = C1R + SC2I = C1I + IF (IUF.NE.3) GO TO 70 + IUF = -4 + S1R = SC1R*CSSR(KFLAG) + S1I = SC1I*CSSR(KFLAG) + S2R = SC2R*CSSR(KFLAG) + S2I = SC2I*CSSR(KFLAG) + STR = SC2R + STI = SC2I + 70 CONTINUE + PTR = CSPNR*C1R - CSPNI*C1I + PTI = CSPNR*C1I + CSPNI*C1R + YR(I) = PTR + CSGNR*C2R - CSGNI*C2I + YI(I) = PTI + CSGNR*C2I + CSGNI*C2R + CKR = CKR + RZR + CKI = CKI + RZI + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (KFLAG.GE.3) GO TO 80 + PTR = DABS(C1R) + PTI = DABS(C1I) + C1M = DMAX1(PTR,PTI) + IF (C1M.LE.BSCLE) GO TO 80 + KFLAG = KFLAG + 1 + BSCLE = BRY(KFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = STR + S2I = STI + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + CSR = CSRR(KFLAG) + 80 CONTINUE + RETURN + 90 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zairy.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zairy.f new file mode 100644 index 00000000..6adab8f5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zairy.f @@ -0,0 +1,395 @@ + SUBROUTINE ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR) +C***BEGIN PROLOGUE ZAIRY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR +C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON +C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* +C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN +C -PI/3.LT.ARG(Z).LT.PI/3 AND THE EXPONENTIAL GROWTH IN +C PI/3.LT.ABS(ARG(Z)).LT.PI WHERE ZTA=(2/3)*Z*CSQRT(Z). +C +C WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN +C THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED +C FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS. +C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF +C MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI) +C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C AI=AI(Z) ON ID=0 OR +C AI=DAI(Z)/DZ ON ID=1 +C = 2 RETURNS +C AI=CEXP(ZTA)*AI(Z) ON ID=0 OR +C AI=CEXP(ZTA)*DAI(Z)/DZ ON ID=1 WHERE +C ZTA=(2/3)*Z*CSQRT(Z) +C +C OUTPUT AIR,AII ARE DOUBLE PRECISION +C AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND +C KODE +C NZ - UNDERFLOW INDICATOR +C NZ= 0 , NORMAL RETURN +C NZ= 1 , AI=CMPLX(0.0D0,0.0D0) DUE TO UNDERFLOW IN +C -PI/3.LT.ARG(Z).LT.PI/3 ON KODE=1 +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(ZTA) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED +C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION +C PRODUCE LESS THAN HALF OF MACHINE ACCURACY +C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION +C COMPLETE LOSS OF ACCURACY BY ARGUMENT +C REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C AI AND DAI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE K BESSEL +C FUNCTIONS BY +C +C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) +C C=1.0/(PI*SQRT(3.0)) +C ZTA=(2/3)*Z**(3/2) +C +C WITH THE POWER SERIES FOR CABS(Z).LE.1.0. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES +C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF +C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), +C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR +C FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN +C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT +C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE +C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA +C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, +C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE +C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE +C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- +C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- +C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN +C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN +C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, +C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE +C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER +C MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACAI,ZBKNU,ZEXP,ZSQRT,I1MACH,D1MACH +C***END PROLOGUE ZAIRY +C COMPLEX AI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3 + DOUBLE PRECISION AA, AD, AII, AIR, AK, ALIM, ATRM, AZ, AZ3, BK, + * CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2, DIG, + * DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + * S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + * ZEROR, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, ZABS, ALAZ, BB + INTEGER ID, IERR, IFLAG, K, KODE, K1, K2, MR, NN, NZ, I1MACH + DIMENSION CYR(1), CYI(1) + DATA TTH, C1, C2, COEF /6.66666666666666667D-01, + * 3.55028053887817240D-01,2.58819403792806799D-01, + * 1.83776298473930683D-01/ + DATA ZEROR, ZEROI, CONER, CONEI /0.0D0,0.0D0,1.0D0,0.0D0/ +C***FIRST EXECUTABLE STATEMENT ZAIRY + IERR = 0 + NZ=0 + IF (ID.LT.0 .OR. ID.GT.1) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (IERR.NE.0) RETURN + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + TOL = DMAX1(D1MACH(4),1.0D-18) + FID = DBLE(FLOAT(ID)) + IF (AZ.GT.1.0D0) GO TO 70 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(Z).LE.1. +C----------------------------------------------------------------------- + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + IF (AZ.LT.TOL) GO TO 170 + AA = AZ*AZ + IF (AA.LT.TOL/AZ) GO TO 40 + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0D0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ*AA + AK = 2.0D0 + FID + BK = 3.0D0 - FID - FID + CK = 4.0D0 - FID + DK = 3.0D0 + FID + FID + D1 = AK*DK + D2 = BK*CK + AD = DMIN1(D1,D2) + AK = 24.0D0 + 9.0D0*FID + BK = 30.0D0 - 9.0D0*FID + DO 30 K=1,25 + STR = (TRM1R*Z3R-TRM1I*Z3I)/D1 + TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R-TRM2I*Z3I)/D2 + TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM*AZ3/AD + D1 = D1 + AK + D2 = D2 + BK + AD = DMIN1(D1,D2) + IF (ATRM.LT.TOL*AD) GO TO 40 + AK = AK + 18.0D0 + BK = BK + 18.0D0 + 30 CONTINUE + 40 CONTINUE + IF (ID.EQ.1) THEN + GO TO 50 + END IF + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + CALL ZEXP(ZTAR, ZTAI, STR, STI) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + RETURN + 50 CONTINUE + AIR = -S2R*C2 + AII = -S2I*C2 + IF (AZ.LE.TOL) GO TO 60 + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1/(1.0D0+FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + 60 CONTINUE + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + CALL ZEXP(ZTAR, ZTAI, STR, STI) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + RETURN +C----------------------------------------------------------------------- +C CASE FOR CABS(Z).GT.1.0 +C----------------------------------------------------------------------- + 70 CONTINUE + FNU = (1.0D0+FID)/3.0D0 +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C----------------------------------------------------------------------- + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + ALAZ = DLOG(AZ) +C-------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AA=0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA=DMIN1(AA,BB) + AA=AA**TTH + IF (AZ.GT.AA) GO TO 260 + AA=DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + CALL ZSQRT(ZR, ZI, CSQR, CSQI) + ZTAR = TTH*(ZR*CSQR-ZI*CSQI) + ZTAI = TTH*(ZR*CSQI+ZI*CSQR) +C----------------------------------------------------------------------- +C RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL +C----------------------------------------------------------------------- + IFLAG = 0 + SFAC = 1.0D0 + AK = ZTAI + IF (ZR.GE.0.0D0) GO TO 80 + BK = ZTAR + CK = -DABS(BK) + ZTAR = CK + ZTAI = AK + 80 CONTINUE + IF (ZI.NE.0.0D0) GO TO 90 + IF (ZR.GT.0.0D0) GO TO 90 + ZTAR = 0.0D0 + ZTAI = AK + 90 CONTINUE + AA = ZTAR + IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110 + IF (KODE.EQ.2) GO TO 100 +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + IF (AA.GT.(-ALIM)) GO TO 100 + AA = -AA + 0.25D0*ALAZ + IFLAG = 1 + SFAC = TOL + IF (AA.GT.ELIM) GO TO 270 + 100 CONTINUE +C----------------------------------------------------------------------- +C CBKNU AND CACON RETURN EXP(ZTA)*K(FNU,ZTA) ON KODE=2 +C----------------------------------------------------------------------- + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + CALL ZACAI(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, + * ELIM, ALIM) + IF (NN.LT.0) GO TO 280 + NZ = NZ + NN + GO TO 130 + 110 CONTINUE + IF (KODE.EQ.2) GO TO 120 +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + IF (AA.LT.ALIM) GO TO 120 + AA = -AA - 0.25D0*ALAZ + IFLAG = 2 + SFAC = 1.0D0/TOL + IF (AA.LT.(-ELIM)) GO TO 210 + 120 CONTINUE + CALL ZBKNU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, + * ALIM) + 130 CONTINUE + S1R = CYR(1)*COEF + S1I = CYI(1)*COEF + IF (IFLAG.NE.0) GO TO 150 + IF (ID.EQ.1) GO TO 140 + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + RETURN + 140 CONTINUE + AIR = -(ZR*S1R-ZI*S1I) + AII = -(ZR*S1I+ZI*S1R) + RETURN + 150 CONTINUE + S1R = S1R*SFAC + S1I = S1I*SFAC + IF (ID.EQ.1) GO TO 160 + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R/SFAC + AII = S1I/SFAC + RETURN + 160 CONTINUE + STR = -(S1R*ZR-S1I*ZI) + S1I = -(S1R*ZI+S1I*ZR) + S1R = STR + AIR = S1R/SFAC + AII = S1I/SFAC + RETURN + 170 CONTINUE + AA = 1.0D+3*D1MACH(1) + S1R = ZEROR + S1I = ZEROI + IF (ID.EQ.1) GO TO 190 + IF (AZ.LE.AA) GO TO 180 + S1R = C2*ZR + S1I = C2*ZI + 180 CONTINUE + AIR = C1 - S1R + AII = -S1I + RETURN + 190 CONTINUE + AIR = -C2 + AII = 0.0D0 + AA = DSQRT(AA) + IF (AZ.LE.AA) GO TO 200 + S1R = 0.5D0*(ZR*ZR-ZI*ZI) + S1I = ZR*ZI + 200 CONTINUE + AIR = AIR + C1*S1R + AII = AII + C1*S1I + RETURN + 210 CONTINUE + NZ = 1 + AIR = ZEROR + AII = ZEROI + RETURN + 270 CONTINUE + NZ = 0 + IERR=2 + RETURN + 280 CONTINUE + IF(NN.EQ.(-1)) GO TO 270 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + IERR=4 + NZ=0 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zasyi.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zasyi.f new file mode 100644 index 00000000..139d7390 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zasyi.f @@ -0,0 +1,169 @@ + SUBROUTINE ZASYI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZASYI +C***REFER TO ZBESI,ZBESK +C +C ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY +C MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +C REGION CABS(Z).GT.MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL RETURN. +C NZ.LT.0 INDICATES AN OVERFLOW ON KODE=1. +C +C***ROUTINES CALLED D1MACH,ZABS,ZDIV,ZEXP,ZMLT,ZSQRT +C***END PROLOGUE ZASYI +C COMPLEX AK1,CK,CONE,CS1,CS2,CZ,CZERO,DK,EZ,P1,RZ,S2,Y,Z + DOUBLE PRECISION AA, AEZ, AK, AK1I, AK1R, ALIM, ARG, ARM, ATOL, + * AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + * CZR, DFNU, DKI, DKR, DNU2, ELIM, EZI, EZR, FDN, FNU, PI, P1I, + * P1R, RAZ, RL, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + * S2R, TOL, TZI, TZR, YI, YR, ZEROI, ZEROR, ZI, ZR, D1MACH, ZABS + INTEGER I, IB, IL, INU, J, JL, K, KODE, KODED, M, N, NN, NZ + DIMENSION YR(N), YI(N) + DATA PI, RTPI /3.14159265358979324D0 , 0.159154943091895336D0 / + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + ARM = 1.0D+3*D1MACH(1) + RTR1 = DSQRT(ARM) + IL = MIN0(2,N) + DFNU = FNU + DBLE(FLOAT(N-IL)) +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + AK1R = RTPI*STR*RAZ + AK1I = RTPI*STI*RAZ + CALL ZSQRT(AK1R, AK1I, AK1R, AK1I) + CZR = ZR + CZI = ZI + IF (KODE.NE.2) GO TO 10 + CZR = ZEROR + CZI = ZI + 10 CONTINUE + IF (DABS(CZR).GT.ELIM) GO TO 100 + DNU2 = DFNU + DFNU + KODED = 1 + IF ((DABS(CZR).GT.ALIM) .AND. (N.GT.2)) GO TO 20 + KODED = 0 + CALL ZEXP(CZR, CZI, STR, STI) + CALL ZMLT(AK1R, AK1I, STR, STI, AK1R, AK1I) + 20 CONTINUE + FDN = 0.0D0 + IF (DNU2.GT.RTR1) THEN + FDN = DNU2*DNU2 + END IF + EZR = ZR*8.0D0 + EZI = ZI*8.0D0 +C----------------------------------------------------------------------- +C WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE +C FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE +C EXPANSION FOR THE IMAGINARY PART. +C----------------------------------------------------------------------- + AEZ = 8.0D0*AZ + S = TOL/AEZ + JL = INT(SNGL(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + IF (ZI.EQ.0.0D0) GO TO 30 +C----------------------------------------------------------------------- +C CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF +C SIGNIFICANCE WHEN FNU OR N IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*PI + INU = INU + N - IL + AK = -DSIN(ARG) + BK = DCOS(ARG) + IF (ZI.LT.0.0D0) BK = -BK + P1R = AK + P1I = BK + IF (MOD(INU,2).EQ.0) GO TO 30 + P1R = -P1R + P1I = -P1I + 30 CONTINUE + DO 70 K=1,IL + SQK = FDN - 1.0D0 + ATOL = S*DABS(SQK) + SGN = 1.0D0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0D0 + AA = 1.0D0 + BB = AEZ + DKR = EZR + DKI = EZI + DO 40 J=1,JL + CALL ZDIV(CKR, CKI, DKR, DKI, STR, STI) + CKR = STR*SQK + CKI = STI*SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA*DABS(SQK)/BB + BB = BB + AEZ + AK = AK + 8.0D0 + SQK = SQK - AK + IF (AA.LE.ATOL) THEN + GO TO 50 + END IF + 40 CONTINUE + GO TO 110 + 50 CONTINUE + S2R = CS1R + S2I = CS1I + IF (ZR+ZR.GE.ELIM) GO TO 60 + TZR = ZR + ZR + TZI = ZI + ZI + CALL ZEXP(-TZR, -TZI, STR, STI) + CALL ZMLT(STR, STI, P1R, P1I, STR, STI) + CALL ZMLT(STR, STI, CS2R, CS2I, STR, STI) + S2R = S2R + STR + S2I = S2I + STI + 60 CONTINUE + FDN = FDN + 8.0D0*DFNU + 4.0D0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR(M) = S2R*AK1R - S2I*AK1I + YI(M) = S2R*AK1I + S2I*AK1R + 70 CONTINUE + IF (N.LE.2) RETURN + NN = N + K = NN - 2 + AK = DBLE(FLOAT(K)) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + IB = 3 + DO 80 I=IB,NN + YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2) + YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2) + AK = AK - 1.0D0 + K = K - 1 + 80 CONTINUE + IF (KODED.EQ.0) RETURN + CALL ZEXP(CZR, CZI, CKR, CKI) + DO 90 I=1,NN + STR = YR(I)*CKR - YI(I)*CKI + YI(I) = YR(I)*CKI + YI(I)*CKR + YR(I) = STR + 90 CONTINUE + RETURN + 100 CONTINUE + NZ = -1 + RETURN + 110 CONTINUE + NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesh.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesh.f new file mode 100644 index 00000000..a055ae46 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesh.f @@ -0,0 +1,348 @@ + SUBROUTINE ZBESH(ZR, ZI, FNU, KODE, M, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESH +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS H-BESSEL FUNCTIONS,BESSEL FUNCTIONS OF COMPLEX ARGUMENT, +C BESSEL FUNCTIONS OF THIRD KIND,HANKEL FUNCTIONS +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE H-BESSEL FUNCTIONS OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZBESH COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C HANKEL (BESSEL) FUNCTIONS CY(J)=H(M,FNU+J-1,Z) FOR KINDS M=1 +C OR 2, REAL, NONNEGATIVE ORDERS FNU+J-1, J=1,...,N, AND COMPLEX +C Z.NE.CMPLX(0.0,0.0) IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. +C ON KODE=2, ZBESH RETURNS THE SCALED HANKEL FUNCTIONS +C +C CY(I)=EXP(-MM*Z*I)*H(M,FNU+J-1,Z) MM=3-2*M, I**2=-1. +C +C WHICH REMOVES THE EXPONENTIAL BEHAVIOR IN BOTH THE UPPER AND +C LOWER HALF PLANES. DEFINITIONS AND NOTATION ARE FOUND IN THE +C NBS HANDBOOK OF MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PT.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL H FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(J)=H(M,FNU+J-1,Z), J=1,...,N +C = 2 RETURNS +C CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M)) +C J=1,...,N , I**2=-1 +C M - KIND OF HANKEL FUNCTION, M=1 OR 2 +C N - NUMBER OF MEMBERS IN THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(J)=H(M,FNU+J-1,Z) OR +C CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M)) J=1,...,N +C DEPENDING ON KODE, I**2=-1. +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE +C TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0) +C J=1,...,NZ WHEN Y.GT.0.0 AND M=1 OR +C Y.LT.0.0 AND M=2. FOR THE COMPLMENTARY +C HALF PLANES, NZ STATES ONLY THE NUMBER +C OF UNDERFLOWS. +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU TOO +C LARGE OR CABS(Z) TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE RELATION +C +C H(M,FNU,Z)=(1/MP)*EXP(-MP*FNU)*K(FNU,Z*EXP(-MP)) +C MP=MM*HPI*I, MM=3-2*M, HPI=PI/2, I**2=-1 +C +C FOR M=1 OR 2 WHERE THE K BESSEL FUNCTION IS COMPUTED FOR THE +C RIGHT HALF PLANE RE(Z).GE.0.0. THE K FUNCTION IS CONTINUED +C TO THE LEFT HALF PLANE BY THE RELATION +C +C K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z) +C MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1 +C +C WHERE I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C EXPONENTIAL DECAY OF H(M,FNU,Z) OCCURS IN THE UPPER HALF Z +C PLANE FOR M=1 AND THE LOWER HALF Z PLANE FOR M=2. EXPONENTIAL +C GROWTH OCCURS IN THE COMPLEMENTARY HALF PLANES. SCALING +C BY EXP(-MM*Z*I) REMOVES THE EXPONENTIAL BEHAVIOR IN THE +C WHOLE Z PLANE FOR Z TO INFINITY. +C +C FOR NEGATIVE ORDERS,THE FORMULAE +C +C H(1,-FNU,Z) = H(1,FNU,Z)*CEXP( PI*FNU*I) +C H(2,-FNU,Z) = H(2,FNU,Z)*CEXP(-PI*FNU*I) +C I**2=-1 +C +C CAN BE USED. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0D-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACON,ZBKNU,ZBUNK,ZUOIK,ZABS,I1MACH,D1MACH +C***END PROLOGUE ZBESH +C +C COMPLEX CY,Z,ZN,ZT,CSGN + DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM, + * FMM, FN, FNU, FNUL, HPI, RHPI, RL, R1M5, SGN, STR, TOL, UFL, ZI, + * ZNI, ZNR, ZR, ZTI, D1MACH, ZABS, BB, ASCLE, RTOL, ATOL, STI, + * CSGNR, CSGNI + INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, M, + * MM, MR, N, NN, NUF, NW, NZ, I1MACH + DIMENSION CYR(N), CYI(N) +C + DATA HPI /1.57079632679489662D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESH + IERR = 0 + NZ=0 + IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (M.LT.1 .OR. M.GT.2) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + NN = N +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) + RL = 1.2D0*DIG + 3.0D0 + FN = FNU + DBLE(FLOAT(NN-1)) + MM = 3 - M - M + FMM = DBLE(FLOAT(MM)) + ZNR = FMM*ZI + ZNI = -FMM*ZR +C----------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE +C----------------------------------------------------------------------- + UFL = D1MACH(1)*1.0D+3 + IF (AZ.LT.UFL) GO TO 230 + IF (FNU.GT.FNUL) GO TO 90 + IF (FN.LE.1.0D0) GO TO 70 + IF (FN.GT.2.0D0) GO TO 60 + IF (AZ.GT.TOL) GO TO 70 + ARG = 0.5D0*AZ + ALN = -FN*DLOG(ARG) + IF (ALN.GT.ELIM) GO TO 230 + GO TO 70 + 60 CONTINUE + CALL ZUOIK(ZNR, ZNI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM, + * ALIM) + IF (NUF.LT.0) GO TO 230 + NZ = NZ + NUF + NN = NN - NUF +C----------------------------------------------------------------------- +C HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK +C IF NUF=NN, THEN CY(I)=CZERO FOR ALL I +C----------------------------------------------------------------------- + IF (NN.EQ.0) GO TO 140 + 70 CONTINUE + IF ((ZNR.LT.0.0D0) .OR. (ZNR.EQ.0.0D0 .AND. ZNI.LT.0.0D0 .AND. + * M.EQ.2)) GO TO 80 +C----------------------------------------------------------------------- +C RIGHT HALF PLANE COMPUTATION, XN.GE.0. .AND. (XN.NE.0. .OR. +C YN.GE.0. .OR. M=1) +C----------------------------------------------------------------------- + CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NZ, TOL, ELIM, ALIM) + GO TO 110 +C----------------------------------------------------------------------- +C LEFT HALF PLANE COMPUTATION +C----------------------------------------------------------------------- + 80 CONTINUE + MR = -MM + CALL ZACON(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 240 + NZ=NW + GO TO 110 + 90 CONTINUE +C----------------------------------------------------------------------- +C UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL +C----------------------------------------------------------------------- + MR = 0 + IF ((ZNR.GE.0.0D0) .AND. (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0 .OR. + * M.NE.2)) GO TO 100 + MR = -MM + IF (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0) GO TO 100 + ZNR = -ZNR + ZNI = -ZNI + 100 CONTINUE + CALL ZBUNK(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 240 + NZ = NZ + NW + 110 CONTINUE +C----------------------------------------------------------------------- +C H(M,FNU,Z) = -FMM*(I/HPI)*(ZT**FNU)*K(FNU,-Z*ZT) +C +C ZT=EXP(-FMM*HPI*I) = CMPLX(0.0,-FMM), FMM=3-2*M, M=1,2 +C----------------------------------------------------------------------- + SGN = DSIGN(HPI,-FMM) +C----------------------------------------------------------------------- +C CALCULATE EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + INUH = INU/2 + IR = INU - 2*INUH + ARG = (FNU-DBLE(FLOAT(INU-IR)))*SGN + RHPI = 1.0D0/SGN +C ZNI = RHPI*DCOS(ARG) +C ZNR = -RHPI*DSIN(ARG) + CSGNI = RHPI*DCOS(ARG) + CSGNR = -RHPI*DSIN(ARG) + IF (MOD(INUH,2).EQ.0) GO TO 120 +C ZNR = -ZNR +C ZNI = -ZNI + CSGNR = -CSGNR + CSGNI = -CSGNI + 120 CONTINUE + ZTI = -FMM + RTOL = 1.0D0/TOL + ASCLE = UFL*RTOL + DO 130 I=1,NN +C STR = CYR(I)*ZNR - CYI(I)*ZNI +C CYI(I) = CYR(I)*ZNI + CYI(I)*ZNR +C CYR(I) = STR +C STR = -ZNI*ZTI +C ZNI = ZNR*ZTI +C ZNR = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 135 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 135 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + STR = -CSGNI*ZTI + CSGNI = CSGNR*ZTI + CSGNR = STR + 130 CONTINUE + RETURN + 140 CONTINUE + IF (ZNR.LT.0.0D0) GO TO 230 + RETURN + 230 CONTINUE + NZ=0 + IERR=2 + RETURN + 240 CONTINUE + IF(NW.EQ.(-1)) GO TO 230 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesi.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesi.f new file mode 100644 index 00000000..5f7c1407 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesi.f @@ -0,0 +1,269 @@ + SUBROUTINE ZBESI(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESI +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS I-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION, +C MODIFIED BESSEL FUNCTION OF THE FIRST KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE I-BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZBESI COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(J)=I(FNU+J-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, ZBESI RETURNS THE SCALED +C FUNCTIONS +C +C CY(J)=EXP(-ABS(X))*I(FNU+J-1,Z) J = 1,...,N , X=REAL(Z) +C +C WITH THE EXPONENTIAL GROWTH REMOVED IN BOTH THE LEFT AND +C RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL I FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(J)=I(FNU+J-1,Z), J=1,...,N +C = 2 RETURNS +C CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)), J=1,...,N +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(J)=I(FNU+J-1,Z) OR +C CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)) J=1,...,N +C DEPENDING ON KODE, X=REAL(Z) +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , LAST NZ COMPONENTS OF CY SET TO ZERO +C TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0) +C J = N-NZ+1,...,N +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(Z) TOO +C LARGE ON KODE=1 +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE POWER SERIES FOR +C SMALL CABS(Z), THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z), +C THE MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN AND A +C NEUMANN SERIES FOR IMTERMEDIATE MAGNITUDES, AND THE +C UNIFORM ASYMPTOTIC EXPANSIONS FOR I(FNU,Z) AND J(FNU,Z) +C FOR LARGE ORDERS. BACKWARD RECURRENCE IS USED TO GENERATE +C SEQUENCES OR REDUCE ORDERS WHEN NECESSARY. +C +C THE CALCULATIONS ABOVE ARE DONE IN THE RIGHT HALF PLANE AND +C CONTINUED INTO THE LEFT HALF PLANE BY THE FORMULA +C +C I(FNU,Z*EXP(M*PI)) = EXP(M*PI*FNU)*I(FNU,Z) REAL(Z).GT.0.0 +C M = +I OR -I, I**2=-1 +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C I(-FNU,Z) = I(FNU,Z) + (2/PI)*SIN(PI*FNU)*K(FNU,Z) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE +C THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE +C INTEGER,THE MAGNITUDE OF I(-FNU,Z)=I(FNU,Z) IS A LARGE +C NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER, +C K(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF +C TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY +C UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN +C OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE, +C LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,I1MACH,D1MACH +C***END PROLOGUE ZBESI +C COMPLEX CONE,CSGN,CW,CY,CZERO,Z,ZN + DOUBLE PRECISION AA, ALIM, ARG, CONEI, CONER, CSGNI, CSGNR, CYI, + * CYR, DIG, ELIM, FNU, FNUL, PI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR, + * ZR, D1MACH, AZ, BB, FN, ZABS, ASCLE, RTOL, ATOL, STI + INTEGER I, IERR, INU, K, KODE, K1,K2,N,NZ,NN, I1MACH + DIMENSION CYR(N), CYI(N) + DATA PI /3.14159265358979324D0/ + DATA CONER, CONEI /1.0D0,0.0D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESI + IERR = 0 + NZ=0 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU+DBLE(FLOAT(N-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 + ZNR = ZR + ZNI = ZI + CSGNR = CONER + CSGNI = CONEI + IF (ZR.GE.0.0D0) GO TO 40 + ZNR = -ZR + ZNI = -ZI +C----------------------------------------------------------------------- +C CALCULATE CSGN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*PI + IF (ZI.LT.0.0D0) ARG = -ARG + CSGNR = DCOS(ARG) + CSGNI = DSIN(ARG) + IF (MOD(INU,2).EQ.0) GO TO 40 + CSGNR = -CSGNR + CSGNI = -CSGNI + 40 CONTINUE + CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 120 + IF (ZR.GE.0.0D0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE +C----------------------------------------------------------------------- + NN = N - NZ + IF (NN.EQ.0) RETURN + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 50 I=1,NN +C STR = CYR(I)*CSGNR - CYI(I)*CSGNI +C CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR +C CYR(I) = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 55 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + CSGNR = -CSGNR + CSGNI = -CSGNI + 50 CONTINUE + RETURN + 120 CONTINUE + IF(NZ.EQ.(-2)) GO TO 130 + NZ = 0 + IERR=2 + RETURN + 130 CONTINUE + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesj.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesj.f new file mode 100644 index 00000000..1fb217f4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesj.f @@ -0,0 +1,266 @@ + SUBROUTINE ZBESJ(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESJ +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS J-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT, +C BESSEL FUNCTION OF FIRST KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE J-BESSEL FUNCTION OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, CBESJ COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(I)=J(FNU+I-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESJ RETURNS THE SCALED +C FUNCTIONS +C +C CY(I)=EXP(-ABS(Y))*J(FNU+I-1,Z) I = 1,...,N , Y=AIMAG(Z) +C +C WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND +C LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL J FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=J(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y)), I=1,...,N +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=J(FNU+I-1,Z) OR +C CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y)) I=1,...,N +C DEPENDING ON KODE, Y=AIMAG(Z). +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , LAST NZ COMPONENTS OF CY SET ZERO DUE +C TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0), +C I = N-NZ+1,...,N +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, AIMAG(Z) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE FORMULA +C +C J(FNU,Z)=EXP( FNU*PI*I/2)*I(FNU,-I*Z) AIMAG(Z).GE.0.0 +C +C J(FNU,Z)=EXP(-FNU*PI*I/2)*I(FNU, I*Z) AIMAG(Z).LT.0.0 +C +C WHERE I**2 = -1 AND I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C J(-FNU,Z) = J(FNU,Z)*COS(PI*FNU) - Y(FNU,Z)*SIN(PI*FNU) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE +C THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE +C INTEGER,THE MAGNITUDE OF J(-FNU,Z)=J(FNU,Z)*COS(PI*FNU) IS A +C LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER, +C Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF +C TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY +C UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN +C OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE, +C LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,I1MACH,D1MACH +C***END PROLOGUE ZBESJ +C +C COMPLEX CI,CSGN,CY,Z,ZN + DOUBLE PRECISION AA, ALIM, ARG, CII, CSGNI, CSGNR, CYI, CYR, DIG, + * ELIM, FNU, FNUL, HPI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR, ZR, + * D1MACH, BB, FN, AZ, ZABS, ASCLE, RTOL, ATOL, STI + INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, N, NL, NZ, I1MACH + DIMENSION CYR(N), CYI(N) + DATA HPI /1.57079632679489662D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESJ + IERR = 0 + NZ=0 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU+DBLE(FLOAT(N-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C CALCULATE CSGN=EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + CII = 1.0D0 + INU = INT(SNGL(FNU)) + INUH = INU/2 + IR = INU - 2*INUH + ARG = (FNU-DBLE(FLOAT(INU-IR)))*HPI + CSGNR = DCOS(ARG) + CSGNI = DSIN(ARG) + IF (MOD(INUH,2).EQ.0) GO TO 40 + CSGNR = -CSGNR + CSGNI = -CSGNI + 40 CONTINUE +C----------------------------------------------------------------------- +C ZN IS IN THE RIGHT HALF PLANE +C----------------------------------------------------------------------- + ZNR = ZI + ZNI = -ZR + IF (ZI.GE.0.0D0) GO TO 50 + ZNR = -ZNR + ZNI = -ZNI + CSGNI = -CSGNI + CII = -CII + 50 CONTINUE + CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 130 + NL = N - NZ + IF (NL.EQ.0) RETURN + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 60 I=1,NL +C STR = CYR(I)*CSGNR - CYI(I)*CSGNI +C CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR +C CYR(I) = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 55 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + STR = -CSGNI*CII + CSGNI = CSGNR*CII + CSGNR = STR + 60 CONTINUE + RETURN + 130 CONTINUE + IF(NZ.EQ.(-2)) GO TO 140 + NZ = 0 + IERR = 2 + RETURN + 140 CONTINUE + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesk.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesk.f new file mode 100644 index 00000000..c2228288 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesk.f @@ -0,0 +1,281 @@ + SUBROUTINE ZBESK(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESK +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS K-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION, +C MODIFIED BESSEL FUNCTION OF THE SECOND KIND, +C BESSEL FUNCTION OF THE THIRD KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE K-BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C +C ON KODE=1, CBESK COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(J)=K(FNU+J-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z.NE.CMPLX(0.0,0.0) +C IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESK +C RETURNS THE SCALED K FUNCTIONS, +C +C CY(J)=EXP(Z)*K(FNU+J-1,Z) , J=1,...,N, +C +C WHICH REMOVE THE EXPONENTIAL BEHAVIOR IN BOTH THE LEFT AND +C RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND +C NOTATION ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL +C FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL K FUNCTION, FNU.GE.0.0D0 +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=K(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=K(FNU+I-1,Z), I=1,...,N OR +C CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N +C DEPENDING ON KODE +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW. +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE +C TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0), +C I=1,...,N WHEN X.GE.0.0. WHEN X.LT.0.0 +C NZ STATES ONLY THE NUMBER OF UNDERFLOWS +C IN THE SEQUENCE. +C +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU IS +C TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C EQUATIONS OF THE REFERENCE ARE IMPLEMENTED FOR SMALL ORDERS +C DNU AND DNU+1.0 IN THE RIGHT HALF PLANE X.GE.0.0. FORWARD +C RECURRENCE GENERATES HIGHER ORDERS. K IS CONTINUED TO THE LEFT +C HALF PLANE BY THE RELATION +C +C K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z) +C MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1 +C +C WHERE I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C FOR LARGE ORDERS, FNU.GT.FNUL, THE K FUNCTION IS COMPUTED +C BY MEANS OF ITS UNIFORM ASYMPTOTIC EXPANSIONS. +C +C FOR NEGATIVE ORDERS, THE FORMULA +C +C K(-FNU,Z) = K(FNU,Z) +C +C CAN BE USED. +C +C CBESK ASSUMES THAT A SIGNIFICANT DIGIT SINH(X) FUNCTION IS +C AVAILABLE. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983. +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACON,ZBKNU,ZBUNK,ZUOIK,ZABS,I1MACH,D1MACH +C***END PROLOGUE ZBESK +C +C COMPLEX CY,Z + DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM, FN, + * FNU, FNUL, RL, R1M5, TOL, UFL, ZI, ZR, D1MACH, ZABS, BB + INTEGER IERR, K, KODE, K1, K2, MR, N, NN, NUF, NW, NZ, I1MACH + DIMENSION CYR(N), CYI(N) +C***FIRST EXECUTABLE STATEMENT ZBESK + IERR = 0 + NZ=0 + IF (ZI.EQ.0.0E0 .AND. ZR.EQ.0.0E0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + NN = N +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) + RL = 1.2D0*DIG + 3.0D0 +C----------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU + DBLE(FLOAT(NN-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE +C----------------------------------------------------------------------- +C UFL = DEXP(-ELIM) + UFL = D1MACH(1)*1.0D+3 + IF (AZ.LT.UFL) GO TO 180 + IF (FNU.GT.FNUL) GO TO 80 + IF (FN.LE.1.0D0) GO TO 60 + IF (FN.GT.2.0D0) GO TO 50 + IF (AZ.GT.TOL) GO TO 60 + ARG = 0.5D0*AZ + ALN = -FN*DLOG(ARG) + IF (ALN.GT.ELIM) GO TO 180 + GO TO 60 + 50 CONTINUE + CALL ZUOIK(ZR, ZI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM, + * ALIM) + IF (NUF.LT.0) GO TO 180 + NZ = NZ + NUF + NN = NN - NUF +C----------------------------------------------------------------------- +C HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK +C IF NUF=NN, THEN CY(I)=CZERO FOR ALL I +C----------------------------------------------------------------------- + IF (NN.EQ.0) GO TO 100 + 60 CONTINUE + IF (ZR.LT.0.0D0) GO TO 70 +C----------------------------------------------------------------------- +C RIGHT HALF PLANE COMPUTATION, REAL(Z).GE.0. +C----------------------------------------------------------------------- + CALL ZBKNU(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 200 + NZ=NW + RETURN +C----------------------------------------------------------------------- +C LEFT HALF PLANE COMPUTATION +C PI/2.LT.ARG(Z).LE.PI AND -PI.LT.ARG(Z).LT.-PI/2. +C----------------------------------------------------------------------- + 70 CONTINUE + IF (NZ.NE.0) GO TO 180 + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + CALL ZACON(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 200 + NZ=NW + RETURN +C----------------------------------------------------------------------- +C UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL +C----------------------------------------------------------------------- + 80 CONTINUE + MR = 0 + IF (ZR.GE.0.0D0) GO TO 90 + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + 90 CONTINUE + CALL ZBUNK(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 200 + NZ = NZ + NW + RETURN + 100 CONTINUE + IF (ZR.LT.0.0D0) GO TO 180 + RETURN + 180 CONTINUE + NZ = 0 + IERR=2 + RETURN + 200 CONTINUE + IF(NW.EQ.(-1)) GO TO 180 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesy.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesy.f new file mode 100644 index 00000000..05ec40be --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbesy.f @@ -0,0 +1,244 @@ + SUBROUTINE ZBESY(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, CWRKR, CWRKI, + * IERR) +C***BEGIN PROLOGUE ZBESY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS Y-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT, +C BESSEL FUNCTION OF SECOND KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE Y-BESSEL FUNCTION OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C +C ON KODE=1, CBESY COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(I)=Y(FNU+I-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESY RETURNS THE SCALED +C FUNCTIONS +C +C CY(I)=EXP(-ABS(Y))*Y(FNU+I-1,Z) I = 1,...,N , Y=AIMAG(Z) +C +C WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND +C LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL Y FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=Y(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)), I=1,...,N +C WHERE Y=AIMAG(Z) +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C CWRKR, - DOUBLE PRECISION WORK VECTORS OF DIMENSION AT +C CWRKI AT LEAST N +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=Y(FNU+I-1,Z) OR +C CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)) I=1,...,N +C DEPENDING ON KODE. +C NZ - NZ=0 , A NORMAL RETURN +C NZ.GT.0 , NZ COMPONENTS OF CY SET TO ZERO DUE TO +C UNDERFLOW (GENERALLY ON KODE=2) +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU IS +C TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE FORMULA +C +C Y(FNU,Z)=0.5*(H(1,FNU,Z)-H(2,FNU,Z))/I +C +C WHERE I**2 = -1 AND THE HANKEL BESSEL FUNCTIONS H(1,FNU,Z) +C AND H(2,FNU,Z) ARE CALCULATED IN CBESH. +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C Y(-FNU,Z) = Y(FNU,Z)*COS(PI*FNU) + J(FNU,Z)*SIN(PI*FNU) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO HALF ODD +C INTEGERS THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE +C POSITIVE HALF ODD INTEGER,THE MAGNITUDE OF Y(-FNU,Z)=J(FNU,Z)* +C SIN(PI*FNU) IS A LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS +C NOT A HALF ODD INTEGER, Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A +C LARGE POSITIVE POWER OF TEN AND THE MOST THAT THE SECOND TERM +C CAN BE REDUCED IS BY UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, +C WIDE CHANGES CAN OCCUR WITHIN UNIT ROUNDOFF OF A LARGE HALF +C ODD INTEGER. HERE, LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBESH,I1MACH,D1MACH +C***END PROLOGUE ZBESY +C +C COMPLEX CWRK,CY,C1,C2,EX,HCI,Z,ZU,ZV + DOUBLE PRECISION CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2R, + * ELIM, EXI, EXR, EY, FNU, HCII, STI, STR, TAY, ZI, ZR, DEXP, + * D1MACH, ASCLE, RTOL, ATOL, AA, BB, TOL + INTEGER I, IERR, K, KODE, K1, K2, N, NZ, NZ1, NZ2, I1MACH + DIMENSION CYR(N), CYI(N), CWRKR(N), CWRKI(N) +C***FIRST EXECUTABLE STATEMENT ZBESY + IERR = 0 + NZ=0 + IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + HCII = 0.5D0 + CALL ZBESH(ZR, ZI, FNU, KODE, 1, N, CYR, CYI, NZ1, IERR) + IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170 + CALL ZBESH(ZR, ZI, FNU, KODE, 2, N, CWRKR, CWRKI, NZ2, IERR) + IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170 + NZ = MIN0(NZ1,NZ2) + IF (KODE.EQ.2) GO TO 60 + DO 50 I=1,N + STR = CWRKR(I) - CYR(I) + STI = CWRKI(I) - CYI(I) + CYR(I) = -STI*HCII + CYI(I) = STR*HCII + 50 CONTINUE + RETURN + 60 CONTINUE + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + K = MIN0(IABS(K1),IABS(K2)) + R1M5 = D1MACH(5) +C----------------------------------------------------------------------- +C ELIM IS THE APPROXIMATE EXPONENTIAL UNDER- AND OVERFLOW LIMIT +C----------------------------------------------------------------------- + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + EXR = DCOS(ZR) + EXI = DSIN(ZR) + EY = 0.0D0 + TAY = DABS(ZI+ZI) + IF (TAY.LT.ELIM) EY = DEXP(-TAY) + IF (ZI.LT.0.0D0) GO TO 90 + C1R = EXR*EY + C1I = EXI*EY + C2R = EXR + C2I = -EXI + 70 CONTINUE + NZ = 0 + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 80 I=1,N +C STR = C1R*CYR(I) - C1I*CYI(I) +C STI = C1R*CYI(I) + C1I*CYR(I) +C STR = -STR + C2R*CWRKR(I) - C2I*CWRKI(I) +C STI = -STI + C2R*CWRKI(I) + C2I*CWRKR(I) +C CYR(I) = -STI*HCII +C CYI(I) = STR*HCII + AA = CWRKR(I) + BB = CWRKI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 75 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 75 CONTINUE + STR = (AA*C2R - BB*C2I)*ATOL + STI = (AA*C2I + BB*C2R)*ATOL + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 85 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 85 CONTINUE + STR = STR - (AA*C1R - BB*C1I)*ATOL + STI = STI - (AA*C1I + BB*C1R)*ATOL + CYR(I) = -STI*HCII + CYI(I) = STR*HCII + IF (STR.EQ.0.0D0 .AND. STI.EQ.0.0D0 .AND. EY.EQ.0.0D0) NZ = NZ + * + 1 + 80 CONTINUE + RETURN + 90 CONTINUE + C1R = EXR + C1I = EXI + C2R = EXR*EY + C2I = -EXI*EY + GO TO 70 + 170 CONTINUE + NZ = 0 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbinu.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbinu.f new file mode 100644 index 00000000..b740e707 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbinu.f @@ -0,0 +1,110 @@ + SUBROUTINE ZBINU(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZBINU +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZAIRY,ZBIRY +C +C ZBINU COMPUTES THE I FUNCTION IN THE RIGHT HALF Z PLANE +C +C***ROUTINES CALLED ZABS,ZASYI,ZBUNI,ZMLRI,ZSERI,ZUOIK,ZWRSK +C***END PROLOGUE ZBINU + DOUBLE PRECISION ALIM, AZ, CWI, CWR, CYI, CYR, DFNU, ELIM, FNU, + * FNUL, RL, TOL, ZEROI, ZEROR, ZI, ZR, ZABS + INTEGER I, INW, KODE, N, NLAST, NN, NUI, NW, NZ + DIMENSION CYR(N), CYI(N), CWR(2), CWI(2) + DATA ZEROR,ZEROI / 0.0D0, 0.0D0 / +C + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + NN = N + DFNU = FNU + DBLE(FLOAT(N-1)) + IF (AZ.LE.2.0D0) GO TO 10 + IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C POWER SERIES +C----------------------------------------------------------------------- + CALL ZSERI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + INW = IABS(NW) + NZ = NZ + INW + NN = NN - INW + IF (NN.EQ.0) RETURN + IF (NW.GE.0) GO TO 120 + DFNU = FNU + DBLE(FLOAT(NN-1)) + 20 CONTINUE + IF (AZ.LT.RL) GO TO 40 + IF (DFNU.LE.1.0D0) GO TO 30 + IF (AZ+AZ.LT.DFNU*DFNU) GO TO 50 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR LARGE Z +C----------------------------------------------------------------------- + 30 CONTINUE + CALL ZASYI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, RL, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 130 + GO TO 120 + 40 CONTINUE + IF (DFNU.LE.1.0D0) GO TO 70 + 50 CONTINUE +C----------------------------------------------------------------------- +C OVERFLOW AND UNDERFLOW TEST ON I SEQUENCE FOR MILLER ALGORITHM +C----------------------------------------------------------------------- + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 130 + NZ = NZ + NW + NN = NN - NW + IF (NN.EQ.0) RETURN + DFNU = FNU+DBLE(FLOAT(NN-1)) + IF (DFNU.GT.FNUL) GO TO 110 + IF (AZ.GT.FNUL) GO TO 110 + 60 CONTINUE + IF (AZ.GT.RL) GO TO 80 + 70 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE SERIES +C----------------------------------------------------------------------- + CALL ZMLRI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL) + IF(NW.LT.0) GO TO 130 + GO TO 120 + 80 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN +C----------------------------------------------------------------------- +C----------------------------------------------------------------------- +C OVERFLOW TEST ON K FUNCTIONS USED IN WRONSKIAN +C----------------------------------------------------------------------- + CALL ZUOIK(ZR, ZI, FNU, KODE, 2, 2, CWR, CWI, NW, TOL, ELIM, + * ALIM) + IF (NW.GE.0) GO TO 100 + NZ = NN + DO 90 I=1,NN + CYR(I) = ZEROR + CYI(I) = ZEROI + 90 CONTINUE + RETURN + 100 CONTINUE + IF (NW.GT.0) GO TO 130 + CALL ZWRSK(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, CWR, CWI, TOL, + * ELIM, ALIM) + IF (NW.LT.0) GO TO 130 + GO TO 120 + 110 CONTINUE +C----------------------------------------------------------------------- +C INCREMENT FNU+NN-1 UP TO FNUL, COMPUTE AND RECUR BACKWARD +C----------------------------------------------------------------------- + NUI = INT(SNGL(FNUL-DFNU)) + 1 + NUI = MAX0(NUI,0) + CALL ZBUNI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, NUI, NLAST, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 130 + NZ = NZ + NW + IF (NLAST.EQ.0) GO TO 120 + NN = NLAST + GO TO 60 + 120 CONTINUE + RETURN + 130 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbiry.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbiry.f new file mode 100644 index 00000000..f042d824 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbiry.f @@ -0,0 +1,364 @@ + SUBROUTINE ZBIRY(ZR, ZI, ID, KODE, BIR, BII, IERR) +C***BEGIN PROLOGUE ZBIRY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE AIRY FUNCTIONS BI(Z) AND DBI(Z) FOR COMPLEX Z +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, CBIRY COMPUTES THE COMPLEX AIRY FUNCTION BI(Z) OR +C ITS DERIVATIVE DBI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON +C KODE=2, A SCALING OPTION CEXP(-AXZTA)*BI(Z) OR CEXP(-AXZTA)* +C DBI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL BEHAVIOR IN +C BOTH THE LEFT AND RIGHT HALF PLANES WHERE +C ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) AND AXZTA=ABS(XZTA). +C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF +C MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI) +C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C BI=BI(Z) ON ID=0 OR +C BI=DBI(Z)/DZ ON ID=1 +C = 2 RETURNS +C BI=CEXP(-AXZTA)*BI(Z) ON ID=0 OR +C BI=CEXP(-AXZTA)*DBI(Z)/DZ ON ID=1 WHERE +C ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) +C AND AXZTA=ABS(XZTA) +C +C OUTPUT BIR,BII ARE DOUBLE PRECISION +C BIR,BII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND +C KODE +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(Z) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED +C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION +C PRODUCE LESS THAN HALF OF MACHINE ACCURACY +C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION +C COMPLETE LOSS OF ACCURACY BY ARGUMENT +C REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C BI AND DBI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE I BESSEL +C FUNCTIONS BY +C +C BI(Z)=C*SQRT(Z)*( I(-1/3,ZTA) + I(1/3,ZTA) ) +C DBI(Z)=C * Z * ( I(-2/3,ZTA) + I(2/3,ZTA) ) +C C=1.0/SQRT(3.0) +C ZTA=(2/3)*Z**(3/2) +C +C WITH THE POWER SERIES FOR CABS(Z).LE.1.0. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES +C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF +C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), +C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR +C FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN +C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT +C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE +C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA +C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, +C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE +C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE +C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- +C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- +C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN +C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN +C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, +C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE +C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER +C MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,ZABS,ZDIV,ZSQRT,D1MACH,I1MACH +C***END PROLOGUE ZBIRY +C COMPLEX BI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3 + DOUBLE PRECISION AA, AD, AK, ALIM, ATRM, AZ, AZ3, BB, BII, BIR, + * BK, CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2, + * DIG, DK, D1, D2, EAA, ELIM, FID, FMR, FNU, FNUL, PI, RL, R1M5, + * SFAC, STI, STR, S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, + * TRM2R, TTH, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, ZABS + INTEGER ID, IERR, K, KODE, K1, K2, NZ, I1MACH + DIMENSION CYR(2), CYI(2) + DATA TTH, C1, C2, COEF, PI /6.66666666666666667D-01, + * 6.14926627446000736D-01,4.48288357353826359D-01, + * 5.77350269189625765D-01,3.14159265358979324D+00/ + DATA CONER, CONEI /1.0D0,0.0D0/ +C***FIRST EXECUTABLE STATEMENT ZBIRY + IERR = 0 + NZ=0 + IF (ID.LT.0 .OR. ID.GT.1) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (IERR.NE.0) RETURN + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + TOL = DMAX1(D1MACH(4),1.0D-18) + FID = DBLE(FLOAT(ID)) + IF (AZ.GT.1.0E0) GO TO 70 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(Z).LE.1. +C----------------------------------------------------------------------- + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + IF (AZ.LT.TOL) GO TO 130 + AA = AZ*AZ + IF (AA.LT.TOL/AZ) GO TO 40 + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0D0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ*AA + AK = 2.0D0 + FID + BK = 3.0D0 - FID - FID + CK = 4.0D0 - FID + DK = 3.0D0 + FID + FID + D1 = AK*DK + D2 = BK*CK + AD = DMIN1(D1,D2) + AK = 24.0D0 + 9.0D0*FID + BK = 30.0D0 - 9.0D0*FID + DO 30 K=1,25 + STR = (TRM1R*Z3R-TRM1I*Z3I)/D1 + TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R-TRM2I*Z3I)/D2 + TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM*AZ3/AD + D1 = D1 + AK + D2 = D2 + BK + AD = DMIN1(D1,D2) + IF (ATRM.LT.TOL*AD) GO TO 40 + AK = AK + 18.0D0 + BK = BK + 18.0D0 + 30 CONTINUE + 40 CONTINUE + IF (ID.EQ.1) GO TO 50 + BIR = C1*S1R + C2*(ZR*S2R-ZI*S2I) + BII = C1*S1I + C2*(ZR*S2I+ZI*S2R) + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + AA = ZTAR + AA = -DABS(AA) + EAA = DEXP(AA) + BIR = BIR*EAA + BII = BII*EAA + RETURN + 50 CONTINUE + BIR = S2R*C2 + BII = S2I*C2 + IF (AZ.LE.TOL) GO TO 60 + CC = C1/(1.0D0+FID) + STR = S1R*ZR - S1I*ZI + STI = S1R*ZI + S1I*ZR + BIR = BIR + CC*(STR*ZR-STI*ZI) + BII = BII + CC*(STR*ZI+STI*ZR) + 60 CONTINUE + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + AA = ZTAR + AA = -DABS(AA) + EAA = DEXP(AA) + BIR = BIR*EAA + BII = BII*EAA + RETURN +C----------------------------------------------------------------------- +C CASE FOR CABS(Z).GT.1.0 +C----------------------------------------------------------------------- + 70 CONTINUE + FNU = (1.0D0+FID)/3.0D0 +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------- +C TEST FOR RANGE +C----------------------------------------------------------------------- + AA=0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA=DMIN1(AA,BB) + AA=AA**TTH + IF (AZ.GT.AA) GO TO 260 + AA=DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + CALL ZSQRT(ZR, ZI, CSQR, CSQI) + ZTAR = TTH*(ZR*CSQR-ZI*CSQI) + ZTAI = TTH*(ZR*CSQI+ZI*CSQR) +C----------------------------------------------------------------------- +C RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL +C----------------------------------------------------------------------- + SFAC = 1.0D0 + AK = ZTAI + IF (ZR.GE.0.0D0) GO TO 80 + BK = ZTAR + CK = -DABS(BK) + ZTAR = CK + ZTAI = AK + 80 CONTINUE + IF (ZI.NE.0.0D0 .OR. ZR.GT.0.0D0) GO TO 90 + ZTAR = 0.0D0 + ZTAI = AK + 90 CONTINUE + AA = ZTAR + IF (KODE.EQ.2) GO TO 100 +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + BB = DABS(AA) + IF (BB.LT.ALIM) GO TO 100 + BB = BB + 0.25D0*DLOG(AZ) + SFAC = TOL + IF (BB.GT.ELIM) GO TO 190 + 100 CONTINUE + FMR = 0.0D0 + IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110 + FMR = PI + IF (ZI.LT.0.0D0) FMR = -PI + ZTAR = -ZTAR + ZTAI = -ZTAI + 110 CONTINUE +C----------------------------------------------------------------------- +C AA=FACTOR FOR ANALYTIC CONTINUATION OF I(FNU,ZTA) +C KODE=2 RETURNS EXP(-ABS(XZTA))*I(FNU,ZTA) FROM CBESI +C----------------------------------------------------------------------- + CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 200 + AA = FMR*FNU + Z3R = SFAC + STR = DCOS(AA) + STI = DSIN(AA) + S1R = (STR*CYR(1)-STI*CYI(1))*Z3R + S1I = (STR*CYI(1)+STI*CYR(1))*Z3R + FNU = (2.0D0-FID)/3.0D0 + CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 2, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + CYR(1) = CYR(1)*Z3R + CYI(1) = CYI(1)*Z3R + CYR(2) = CYR(2)*Z3R + CYI(2) = CYI(2)*Z3R +C----------------------------------------------------------------------- +C BACKWARD RECUR ONE STEP FOR ORDERS -1/3 OR -2/3 +C----------------------------------------------------------------------- + CALL ZDIV(CYR(1), CYI(1), ZTAR, ZTAI, STR, STI) + S2R = (FNU+FNU)*STR + CYR(2) + S2I = (FNU+FNU)*STI + CYI(2) + AA = FMR*(FNU-1.0D0) + STR = DCOS(AA) + STI = DSIN(AA) + S1R = COEF*(S1R+S2R*STR-S2I*STI) + S1I = COEF*(S1I+S2R*STI+S2I*STR) + IF (ID.EQ.1) GO TO 120 + STR = CSQR*S1R - CSQI*S1I + S1I = CSQR*S1I + CSQI*S1R + S1R = STR + BIR = S1R/SFAC + BII = S1I/SFAC + RETURN + 120 CONTINUE + STR = ZR*S1R - ZI*S1I + S1I = ZR*S1I + ZI*S1R + S1R = STR + BIR = S1R/SFAC + BII = S1I/SFAC + RETURN + 130 CONTINUE + AA = C1*(1.0D0-FID) + FID*C2 + BIR = AA + BII = 0.0D0 + RETURN + 190 CONTINUE + IERR=2 + NZ=0 + RETURN + 200 CONTINUE + IF(NZ.EQ.(-1)) GO TO 190 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + IERR=4 + NZ=0 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbknu.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbknu.f new file mode 100644 index 00000000..ef932d40 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbknu.f @@ -0,0 +1,568 @@ + SUBROUTINE ZBKNU(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZBKNU +C***REFER TO ZBESI,ZBESK,ZAIRY,ZBESH +C +C ZBKNU COMPUTES THE K BESSEL FUNCTION IN THE RIGHT HALF Z PLANE. +C +C***ROUTINES CALLED DGAMLN,I1MACH,D1MACH,ZKSCL,ZSHCH,ZUCHK,ZABS,ZDIV, +C ZEXP,ZLOG,ZMLT,ZSQRT +C***END PROLOGUE ZBKNU +C + DOUBLE PRECISION AA, AK, ALIM, ASCLE, A1, A2, BB, BK, BRY, CAZ, + * CBI, CBR, CC, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + * CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CSRR, CSSR, CTWOR, + * CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ELIM, ETEST, FC, FHS, + * FI, FK, FKS, FMUI, FMUR, FNU, FPI, FR, G1, G2, HPI, PI, PR, PTI, + * PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + * RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + * TOL, TTH, T1, T2, YI, YR, ZI, ZR, DGAMLN, D1MACH, ZABS, ELM, + * CELMR, ZDR, ZDI, AS, ALAS, HELIM, CYR, CYI + INTEGER I, IFLAG, INU, K, KFLAG, KK, KMAX, KODE, KODED, N, NZ, + * IDUM, I1MACH, J, IC, INUB, NW + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) +C COMPLEX Z,Y,A,B,RZ,SMU,FU,FMU,F,FLRZ,CZ,S1,S2,CSH,CCH +C COMPLEX CK,P,Q,COEF,P1,P2,CBK,PT,CZERO,CONE,CTWO,ST,EZ,CS,DK +C + DATA KMAX / 30 / + DATA CZEROR,CZEROI,CONER,CONEI,CTWOR,R1/ + 1 0.0D0 , 0.0D0 , 1.0D0 , 0.0D0 , 2.0D0 , 2.0D0 / + DATA DPI, RTHPI, SPI ,HPI, FPI, TTH / + 1 3.14159265358979324D0, 1.25331413731550025D0, + 2 1.90985931710274403D0, 1.57079632679489662D0, + 3 1.89769999331517738D0, 6.66666666666666666D-01/ + DATA CC(1), CC(2), CC(3), CC(4), CC(5), CC(6), CC(7), CC(8)/ + 1 5.77215664901532861D-01, -4.20026350340952355D-02, + 2 -4.21977345555443367D-02, 7.21894324666309954D-03, + 3 -2.15241674114950973D-04, -2.01348547807882387D-05, + 4 1.13302723198169588D-06, 6.11609510448141582D-09/ +C + CAZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + CSCLR = 1.0D0/TOL + CRSCR = TOL + CSSR(1) = CSCLR + CSSR(2) = 1.0D0 + CSSR(3) = CRSCR + CSRR(1) = CRSCR + CSRR(2) = 1.0D0 + CSRR(3) = CSCLR + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0D0/CAZ + STR = ZR*RCAZ + STI = -ZI*RCAZ + RZR = (STR+STR)*RCAZ + RZI = (STI+STI)*RCAZ + INU = INT(SNGL(FNU+0.5D0)) + DNU = FNU - DBLE(FLOAT(INU)) + IF (DABS(DNU).EQ.0.5D0) GO TO 110 + DNU2 = 0.0D0 + IF (DABS(DNU).GT.TOL) DNU2 = DNU*DNU + IF (CAZ.GT.R1) GO TO 110 +C----------------------------------------------------------------------- +C SERIES FOR CABS(Z).LE.R1 +C----------------------------------------------------------------------- + FC = 1.0D0 + CALL ZLOG(RZR, RZI, SMUR, SMUI, IDUM) + FMUR = SMUR*DNU + FMUI = SMUI*DNU + CALL ZSHCH(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI) + IF (DNU.EQ.0.0D0) GO TO 10 + FC = DNU*DPI + FC = FC/DSIN(FC) + SMUR = CSHR/DNU + SMUI = CSHI/DNU + 10 CONTINUE + A2 = 1.0D0 + DNU +C----------------------------------------------------------------------- +C GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU) +C----------------------------------------------------------------------- + T2 = DEXP(-DGAMLN(A2,IDUM)) + T1 = 1.0D0/(T2*FC) + IF (DABS(DNU).GT.0.1D0) GO TO 40 +C----------------------------------------------------------------------- +C SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU) +C----------------------------------------------------------------------- + AK = 1.0D0 + S = CC(1) + DO 20 K=2,8 + AK = AK*DNU2 + TM = CC(K)*AK + S = S + TM + IF (DABS(TM).LT.TOL) GO TO 30 + 20 CONTINUE + 30 G1 = -S + GO TO 50 + 40 CONTINUE + G1 = (T1-T2)/(DNU+DNU) + 50 CONTINUE + G2 = (T1+T2)*0.5D0 + FR = FC*(CCHR*G1+SMUR*G2) + FI = FC*(CCHI*G1+SMUI*G2) + CALL ZEXP(FMUR, FMUI, STR, STI) + PR = 0.5D0*STR/T2 + PI = 0.5D0*STI/T2 + CALL ZDIV(0.5D0, 0.0D0, STR, STI, PTR, PTI) + QR = PTR/T1 + QI = PTI/T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0D0 + A1 = 1.0D0 + CKR = CONER + CKI = CONEI + BK = 1.0D0 - DNU2 + IF (INU.GT.0 .OR. N.GT.1) GO TO 80 +C----------------------------------------------------------------------- +C GENERATE K(FNU,Z), 0.0D0 .LE. FNU .LT. 0.5D0 AND N=1 +C----------------------------------------------------------------------- + IF (CAZ.LT.TOL) GO TO 70 + CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI) + CZR = 0.25D0*CZR + CZI = 0.25D0*CZI + T1 = 0.25D0*CAZ*CAZ + 60 CONTINUE + FR = (FR*AK+PR+QR)/BK + FI = (FI*AK+PI+QI)/BK + STR = 1.0D0/(AK-DNU) + PR = PR*STR + PI = PI*STR + STR = 1.0D0/(AK+DNU) + QR = QR*STR + QI = QI*STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0D0/AK + CKI = (CKR*CZI+CKI*CZR)*RAK + CKR = STR*RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1*T1*RAK + BK = BK + AK + AK + 1.0D0 + AK = AK + 1.0D0 + IF (A1.GT.TOL) GO TO 60 + 70 CONTINUE + YR(1) = S1R + YI(1) = S1I + IF (KODED.EQ.1) RETURN + CALL ZEXP(ZR, ZI, STR, STI) + CALL ZMLT(S1R, S1I, STR, STI, YR(1), YI(1)) + RETURN +C----------------------------------------------------------------------- +C GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE +C----------------------------------------------------------------------- + 80 CONTINUE + IF (CAZ.LT.TOL) GO TO 100 + CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI) + CZR = 0.25D0*CZR + CZI = 0.25D0*CZI + T1 = 0.25D0*CAZ*CAZ + 90 CONTINUE + FR = (FR*AK+PR+QR)/BK + FI = (FI*AK+PI+QI)/BK + STR = 1.0D0/(AK-DNU) + PR = PR*STR + PI = PI*STR + STR = 1.0D0/(AK+DNU) + QR = QR*STR + QI = QI*STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0D0/AK + CKI = (CKR*CZI+CKI*CZR)*RAK + CKR = STR*RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1*T1*RAK + BK = BK + AK + AK + 1.0D0 + AK = AK + 1.0D0 + IF (A1.GT.TOL) GO TO 90 + 100 CONTINUE + KFLAG = 2 + A1 = FNU + 1.0D0 + AK = A1*DABS(SMUR) + IF (AK.GT.ALIM) KFLAG = 3 + STR = CSSR(KFLAG) + P2R = S2R*STR + P2I = S2I*STR + CALL ZMLT(P2R, P2I, RZR, RZI, S2R, S2I) + S1R = S1R*STR + S1I = S1I*STR + IF (KODED.EQ.1) GO TO 210 + CALL ZEXP(ZR, ZI, FR, FI) + CALL ZMLT(S1R, S1I, FR, FI, S1R, S1I) + CALL ZMLT(S2R, S2I, FR, FI, S2R, S2I) + GO TO 210 +C----------------------------------------------------------------------- +C IFLAG=0 MEANS NO UNDERFLOW OCCURRED +C IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH +C KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD +C RECURSION +C----------------------------------------------------------------------- + 110 CONTINUE + CALL ZSQRT(ZR, ZI, STR, STI) + CALL ZDIV(RTHPI, CZEROI, STR, STI, COEFR, COEFI) + KFLAG = 2 + IF (KODED.EQ.2) GO TO 120 + IF (ZR.GT.ALIM) GO TO 290 +C BLANK LINE + STR = DEXP(-ZR)*CSSR(KFLAG) + STI = -STR*DSIN(ZI) + STR = STR*DCOS(ZI) + CALL ZMLT(COEFR, COEFI, STR, STI, COEFR, COEFI) + 120 CONTINUE + IF (DABS(DNU).EQ.0.5D0) GO TO 300 +C----------------------------------------------------------------------- +C MILLER ALGORITHM FOR CABS(Z).GT.R1 +C----------------------------------------------------------------------- + AK = DCOS(DPI*DNU) + AK = DABS(AK) + IF (AK.EQ.CZEROR) GO TO 300 + FHS = DABS(0.25D0-DNU2) + IF (FHS.EQ.CZEROR) GO TO 300 +C----------------------------------------------------------------------- +C COMPUTE R2=F(E). IF CABS(Z).GE.R2, USE FORWARD RECURRENCE TO +C DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON +C 12.LE.E.LE.60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= +C TOL WHERE B IS THE BASE OF THE ARITHMETIC. +C----------------------------------------------------------------------- + T1 = DBLE(FLOAT(I1MACH(14)-1)) + T1 = T1*D1MACH(5)*3.321928094D0 + T1 = DMAX1(T1,12.0D0) + T1 = DMIN1(T1,60.0D0) + T2 = TTH*T1 - 6.0D0 + IF (ZR.NE.0.0D0) GO TO 130 + T1 = HPI + GO TO 140 + 130 CONTINUE + T1 = DATAN(ZI/ZR) + T1 = DABS(T1) + 140 CONTINUE + IF (T2.GT.CAZ) GO TO 170 +C----------------------------------------------------------------------- +C FORWARD RECURRENCE LOOP WHEN CABS(Z).GE.R2 +C----------------------------------------------------------------------- + ETEST = AK/(DPI*CAZ*TOL) + FK = CONER + IF (ETEST.LT.CONER) GO TO 180 + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + DO 150 I=1,KMAX + AK = FHS/FKS + CBR = CKR/(FK+CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = DABS(P2R)*FK + IF (ETEST.LT.STR) GO TO 160 + 150 CONTINUE + GO TO 310 + 160 CONTINUE + FK = FK + SPI*T1*DSQRT(T2/CAZ) + FHS = DABS(0.25D0-DNU2) + GO TO 180 + 170 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE BACKWARD INDEX K FOR CABS(Z).LT.R2 +C----------------------------------------------------------------------- + A2 = DSQRT(CAZ) + AK = FPI*AK/(TOL*DSQRT(A2)) + AA = 3.0D0*T1/(1.0D0+CAZ) + BB = 14.7D0*T1/(28.0D0+CAZ) + AK = (DLOG(AK)+CAZ*DCOS(AA)/(1.0D0+0.008D0*CAZ))/DCOS(BB) + FK = 0.12125D0*AK*AK/CAZ + 1.5D0 + 180 CONTINUE +C----------------------------------------------------------------------- +C BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM +C----------------------------------------------------------------------- + K = INT(SNGL(FK)) + FK = DBLE(FLOAT(K)) + FKS = FK*FK + P1R = CZEROR + P1I = CZEROI + P2R = TOL + P2I = CZEROI + CSR = P2R + CSI = P2I + DO 190 I=1,K + A1 = FKS - FK + AK = (FKS+FK)/(A1+FHS) + RAK = 2.0D0/(FK+CONER) + CBR = (FK+ZR)*RAK + CBI = ZI*RAK + PTR = P2R + PTI = P2I + P2R = (PTR*CBR-PTI*CBI-P1R)*AK + P2I = (PTI*CBR+PTR*CBI-P1I)*AK + P1R = PTR + P1I = PTI + CSR = CSR + P2R + CSI = CSI + P2I + FKS = A1 - FK + CONER + FK = FK - CONER + 190 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER +C SCALING +C----------------------------------------------------------------------- + TM = ZABS(CMPLX(CSR,CSI,kind=KIND(1.0D0))) + PTR = 1.0D0/TM + S1R = P2R*PTR + S1I = P2I*PTR + CSR = CSR*PTR + CSI = -CSI*PTR + CALL ZMLT(COEFR, COEFI, S1R, S1I, STR, STI) + CALL ZMLT(STR, STI, CSR, CSI, S1R, S1I) + IF (INU.GT.0 .OR. N.GT.1) GO TO 200 + ZDR = ZR + ZDI = ZI + IF(IFLAG.EQ.1) GO TO 270 + GO TO 240 + 200 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING +C----------------------------------------------------------------------- + TM = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + PTR = 1.0D0/TM + P1R = P1R*PTR + P1I = P1I*PTR + P2R = P2R*PTR + P2I = -P2I*PTR + CALL ZMLT(P1R, P1I, P2R, P2I, PTR, PTI) + STR = DNU + 0.5D0 - PTR + STI = -PTI + CALL ZDIV(STR, STI, ZR, ZI, STR, STI) + STR = STR + 1.0D0 + CALL ZMLT(STR, STI, S1R, S1I, S2R, S2I) +C----------------------------------------------------------------------- +C FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH +C SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +C----------------------------------------------------------------------- + 210 CONTINUE + STR = DNU + 1.0D0 + CKR = STR*RZR + CKI = STR*RZI + IF (N.EQ.1) INU = INU - 1 + IF (INU.GT.0) GO TO 220 + IF (N.GT.1) GO TO 215 + S1R = S2R + S1I = S2I + 215 CONTINUE + ZDR = ZR + ZDI = ZI + IF(IFLAG.EQ.1) GO TO 270 + GO TO 240 + 220 CONTINUE + INUB = 1 + IF(IFLAG.EQ.1) GO TO 261 + 225 CONTINUE + P1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 230 I=INUB,INU + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + IF (KFLAG.GE.3) GO TO 230 + P2R = S2R*P1R + P2I = S2I*P1R + STR = DABS(P2R) + STI = DABS(P2I) + P2M = DMAX1(STR,STI) + IF (P2M.LE.ASCLE) GO TO 230 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*P1R + S1I = S1I*P1R + S2R = P2R + S2I = P2I + STR = CSSR(KFLAG) + S1R = S1R*STR + S1I = S1I*STR + S2R = S2R*STR + S2I = S2I*STR + P1R = CSRR(KFLAG) + 230 CONTINUE + IF (N.NE.1) GO TO 240 + S1R = S2R + S1I = S2I + 240 CONTINUE + STR = CSRR(KFLAG) + YR(1) = S1R*STR + YI(1) = S1I*STR + IF (N.EQ.1) RETURN + YR(2) = S2R*STR + YI(2) = S2I*STR + IF (N.EQ.2) RETURN + KK = 2 + 250 CONTINUE + KK = KK + 1 + IF (KK.GT.N) RETURN + P1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 260 I=KK,N + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R*P1R + P2I = S2I*P1R + YR(I) = P2R + YI(I) = P2I + IF (KFLAG.GE.3) GO TO 260 + STR = DABS(P2R) + STI = DABS(P2I) + P2M = DMAX1(STR,STI) + IF (P2M.LE.ASCLE) GO TO 260 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*P1R + S1I = S1I*P1R + S2R = P2R + S2I = P2I + STR = CSSR(KFLAG) + S1R = S1R*STR + S1I = S1I*STR + S2R = S2R*STR + S2I = S2I*STR + P1R = CSRR(KFLAG) + 260 CONTINUE + RETURN +C----------------------------------------------------------------------- +C IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW +C----------------------------------------------------------------------- + 261 CONTINUE + HELIM = 0.5D0*ELIM + ELM = DEXP(-ELIM) + CELMR = ELM + ASCLE = BRY(1) + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + DO 262 I=1,INU + STR = S2R + STI = S2I + S2R = STR*CKR-STI*CKI+S1R + S2I = STI*CKR+STR*CKI+S1I + S1R = STR + S1I = STI + CKR = CKR+RZR + CKI = CKI+RZI + AS = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + ALAS = DLOG(AS) + P2R = -ZDR+ALAS + IF(P2R.LT.(-ELIM)) GO TO 263 + CALL ZLOG(S2R,S2I,STR,STI,IDUM) + P2R = -ZDR+STR + P2I = -ZDI+STI + P2M = DEXP(P2R)/TOL + P1R = P2M*DCOS(P2I) + P1I = P2M*DSIN(P2I) + CALL ZUCHK(P1R,P1I,NW,ASCLE,TOL) + IF(NW.NE.0) GO TO 263 + J = 3 - J + CYR(J) = P1R + CYI(J) = P1I + IF(IC.EQ.(I-1)) GO TO 264 + IC = I + GO TO 262 + 263 CONTINUE + IF(ALAS.LT.HELIM) GO TO 262 + ZDR = ZDR-ELIM + S1R = S1R*CELMR + S1I = S1I*CELMR + S2R = S2R*CELMR + S2I = S2I*CELMR + 262 CONTINUE + IF(N.NE.1) GO TO 270 + S1R = S2R + S1I = S2I + GO TO 270 + 264 CONTINUE + KFLAG = 1 + INUB = I+1 + S2R = CYR(J) + S2I = CYI(J) + J = 3 - J + S1R = CYR(J) + S1I = CYI(J) + IF(INUB.LE.INU) GO TO 225 + IF(N.NE.1) GO TO 240 + S1R = S2R + S1I = S2I + GO TO 240 + 270 CONTINUE + YR(1) = S1R + YI(1) = S1I + IF(N.EQ.1) GO TO 280 + YR(2) = S2R + YI(2) = S2I + 280 CONTINUE + ASCLE = BRY(1) + CALL ZKSCL(ZDR,ZDI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM) + INU = N - NZ + IF (INU.LE.0) RETURN + KK = NZ + 1 + S1R = YR(KK) + S1I = YI(KK) + YR(KK) = S1R*CSRR(1) + YI(KK) = S1I*CSRR(1) + IF (INU.EQ.1) RETURN + KK = NZ + 2 + S2R = YR(KK) + S2I = YI(KK) + YR(KK) = S2R*CSRR(1) + YI(KK) = S2I*CSRR(1) + IF (INU.EQ.2) RETURN + T2 = FNU + DBLE(FLOAT(KK-1)) + CKR = T2*RZR + CKI = T2*RZI + KFLAG = 1 + GO TO 250 + 290 CONTINUE +C----------------------------------------------------------------------- +C SCALE BY DEXP(Z), IFLAG = 1 CASES +C----------------------------------------------------------------------- + KODED = 2 + IFLAG = 1 + KFLAG = 2 + GO TO 120 +C----------------------------------------------------------------------- +C FNU=HALF ODD INTEGER CASE, DNU=-0.5 +C----------------------------------------------------------------------- + 300 CONTINUE + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + GO TO 210 +C +C + 310 CONTINUE + NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbuni.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbuni.f new file mode 100644 index 00000000..3811b89a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbuni.f @@ -0,0 +1,174 @@ + SUBROUTINE ZBUNI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NUI, NLAST, + * FNUL, TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZBUNI +C***REFER TO ZBESI,ZBESK +C +C ZBUNI COMPUTES THE I BESSEL FUNCTION FOR LARGE CABS(Z).GT. +C FNUL AND FNU+N-1.LT.FNUL. THE ORDER IS INCREASED FROM +C FNU+N-1 GREATER THAN FNUL BY ADDING NUI AND COMPUTING +C ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR I(FNU,Z) +C ON IFORM=1 AND THE EXPANSION FOR J(FNU,Z) ON IFORM=2 +C +C***ROUTINES CALLED ZUNI1,ZUNI2,ZABS,D1MACH +C***END PROLOGUE ZBUNI +C COMPLEX CSCL,CSCR,CY,RZ,ST,S1,S2,Y,Z + DOUBLE PRECISION ALIM, AX, AY, CSCLR, CSCRR, CYI, CYR, DFNU, + * ELIM, FNU, FNUI, FNUL, GNU, RAZ, RZI, RZR, STI, STR, S1I, S1R, + * S2I, S2R, TOL, YI, YR, ZI, ZR, ZABS, ASCLE, BRY, C1R, C1I, C1M, + * D1MACH + INTEGER I, IFLAG, IFORM, K, KODE, N, NL, NLAST, NUI, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2), BRY(3) + NZ = 0 + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IFORM = 1 + IF (AY.GT.AX) IFORM = 2 + IF (NUI.EQ.0) GO TO 60 + FNUI = DBLE(FLOAT(NUI)) + DFNU = FNU + DBLE(FLOAT(N-1)) + GNU = DFNU + FNUI + IF (IFORM.EQ.2) GO TO 10 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNI1(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNI2(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + 20 CONTINUE + IF (NW.LT.0) GO TO 50 + IF (NW.NE.0) GO TO 90 + STR = ZABS(CMPLX(CYR(1),CYI(1),kind=KIND(1.0D0))) +C---------------------------------------------------------------------- +C SCALE BACKWARD RECURRENCE, BRY(3) IS DEFINED BUT NEVER USED +C---------------------------------------------------------------------- + BRY(1)=1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = BRY(2) + IFLAG = 2 + ASCLE = BRY(2) + CSCLR = 1.0D0 + IF (STR.GT.BRY(1)) GO TO 21 + IFLAG = 1 + ASCLE = BRY(1) + CSCLR = 1.0D0/TOL + GO TO 25 + 21 CONTINUE + IF (STR.LT.BRY(2)) GO TO 25 + IFLAG = 3 + ASCLE=BRY(3) + CSCLR = TOL + 25 CONTINUE + CSCRR = 1.0D0/CSCLR + S1R = CYR(2)*CSCLR + S1I = CYI(2)*CSCLR + S2R = CYR(1)*CSCLR + S2I = CYI(1)*CSCLR + RAZ = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + DO 30 I=1,NUI + STR = S2R + STI = S2I + S2R = (DFNU+FNUI)*(RZR*STR-RZI*STI) + S1R + S2I = (DFNU+FNUI)*(RZR*STI+RZI*STR) + S1I + S1R = STR + S1I = STI + FNUI = FNUI - 1.0D0 + IF (IFLAG.GE.3) GO TO 30 + STR = S2R*CSCRR + STI = S2I*CSCRR + C1R = DABS(STR) + C1I = DABS(STI) + C1M = DMAX1(C1R,C1I) + IF (C1M.LE.ASCLE) GO TO 30 + IFLAG = IFLAG+1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSCRR + S1I = S1I*CSCRR + S2R = STR + S2I = STI + CSCLR = CSCLR*TOL + CSCRR = 1.0D0/CSCLR + S1R = S1R*CSCLR + S1I = S1I*CSCLR + S2R = S2R*CSCLR + S2I = S2I*CSCLR + 30 CONTINUE + YR(N) = S2R*CSCRR + YI(N) = S2I*CSCRR + IF (N.EQ.1) RETURN + NL = N - 1 + FNUI = DBLE(FLOAT(NL)) + K = NL + DO 40 I=1,NL + STR = S2R + STI = S2I + S2R = (FNU+FNUI)*(RZR*STR-RZI*STI) + S1R + S2I = (FNU+FNUI)*(RZR*STI+RZI*STR) + S1I + S1R = STR + S1I = STI + STR = S2R*CSCRR + STI = S2I*CSCRR + YR(K) = STR + YI(K) = STI + FNUI = FNUI - 1.0D0 + K = K - 1 + IF (IFLAG.GE.3) GO TO 40 + C1R = DABS(STR) + C1I = DABS(STI) + C1M = DMAX1(C1R,C1I) + IF (C1M.LE.ASCLE) GO TO 40 + IFLAG = IFLAG+1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSCRR + S1I = S1I*CSCRR + S2R = STR + S2I = STI + CSCLR = CSCLR*TOL + CSCRR = 1.0D0/CSCLR + S1R = S1R*CSCLR + S1I = S1I*CSCLR + S2R = S2R*CSCLR + S2I = S2I*CSCLR + 40 CONTINUE + RETURN + 50 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + 60 CONTINUE + IF (IFORM.EQ.2) GO TO 70 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + GO TO 80 + 70 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + 80 CONTINUE + IF (NW.LT.0) GO TO 50 + NZ = NW + RETURN + 90 CONTINUE + NLAST = N + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbunk.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbunk.f new file mode 100644 index 00000000..b20b79f3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zbunk.f @@ -0,0 +1,35 @@ + SUBROUTINE ZBUNK(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZBUNK +C***REFER TO ZBESK,ZBESH +C +C ZBUNK COMPUTES THE K BESSEL FUNCTION FOR FNU.GT.FNUL. +C ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR K(FNU,Z) +C IN ZUNK1 AND THE EXPANSION FOR H(2,FNU,Z) IN ZUNK2 +C +C***ROUTINES CALLED ZUNK1,ZUNK2 +C***END PROLOGUE ZBUNK +C COMPLEX Y,Z + DOUBLE PRECISION ALIM, AX, AY, ELIM, FNU, TOL, YI, YR, ZI, ZR + INTEGER KODE, MR, N, NZ + DIMENSION YR(N), YI(N) + NZ = 0 + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IF (AY.GT.AX) GO TO 10 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR K(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM) + GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR H(2,FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM) + 20 CONTINUE + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zdiv.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zdiv.f new file mode 100644 index 00000000..ac73b86d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zdiv.f @@ -0,0 +1,19 @@ + SUBROUTINE ZDIV(AR, AI, BR, BI, CR, CI) +C***BEGIN PROLOGUE ZDIV +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX DIVIDE C=A/B. +C +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZDIV + DOUBLE PRECISION AR, AI, BR, BI, CR, CI, BM, CA, CB, CC, CD + DOUBLE PRECISION ZABS + BM = 1.0D0/ZABS(CMPLX(BR,BI,kind=KIND(1.0D0))) + CC = BR*BM + CD = BI*BM + CA = (AR*CC+AI*CD)*BM + CB = (AI*CC-AR*CD)*BM + CR = CA + CI = CB + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zexp.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zexp.f new file mode 100644 index 00000000..fcb553c1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zexp.f @@ -0,0 +1,16 @@ + SUBROUTINE ZEXP(AR, AI, BR, BI) +C***BEGIN PROLOGUE ZEXP +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX EXPONENTIAL FUNCTION B=EXP(A) +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZEXP + DOUBLE PRECISION AR, AI, BR, BI, ZM, CA, CB + ZM = DEXP(AR) + CA = ZM*DCOS(AI) + CB = ZM*DSIN(AI) + BR = CA + BI = CB + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zkscl.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zkscl.f new file mode 100644 index 00000000..eeda4715 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zkscl.f @@ -0,0 +1,121 @@ + SUBROUTINE ZKSCL(ZRR,ZRI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM) +C***BEGIN PROLOGUE ZKSCL +C***REFER TO ZBESK +C +C SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +C ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +C RETURN WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +C +C***ROUTINES CALLED ZUCHK,ZABS,ZLOG +C***END PROLOGUE ZKSCL +C COMPLEX CK,CS,CY,CZERO,RZ,S1,S2,Y,ZR,ZD,CELM + DOUBLE PRECISION ACS, AS, ASCLE, CKI, CKR, CSI, CSR, CYI, + * CYR, ELIM, FN, FNU, RZI, RZR, STR, S1I, S1R, S2I, + * S2R, TOL, YI, YR, ZEROI, ZEROR, ZRI, ZRR, ZABS, + * ZDR, ZDI, CELMR, ELM, HELIM, ALAS + INTEGER I, IC, IDUM, KK, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2) + DATA ZEROR,ZEROI / 0.0D0 , 0.0D0 / +C + NZ = 0 + IC = 0 + NN = MIN0(2,N) + DO 10 I=1,NN + S1R = YR(I) + S1I = YI(I) + CYR(I) = S1R + CYI(I) = S1I + AS = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + ACS = -ZRR + DLOG(AS) + NZ = NZ + 1 + YR(I) = ZEROR + YI(I) = ZEROI + IF (ACS.LT.(-ELIM)) GO TO 10 + CALL ZLOG(S1R, S1I, CSR, CSI, IDUM) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = DEXP(CSR)/TOL + CSR = STR*DCOS(CSI) + CSI = STR*DSIN(CSI) + CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 10 + YR(I) = CSR + YI(I) = CSI + IC = I + NZ = NZ - 1 + 10 CONTINUE + IF (N.EQ.1) RETURN + IF (IC.GT.1) GO TO 20 + YR(1) = ZEROR + YI(1) = ZEROI + NZ = 2 + 20 CONTINUE + IF (N.EQ.2) RETURN + IF (NZ.EQ.0) RETURN + FN = FNU + 1.0D0 + CKR = FN*RZR + CKI = FN*RZI + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + HELIM = 0.5D0*ELIM + ELM = DEXP(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI +C +C FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF +C S2 GETS LARGER THAN EXP(ELIM/2) +C + DO 30 I=3,N + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + ALAS = DLOG(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR(I) = ZEROR + YI(I) = ZEROI + IF (ACS.LT.(-ELIM)) GO TO 25 + CALL ZLOG(S2R, S2I, CSR, CSI, IDUM) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = DEXP(CSR)/TOL + CSR = STR*DCOS(CSI) + CSI = STR*DSIN(CSI) + CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 25 + YR(I) = CSR + YI(I) = CSI + NZ = NZ - 1 + IF (IC.EQ.KK-1) GO TO 40 + IC = KK + GO TO 30 + 25 CONTINUE + IF(ALAS.LT.HELIM) GO TO 30 + ZDR = ZDR - ELIM + S1R = S1R*CELMR + S1I = S1I*CELMR + S2R = S2R*CELMR + S2I = S2I*CELMR + 30 CONTINUE + NZ = N + IF(IC.EQ.N) NZ=N-1 + GO TO 45 + 40 CONTINUE + NZ = KK - 2 + 45 CONTINUE + DO 50 I=1,NZ + YR(I) = ZEROR + YI(I) = ZEROI + 50 CONTINUE + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zlog.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zlog.f new file mode 100644 index 00000000..bb22cd01 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zlog.f @@ -0,0 +1,41 @@ + SUBROUTINE ZLOG(AR, AI, BR, BI, IERR) +C***BEGIN PROLOGUE ZLOG +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX LOGARITHM B=CLOG(A) +C IERR=0,NORMAL RETURN IERR=1, Z=CMPLX(0.0,0.0) +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZLOG + DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DHPI + DOUBLE PRECISION ZABS + DATA DPI , DHPI / 3.141592653589793238462643383D+0, + 1 1.570796326794896619231321696D+0/ +C + IERR=0 + IF (AR.EQ.0.0D+0) GO TO 10 + IF (AI.EQ.0.0D+0) GO TO 20 + DTHETA = DATAN(AI/AR) + IF (DTHETA.LE.0.0D+0) GO TO 40 + IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI + GO TO 50 + 10 IF (AI.EQ.0.0D+0) GO TO 60 + BI = DHPI + BR = DLOG(DABS(AI)) + IF (AI.LT.0.0D+0) BI = -BI + RETURN + 20 IF (AR.GT.0.0D+0) GO TO 30 + BR = DLOG(DABS(AR)) + BI = DPI + RETURN + 30 BR = DLOG(AR) + BI = 0.0D+0 + RETURN + 40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI + 50 ZM = ZABS(CMPLX(AR,AI,kind=KIND(1.0D0))) + BR = DLOG(ZM) + BI = DTHETA + RETURN + 60 CONTINUE + IERR=1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlri.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlri.f new file mode 100644 index 00000000..c112f79d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlri.f @@ -0,0 +1,206 @@ + SUBROUTINE ZMLRI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL) +C***BEGIN PROLOGUE ZMLRI +C***REFER TO ZBESI,ZBESK +C +C ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY THE +C MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +C +C***ROUTINES CALLED DGAMLN,D1MACH,ZABS,ZEXP,ZLOG,ZMLT +C***END PROLOGUE ZMLRI +C COMPLEX CK,CNORM,CONE,CTWO,CZERO,PT,P1,P2,RZ,SUM,Y,Z + DOUBLE PRECISION ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + * CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, FNU, PTI, PTR, P1I, + * P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + * SUMR, TFNF, TOL, TST, YI, YR, ZEROI, ZEROR, ZI, ZR, DGAMLN, + * D1MACH, ZABS + INTEGER I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, KODE, M, N, NZ + DIMENSION YR(N), YI(N) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / + SCLE = D1MACH(1)/TOL + NZ=0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + IAZ = INT(SNGL(AZ)) + IFNU = INT(SNGL(FNU)) + INU = IFNU + N - 1 + AT = DBLE(FLOAT(IAZ)) + 1.0D0 + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + CKR = STR*AT*RAZ + CKI = STI*AT*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT+1.0D0)*RAZ + RHO = ACK + DSQRT(ACK*ACK-1.0D0) + RHO2 = RHO*RHO + TST = (RHO2+RHO2)/((RHO2-1.0D0)*(RHO-1.0D0)) + TST = TST/TOL +C----------------------------------------------------------------------- +C COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES +C----------------------------------------------------------------------- + AK = AT + DO 10 I=1,80 + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR-CKI*PTI) + P2I = P1I - (CKI*PTR+CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP.GT.TST*AK*AK) THEN + GO TO 20 + END IF + AK = AK + 1.0D0 + 10 CONTINUE + GO TO 110 + 20 CONTINUE + I = I + 1 + K = 0 + IF (INU.LT.IAZ) GO TO 40 +C----------------------------------------------------------------------- +C COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS +C----------------------------------------------------------------------- + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = DBLE(FLOAT(INU)) + 1.0D0 + STR = ZR*RAZ + STI = -ZI*RAZ + CKR = STR*AT*RAZ + CKI = STI*AT*RAZ + ACK = AT*RAZ + TST = DSQRT(ACK/TOL) + ITIME = 1 + DO 30 K=1,80 + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR-CKI*PTI) + P2I = P1I - (CKR*PTI+CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP.LT.TST) GO TO 30 + IF (ITIME.EQ.2) GO TO 40 + ACK = ZABS(CMPLX(CKR,CKI,kind=KIND(1.0D0))) + FLAM = ACK + DSQRT(ACK*ACK-1.0D0) + FKAP = AP/ZABS(CMPLX(P1R,P1I,kind=KIND(1.0D0))) + RHO = DMIN1(FLAM,FKAP) + TST = TST*DSQRT(RHO/(RHO*RHO-1.0D0)) + ITIME = 2 + 30 CONTINUE + GO TO 110 + 40 CONTINUE +C----------------------------------------------------------------------- +C BACKWARD RECURRENCE AND SUM NORMALIZING RELATION +C----------------------------------------------------------------------- + K = K + 1 + KK = MAX0(I+IAZ,K+INU) + FKK = DBLE(FLOAT(KK)) + P1R = ZEROR + P1I = ZEROI +C----------------------------------------------------------------------- +C SCALE P2 AND SUM BY SCLE +C----------------------------------------------------------------------- + P2R = SCLE + P2I = ZEROI + FNF = FNU - DBLE(FLOAT(IFNU)) + TFNF = FNF + FNF + BK = DGAMLN(FKK+TFNF+1.0D0,IDUM) - DGAMLN(FKK+1.0D0,IDUM) - + * DGAMLN(TFNF+1.0D0,IDUM) + BK = DEXP(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + DO 50 I=1,KM + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + 50 CONTINUE + YR(N) = P2R + YI(N) = P2I + IF (N.EQ.1) GO TO 70 + DO 60 I=2,N + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + M = N - I + 1 + YR(M) = P2R + YI(M) = P2I + 60 CONTINUE + 70 CONTINUE + IF (IFNU.LE.0) GO TO 90 + DO 80 I=1,IFNU + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + 80 CONTINUE + 90 CONTINUE + PTR = ZR + PTI = ZI + IF (KODE.EQ.2) PTR = ZEROR + CALL ZLOG(RZR, RZI, STR, STI, IDUM) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = DGAMLN(1.0D0+FNF,IDUM) + PTR = P1R - AP + PTI = P1I +C----------------------------------------------------------------------- +C THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW +C IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES +C----------------------------------------------------------------------- + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + P1R = 1.0D0/AP + CALL ZEXP(PTR, PTI, STR, STI) + CKR = STR*P1R + CKI = STI*P1R + PTR = P2R*P1R + PTI = -P2I*P1R + CALL ZMLT(CKR, CKI, PTR, PTI, CNORMR, CNORMI) + DO 100 I=1,N + STR = YR(I)*CNORMR - YI(I)*CNORMI + YI(I) = YR(I)*CNORMI + YI(I)*CNORMR + YR(I) = STR + 100 CONTINUE + RETURN + 110 CONTINUE + NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlt.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlt.f new file mode 100644 index 00000000..3bde7d34 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zmlt.f @@ -0,0 +1,15 @@ + SUBROUTINE ZMLT(AR, AI, BR, BI, CR, CI) +C***BEGIN PROLOGUE ZMLT +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX MULTIPLY, C=A*B. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZMLT + DOUBLE PRECISION AR, AI, BR, BI, CR, CI, CA, CB + CA = AR*BR - AI*BI + CB = AR*BI + AI*BR + CR = CA + CI = CB + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zrati.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zrati.f new file mode 100644 index 00000000..b66bd201 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zrati.f @@ -0,0 +1,132 @@ + SUBROUTINE ZRATI(ZR, ZI, FNU, N, CYR, CYI, TOL) +C***BEGIN PROLOGUE ZRATI +C***REFER TO ZBESI,ZBESK,ZBESH +C +C ZRATI COMPUTES RATIOS OF I BESSEL FUNCTIONS BY BACKWARD +C RECURRENCE. THE STARTING INDEX IS DETERMINED BY FORWARD +C RECURRENCE AS DESCRIBED IN J. RES. OF NAT. BUR. OF STANDARDS-B, +C MATHEMATICAL SCIENCES, VOL 77B, P111-114, SEPTEMBER, 1973, +C BESSEL FUNCTIONS I AND J OF COMPLEX ARGUMENT AND INTEGER ORDER, +C BY D. J. SOOKNE. +C +C***ROUTINES CALLED ZABS,ZDIV +C***END PROLOGUE ZRATI +C COMPLEX Z,CY(1),CONE,CZERO,P1,P2,T1,RZ,PT,CDFNU + DOUBLE PRECISION AK, AMAGZ, AP1, AP2, ARG, AZ, CDFNUI, CDFNUR, + * CONEI, CONER, CYI, CYR, CZEROI, CZEROR, DFNU, FDNU, FLAM, FNU, + * FNUP, PTI, PTR, P1I, P1R, P2I, P2R, RAK, RAP1, RHO, RT2, RZI, + * RZR, TEST, TEST1, TOL, TTI, TTR, T1I, T1R, ZI, ZR, ZABS + INTEGER I, ID, IDNU, INU, ITIME, K, KK, MAGZ, N + DIMENSION CYR(N), CYI(N) + DATA CZEROR,CZEROI,CONER,CONEI,RT2/ + 1 0.0D0, 0.0D0, 1.0D0, 0.0D0, 1.41421356237309505D0 / + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + INU = INT(SNGL(FNU)) + IDNU = INU + N - 1 + MAGZ = INT(SNGL(AZ)) + AMAGZ = DBLE(FLOAT(MAGZ+1)) + FDNU = DBLE(FLOAT(IDNU)) + FNUP = DMAX1(AMAGZ,FDNU) + ID = IDNU - MAGZ - 1 + ITIME = 1 + K = 1 + PTR = 1.0D0/AZ + RZR = PTR*(ZR+ZR)*PTR + RZI = -PTR*(ZI+ZI)*PTR + T1R = RZR*FNUP + T1I = RZI*FNUP + P2R = -T1R + P2I = -T1I + P1R = CONER + P1I = CONEI + T1R = T1R + RZR + T1I = T1I + RZI + IF (ID.GT.0) ID = 0 + AP2 = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + AP1 = ZABS(CMPLX(P1R,P1I,kind=KIND(1.0D0))) +C----------------------------------------------------------------------- +C THE OVERFLOW TEST ON K(FNU+I-1,Z) BEFORE THE CALL TO CBKNU +C GUARANTEES THAT P2 IS ON SCALE. SCALE TEST1 AND ALL SUBSEQUENT +C P2 VALUES BY AP1 TO ENSURE THAT AN OVERFLOW DOES NOT OCCUR +C PREMATURELY. +C----------------------------------------------------------------------- + ARG = (AP2+AP2)/(AP1*TOL) + TEST1 = DSQRT(ARG) + TEST = TEST1 + RAP1 = 1.0D0/AP1 + P1R = P1R*RAP1 + P1I = P1I*RAP1 + P2R = P2R*RAP1 + P2I = P2I*RAP1 + AP2 = AP2*RAP1 + 10 CONTINUE + K = K + 1 + AP1 = AP2 + PTR = P2R + PTI = P2I + P2R = P1R - (T1R*PTR-T1I*PTI) + P2I = P1I - (T1R*PTI+T1I*PTR) + P1R = PTR + P1I = PTI + T1R = T1R + RZR + T1I = T1I + RZI + AP2 = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP1.LE.TEST) GO TO 10 + IF (ITIME.EQ.2) GO TO 20 + AK = ZABS(CMPLX(T1R,T1I,kind=KIND(1.0D0))*0.5D0) + FLAM = AK + DSQRT(AK*AK-1.0D0) + RHO = DMIN1(AP2/AP1,FLAM) + TEST = TEST1*DSQRT(RHO/(RHO*RHO-1.0D0)) + ITIME = 2 + GO TO 10 + 20 CONTINUE + KK = K + 1 - ID + AK = DBLE(FLOAT(KK)) + T1R = AK + T1I = CZEROI + DFNU = FNU + DBLE(FLOAT(N-1)) + P1R = 1.0D0/AP2 + P1I = CZEROI + P2R = CZEROR + P2I = CZEROI + DO 30 I=1,KK + PTR = P1R + PTI = P1I + RAP1 = DFNU + T1R + TTR = RZR*RAP1 + TTI = RZI*RAP1 + P1R = (PTR*TTR-PTI*TTI) + P2R + P1I = (PTR*TTI+PTI*TTR) + P2I + P2R = PTR + P2I = PTI + T1R = T1R - CONER + 30 CONTINUE + IF (P1R.NE.CZEROR .OR. P1I.NE.CZEROI) GO TO 40 + P1R = TOL + P1I = TOL + 40 CONTINUE + CALL ZDIV(P2R, P2I, P1R, P1I, CYR(N), CYI(N)) + IF (N.EQ.1) RETURN + K = N - 1 + AK = DBLE(FLOAT(K)) + T1R = AK + T1I = CZEROI + CDFNUR = FNU*RZR + CDFNUI = FNU*RZI + DO 60 I=2,N + PTR = CDFNUR + (T1R*RZR-T1I*RZI) + CYR(K+1) + PTI = CDFNUI + (T1R*RZI+T1I*RZR) + CYI(K+1) + AK = ZABS(CMPLX(PTR,PTI,kind=KIND(1.0D0))) + IF (AK.NE.CZEROR) GO TO 50 + PTR = TOL + PTI = TOL + AK = TOL*RT2 + 50 CONTINUE + RAK = CONER/AK + CYR(K) = RAK*PTR*RAK + CYI(K) = -RAK*PTI*RAK + T1R = T1R - CONER + K = K - 1 + 60 CONTINUE + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zs1s2.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zs1s2.f new file mode 100644 index 00000000..0a6da311 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zs1s2.f @@ -0,0 +1,51 @@ + SUBROUTINE ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, + * IUF) +C***BEGIN PROLOGUE ZS1S2 +C***REFER TO ZBESK,ZAIRY +C +C ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE +C ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON- +C TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION. +C ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF +C MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER +C OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE +C PRECISION ABOVE THE UNDERFLOW LIMIT. +C +C***ROUTINES CALLED ZABS,ZEXP,ZLOG +C***END PROLOGUE ZS1S2 +C COMPLEX CZERO,C1,S1,S1D,S2,ZR + DOUBLE PRECISION AA, ALIM, ALN, ASCLE, AS1, AS2, C1I, C1R, S1DI, + * S1DR, S1I, S1R, S2I, S2R, ZEROI, ZEROR, ZRI, ZRR, ZABS + INTEGER IUF, IDUM, NZ + DATA ZEROR,ZEROI / 0.0D0 , 0.0D0 / + NZ = 0 + AS1 = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + AS2 = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + IF (S1R.EQ.0.0D0 .AND. S1I.EQ.0.0D0) GO TO 10 + IF (AS1.EQ.0.0D0) GO TO 10 + ALN = -ZRR - ZRR + DLOG(AS1) + S1DR = S1R + S1DI = S1I + S1R = ZEROR + S1I = ZEROI + AS1 = ZEROR + IF (ALN.LT.(-ALIM)) GO TO 10 + CALL ZLOG(S1DR, S1DI, C1R, C1I, IDUM) + C1R = C1R - ZRR - ZRR + C1I = C1I - ZRI - ZRI + CALL ZEXP(C1R, C1I, S1R, S1I) + AS1 = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + IUF = IUF + 1 + 10 CONTINUE + AA = DMAX1(AS1,AS2) + IF (AA.GT.ASCLE) THEN + RETURN + END IF + S1R = ZEROR + S1I = ZEROI + S2R = ZEROR + S2I = ZEROI + NZ = 1 + IUF = 0 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zseri.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zseri.f new file mode 100644 index 00000000..862fbf61 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zseri.f @@ -0,0 +1,195 @@ + SUBROUTINE ZSERI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZSERI +C***REFER TO ZBESI,ZBESK +C +C ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY +C MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE +C REGION CABS(Z).LE.2*SQRT(FNU+1). NZ=0 IS A NORMAL RETURN. +C NZ.GT.0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO +C DUE TO UNDERFLOW. NZ.LT.0 MEANS UNDERFLOW OCCURRED, BUT THE +C CONDITION CABS(Z).LE.2*SQRT(FNU+1) WAS VIOLATED AND THE +C COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ). +C +C***ROUTINES CALLED DGAMLN,D1MACH,ZUCHK,ZABS,ZDIV,ZLOG,ZMLT +C***END PROLOGUE ZSERI +C COMPLEX AK1,CK,COEF,CONE,CRSC,CSCL,CZ,CZERO,HZ,RZ,S1,S2,Y,Z + DOUBLE PRECISION AA, ACZ, AK, AK1I, AK1R, ALIM, ARM, ASCLE, ATOL, + * AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU, + * ELIM, FNU, FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI, + * STR, S1I, S1R, S2I, S2R, TOL, YI, YR, WI, WR, ZEROI, ZEROR, ZI, + * ZR, DGAMLN, D1MACH, ZABS + INTEGER I, IB, IDUM, IFLAG, IL, K, KODE, L, M, N, NN, NZ, NW + DIMENSION YR(N), YI(N), WR(2), WI(2) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + IF (AZ.EQ.0.0D0) GO TO 160 + ARM = 1.0D+3*D1MACH(1) + RTR1 = DSQRT(ARM) + CRSCR = 1.0D0 + IFLAG = 0 + IF (AZ.LT.ARM) THEN + GO TO 150 + END IF + HZR = 0.5D0*ZR + HZI = 0.5D0*ZI + CZR = ZEROR + CZI = ZEROI + IF (AZ.LE.RTR1) GO TO 10 + CALL ZMLT(HZR, HZI, HZR, HZI, CZR, CZI) + 10 CONTINUE + ACZ = ZABS(CMPLX(CZR,CZI,kind=KIND(1.0D0))) + NN = N + CALL ZLOG(HZR, HZI, CKR, CKI, IDUM) + 20 CONTINUE + DFNU = FNU + DBLE(FLOAT(NN-1)) + FNUP = DFNU + 1.0D0 +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + AK1R = CKR*DFNU + AK1I = CKI*DFNU + AK = DGAMLN(FNUP,IDUM) + AK1R = AK1R - AK + IF (KODE.EQ.2) AK1R = AK1R - ZR + IF (AK1R.GT.(-ELIM)) GO TO 40 + 30 CONTINUE + NZ = NZ + 1 + YR(NN) = ZEROR + YI(NN) = ZEROI + IF (ACZ.GT.DFNU) GO TO 190 + NN = NN - 1 + IF (NN.EQ.0) RETURN + GO TO 20 + 40 CONTINUE + IF (AK1R.GT.(-ALIM)) GO TO 50 + IFLAG = 1 + SS = 1.0D0/TOL + CRSCR = TOL + ASCLE = ARM*SS + 50 CONTINUE + AA = DEXP(AK1R) + IF (IFLAG.EQ.1) AA = AA*SS + COEFR = AA*DCOS(AK1I) + COEFI = AA*DSIN(AK1I) + ATOL = TOL*ACZ/FNUP + IL = MIN0(2,NN) + DO 90 I=1,IL + DFNU = FNU + DBLE(FLOAT(NN-I)) + FNUP = DFNU + 1.0D0 + S1R = CONER + S1I = CONEI + IF (ACZ.LT.TOL*FNUP) GO TO 70 + AK1R = CONER + AK1I = CONEI + AK = FNUP + 2.0D0 + S = FNUP + AA = 2.0D0 + 60 CONTINUE + RS = 1.0D0/S + STR = AK1R*CZR - AK1I*CZI + STI = AK1R*CZI + AK1I*CZR + AK1R = STR*RS + AK1I = STI*RS + S1R = S1R + AK1R + S1I = S1I + AK1I + S = S + AK + AK = AK + 2.0D0 + AA = AA*ACZ*RS + IF (AA.GT.ATOL) GO TO 60 + 70 CONTINUE + S2R = S1R*COEFR - S1I*COEFI + S2I = S1R*COEFI + S1I*COEFR + WR(I) = S2R + WI(I) = S2I + IF (IFLAG.EQ.0) GO TO 80 + CALL ZUCHK(S2R, S2I, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 30 + 80 CONTINUE + M = NN - I + 1 + YR(M) = S2R*CRSCR + YI(M) = S2I*CRSCR + IF (I.EQ.IL) GO TO 90 + CALL ZDIV(COEFR, COEFI, HZR, HZI, STR, STI) + COEFR = STR*DFNU + COEFI = STI*DFNU + 90 CONTINUE + IF (NN.LE.2) THEN + RETURN + END IF + K = NN - 2 + AK = DBLE(FLOAT(K)) + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + IF (IFLAG.EQ.1) GO TO 120 + IB = 3 + 100 CONTINUE + DO 110 I=IB,NN + YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2) + YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2) + AK = AK - 1.0D0 + K = K - 1 + 110 CONTINUE + RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD WITH SCALED VALUES +C----------------------------------------------------------------------- + 120 CONTINUE +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE +C UNDERFLOW LIMIT = ASCLE = D1MACH(1)*SS*1.0D+3 +C----------------------------------------------------------------------- + S1R = WR(1) + S1I = WI(1) + S2R = WR(2) + S2I = WI(2) + DO 130 L=3,NN + CKR = S2R + CKI = S2I + S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI) + S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR) + S1R = CKR + S1I = CKI + CKR = S2R*CRSCR + CKI = S2I*CRSCR + YR(K) = CKR + YI(K) = CKI + AK = AK - 1.0D0 + K = K - 1 + IF (ZABS(CMPLX(CKR,CKI,kind=KIND(1.0D0))).GT.ASCLE) GO TO 140 + 130 CONTINUE + RETURN + 140 CONTINUE + IB = L + 1 + IF (IB.GT.NN) RETURN + GO TO 100 + 150 CONTINUE + NZ = N + IF (FNU.EQ.0.0D0) NZ = NZ - 1 + 160 CONTINUE + YR(1) = ZEROR + YI(1) = ZEROI + IF (FNU.NE.0.0D0) GO TO 170 + YR(1) = CONER + YI(1) = CONEI + 170 CONTINUE + IF (N.EQ.1) RETURN + DO 180 I=2,N + YR(I) = ZEROR + YI(I) = ZEROI + 180 CONTINUE + RETURN +C----------------------------------------------------------------------- +C RETURN WITH NZ.LT.0 IF CABS(Z*Z/4).GT.FNU+N-NZ-1 COMPLETE +C THE CALCULATION IN CBINU WITH N=N-IABS(NZ) +C----------------------------------------------------------------------- + 190 CONTINUE + NZ = -NZ + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zshch.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zshch.f new file mode 100644 index 00000000..168e62e5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zshch.f @@ -0,0 +1,22 @@ + SUBROUTINE ZSHCH(ZR, ZI, CSHR, CSHI, CCHR, CCHI) +C***BEGIN PROLOGUE ZSHCH +C***REFER TO ZBESK,ZBESH +C +C ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+I*Y) +C AND CCH=COSH(X+I*Y), WHERE I**2=-1. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZSHCH +C + DOUBLE PRECISION CCHI, CCHR, CH, CN, CSHI, CSHR, SH, SN, ZI, ZR, + * DCOSH, DSINH + SH = DSINH(ZR) + CH = DCOSH(ZR) + SN = DSIN(ZI) + CN = DCOS(ZI) + CSHR = SH*CN + CSHI = CH*SN + CCHR = CH*CN + CCHI = SH*SN + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zsqrt.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zsqrt.f new file mode 100644 index 00000000..289545cd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zsqrt.f @@ -0,0 +1,45 @@ + SUBROUTINE ZSQRT(AR, AI, BR, BI) +C***BEGIN PROLOGUE ZSQRT +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX SQUARE ROOT, B=CSQRT(A) +C +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZSQRT + DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DRT + DOUBLE PRECISION ZABS + + DATA DRT , DPI / 7.071067811865475244008443621D-1, + 1 3.141592653589793238462643383D+0/ + ZM = ZABS(CMPLX(AR,AI,kind=KIND(1.0D0))) + ZM = DSQRT(ZM) + IF (AR.EQ.0.0D+0) GO TO 10 + IF (AI.EQ.0.0D+0) GO TO 20 + DTHETA = DATAN(AI/AR) + IF (DTHETA.LE.0.0D+0) GO TO 40 + IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI + GO TO 50 + 10 IF (AI.GT.0.0D+0) GO TO 60 + IF (AI.LT.0.0D+0) GO TO 70 + BR = 0.0D+0 + BI = 0.0D+0 + RETURN + 20 IF (AR.GT.0.0D+0) GO TO 30 + BR = 0.0D+0 + BI = DSQRT(DABS(AR)) + RETURN + 30 BR = DSQRT(AR) + BI = 0.0D+0 + RETURN + 40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI + 50 DTHETA = DTHETA*0.5D+0 + BR = ZM*DCOS(DTHETA) + BI = ZM*DSIN(DTHETA) + RETURN + 60 BR = ZM*DRT + BI = ZM*DRT + RETURN + 70 BR = ZM*DRT + BI = -ZM*DRT + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuchk.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuchk.f new file mode 100644 index 00000000..d15dc841 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuchk.f @@ -0,0 +1,28 @@ + SUBROUTINE ZUCHK(YR, YI, NZ, ASCLE, TOL) +C***BEGIN PROLOGUE ZUCHK +C***REFER TO ZSERI,ZUOIK,ZUNK1,ZUNK2,ZUNI1,ZUNI2,ZKSCL +C +C Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN +C EXP(-ALIM)=ASCLE=1.0E+3*D1MACH(1)/TOL. THE TEST IS MADE TO SEE +C IF THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW +C WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED +C IF THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE +C OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE +C ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZUCHK +C +C COMPLEX Y + DOUBLE PRECISION ASCLE, SS, ST, TOL, WR, WI, YR, YI + INTEGER NZ + NZ = 0 + WR = DABS(YR) + WI = DABS(YI) + ST = DMIN1(WR,WI) + IF (ST.GT.ASCLE) RETURN + SS = DMAX1(WR,WI) + ST = ST/TOL + IF (SS.LT.ST) NZ = 1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunhj.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunhj.f new file mode 100644 index 00000000..9b4df7a1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunhj.f @@ -0,0 +1,714 @@ + SUBROUTINE ZUNHJ(ZR, ZI, FNU, IPMTR, TOL, PHIR, PHII, ARGR, ARGI, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) +C***BEGIN PROLOGUE ZUNHJ +C***REFER TO ZBESI,ZBESK +C +C REFERENCES +C HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ AND I.A. +C STEGUN, AMS55, NATIONAL BUREAU OF STANDARDS, 1965, CHAPTER 9. +C +C ASYMPTOTICS AND SPECIAL FUNCTIONS BY F.W.J. OLVER, ACADEMIC +C PRESS, N.Y., 1974, PAGE 420 +C +C ABSTRACT +C ZUNHJ COMPUTES PARAMETERS FOR BESSEL FUNCTIONS C(FNU,Z) = +C J(FNU,Z), Y(FNU,Z) OR H(I,FNU,Z) I=1,2 FOR LARGE ORDERS FNU +C BY MEANS OF THE UNIFORM ASYMPTOTIC EXPANSION +C +C C(FNU,Z)=C1*PHI*( ASUM*AIRY(ARG) + C2*BSUM*DAIRY(ARG) ) +C +C FOR PROPER CHOICES OF C1, C2, AIRY AND DAIRY WHERE AIRY IS +C AN AIRY FUNCTION AND DAIRY IS ITS DERIVATIVE. +C +C (2/3)*FNU*ZETA**1.5 = ZETA1-ZETA2, +C +C ZETA1=0.5*FNU*CLOG((1+W)/(1-W)), ZETA2=FNU*W FOR SCALING +C PURPOSES IN AIRY FUNCTIONS FROM CAIRY OR CBIRY. +C +C MCONJ=SIGN OF AIMAG(Z), BUT IS AMBIGUOUS WHEN Z IS REAL AND +C MUST BE SPECIFIED. IPMTR=0 RETURNS ALL PARAMETERS. IPMTR= +C 1 COMPUTES ALL EXCEPT ASUM AND BSUM. +C +C***ROUTINES CALLED ZABS,ZDIV,ZLOG,ZSQRT,D1MACH +C***END PROLOGUE ZUNHJ +C COMPLEX ARG,ASUM,BSUM,CFNU,CONE,CR,CZERO,DR,P,PHI,PRZTH,PTFN, +C *RFN13,RTZTA,RZTH,SUMA,SUMB,TFN,T2,UP,W,W2,Z,ZA,ZB,ZC,ZETA,ZETA1, +C *ZETA2,ZTH + DOUBLE PRECISION ALFA, ANG, AP, AR, ARGI, ARGR, ASUMI, ASUMR, + * ATOL, AW2, AZTH, BETA, BR, BSUMI, BSUMR, BTOL, C, CONEI, CONER, + * CRI, CRR, DRI, DRR, EX1, EX2, FNU, FN13, FN23, GAMA, GPI, HPI, + * PHII, PHIR, PI, PP, PR, PRZTHI, PRZTHR, PTFNI, PTFNR, RAW, RAW2, + * RAZTH, RFNU, RFNU2, RFN13, RTZTI, RTZTR, RZTHI, RZTHR, STI, STR, + * SUMAI, SUMAR, SUMBI, SUMBR, TEST, TFNI, TFNR, THPI, TOL, TZAI, + * TZAR, T2I, T2R, UPI, UPR, WI, WR, W2I, W2R, ZAI, ZAR, ZBI, ZBR, + * ZCI, ZCR, ZEROI, ZEROR, ZETAI, ZETAR, ZETA1I, ZETA1R, ZETA2I, + * ZETA2R, ZI, ZR, ZTHI, ZTHR, ZABS, AC, D1MACH + INTEGER IAS, IBS, IPMTR, IS, J, JR, JU, K, KMAX, KP1, KS, L, LR, + * LRP1, L1, L2, M, IDUM + DIMENSION AR(14), BR(14), C(105), ALFA(180), BETA(210), GAMA(30), + * AP(30), PR(30), PI(30), UPR(14), UPI(14), CRR(14), CRI(14), + * DRR(14), DRI(14) + DATA AR(1), AR(2), AR(3), AR(4), AR(5), AR(6), AR(7), AR(8), + 1 AR(9), AR(10), AR(11), AR(12), AR(13), AR(14)/ + 2 1.00000000000000000D+00, 1.04166666666666667D-01, + 3 8.35503472222222222D-02, 1.28226574556327160D-01, + 4 2.91849026464140464D-01, 8.81627267443757652D-01, + 5 3.32140828186276754D+00, 1.49957629868625547D+01, + 6 7.89230130115865181D+01, 4.74451538868264323D+02, + 7 3.20749009089066193D+03, 2.40865496408740049D+04, + 8 1.98923119169509794D+05, 1.79190200777534383D+06/ + DATA BR(1), BR(2), BR(3), BR(4), BR(5), BR(6), BR(7), BR(8), + 1 BR(9), BR(10), BR(11), BR(12), BR(13), BR(14)/ + 2 1.00000000000000000D+00, -1.45833333333333333D-01, + 3 -9.87413194444444444D-02, -1.43312053915895062D-01, + 4 -3.17227202678413548D-01, -9.42429147957120249D-01, + 5 -3.51120304082635426D+00, -1.57272636203680451D+01, + 6 -8.22814390971859444D+01, -4.92355370523670524D+02, + 7 -3.31621856854797251D+03, -2.48276742452085896D+04, + 8 -2.04526587315129788D+05, -1.83844491706820990D+06/ + DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), + 1 C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18), + 2 C(19), C(20), C(21), C(22), C(23), C(24)/ + 3 1.00000000000000000D+00, -2.08333333333333333D-01, + 4 1.25000000000000000D-01, 3.34201388888888889D-01, + 5 -4.01041666666666667D-01, 7.03125000000000000D-02, + 6 -1.02581259645061728D+00, 1.84646267361111111D+00, + 7 -8.91210937500000000D-01, 7.32421875000000000D-02, + 8 4.66958442342624743D+00, -1.12070026162229938D+01, + 9 8.78912353515625000D+00, -2.36408691406250000D+00, + A 1.12152099609375000D-01, -2.82120725582002449D+01, + B 8.46362176746007346D+01, -9.18182415432400174D+01, + C 4.25349987453884549D+01, -7.36879435947963170D+00, + D 2.27108001708984375D-01, 2.12570130039217123D+02, + E -7.65252468141181642D+02, 1.05999045252799988D+03/ + DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32), + 1 C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40), + 2 C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/ + 3 -6.99579627376132541D+02, 2.18190511744211590D+02, + 4 -2.64914304869515555D+01, 5.72501420974731445D-01, + 5 -1.91945766231840700D+03, 8.06172218173730938D+03, + 6 -1.35865500064341374D+04, 1.16553933368645332D+04, + 7 -5.30564697861340311D+03, 1.20090291321635246D+03, + 8 -1.08090919788394656D+02, 1.72772750258445740D+00, + 9 2.02042913309661486D+04, -9.69805983886375135D+04, + A 1.92547001232531532D+05, -2.03400177280415534D+05, + B 1.22200464983017460D+05, -4.11926549688975513D+04, + C 7.10951430248936372D+03, -4.93915304773088012D+02, + D 6.07404200127348304D+00, -2.42919187900551333D+05, + E 1.31176361466297720D+06, -2.99801591853810675D+06/ + DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56), + 1 C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64), + 2 C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/ + 3 3.76327129765640400D+06, -2.81356322658653411D+06, + 4 1.26836527332162478D+06, -3.31645172484563578D+05, + 5 4.52187689813627263D+04, -2.49983048181120962D+03, + 6 2.43805296995560639D+01, 3.28446985307203782D+06, + 7 -1.97068191184322269D+07, 5.09526024926646422D+07, + 8 -7.41051482115326577D+07, 6.63445122747290267D+07, + 9 -3.75671766607633513D+07, 1.32887671664218183D+07, + A -2.78561812808645469D+06, 3.08186404612662398D+05, + B -1.38860897537170405D+04, 1.10017140269246738D+02, + C -4.93292536645099620D+07, 3.25573074185765749D+08, + D -9.39462359681578403D+08, 1.55359689957058006D+09, + E -1.62108055210833708D+09, 1.10684281682301447D+09/ + DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80), + 1 C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88), + 2 C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/ + 3 -4.95889784275030309D+08, 1.42062907797533095D+08, + 4 -2.44740627257387285D+07, 2.24376817792244943D+06, + 5 -8.40054336030240853D+04, 5.51335896122020586D+02, + 6 8.14789096118312115D+08, -5.86648149205184723D+09, + 7 1.86882075092958249D+10, -3.46320433881587779D+10, + 8 4.12801855797539740D+10, -3.30265997498007231D+10, + 9 1.79542137311556001D+10, -6.56329379261928433D+09, + A 1.55927986487925751D+09, -2.25105661889415278D+08, + B 1.73951075539781645D+07, -5.49842327572288687D+05, + C 3.03809051092238427D+03, -1.46792612476956167D+10, + D 1.14498237732025810D+11, -3.99096175224466498D+11, + E 8.19218669548577329D+11, -1.09837515608122331D+12/ + DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104), + 1 C(105)/ + 2 1.00815810686538209D+12, -6.45364869245376503D+11, + 3 2.87900649906150589D+11, -8.78670721780232657D+10, + 4 1.76347306068349694D+10, -2.16716498322379509D+09, + 5 1.43157876718888981D+08, -3.87183344257261262D+06, + 6 1.82577554742931747D+04/ + DATA ALFA(1), ALFA(2), ALFA(3), ALFA(4), ALFA(5), ALFA(6), + 1 ALFA(7), ALFA(8), ALFA(9), ALFA(10), ALFA(11), ALFA(12), + 2 ALFA(13), ALFA(14), ALFA(15), ALFA(16), ALFA(17), ALFA(18), + 3 ALFA(19), ALFA(20), ALFA(21), ALFA(22)/ + 4 -4.44444444444444444D-03, -9.22077922077922078D-04, + 5 -8.84892884892884893D-05, 1.65927687832449737D-04, + 6 2.46691372741792910D-04, 2.65995589346254780D-04, + 7 2.61824297061500945D-04, 2.48730437344655609D-04, + 8 2.32721040083232098D-04, 2.16362485712365082D-04, + 9 2.00738858762752355D-04, 1.86267636637545172D-04, + A 1.73060775917876493D-04, 1.61091705929015752D-04, + B 1.50274774160908134D-04, 1.40503497391269794D-04, + C 1.31668816545922806D-04, 1.23667445598253261D-04, + D 1.16405271474737902D-04, 1.09798298372713369D-04, + E 1.03772410422992823D-04, 9.82626078369363448D-05/ + DATA ALFA(23), ALFA(24), ALFA(25), ALFA(26), ALFA(27), ALFA(28), + 1 ALFA(29), ALFA(30), ALFA(31), ALFA(32), ALFA(33), ALFA(34), + 2 ALFA(35), ALFA(36), ALFA(37), ALFA(38), ALFA(39), ALFA(40), + 3 ALFA(41), ALFA(42), ALFA(43), ALFA(44)/ + 4 9.32120517249503256D-05, 8.85710852478711718D-05, + 5 8.42963105715700223D-05, 8.03497548407791151D-05, + 6 7.66981345359207388D-05, 7.33122157481777809D-05, + 7 7.01662625163141333D-05, 6.72375633790160292D-05, + 8 6.93735541354588974D-04, 2.32241745182921654D-04, + 9 -1.41986273556691197D-05, -1.16444931672048640D-04, + A -1.50803558053048762D-04, -1.55121924918096223D-04, + B -1.46809756646465549D-04, -1.33815503867491367D-04, + C -1.19744975684254051D-04, -1.06184319207974020D-04, + D -9.37699549891194492D-05, -8.26923045588193274D-05, + E -7.29374348155221211D-05, -6.44042357721016283D-05/ + DATA ALFA(45), ALFA(46), ALFA(47), ALFA(48), ALFA(49), ALFA(50), + 1 ALFA(51), ALFA(52), ALFA(53), ALFA(54), ALFA(55), ALFA(56), + 2 ALFA(57), ALFA(58), ALFA(59), ALFA(60), ALFA(61), ALFA(62), + 3 ALFA(63), ALFA(64), ALFA(65), ALFA(66)/ + 4 -5.69611566009369048D-05, -5.04731044303561628D-05, + 5 -4.48134868008882786D-05, -3.98688727717598864D-05, + 6 -3.55400532972042498D-05, -3.17414256609022480D-05, + 7 -2.83996793904174811D-05, -2.54522720634870566D-05, + 8 -2.28459297164724555D-05, -2.05352753106480604D-05, + 9 -1.84816217627666085D-05, -1.66519330021393806D-05, + A -1.50179412980119482D-05, -1.35554031379040526D-05, + B -1.22434746473858131D-05, -1.10641884811308169D-05, + C -3.54211971457743841D-04, -1.56161263945159416D-04, + D 3.04465503594936410D-05, 1.30198655773242693D-04, + E 1.67471106699712269D-04, 1.70222587683592569D-04/ + DATA ALFA(67), ALFA(68), ALFA(69), ALFA(70), ALFA(71), ALFA(72), + 1 ALFA(73), ALFA(74), ALFA(75), ALFA(76), ALFA(77), ALFA(78), + 2 ALFA(79), ALFA(80), ALFA(81), ALFA(82), ALFA(83), ALFA(84), + 3 ALFA(85), ALFA(86), ALFA(87), ALFA(88)/ + 4 1.56501427608594704D-04, 1.36339170977445120D-04, + 5 1.14886692029825128D-04, 9.45869093034688111D-05, + 6 7.64498419250898258D-05, 6.07570334965197354D-05, + 7 4.74394299290508799D-05, 3.62757512005344297D-05, + 8 2.69939714979224901D-05, 1.93210938247939253D-05, + 9 1.30056674793963203D-05, 7.82620866744496661D-06, + A 3.59257485819351583D-06, 1.44040049814251817D-07, + B -2.65396769697939116D-06, -4.91346867098485910D-06, + C -6.72739296091248287D-06, -8.17269379678657923D-06, + D -9.31304715093561232D-06, -1.02011418798016441D-05, + E -1.08805962510592880D-05, -1.13875481509603555D-05/ + DATA ALFA(89), ALFA(90), ALFA(91), ALFA(92), ALFA(93), ALFA(94), + 1 ALFA(95), ALFA(96), ALFA(97), ALFA(98), ALFA(99), ALFA(100), + 2 ALFA(101), ALFA(102), ALFA(103), ALFA(104), ALFA(105), + 3 ALFA(106), ALFA(107), ALFA(108), ALFA(109), ALFA(110)/ + 4 -1.17519675674556414D-05, -1.19987364870944141D-05, + 5 3.78194199201772914D-04, 2.02471952761816167D-04, + 6 -6.37938506318862408D-05, -2.38598230603005903D-04, + 7 -3.10916256027361568D-04, -3.13680115247576316D-04, + 8 -2.78950273791323387D-04, -2.28564082619141374D-04, + 9 -1.75245280340846749D-04, -1.25544063060690348D-04, + A -8.22982872820208365D-05, -4.62860730588116458D-05, + B -1.72334302366962267D-05, 5.60690482304602267D-06, + C 2.31395443148286800D-05, 3.62642745856793957D-05, + D 4.58006124490188752D-05, 5.24595294959114050D-05, + E 5.68396208545815266D-05, 5.94349820393104052D-05/ + DATA ALFA(111), ALFA(112), ALFA(113), ALFA(114), ALFA(115), + 1 ALFA(116), ALFA(117), ALFA(118), ALFA(119), ALFA(120), + 2 ALFA(121), ALFA(122), ALFA(123), ALFA(124), ALFA(125), + 3 ALFA(126), ALFA(127), ALFA(128), ALFA(129), ALFA(130)/ + 4 6.06478527578421742D-05, 6.08023907788436497D-05, + 5 6.01577894539460388D-05, 5.89199657344698500D-05, + 6 5.72515823777593053D-05, 5.52804375585852577D-05, + 7 5.31063773802880170D-05, 5.08069302012325706D-05, + 8 4.84418647620094842D-05, 4.60568581607475370D-05, + 9 -6.91141397288294174D-04, -4.29976633058871912D-04, + A 1.83067735980039018D-04, 6.60088147542014144D-04, + B 8.75964969951185931D-04, 8.77335235958235514D-04, + C 7.49369585378990637D-04, 5.63832329756980918D-04, + D 3.68059319971443156D-04, 1.88464535514455599D-04/ + DATA ALFA(131), ALFA(132), ALFA(133), ALFA(134), ALFA(135), + 1 ALFA(136), ALFA(137), ALFA(138), ALFA(139), ALFA(140), + 2 ALFA(141), ALFA(142), ALFA(143), ALFA(144), ALFA(145), + 3 ALFA(146), ALFA(147), ALFA(148), ALFA(149), ALFA(150)/ + 4 3.70663057664904149D-05, -8.28520220232137023D-05, + 5 -1.72751952869172998D-04, -2.36314873605872983D-04, + 6 -2.77966150694906658D-04, -3.02079514155456919D-04, + 7 -3.12594712643820127D-04, -3.12872558758067163D-04, + 8 -3.05678038466324377D-04, -2.93226470614557331D-04, + 9 -2.77255655582934777D-04, -2.59103928467031709D-04, + A -2.39784014396480342D-04, -2.20048260045422848D-04, + B -2.00443911094971498D-04, -1.81358692210970687D-04, + C -1.63057674478657464D-04, -1.45712672175205844D-04, + D -1.29425421983924587D-04, -1.14245691942445952D-04/ + DATA ALFA(151), ALFA(152), ALFA(153), ALFA(154), ALFA(155), + 1 ALFA(156), ALFA(157), ALFA(158), ALFA(159), ALFA(160), + 2 ALFA(161), ALFA(162), ALFA(163), ALFA(164), ALFA(165), + 3 ALFA(166), ALFA(167), ALFA(168), ALFA(169), ALFA(170)/ + 4 1.92821964248775885D-03, 1.35592576302022234D-03, + 5 -7.17858090421302995D-04, -2.58084802575270346D-03, + 6 -3.49271130826168475D-03, -3.46986299340960628D-03, + 7 -2.82285233351310182D-03, -1.88103076404891354D-03, + 8 -8.89531718383947600D-04, 3.87912102631035228D-06, + 9 7.28688540119691412D-04, 1.26566373053457758D-03, + A 1.62518158372674427D-03, 1.83203153216373172D-03, + B 1.91588388990527909D-03, 1.90588846755546138D-03, + C 1.82798982421825727D-03, 1.70389506421121530D-03, + D 1.55097127171097686D-03, 1.38261421852276159D-03/ + DATA ALFA(171), ALFA(172), ALFA(173), ALFA(174), ALFA(175), + 1 ALFA(176), ALFA(177), ALFA(178), ALFA(179), ALFA(180)/ + 2 1.20881424230064774D-03, 1.03676532638344962D-03, + 3 8.71437918068619115D-04, 7.16080155297701002D-04, + 4 5.72637002558129372D-04, 4.42089819465802277D-04, + 5 3.24724948503090564D-04, 2.20342042730246599D-04, + 6 1.28412898401353882D-04, 4.82005924552095464D-05/ + DATA BETA(1), BETA(2), BETA(3), BETA(4), BETA(5), BETA(6), + 1 BETA(7), BETA(8), BETA(9), BETA(10), BETA(11), BETA(12), + 2 BETA(13), BETA(14), BETA(15), BETA(16), BETA(17), BETA(18), + 3 BETA(19), BETA(20), BETA(21), BETA(22)/ + 4 1.79988721413553309D-02, 5.59964911064388073D-03, + 5 2.88501402231132779D-03, 1.80096606761053941D-03, + 6 1.24753110589199202D-03, 9.22878876572938311D-04, + 7 7.14430421727287357D-04, 5.71787281789704872D-04, + 8 4.69431007606481533D-04, 3.93232835462916638D-04, + 9 3.34818889318297664D-04, 2.88952148495751517D-04, + A 2.52211615549573284D-04, 2.22280580798883327D-04, + B 1.97541838033062524D-04, 1.76836855019718004D-04, + C 1.59316899661821081D-04, 1.44347930197333986D-04, + D 1.31448068119965379D-04, 1.20245444949302884D-04, + E 1.10449144504599392D-04, 1.01828770740567258D-04/ + DATA BETA(23), BETA(24), BETA(25), BETA(26), BETA(27), BETA(28), + 1 BETA(29), BETA(30), BETA(31), BETA(32), BETA(33), BETA(34), + 2 BETA(35), BETA(36), BETA(37), BETA(38), BETA(39), BETA(40), + 3 BETA(41), BETA(42), BETA(43), BETA(44)/ + 4 9.41998224204237509D-05, 8.74130545753834437D-05, + 5 8.13466262162801467D-05, 7.59002269646219339D-05, + 6 7.09906300634153481D-05, 6.65482874842468183D-05, + 7 6.25146958969275078D-05, 5.88403394426251749D-05, + 8 -1.49282953213429172D-03, -8.78204709546389328D-04, + 9 -5.02916549572034614D-04, -2.94822138512746025D-04, + A -1.75463996970782828D-04, -1.04008550460816434D-04, + B -5.96141953046457895D-05, -3.12038929076098340D-05, + C -1.26089735980230047D-05, -2.42892608575730389D-07, + D 8.05996165414273571D-06, 1.36507009262147391D-05, + E 1.73964125472926261D-05, 1.98672978842133780D-05/ + DATA BETA(45), BETA(46), BETA(47), BETA(48), BETA(49), BETA(50), + 1 BETA(51), BETA(52), BETA(53), BETA(54), BETA(55), BETA(56), + 2 BETA(57), BETA(58), BETA(59), BETA(60), BETA(61), BETA(62), + 3 BETA(63), BETA(64), BETA(65), BETA(66)/ + 4 2.14463263790822639D-05, 2.23954659232456514D-05, + 5 2.28967783814712629D-05, 2.30785389811177817D-05, + 6 2.30321976080909144D-05, 2.28236073720348722D-05, + 7 2.25005881105292418D-05, 2.20981015361991429D-05, + 8 2.16418427448103905D-05, 2.11507649256220843D-05, + 9 2.06388749782170737D-05, 2.01165241997081666D-05, + A 1.95913450141179244D-05, 1.90689367910436740D-05, + B 1.85533719641636667D-05, 1.80475722259674218D-05, + C 5.52213076721292790D-04, 4.47932581552384646D-04, + D 2.79520653992020589D-04, 1.52468156198446602D-04, + E 6.93271105657043598D-05, 1.76258683069991397D-05/ + DATA BETA(67), BETA(68), BETA(69), BETA(70), BETA(71), BETA(72), + 1 BETA(73), BETA(74), BETA(75), BETA(76), BETA(77), BETA(78), + 2 BETA(79), BETA(80), BETA(81), BETA(82), BETA(83), BETA(84), + 3 BETA(85), BETA(86), BETA(87), BETA(88)/ + 4 -1.35744996343269136D-05, -3.17972413350427135D-05, + 5 -4.18861861696693365D-05, -4.69004889379141029D-05, + 6 -4.87665447413787352D-05, -4.87010031186735069D-05, + 7 -4.74755620890086638D-05, -4.55813058138628452D-05, + 8 -4.33309644511266036D-05, -4.09230193157750364D-05, + 9 -3.84822638603221274D-05, -3.60857167535410501D-05, + A -3.37793306123367417D-05, -3.15888560772109621D-05, + B -2.95269561750807315D-05, -2.75978914828335759D-05, + C -2.58006174666883713D-05, -2.41308356761280200D-05, + D -2.25823509518346033D-05, -2.11479656768912971D-05, + E -1.98200638885294927D-05, -1.85909870801065077D-05/ + DATA BETA(89), BETA(90), BETA(91), BETA(92), BETA(93), BETA(94), + 1 BETA(95), BETA(96), BETA(97), BETA(98), BETA(99), BETA(100), + 2 BETA(101), BETA(102), BETA(103), BETA(104), BETA(105), + 3 BETA(106), BETA(107), BETA(108), BETA(109), BETA(110)/ + 4 -1.74532699844210224D-05, -1.63997823854497997D-05, + 5 -4.74617796559959808D-04, -4.77864567147321487D-04, + 6 -3.20390228067037603D-04, -1.61105016119962282D-04, + 7 -4.25778101285435204D-05, 3.44571294294967503D-05, + 8 7.97092684075674924D-05, 1.03138236708272200D-04, + 9 1.12466775262204158D-04, 1.13103642108481389D-04, + A 1.08651634848774268D-04, 1.01437951597661973D-04, + B 9.29298396593363896D-05, 8.40293133016089978D-05, + C 7.52727991349134062D-05, 6.69632521975730872D-05, + D 5.92564547323194704D-05, 5.22169308826975567D-05, + E 4.58539485165360646D-05, 4.01445513891486808D-05/ + DATA BETA(111), BETA(112), BETA(113), BETA(114), BETA(115), + 1 BETA(116), BETA(117), BETA(118), BETA(119), BETA(120), + 2 BETA(121), BETA(122), BETA(123), BETA(124), BETA(125), + 3 BETA(126), BETA(127), BETA(128), BETA(129), BETA(130)/ + 4 3.50481730031328081D-05, 3.05157995034346659D-05, + 5 2.64956119950516039D-05, 2.29363633690998152D-05, + 6 1.97893056664021636D-05, 1.70091984636412623D-05, + 7 1.45547428261524004D-05, 1.23886640995878413D-05, + 8 1.04775876076583236D-05, 8.79179954978479373D-06, + 9 7.36465810572578444D-04, 8.72790805146193976D-04, + A 6.22614862573135066D-04, 2.85998154194304147D-04, + B 3.84737672879366102D-06, -1.87906003636971558D-04, + C -2.97603646594554535D-04, -3.45998126832656348D-04, + D -3.53382470916037712D-04, -3.35715635775048757D-04/ + DATA BETA(131), BETA(132), BETA(133), BETA(134), BETA(135), + 1 BETA(136), BETA(137), BETA(138), BETA(139), BETA(140), + 2 BETA(141), BETA(142), BETA(143), BETA(144), BETA(145), + 3 BETA(146), BETA(147), BETA(148), BETA(149), BETA(150)/ + 4 -3.04321124789039809D-04, -2.66722723047612821D-04, + 5 -2.27654214122819527D-04, -1.89922611854562356D-04, + 6 -1.55058918599093870D-04, -1.23778240761873630D-04, + 7 -9.62926147717644187D-05, -7.25178327714425337D-05, + 8 -5.22070028895633801D-05, -3.50347750511900522D-05, + 9 -2.06489761035551757D-05, -8.70106096849767054D-06, + A 1.13698686675100290D-06, 9.16426474122778849D-06, + B 1.56477785428872620D-05, 2.08223629482466847D-05, + C 2.48923381004595156D-05, 2.80340509574146325D-05, + D 3.03987774629861915D-05, 3.21156731406700616D-05/ + DATA BETA(151), BETA(152), BETA(153), BETA(154), BETA(155), + 1 BETA(156), BETA(157), BETA(158), BETA(159), BETA(160), + 2 BETA(161), BETA(162), BETA(163), BETA(164), BETA(165), + 3 BETA(166), BETA(167), BETA(168), BETA(169), BETA(170)/ + 4 -1.80182191963885708D-03, -2.43402962938042533D-03, + 5 -1.83422663549856802D-03, -7.62204596354009765D-04, + 6 2.39079475256927218D-04, 9.49266117176881141D-04, + 7 1.34467449701540359D-03, 1.48457495259449178D-03, + 8 1.44732339830617591D-03, 1.30268261285657186D-03, + 9 1.10351597375642682D-03, 8.86047440419791759D-04, + A 6.73073208165665473D-04, 4.77603872856582378D-04, + B 3.05991926358789362D-04, 1.60315694594721630D-04, + C 4.00749555270613286D-05, -5.66607461635251611D-05, + D -1.32506186772982638D-04, -1.90296187989614057D-04/ + DATA BETA(171), BETA(172), BETA(173), BETA(174), BETA(175), + 1 BETA(176), BETA(177), BETA(178), BETA(179), BETA(180), + 2 BETA(181), BETA(182), BETA(183), BETA(184), BETA(185), + 3 BETA(186), BETA(187), BETA(188), BETA(189), BETA(190)/ + 4 -2.32811450376937408D-04, -2.62628811464668841D-04, + 5 -2.82050469867598672D-04, -2.93081563192861167D-04, + 6 -2.97435962176316616D-04, -2.96557334239348078D-04, + 7 -2.91647363312090861D-04, -2.83696203837734166D-04, + 8 -2.73512317095673346D-04, -2.61750155806768580D-04, + 9 6.38585891212050914D-03, 9.62374215806377941D-03, + A 7.61878061207001043D-03, 2.83219055545628054D-03, + B -2.09841352012720090D-03, -5.73826764216626498D-03, + C -7.70804244495414620D-03, -8.21011692264844401D-03, + D -7.65824520346905413D-03, -6.47209729391045177D-03/ + DATA BETA(191), BETA(192), BETA(193), BETA(194), BETA(195), + 1 BETA(196), BETA(197), BETA(198), BETA(199), BETA(200), + 2 BETA(201), BETA(202), BETA(203), BETA(204), BETA(205), + 3 BETA(206), BETA(207), BETA(208), BETA(209), BETA(210)/ + 4 -4.99132412004966473D-03, -3.45612289713133280D-03, + 5 -2.01785580014170775D-03, -7.59430686781961401D-04, + 6 2.84173631523859138D-04, 1.10891667586337403D-03, + 7 1.72901493872728771D-03, 2.16812590802684701D-03, + 8 2.45357710494539735D-03, 2.61281821058334862D-03, + 9 2.67141039656276912D-03, 2.65203073395980430D-03, + A 2.57411652877287315D-03, 2.45389126236094427D-03, + B 2.30460058071795494D-03, 2.13684837686712662D-03, + C 1.95896528478870911D-03, 1.77737008679454412D-03, + D 1.59690280765839059D-03, 1.42111975664438546D-03/ + DATA GAMA(1), GAMA(2), GAMA(3), GAMA(4), GAMA(5), GAMA(6), + 1 GAMA(7), GAMA(8), GAMA(9), GAMA(10), GAMA(11), GAMA(12), + 2 GAMA(13), GAMA(14), GAMA(15), GAMA(16), GAMA(17), GAMA(18), + 3 GAMA(19), GAMA(20), GAMA(21), GAMA(22)/ + 4 6.29960524947436582D-01, 2.51984209978974633D-01, + 5 1.54790300415655846D-01, 1.10713062416159013D-01, + 6 8.57309395527394825D-02, 6.97161316958684292D-02, + 7 5.86085671893713576D-02, 5.04698873536310685D-02, + 8 4.42600580689154809D-02, 3.93720661543509966D-02, + 9 3.54283195924455368D-02, 3.21818857502098231D-02, + A 2.94646240791157679D-02, 2.71581677112934479D-02, + B 2.51768272973861779D-02, 2.34570755306078891D-02, + C 2.19508390134907203D-02, 2.06210828235646240D-02, + D 1.94388240897880846D-02, 1.83810633800683158D-02, + E 1.74293213231963172D-02, 1.65685837786612353D-02/ + DATA GAMA(23), GAMA(24), GAMA(25), GAMA(26), GAMA(27), GAMA(28), + 1 GAMA(29), GAMA(30)/ + 2 1.57865285987918445D-02, 1.50729501494095594D-02, + 3 1.44193250839954639D-02, 1.38184805735341786D-02, + 4 1.32643378994276568D-02, 1.27517121970498651D-02, + 5 1.22761545318762767D-02, 1.18338262398482403D-02/ + DATA EX1, EX2, HPI, GPI, THPI / + 1 3.33333333333333333D-01, 6.66666666666666667D-01, + 2 1.57079632679489662D+00, 3.14159265358979324D+00, + 3 4.71238898038468986D+00/ + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + RFNU = 1.0D0/FNU +C----------------------------------------------------------------------- +C OVERFLOW TEST (Z/FNU TOO SMALL) +C----------------------------------------------------------------------- + TEST = D1MACH(1)*1.0D+3 + AC = FNU*TEST + IF (DABS(ZR).GT.AC .OR. DABS(ZI).GT.AC) GO TO 15 + ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU + ZETA1I = 0.0D0 + ZETA2R = FNU + ZETA2I = 0.0D0 + PHIR = 1.0D0 + PHII = 0.0D0 + ARGR = 1.0D0 + ARGI = 0.0D0 + RETURN + 15 CONTINUE + ZBR = ZR*RFNU + ZBI = ZI*RFNU + RFNU2 = RFNU*RFNU +C----------------------------------------------------------------------- +C COMPUTE IN THE FOURTH QUADRANT +C----------------------------------------------------------------------- + FN13 = FNU**EX1 + FN23 = FN13*FN13 + RFN13 = 1.0D0/FN13 + W2R = CONER - ZBR*ZBR + ZBI*ZBI + W2I = CONEI - ZBR*ZBI - ZBR*ZBI + AW2 = ZABS(CMPLX(W2R,W2I,kind=KIND(1.0D0))) + IF (AW2.GT.0.25D0) GO TO 130 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(W2).LE.0.25D0 +C----------------------------------------------------------------------- + K = 1 + PR(1) = CONER + PI(1) = CONEI + SUMAR = GAMA(1) + SUMAI = ZEROI + AP(1) = 1.0D0 + IF (AW2.LT.TOL) GO TO 20 + DO 10 K=2,30 + PR(K) = PR(K-1)*W2R - PI(K-1)*W2I + PI(K) = PR(K-1)*W2I + PI(K-1)*W2R + SUMAR = SUMAR + PR(K)*GAMA(K) + SUMAI = SUMAI + PI(K)*GAMA(K) + AP(K) = AP(K-1)*AW2 + IF (AP(K).LT.TOL) GO TO 20 + 10 CONTINUE + K = 30 + 20 CONTINUE + KMAX = K + ZETAR = W2R*SUMAR - W2I*SUMAI + ZETAI = W2R*SUMAI + W2I*SUMAR + ARGR = ZETAR*FN23 + ARGI = ZETAI*FN23 + CALL ZSQRT(SUMAR, SUMAI, ZAR, ZAI) + CALL ZSQRT(W2R, W2I, STR, STI) + ZETA2R = STR*FNU + ZETA2I = STI*FNU + STR = CONER + EX2*(ZETAR*ZAR-ZETAI*ZAI) + STI = CONEI + EX2*(ZETAR*ZAI+ZETAI*ZAR) + ZETA1R = STR*ZETA2R - STI*ZETA2I + ZETA1I = STR*ZETA2I + STI*ZETA2R + ZAR = ZAR + ZAR + ZAI = ZAI + ZAI + CALL ZSQRT(ZAR, ZAI, STR, STI) + PHIR = STR*RFN13 + PHII = STI*RFN13 + IF (IPMTR.EQ.1) GO TO 120 +C----------------------------------------------------------------------- +C SUM SERIES FOR ASUM AND BSUM +C----------------------------------------------------------------------- + SUMBR = ZEROR + SUMBI = ZEROI + DO 30 K=1,KMAX + SUMBR = SUMBR + PR(K)*BETA(K) + SUMBI = SUMBI + PI(K)*BETA(K) + 30 CONTINUE + ASUMR = ZEROR + ASUMI = ZEROI + BSUMR = SUMBR + BSUMI = SUMBI + L1 = 0 + L2 = 30 + BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI)) + ATOL = TOL + PP = 1.0D0 + IAS = 0 + IBS = 0 + IF (RFNU2.LT.TOL) GO TO 110 + DO 100 IS=2,7 + ATOL = ATOL/RFNU2 + PP = PP*RFNU2 + IF (IAS.EQ.1) GO TO 60 + SUMAR = ZEROR + SUMAI = ZEROI + DO 40 K=1,KMAX + M = L1 + K + SUMAR = SUMAR + PR(K)*ALFA(M) + SUMAI = SUMAI + PI(K)*ALFA(M) + IF (AP(K).LT.ATOL) GO TO 50 + 40 CONTINUE + 50 CONTINUE + ASUMR = ASUMR + SUMAR*PP + ASUMI = ASUMI + SUMAI*PP + IF (PP.LT.TOL) IAS = 1 + 60 CONTINUE + IF (IBS.EQ.1) GO TO 90 + SUMBR = ZEROR + SUMBI = ZEROI + DO 70 K=1,KMAX + M = L2 + K + SUMBR = SUMBR + PR(K)*BETA(M) + SUMBI = SUMBI + PI(K)*BETA(M) + IF (AP(K).LT.ATOL) GO TO 80 + 70 CONTINUE + 80 CONTINUE + BSUMR = BSUMR + SUMBR*PP + BSUMI = BSUMI + SUMBI*PP + IF (PP.LT.BTOL) IBS = 1 + 90 CONTINUE + IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 110 + L1 = L1 + 30 + L2 = L2 + 30 + 100 CONTINUE + 110 CONTINUE + ASUMR = ASUMR + CONER + PP = RFNU*RFN13 + BSUMR = BSUMR*PP + BSUMI = BSUMI*PP + 120 CONTINUE + RETURN +C----------------------------------------------------------------------- +C CABS(W2).GT.0.25D0 +C----------------------------------------------------------------------- + 130 CONTINUE + CALL ZSQRT(W2R, W2I, WR, WI) + IF (WR.LT.0.0D0) WR = 0.0D0 + IF (WI.LT.0.0D0) WI = 0.0D0 + STR = CONER + WR + STI = WI + CALL ZDIV(STR, STI, ZBR, ZBI, ZAR, ZAI) + CALL ZLOG(ZAR, ZAI, ZCR, ZCI, IDUM) + IF (ZCI.LT.0.0D0) ZCI = 0.0D0 + IF (ZCI.GT.HPI) ZCI = HPI + IF (ZCR.LT.0.0D0) ZCR = 0.0D0 + ZTHR = (ZCR-WR)*1.5D0 + ZTHI = (ZCI-WI)*1.5D0 + ZETA1R = ZCR*FNU + ZETA1I = ZCI*FNU + ZETA2R = WR*FNU + ZETA2I = WI*FNU + AZTH = ZABS(CMPLX(ZTHR,ZTHI,kind=KIND(1.0D0))) + ANG = THPI + IF (ZTHR.GE.0.0D0 .AND. ZTHI.LT.0.0D0) GO TO 140 + ANG = HPI + IF (ZTHR.EQ.0.0D0) GO TO 140 + ANG = DATAN(ZTHI/ZTHR) + IF (ZTHR.LT.0.0D0) ANG = ANG + GPI + 140 CONTINUE + PP = AZTH**EX2 + ANG = ANG*EX2 + ZETAR = PP*DCOS(ANG) + ZETAI = PP*DSIN(ANG) + IF (ZETAI.LT.0.0D0) ZETAI = 0.0D0 + ARGR = ZETAR*FN23 + ARGI = ZETAI*FN23 + CALL ZDIV(ZTHR, ZTHI, ZETAR, ZETAI, RTZTR, RTZTI) + CALL ZDIV(RTZTR, RTZTI, WR, WI, ZAR, ZAI) + TZAR = ZAR + ZAR + TZAI = ZAI + ZAI + CALL ZSQRT(TZAR, TZAI, STR, STI) + PHIR = STR*RFN13 + PHII = STI*RFN13 + IF (IPMTR.EQ.1) GO TO 120 + RAW = 1.0D0/DSQRT(AW2) + STR = WR*RAW + STI = -WI*RAW + TFNR = STR*RFNU*RAW + TFNI = STI*RFNU*RAW + RAZTH = 1.0D0/AZTH + STR = ZTHR*RAZTH + STI = -ZTHI*RAZTH + RZTHR = STR*RAZTH*RFNU + RZTHI = STI*RAZTH*RFNU + ZCR = RZTHR*AR(2) + ZCI = RZTHI*AR(2) + RAW2 = 1.0D0/AW2 + STR = W2R*RAW2 + STI = -W2I*RAW2 + T2R = STR*RAW2 + T2I = STI*RAW2 + STR = T2R*C(2) + C(3) + STI = T2I*C(2) + UPR(2) = STR*TFNR - STI*TFNI + UPI(2) = STR*TFNI + STI*TFNR + BSUMR = UPR(2) + ZCR + BSUMI = UPI(2) + ZCI + ASUMR = ZEROR + ASUMI = ZEROI + IF (RFNU.LT.TOL) GO TO 220 + PRZTHR = RZTHR + PRZTHI = RZTHI + PTFNR = TFNR + PTFNI = TFNI + UPR(1) = CONER + UPI(1) = CONEI + PP = 1.0D0 + BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI)) + KS = 0 + KP1 = 2 + L = 3 + IAS = 0 + IBS = 0 + DO 210 LR=2,12,2 + LRP1 = LR + 1 +C----------------------------------------------------------------------- +C COMPUTE TWO ADDITIONAL CR, DR, AND UP FOR TWO MORE TERMS IN +C NEXT SUMA AND SUMB +C----------------------------------------------------------------------- + DO 160 K=LR,LRP1 + KS = KS + 1 + KP1 = KP1 + 1 + L = L + 1 + ZAR = C(L) + ZAI = ZEROI + DO 150 J=2,KP1 + L = L + 1 + STR = ZAR*T2R - T2I*ZAI + C(L) + ZAI = ZAR*T2I + ZAI*T2R + ZAR = STR + 150 CONTINUE + STR = PTFNR*TFNR - PTFNI*TFNI + PTFNI = PTFNR*TFNI + PTFNI*TFNR + PTFNR = STR + UPR(KP1) = PTFNR*ZAR - PTFNI*ZAI + UPI(KP1) = PTFNI*ZAR + PTFNR*ZAI + CRR(KS) = PRZTHR*BR(KS+1) + CRI(KS) = PRZTHI*BR(KS+1) + STR = PRZTHR*RZTHR - PRZTHI*RZTHI + PRZTHI = PRZTHR*RZTHI + PRZTHI*RZTHR + PRZTHR = STR + DRR(KS) = PRZTHR*AR(KS+2) + DRI(KS) = PRZTHI*AR(KS+2) + 160 CONTINUE + PP = PP*RFNU2 + IF (IAS.EQ.1) GO TO 180 + SUMAR = UPR(LRP1) + SUMAI = UPI(LRP1) + JU = LRP1 + DO 170 JR=1,LR + JU = JU - 1 + SUMAR = SUMAR + CRR(JR)*UPR(JU) - CRI(JR)*UPI(JU) + SUMAI = SUMAI + CRR(JR)*UPI(JU) + CRI(JR)*UPR(JU) + 170 CONTINUE + ASUMR = ASUMR + SUMAR + ASUMI = ASUMI + SUMAI + TEST = DABS(SUMAR) + DABS(SUMAI) + IF (PP.LT.TOL .AND. TEST.LT.TOL) IAS = 1 + 180 CONTINUE + IF (IBS.EQ.1) GO TO 200 + SUMBR = UPR(LR+2) + UPR(LRP1)*ZCR - UPI(LRP1)*ZCI + SUMBI = UPI(LR+2) + UPR(LRP1)*ZCI + UPI(LRP1)*ZCR + JU = LRP1 + DO 190 JR=1,LR + JU = JU - 1 + SUMBR = SUMBR + DRR(JR)*UPR(JU) - DRI(JR)*UPI(JU) + SUMBI = SUMBI + DRR(JR)*UPI(JU) + DRI(JR)*UPR(JU) + 190 CONTINUE + BSUMR = BSUMR + SUMBR + BSUMI = BSUMI + SUMBI + TEST = DABS(SUMBR) + DABS(SUMBI) + IF (PP.LT.BTOL .AND. TEST.LT.BTOL) IBS = 1 + 200 CONTINUE + IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 220 + 210 CONTINUE + 220 CONTINUE + ASUMR = ASUMR + CONER + STR = -BSUMR*RFN13 + STI = -BSUMI*RFN13 + CALL ZDIV(STR, STI, RTZTR, RTZTI, BSUMR, BSUMI) + GO TO 120 + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni1.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni1.f new file mode 100644 index 00000000..f3a0f246 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni1.f @@ -0,0 +1,204 @@ + SUBROUTINE ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZUNI1 +C***REFER TO ZBESI,ZBESK +C +C ZUNI1 COMPUTES I(FNU,Z) BY MEANS OF THE UNIFORM ASYMPTOTIC +C EXPANSION FOR I(FNU,Z) IN -PI/3.LE.ARG Z.LE.PI/3. +C +C FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC +C EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET. +C NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER +C FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL. +C Y(I)=CZERO FOR I=NLAST+1,N +C +C***ROUTINES CALLED ZUCHK,ZUNIK,ZUOIK,D1MACH,ZABS +C***END PROLOGUE ZUNI1 +C COMPLEX CFN,CONE,CRSC,CSCL,CSR,CSS,CWRK,CZERO,C1,C2,PHI,RZ,SUM,S1, +C *S2,Y,Z,ZETA1,ZETA2 + DOUBLE PRECISION ALIM, APHI, ASCLE, BRY, CONER, CRSC, + * CSCL, CSRR, CSSR, CWRKI, CWRKR, C1R, C2I, C2M, C2R, ELIM, FN, + * FNU, FNUL, PHII, PHIR, RAST, RS1, RZI, RZR, STI, STR, SUMI, + * SUMR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I, + * ZETA1R, ZETA2I, ZETA2R, ZI, ZR, CYR, CYI, D1MACH, ZABS + INTEGER I, IFLAG, INIT, K, KODE, M, N, ND, NLAST, NN, NUF, NW, NZ + DIMENSION BRY(3), YR(N), YI(N), CWRKR(16), CWRKI(16), CSSR(3), + * CSRR(3), CYR(2), CYI(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / +C + NZ = 0 + ND = N + NLAST = 0 +C----------------------------------------------------------------------- +C COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG- +C NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE, +C EXP(ALIM)=EXP(ELIM)*TOL +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL +C----------------------------------------------------------------------- +C CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER +C----------------------------------------------------------------------- + FN = DMAX1(FNU,1.0D0) + INIT = 0 + CALL ZUNIK(ZR, ZI, FN, 1, 1, TOL, INIT, PHIR, PHII, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + IF (KODE.EQ.1) GO TO 10 + STR = ZR + ZETA2R + STI = ZI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + GO TO 20 + 10 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 20 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 130 + 30 CONTINUE + NN = MIN0(2,ND) + DO 80 I=1,NN + FN = FNU + DBLE(FLOAT(ND-I)) + INIT = 0 + CALL ZUNIK(ZR, ZI, FN, 1, 0, TOL, INIT, PHIR, PHII, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + IF (KODE.EQ.1) GO TO 40 + STR = ZR + ZETA2R + STI = ZI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + ZI + GO TO 50 + 40 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 50 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 110 + IF (I.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 60 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 110 + IF (I.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 60 + IF (I.EQ.1) IFLAG = 3 + 60 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 IF CABS(S1).LT.ASCLE +C----------------------------------------------------------------------- + S2R = PHIR*SUMR - PHII*SUMI + S2I = PHIR*SUMI + PHII*SUMR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 70 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 110 + 70 CONTINUE + CYR(I) = S2R + CYI(I) = S2I + M = ND - I + 1 + YR(M) = S2R*CSRR(IFLAG) + YI(M) = S2I*CSRR(IFLAG) + 80 CONTINUE + IF (ND.LE.2) GO TO 100 + RAST = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAST + STI = -ZI*RAST + RZR = (STR+STR)*RAST + RZI = (STI+STI)*RAST + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + K = ND - 2 + FN = DBLE(FLOAT(K)) + DO 90 I=3,ND + C2R = S2R + C2I = S2I + S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + C2R = S2R*C1R + C2I = S2I*C1R + YR(K) = C2R + YI(K) = C2I + K = K - 1 + FN = FN - 1.0D0 + IF (IFLAG.GE.3) GO TO 90 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 90 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + C1R = CSRR(IFLAG) + 90 CONTINUE + 100 CONTINUE + RETURN +C----------------------------------------------------------------------- +C SET UNDERFLOW AND UPDATE PARAMETERS +C----------------------------------------------------------------------- + 110 CONTINUE + IF (RS1.GT.0.0D0) GO TO 120 + YR(ND) = ZEROR + YI(ND) = ZEROI + NZ = NZ + 1 + ND = ND - 1 + IF (ND.EQ.0) GO TO 100 + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM) + IF (NUF.LT.0) GO TO 120 + ND = ND - NUF + NZ = NZ + NUF + IF (ND.EQ.0) GO TO 100 + FN = FNU + DBLE(FLOAT(ND-1)) + IF (FN.GE.FNUL) GO TO 30 + NLAST = ND + RETURN + 120 CONTINUE + NZ = -1 + RETURN + 130 CONTINUE + IF (RS1.GT.0.0D0) GO TO 120 + NZ = N + DO 140 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 140 CONTINUE + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni2.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni2.f new file mode 100644 index 00000000..9e5cfcdd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuni2.f @@ -0,0 +1,267 @@ + SUBROUTINE ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZUNI2 +C***REFER TO ZBESI,ZBESK +C +C ZUNI2 COMPUTES I(FNU,Z) IN THE RIGHT HALF PLANE BY MEANS OF +C UNIFORM ASYMPTOTIC EXPANSION FOR J(FNU,ZN) WHERE ZN IS Z*I +C OR -Z*I AND ZN IS IN THE RIGHT HALF PLANE ALSO. +C +C FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC +C EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET. +C NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER +C FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL. +C Y(I)=CZERO FOR I=NLAST+1,N +C +C***ROUTINES CALLED ZAIRY,ZUCHK,ZUNHJ,ZUOIK,D1MACH,ZABS +C***END PROLOGUE ZUNI2 +C COMPLEX AI,ARG,ASUM,BSUM,CFN,CI,CID,CIP,CONE,CRSC,CSCL,CSR,CSS, +C *CZERO,C1,C2,DAI,PHI,RZ,S1,S2,Y,Z,ZB,ZETA1,ZETA2,ZN + DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGI, + * ARGR, ASCLE, ASUMI, ASUMR, BRY, BSUMI, BSUMR, CIDI, CIPI, CIPR, + * CONER, CRSC, CSCL, CSRR, CSSR, C1R, C2I, C2M, C2R, DAII, + * DAIR, ELIM, FN, FNU, FNUL, HPI, PHII, PHIR, RAST, RAZ, RS1, RZI, + * RZR, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZBI, ZBR, ZEROI, + * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI, ZNI, ZNR, ZR, CYR, + * CYI, D1MACH, ZABS, CAR, SAR + INTEGER I, IFLAG, IN, INU, J, K, KODE, N, NAI, ND, NDAI, NLAST, + * NN, NUF, NW, NZ, IDUM + DIMENSION BRY(3), YR(N), YI(N), CIPR(4), CIPI(4), CSSR(3), + * CSRR(3), CYR(2), CYI(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / + DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4), + * CIPI(4)/ 1.0D0,0.0D0, 0.0D0,1.0D0, -1.0D0,0.0D0, 0.0D0,-1.0D0/ + DATA HPI, AIC / + 1 1.57079632679489662D+00, 1.265512123484645396D+00/ +C + NZ = 0 + ND = N + NLAST = 0 +C----------------------------------------------------------------------- +C COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG- +C NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE, +C EXP(ALIM)=EXP(ELIM)*TOL +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL +C----------------------------------------------------------------------- +C ZN IS IN THE RIGHT HALF PLANE AFTER ROTATION BY CI OR -CI +C----------------------------------------------------------------------- + ZNR = ZI + ZNI = -ZR + ZBR = ZR + ZBI = ZI + CIDI = -CONER + INU = INT(SNGL(FNU)) + ANG = HPI*(FNU-DBLE(FLOAT(INU))) + C2R = DCOS(ANG) + C2I = DSIN(ANG) + CAR = C2R + SAR = C2I + IN = INU + N - 1 + IN = MOD(IN,4) + 1 + STR = C2R*CIPR(IN) - C2I*CIPI(IN) + C2I = C2R*CIPI(IN) + C2I*CIPR(IN) + C2R = STR + IF (ZI.GT.0.0D0) GO TO 10 + ZNR = -ZNR + ZBI = -ZBI + CIDI = -CIDI + C2I = -C2I + 10 CONTINUE +C----------------------------------------------------------------------- +C CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER +C----------------------------------------------------------------------- + FN = DMAX1(FNU,1.0D0) + CALL ZUNHJ(ZNR, ZNI, FN, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + IF (KODE.EQ.1) GO TO 20 + STR = ZBR + ZETA2R + STI = ZBI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + GO TO 30 + 20 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 30 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 150 + 40 CONTINUE + NN = MIN0(2,ND) + DO 90 I=1,NN + FN = FNU + DBLE(FLOAT(ND-I)) + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR, PHII, ARGR, ARGI, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + IF (KODE.EQ.1) GO TO 50 + STR = ZBR + ZETA2R + STI = ZBI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + DABS(ZI) + GO TO 60 + 50 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 60 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 120 + IF (I.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 70 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 120 + IF (I.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 70 + IF (I.EQ.1) IFLAG = 3 + 70 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + CALL ZAIRY(ARGR, ARGI, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(ARGR, ARGI, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMR - DAII*BSUMI + STI = DAIR*BSUMI + DAII*BSUMR + STR = STR + (AIR*ASUMR-AII*ASUMI) + STI = STI + (AIR*ASUMI+AII*ASUMR) + S2R = PHIR*STR - PHII*STI + S2I = PHIR*STI + PHII*STR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 80 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 120 + 80 CONTINUE + IF (ZI.LE.0.0D0) S2I = -S2I + STR = S2R*C2R - S2I*C2I + S2I = S2R*C2I + S2I*C2R + S2R = STR + CYR(I) = S2R + CYI(I) = S2I + J = ND - I + 1 + YR(J) = S2R*CSRR(IFLAG) + YI(J) = S2I*CSRR(IFLAG) + STR = -C2I*CIDI + C2I = C2R*CIDI + C2R = STR + 90 CONTINUE + IF (ND.LE.2) GO TO 110 + RAZ = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + K = ND - 2 + FN = DBLE(FLOAT(K)) + DO 100 I=3,ND + C2R = S2R + C2I = S2I + S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + C2R = S2R*C1R + C2I = S2I*C1R + YR(K) = C2R + YI(K) = C2I + K = K - 1 + FN = FN - 1.0D0 + IF (IFLAG.GE.3) GO TO 100 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 100 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + C1R = CSRR(IFLAG) + 100 CONTINUE + 110 CONTINUE + RETURN + 120 CONTINUE + IF (RS1.GT.0.0D0) GO TO 140 +C----------------------------------------------------------------------- +C SET UNDERFLOW AND UPDATE PARAMETERS +C----------------------------------------------------------------------- + YR(ND) = ZEROR + YI(ND) = ZEROI + NZ = NZ + 1 + ND = ND - 1 + IF (ND.EQ.0) GO TO 110 + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM) + IF (NUF.LT.0) GO TO 140 + ND = ND - NUF + NZ = NZ + NUF + IF (ND.EQ.0) GO TO 110 + FN = FNU + DBLE(FLOAT(ND-1)) + IF (FN.LT.FNUL) GO TO 130 +C FN = CIDI +C J = NUF + 1 +C K = MOD(J,4) + 1 +C S1R = CIPR(K) +C S1I = CIPI(K) +C IF (FN.LT.0.0D0) S1I = -S1I +C STR = C2R*S1R - C2I*S1I +C C2I = C2R*S1I + C2I*S1R +C C2R = STR + IN = INU + ND - 1 + IN = MOD(IN,4) + 1 + C2R = CAR*CIPR(IN) - SAR*CIPI(IN) + C2I = CAR*CIPI(IN) + SAR*CIPR(IN) + IF (ZI.LE.0.0D0) C2I = -C2I + GO TO 40 + 130 CONTINUE + NLAST = ND + RETURN + 140 CONTINUE + NZ = -1 + RETURN + 150 CONTINUE + IF (RS1.GT.0.0D0) GO TO 140 + NZ = N + DO 160 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 160 CONTINUE + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunik.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunik.f new file mode 100644 index 00000000..3e8293e3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunik.f @@ -0,0 +1,211 @@ + SUBROUTINE ZUNIK(ZRR, ZRI, FNU, IKFLG, IPMTR, TOL, INIT, PHIR, + * PHII, ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) +C***BEGIN PROLOGUE ZUNIK +C***REFER TO ZBESI,ZBESK +C +C ZUNIK COMPUTES PARAMETERS FOR THE UNIFORM ASYMPTOTIC +C EXPANSIONS OF THE I AND K FUNCTIONS ON IKFLG= 1 OR 2 +C RESPECTIVELY BY +C +C W(FNU,ZR) = PHI*EXP(ZETA)*SUM +C +C WHERE ZETA=-ZETA1 + ZETA2 OR +C ZETA1 - ZETA2 +C +C THE FIRST CALL MUST HAVE INIT=0. SUBSEQUENT CALLS WITH THE +C SAME ZR AND FNU WILL RETURN THE I OR K FUNCTION ON IKFLG= +C 1 OR 2 WITH NO CHANGE IN INIT. CWRK IS A COMPLEX WORK +C ARRAY. IPMTR=0 COMPUTES ALL PARAMETERS. IPMTR=1 COMPUTES PHI, +C ZETA1,ZETA2. +C +C***ROUTINES CALLED ZDIV,ZLOG,ZSQRT,D1MACH +C***END PROLOGUE ZUNIK +C COMPLEX CFN,CON,CONE,CRFN,CWRK,CZERO,PHI,S,SR,SUM,T,T2,ZETA1, +C *ZETA2,ZN,ZR + DOUBLE PRECISION AC, C, CON, CONEI, CONER, CRFNI, CRFNR, CWRKI, + * CWRKR, FNU, PHII, PHIR, RFN, SI, SR, SRI, SRR, STI, STR, SUMI, + * SUMR, TEST, TI, TOL, TR, T2I, T2R, ZEROI, ZEROR, ZETA1I, ZETA1R, + * ZETA2I, ZETA2R, ZNI, ZNR, ZRI, ZRR, D1MACH + INTEGER I, IDUM, IKFLG, INIT, IPMTR, J, K, L + DIMENSION C(120), CWRKR(16), CWRKI(16), CON(2) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / + DATA CON(1), CON(2) / + 1 3.98942280401432678D-01, 1.25331413731550025D+00 / + DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), + 1 C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18), + 2 C(19), C(20), C(21), C(22), C(23), C(24)/ + 3 1.00000000000000000D+00, -2.08333333333333333D-01, + 4 1.25000000000000000D-01, 3.34201388888888889D-01, + 5 -4.01041666666666667D-01, 7.03125000000000000D-02, + 6 -1.02581259645061728D+00, 1.84646267361111111D+00, + 7 -8.91210937500000000D-01, 7.32421875000000000D-02, + 8 4.66958442342624743D+00, -1.12070026162229938D+01, + 9 8.78912353515625000D+00, -2.36408691406250000D+00, + A 1.12152099609375000D-01, -2.82120725582002449D+01, + B 8.46362176746007346D+01, -9.18182415432400174D+01, + C 4.25349987453884549D+01, -7.36879435947963170D+00, + D 2.27108001708984375D-01, 2.12570130039217123D+02, + E -7.65252468141181642D+02, 1.05999045252799988D+03/ + DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32), + 1 C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40), + 2 C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/ + 3 -6.99579627376132541D+02, 2.18190511744211590D+02, + 4 -2.64914304869515555D+01, 5.72501420974731445D-01, + 5 -1.91945766231840700D+03, 8.06172218173730938D+03, + 6 -1.35865500064341374D+04, 1.16553933368645332D+04, + 7 -5.30564697861340311D+03, 1.20090291321635246D+03, + 8 -1.08090919788394656D+02, 1.72772750258445740D+00, + 9 2.02042913309661486D+04, -9.69805983886375135D+04, + A 1.92547001232531532D+05, -2.03400177280415534D+05, + B 1.22200464983017460D+05, -4.11926549688975513D+04, + C 7.10951430248936372D+03, -4.93915304773088012D+02, + D 6.07404200127348304D+00, -2.42919187900551333D+05, + E 1.31176361466297720D+06, -2.99801591853810675D+06/ + DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56), + 1 C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64), + 2 C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/ + 3 3.76327129765640400D+06, -2.81356322658653411D+06, + 4 1.26836527332162478D+06, -3.31645172484563578D+05, + 5 4.52187689813627263D+04, -2.49983048181120962D+03, + 6 2.43805296995560639D+01, 3.28446985307203782D+06, + 7 -1.97068191184322269D+07, 5.09526024926646422D+07, + 8 -7.41051482115326577D+07, 6.63445122747290267D+07, + 9 -3.75671766607633513D+07, 1.32887671664218183D+07, + A -2.78561812808645469D+06, 3.08186404612662398D+05, + B -1.38860897537170405D+04, 1.10017140269246738D+02, + C -4.93292536645099620D+07, 3.25573074185765749D+08, + D -9.39462359681578403D+08, 1.55359689957058006D+09, + E -1.62108055210833708D+09, 1.10684281682301447D+09/ + DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80), + 1 C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88), + 2 C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/ + 3 -4.95889784275030309D+08, 1.42062907797533095D+08, + 4 -2.44740627257387285D+07, 2.24376817792244943D+06, + 5 -8.40054336030240853D+04, 5.51335896122020586D+02, + 6 8.14789096118312115D+08, -5.86648149205184723D+09, + 7 1.86882075092958249D+10, -3.46320433881587779D+10, + 8 4.12801855797539740D+10, -3.30265997498007231D+10, + 9 1.79542137311556001D+10, -6.56329379261928433D+09, + A 1.55927986487925751D+09, -2.25105661889415278D+08, + B 1.73951075539781645D+07, -5.49842327572288687D+05, + C 3.03809051092238427D+03, -1.46792612476956167D+10, + D 1.14498237732025810D+11, -3.99096175224466498D+11, + E 8.19218669548577329D+11, -1.09837515608122331D+12/ + DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104), + 1 C(105), C(106), C(107), C(108), C(109), C(110), C(111), + 2 C(112), C(113), C(114), C(115), C(116), C(117), C(118)/ + 3 1.00815810686538209D+12, -6.45364869245376503D+11, + 4 2.87900649906150589D+11, -8.78670721780232657D+10, + 5 1.76347306068349694D+10, -2.16716498322379509D+09, + 6 1.43157876718888981D+08, -3.87183344257261262D+06, + 7 1.82577554742931747D+04, 2.86464035717679043D+11, + 8 -2.40629790002850396D+12, 9.10934118523989896D+12, + 9 -2.05168994109344374D+13, 3.05651255199353206D+13, + A -3.16670885847851584D+13, 2.33483640445818409D+13, + B -1.23204913055982872D+13, 4.61272578084913197D+12, + C -1.19655288019618160D+12, 2.05914503232410016D+11, + D -2.18229277575292237D+10, 1.24700929351271032D+09/ + DATA C(119), C(120)/ + 1 -2.91883881222208134D+07, 1.18838426256783253D+05/ +C + IF (INIT.NE.0) GO TO 40 +C----------------------------------------------------------------------- +C INITIALIZE ALL VARIABLES +C----------------------------------------------------------------------- + RFN = 1.0D0/FNU +C----------------------------------------------------------------------- +C OVERFLOW TEST (ZR/FNU TOO SMALL) +C----------------------------------------------------------------------- + TEST = D1MACH(1)*1.0D+3 + AC = FNU*TEST + IF (DABS(ZRR).GT.AC .OR. DABS(ZRI).GT.AC) GO TO 15 + ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU + ZETA1I = 0.0D0 + ZETA2R = FNU + ZETA2I = 0.0D0 + PHIR = 1.0D0 + PHII = 0.0D0 + RETURN + 15 CONTINUE + TR = ZRR*RFN + TI = ZRI*RFN + SR = CONER + (TR*TR-TI*TI) + SI = CONEI + (TR*TI+TI*TR) + CALL ZSQRT(SR, SI, SRR, SRI) + STR = CONER + SRR + STI = CONEI + SRI + CALL ZDIV(STR, STI, TR, TI, ZNR, ZNI) + CALL ZLOG(ZNR, ZNI, STR, STI, IDUM) + ZETA1R = FNU*STR + ZETA1I = FNU*STI + ZETA2R = FNU*SRR + ZETA2I = FNU*SRI + CALL ZDIV(CONER, CONEI, SRR, SRI, TR, TI) + SRR = TR*RFN + SRI = TI*RFN + CALL ZSQRT(SRR, SRI, CWRKR(16), CWRKI(16)) + PHIR = CWRKR(16)*CON(IKFLG) + PHII = CWRKI(16)*CON(IKFLG) + IF (IPMTR.NE.0) RETURN + CALL ZDIV(CONER, CONEI, SR, SI, T2R, T2I) + CWRKR(1) = CONER + CWRKI(1) = CONEI + CRFNR = CONER + CRFNI = CONEI + AC = 1.0D0 + L = 1 + DO 20 K=2,15 + SR = ZEROR + SI = ZEROI + DO 10 J=1,K + L = L + 1 + STR = SR*T2R - SI*T2I + C(L) + SI = SR*T2I + SI*T2R + SR = STR + 10 CONTINUE + STR = CRFNR*SRR - CRFNI*SRI + CRFNI = CRFNR*SRI + CRFNI*SRR + CRFNR = STR + CWRKR(K) = CRFNR*SR - CRFNI*SI + CWRKI(K) = CRFNR*SI + CRFNI*SR + AC = AC*RFN + TEST = DABS(CWRKR(K)) + DABS(CWRKI(K)) + IF (AC.LT.TOL .AND. TEST.LT.TOL) GO TO 30 + 20 CONTINUE + K = 15 + 30 CONTINUE + INIT = K + 40 CONTINUE + IF (IKFLG.EQ.2) GO TO 60 +C----------------------------------------------------------------------- +C COMPUTE SUM FOR THE I FUNCTION +C----------------------------------------------------------------------- + SR = ZEROR + SI = ZEROI + DO 50 I=1,INIT + SR = SR + CWRKR(I) + SI = SI + CWRKI(I) + 50 CONTINUE + SUMR = SR + SUMI = SI + PHIR = CWRKR(16)*CON(1) + PHII = CWRKI(16)*CON(1) + RETURN + 60 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE SUM FOR THE K FUNCTION +C----------------------------------------------------------------------- + SR = ZEROR + SI = ZEROI + TR = CONER + DO 70 I=1,INIT + SR = SR + TR*CWRKR(I) + SI = SI + TR*CWRKI(I) + TR = -TR + 70 CONTINUE + SUMR = SR + SUMI = SI + PHIR = CWRKR(16)*CON(2) + PHII = CWRKI(16)*CON(2) + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk1.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk1.f new file mode 100644 index 00000000..6b2418dd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk1.f @@ -0,0 +1,426 @@ + SUBROUTINE ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZUNK1 +C***REFER TO ZBESK +C +C ZUNK1 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE +C RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE +C UNIFORM ASYMPTOTIC EXPANSION. +C MR INDICATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION. +C NZ=-1 MEANS AN OVERFLOW WILL OCCUR +C +C***ROUTINES CALLED ZKSCL,ZS1S2,ZUCHK,ZUNIK,D1MACH,ZABS +C***END PROLOGUE ZUNK1 +C COMPLEX CFN,CK,CONE,CRSC,CS,CSCL,CSGN,CSPN,CSR,CSS,CWRK,CY,CZERO, +C *C1,C2,PHI,PHID,RZ,SUM,SUMD,S1,S2,Y,Z,ZETA1,ZETA1D,ZETA2,ZETA2D,ZR + DOUBLE PRECISION ALIM, ANG, APHI, ASC, ASCLE, BRY, CKI, CKR, + * CONER, CRSC, CSCL, CSGNI, CSPNI, CSPNR, CSR, CSRR, CSSR, + * CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2M, C2R, ELIM, FMR, FN, + * FNF, FNU, PHIDI, PHIDR, PHII, PHIR, PI, RAST, RAZR, RS1, RZI, + * RZR, SGN, STI, STR, SUMDI, SUMDR, SUMI, SUMR, S1I, S1R, S2I, + * S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, + * ZET1DI, ZET1DR, ZET2DI, ZET2DR, ZI, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IB, IFLAG, IFN, IL, INIT, INU, IUF, K, KDFLG, KFLAG, + * KK, KODE, MR, N, NW, NZ, INITD, IC, IPARD, J + DIMENSION BRY(3), INIT(2), YR(N), YI(N), SUMR(2), SUMI(2), + * ZETA1R(2), ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2), + * CWRKR(16,3), CWRKI(16,3), CSSR(3), CSRR(3), PHIR(2), PHII(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / + DATA PI / 3.14159265358979324D0 / +C + KDFLG = 1 + NZ = 0 +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN +C THE UNDERFLOW LIMIT +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + J = 2 + DO 70 I=1,N +C----------------------------------------------------------------------- +C J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J +C----------------------------------------------------------------------- + J = 3 - J + FN = FNU + DBLE(FLOAT(I-1)) + INIT(J) = 0 + CALL ZUNIK(ZRR, ZRI, FN, 2, 0, TOL, INIT(J), PHIR(J), PHII(J), + * ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), SUMR(J), SUMI(J), + * CWRKR(1,J), CWRKI(1,J)) + IF (KODE.EQ.1) GO TO 20 + STR = ZRR + ZETA2R(J) + STI = ZRI + ZETA2I(J) + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZETA1R(J) - STR + S1I = ZETA1I(J) - STI + GO TO 30 + 20 CONTINUE + S1R = ZETA1R(J) - ZETA2R(J) + S1I = ZETA1I(J) - ZETA2I(J) + 30 CONTINUE + RS1 = S1R +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + IF (DABS(RS1).GT.ELIM) GO TO 60 + IF (KDFLG.EQ.1) KFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 40 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR(J),PHII(J),kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 60 + IF (KDFLG.EQ.1) KFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 40 + IF (KDFLG.EQ.1) KFLAG = 3 + 40 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + S2R = PHIR(J)*SUMR(J) - PHII(J)*SUMI(J) + S2I = PHIR(J)*SUMI(J) + PHII(J)*SUMR(J) + STR = DEXP(S1R)*CSSR(KFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S1R*S2I + S2R*S1I + S2R = STR + IF (KFLAG.NE.1) GO TO 50 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 60 + 50 CONTINUE + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + YR(I) = S2R*CSRR(KFLAG) + YI(I) = S2I*CSRR(KFLAG) + IF (KDFLG.EQ.2) GO TO 75 + KDFLG = 2 + GO TO 70 + 60 CONTINUE + IF (RS1.GT.0.0D0) GO TO 300 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 300 + KDFLG = 1 + YR(I)=ZEROR + YI(I)=ZEROI + NZ=NZ+1 + IF (I.EQ.1) GO TO 70 + IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 70 + YR(I-1)=ZEROR + YI(I-1)=ZEROI + NZ=NZ+1 + 70 CONTINUE + I = N + 75 CONTINUE + RAZR = 1.0D0/ZABS(CMPLX(ZRR,ZRI,kind=KIND(1.0D0))) + STR = ZRR*RAZR + STI = -ZRI*RAZR + RZR = (STR+STR)*RAZR + RZI = (STI+STI)*RAZR + CKR = FN*RZR + CKI = FN*RZI + IB = I + 1 + IF (N.LT.IB) GO TO 160 +C----------------------------------------------------------------------- +C TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO +C ON UNDERFLOW. +C----------------------------------------------------------------------- + FN = FNU + DBLE(FLOAT(N-1)) + IPARD = 1 + IF (MR.NE.0) IPARD = 0 + INITD = 0 + CALL ZUNIK(ZRR, ZRI, FN, 2, IPARD, TOL, INITD, PHIDR, PHIDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI, CWRKR(1,3), + * CWRKI(1,3)) + IF (KODE.EQ.1) GO TO 80 + STR = ZRR + ZET2DR + STI = ZRI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZET1DR - STR + S1I = ZET1DI - STI + GO TO 90 + 80 CONTINUE + S1R = ZET1DR - ZET2DR + S1I = ZET1DI - ZET2DI + 90 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 95 + IF (DABS(RS1).LT.ALIM) GO TO 100 +C---------------------------------------------------------------------------- +C REFINE ESTIMATE AND TEST +C------------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1+DLOG(APHI) + IF (DABS(RS1).LT.ELIM) GO TO 100 + 95 CONTINUE + IF (DABS(RS1).GT.0.0D0) GO TO 300 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 300 + NZ = N + DO 96 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 96 CONTINUE + RETURN +C--------------------------------------------------------------------------- +C FORWARD RECUR FOR REMAINDER OF THE SEQUENCE +C---------------------------------------------------------------------------- + 100 CONTINUE + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 120 I=IB,N + C2R = S2R + C2I = S2I + S2R = CKR*C2R - CKI*C2I + S1R + S2I = CKR*C2I + CKI*C2R + S1I + S1R = C2R + S1I = C2I + CKR = CKR + RZR + CKI = CKI + RZI + C2R = S2R*C1R + C2I = S2I*C1R + YR(I) = C2R + YI(I) = C2I + IF (KFLAG.GE.3) GO TO 120 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 120 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + C1R = CSRR(KFLAG) + 120 CONTINUE + 160 CONTINUE + IF (MR.EQ.0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0 +C----------------------------------------------------------------------- + NZ = 0 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) +C----------------------------------------------------------------------- +C CSPN AND CSGN ARE COEFF OF K AND I FUNCTIONS RESP. +C----------------------------------------------------------------------- + CSGNI = SGN + INU = INT(SNGL(FNU)) + FNF = FNU - DBLE(FLOAT(INU)) + IFN = INU + N - 1 + ANG = FNF*SGN + CSPNR = DCOS(ANG) + CSPNI = DSIN(ANG) + IF (MOD(IFN,2).EQ.0) GO TO 170 + CSPNR = -CSPNR + CSPNI = -CSPNI + 170 CONTINUE + ASC = BRY(1) + IUF = 0 + KK = N + KDFLG = 1 + IB = IB - 1 + IC = IB - 1 + DO 270 K=1,N + FN = FNU + DBLE(FLOAT(KK-1)) +C----------------------------------------------------------------------- +C LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K +C FUNCTION ABOVE +C----------------------------------------------------------------------- + M=3 + IF (N.GT.2) GO TO 175 + 172 CONTINUE + INITD = INIT(J) + PHIDR = PHIR(J) + PHIDI = PHII(J) + ZET1DR = ZETA1R(J) + ZET1DI = ZETA1I(J) + ZET2DR = ZETA2R(J) + ZET2DI = ZETA2I(J) + SUMDR = SUMR(J) + SUMDI = SUMI(J) + M = J + J = 3 - J + GO TO 180 + 175 CONTINUE + IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 180 + IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172 + INITD = 0 + 180 CONTINUE + CALL ZUNIK(ZRR, ZRI, FN, 1, 0, TOL, INITD, PHIDR, PHIDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI, + * CWRKR(1,M), CWRKI(1,M)) + IF (KODE.EQ.1) GO TO 200 + STR = ZRR + ZET2DR + STI = ZRI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZET1DR + STR + S1I = -ZET1DI + STI + GO TO 210 + 200 CONTINUE + S1R = -ZET1DR + ZET2DR + S1I = -ZET1DI + ZET2DI + 210 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 260 + IF (KDFLG.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 220 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 260 + IF (KDFLG.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 220 + IF (KDFLG.EQ.1) IFLAG = 3 + 220 CONTINUE + STR = PHIDR*SUMDR - PHIDI*SUMDI + STI = PHIDR*SUMDI + PHIDI*SUMDR + S2R = -CSGNI*STI + S2I = CSGNI*STR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 230 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.EQ.0) GO TO 230 + S2R = ZEROR + S2I = ZEROI + 230 CONTINUE + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + C2R = S2R + C2I = S2I + S2R = S2R*CSRR(IFLAG) + S2I = S2I*CSRR(IFLAG) +C----------------------------------------------------------------------- +C ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N +C----------------------------------------------------------------------- + S1R = YR(KK) + S1I = YI(KK) + IF (KODE.EQ.1) GO TO 250 + CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 250 CONTINUE + YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R + YI(KK) = CSPNR*S1I + CSPNI*S1R + S2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255 + KDFLG = 1 + GO TO 270 + 255 CONTINUE + IF (KDFLG.EQ.2) GO TO 275 + KDFLG = 2 + GO TO 270 + 260 CONTINUE + IF (RS1.GT.0.0D0) GO TO 300 + S2R = ZEROR + S2I = ZEROI + GO TO 230 + 270 CONTINUE + K = N + 275 CONTINUE + IL = N - K + IF (IL.EQ.0) RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE +C K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP +C INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES. +C----------------------------------------------------------------------- + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + CSR = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + FN = DBLE(FLOAT(INU+IL)) + DO 290 I=1,IL + C2R = S2R + C2I = S2I + S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + FN = FN - 1.0D0 + C2R = S2R*CSR + C2I = S2I*CSR + CKR = C2R + CKI = C2I + C1R = YR(KK) + C1I = YI(KK) + IF (KODE.EQ.1) GO TO 280 + CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 280 CONTINUE + YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R + YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (IFLAG.GE.3) GO TO 290 + C2R = DABS(CKR) + C2I = DABS(CKI) + C2M = DMAX1(C2R,C2I) + IF (C2M.LE.ASCLE) GO TO 290 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = CKR + S2I = CKI + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + CSR = CSRR(IFLAG) + 290 CONTINUE + RETURN + 300 CONTINUE + NZ = -1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk2.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk2.f new file mode 100644 index 00000000..6859f5ec --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zunk2.f @@ -0,0 +1,505 @@ + SUBROUTINE ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZUNK2 +C***REFER TO ZBESK +C +C ZUNK2 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE +C RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE +C UNIFORM ASYMPTOTIC EXPANSIONS FOR H(KIND,FNU,ZN) AND J(FNU,ZN) +C WHERE ZN IS IN THE RIGHT HALF PLANE, KIND=(3-MR)/2, MR=+1 OR +C -1. HERE ZN=ZR*I OR -ZR*I WHERE ZR=Z IF Z IS IN THE RIGHT +C HALF PLANE OR ZR=-Z IF Z IS IN THE LEFT HALF PLANE. MR INDIC- +C ATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION. +C NZ=-1 MEANS AN OVERFLOW WILL OCCUR +C +C***ROUTINES CALLED ZAIRY,ZKSCL,ZS1S2,ZUCHK,ZUNHJ,D1MACH,ZABS +C***END PROLOGUE ZUNK2 +C COMPLEX AI,ARG,ARGD,ASUM,ASUMD,BSUM,BSUMD,CFN,CI,CIP,CK,CONE,CRSC, +C *CR1,CR2,CS,CSCL,CSGN,CSPN,CSR,CSS,CY,CZERO,C1,C2,DAI,PHI,PHID,RZ, +C *S1,S2,Y,Z,ZB,ZETA1,ZETA1D,ZETA2,ZETA2D,ZN,ZR + DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGDI, + * ARGDR, ARGI, ARGR, ASC, ASCLE, ASUMDI, ASUMDR, ASUMI, ASUMR, + * BRY, BSUMDI, BSUMDR, BSUMI, BSUMR, CAR, CIPI, CIPR, CKI, CKR, + * CONER, CRSC, CR1I, CR1R, CR2I, CR2R, CSCL, CSGNI, CSI, + * CSPNI, CSPNR, CSR, CSRR, CSSR, CYI, CYR, C1I, C1R, C2I, C2M, + * C2R, DAII, DAIR, ELIM, FMR, FN, FNF, FNU, HPI, PHIDI, PHIDR, + * PHII, PHIR, PI, PTI, PTR, RAST, RAZR, RS1, RZI, RZR, SAR, SGN, + * STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, YY, ZBI, ZBR, ZEROI, + * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZET1DI, ZET1DR, ZET2DI, + * ZET2DR, ZI, ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IB, IFLAG, IFN, IL, IN, INU, IUF, K, KDFLG, KFLAG, KK, + * KODE, MR, N, NAI, NDAI, NW, NZ, IDUM, J, IPARD, IC + DIMENSION BRY(3), YR(N), YI(N), ASUMR(2), ASUMI(2), BSUMR(2), + * BSUMI(2), PHIR(2), PHII(2), ARGR(2), ARGI(2), ZETA1R(2), + * ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2), CIPR(4), + * CIPI(4), CSSR(3), CSRR(3) + DATA ZEROR,ZEROI,CONER,CR1R,CR1I,CR2R,CR2I / + 1 0.0D0, 0.0D0, 1.0D0, + 1 1.0D0,1.73205080756887729D0 , -0.5D0,-8.66025403784438647D-01 / + DATA HPI, PI, AIC / + 1 1.57079632679489662D+00, 3.14159265358979324D+00, + 1 1.26551212348464539D+00/ + DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4), + * CIPI(4) / + 1 1.0D0,0.0D0 , 0.0D0,-1.0D0 , -1.0D0,0.0D0 , 0.0D0,1.0D0 / +C + KDFLG = 1 + NZ = 0 +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN +C THE UNDERFLOW LIMIT +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + YY = ZRI + ZNR = ZRI + ZNI = -ZRR + ZBR = ZRR + ZBI = ZRI + INU = INT(SNGL(FNU)) + FNF = FNU - DBLE(FLOAT(INU)) + ANG = -HPI*FNF + CAR = DCOS(ANG) + SAR = DSIN(ANG) + C2R = HPI*SAR + C2I = -HPI*CAR + KK = MOD(INU,4) + 1 + STR = C2R*CIPR(KK) - C2I*CIPI(KK) + STI = C2R*CIPI(KK) + C2I*CIPR(KK) + CSR = CR1R*STR - CR1I*STI + CSI = CR1R*STI + CR1I*STR + IF (YY.GT.0.0D0) GO TO 20 + ZNR = -ZNR + ZBI = -ZBI + 20 CONTINUE +C----------------------------------------------------------------------- +C K(FNU,Z) IS COMPUTED FROM H(2,FNU,-I*Z) WHERE Z IS IN THE FIRST +C QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY +C CONJUGATION SINCE THE K FUNCTION IS REAL ON THE POSITIVE REAL AXIS +C----------------------------------------------------------------------- + J = 2 + DO 80 I=1,N +C----------------------------------------------------------------------- +C J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J +C----------------------------------------------------------------------- + J = 3 - J + FN = FNU + DBLE(FLOAT(I-1)) + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR(J), PHII(J), ARGR(J), + * ARGI(J), ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), ASUMR(J), + * ASUMI(J), BSUMR(J), BSUMI(J)) + IF (KODE.EQ.1) GO TO 30 + STR = ZBR + ZETA2R(J) + STI = ZBI + ZETA2I(J) + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZETA1R(J) - STR + S1I = ZETA1I(J) - STI + GO TO 40 + 30 CONTINUE + S1R = ZETA1R(J) - ZETA2R(J) + S1I = ZETA1I(J) - ZETA2I(J) + 40 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 70 + IF (KDFLG.EQ.1) KFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 50 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR(J),PHII(J),kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGR(J),ARGI(J),kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 70 + IF (KDFLG.EQ.1) KFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 50 + IF (KDFLG.EQ.1) KFLAG = 3 + 50 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + C2R = ARGR(J)*CR2R - ARGI(J)*CR2I + C2I = ARGR(J)*CR2I + ARGI(J)*CR2R + CALL ZAIRY(C2R, C2I, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(C2R, C2I, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMR(J) - DAII*BSUMI(J) + STI = DAIR*BSUMI(J) + DAII*BSUMR(J) + PTR = STR*CR2R - STI*CR2I + PTI = STR*CR2I + STI*CR2R + STR = PTR + (AIR*ASUMR(J)-AII*ASUMI(J)) + STI = PTI + (AIR*ASUMI(J)+AII*ASUMR(J)) + PTR = STR*PHIR(J) - STI*PHII(J) + PTI = STR*PHII(J) + STI*PHIR(J) + S2R = PTR*CSR - PTI*CSI + S2I = PTR*CSI + PTI*CSR + STR = DEXP(S1R)*CSSR(KFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S1R*S2I + S2R*S1I + S2R = STR + IF (KFLAG.NE.1) GO TO 60 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 70 + 60 CONTINUE + IF (YY.LE.0.0D0) S2I = -S2I + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + YR(I) = S2R*CSRR(KFLAG) + YI(I) = S2I*CSRR(KFLAG) + STR = CSI + CSI = -CSR + CSR = STR + IF (KDFLG.EQ.2) GO TO 85 + KDFLG = 2 + GO TO 80 + 70 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 320 + KDFLG = 1 + YR(I)=ZEROR + YI(I)=ZEROI + NZ=NZ+1 + STR = CSI + CSI =-CSR + CSR = STR + IF (I.EQ.1) GO TO 80 + IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 80 + YR(I-1)=ZEROR + YI(I-1)=ZEROI + NZ=NZ+1 + 80 CONTINUE + I = N + 85 CONTINUE + RAZR = 1.0D0/ZABS(CMPLX(ZRR,ZRI,kind=KIND(1.0D0))) + STR = ZRR*RAZR + STI = -ZRI*RAZR + RZR = (STR+STR)*RAZR + RZI = (STI+STI)*RAZR + CKR = FN*RZR + CKI = FN*RZI + IB = I + 1 + IF (N.LT.IB) GO TO 180 +C----------------------------------------------------------------------- +C TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO +C ON UNDERFLOW. +C----------------------------------------------------------------------- + FN = FNU + DBLE(FLOAT(N-1)) + IPARD = 1 + IF (MR.NE.0) IPARD = 0 + CALL ZUNHJ(ZNR, ZNI, FN, IPARD, TOL, PHIDR, PHIDI, ARGDR, ARGDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR, ASUMDI, BSUMDR, BSUMDI) + IF (KODE.EQ.1) GO TO 90 + STR = ZBR + ZET2DR + STI = ZBI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZET1DR - STR + S1I = ZET1DI - STI + GO TO 100 + 90 CONTINUE + S1R = ZET1DR - ZET2DR + S1I = ZET1DI - ZET2DI + 100 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 105 + IF (DABS(RS1).LT.ALIM) GO TO 120 +C---------------------------------------------------------------------------- +C REFINE ESTIMATE AND TEST +C------------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1+DLOG(APHI) + IF (DABS(RS1).LT.ELIM) GO TO 120 + 105 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 320 + NZ = N + DO 106 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 106 CONTINUE + RETURN + 120 CONTINUE + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 130 I=IB,N + C2R = S2R + C2I = S2I + S2R = CKR*C2R - CKI*C2I + S1R + S2I = CKR*C2I + CKI*C2R + S1I + S1R = C2R + S1I = C2I + CKR = CKR + RZR + CKI = CKI + RZI + C2R = S2R*C1R + C2I = S2I*C1R + YR(I) = C2R + YI(I) = C2I + IF (KFLAG.GE.3) GO TO 130 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 130 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + C1R = CSRR(KFLAG) + 130 CONTINUE + 180 CONTINUE + IF (MR.EQ.0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0 +C----------------------------------------------------------------------- + NZ = 0 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) +C----------------------------------------------------------------------- +C CSPN AND CSGN ARE COEFF OF K AND I FUNCIONS RESP. +C----------------------------------------------------------------------- + CSGNI = SGN + IF (YY.LE.0.0D0) CSGNI = -CSGNI + IFN = INU + N - 1 + ANG = FNF*SGN + CSPNR = DCOS(ANG) + CSPNI = DSIN(ANG) + IF (MOD(IFN,2).EQ.0) GO TO 190 + CSPNR = -CSPNR + CSPNI = -CSPNI + 190 CONTINUE +C----------------------------------------------------------------------- +C CS=COEFF OF THE J FUNCTION TO GET THE I FUNCTION. I(FNU,Z) IS +C COMPUTED FROM EXP(I*FNU*HPI)*J(FNU,-I*Z) WHERE Z IS IN THE FIRST +C QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY +C CONJUGATION SINCE THE I FUNCTION IS REAL ON THE POSITIVE REAL AXIS +C----------------------------------------------------------------------- + CSR = SAR*CSGNI + CSI = CAR*CSGNI + IN = MOD(IFN,4) + 1 + C2R = CIPR(IN) + C2I = CIPI(IN) + STR = CSR*C2R + CSI*C2I + CSI = -CSR*C2I + CSI*C2R + CSR = STR + ASC = BRY(1) + IUF = 0 + KK = N + KDFLG = 1 + IB = IB - 1 + IC = IB - 1 + DO 290 K=1,N + FN = FNU + DBLE(FLOAT(KK-1)) +C----------------------------------------------------------------------- +C LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K +C FUNCTION ABOVE +C----------------------------------------------------------------------- + IF (N.GT.2) GO TO 175 + 172 CONTINUE + PHIDR = PHIR(J) + PHIDI = PHII(J) + ARGDR = ARGR(J) + ARGDI = ARGI(J) + ZET1DR = ZETA1R(J) + ZET1DI = ZETA1I(J) + ZET2DR = ZETA2R(J) + ZET2DI = ZETA2I(J) + ASUMDR = ASUMR(J) + ASUMDI = ASUMI(J) + BSUMDR = BSUMR(J) + BSUMDI = BSUMI(J) + J = 3 - J + GO TO 210 + 175 CONTINUE + IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 210 + IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172 + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIDR, PHIDI, ARGDR, + * ARGDI, ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR, + * ASUMDI, BSUMDR, BSUMDI) + 210 CONTINUE + IF (KODE.EQ.1) GO TO 220 + STR = ZBR + ZET2DR + STI = ZBI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZET1DR + STR + S1I = -ZET1DI + STI + GO TO 230 + 220 CONTINUE + S1R = -ZET1DR + ZET2DR + S1I = -ZET1DI + ZET2DI + 230 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 280 + IF (KDFLG.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 240 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGDR,ARGDI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 280 + IF (KDFLG.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 240 + IF (KDFLG.EQ.1) IFLAG = 3 + 240 CONTINUE + CALL ZAIRY(ARGDR, ARGDI, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(ARGDR, ARGDI, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMDR - DAII*BSUMDI + STI = DAIR*BSUMDI + DAII*BSUMDR + STR = STR + (AIR*ASUMDR-AII*ASUMDI) + STI = STI + (AIR*ASUMDI+AII*ASUMDR) + PTR = STR*PHIDR - STI*PHIDI + PTI = STR*PHIDI + STI*PHIDR + S2R = PTR*CSR - PTI*CSI + S2I = PTR*CSI + PTI*CSR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 250 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.EQ.0) GO TO 250 + S2R = ZEROR + S2I = ZEROI + 250 CONTINUE + IF (YY.LE.0.0D0) S2I = -S2I + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + C2R = S2R + C2I = S2I + S2R = S2R*CSRR(IFLAG) + S2I = S2I*CSRR(IFLAG) +C----------------------------------------------------------------------- +C ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N +C----------------------------------------------------------------------- + S1R = YR(KK) + S1I = YI(KK) + IF (KODE.EQ.1) GO TO 270 + CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 270 CONTINUE + YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R + YI(KK) = S1R*CSPNI + S1I*CSPNR + S2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + STR = CSI + CSI = -CSR + CSR = STR + IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255 + KDFLG = 1 + GO TO 290 + 255 CONTINUE + IF (KDFLG.EQ.2) GO TO 295 + KDFLG = 2 + GO TO 290 + 280 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 + S2R = ZEROR + S2I = ZEROI + GO TO 250 + 290 CONTINUE + K = N + 295 CONTINUE + IL = N - K + IF (IL.EQ.0) RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE +C K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP +C INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES. +C----------------------------------------------------------------------- + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + CSR = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + FN = DBLE(FLOAT(INU+IL)) + DO 310 I=1,IL + C2R = S2R + C2I = S2I + S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + FN = FN - 1.0D0 + C2R = S2R*CSR + C2I = S2I*CSR + CKR = C2R + CKI = C2I + C1R = YR(KK) + C1I = YI(KK) + IF (KODE.EQ.1) GO TO 300 + CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 300 CONTINUE + YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R + YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (IFLAG.GE.3) GO TO 310 + C2R = DABS(CKR) + C2I = DABS(CKI) + C2M = DMAX1(C2R,C2I) + IF (C2M.LE.ASCLE) GO TO 310 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = CKR + S2I = CKI + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + CSR = CSRR(IFLAG) + 310 CONTINUE + RETURN + 320 CONTINUE + NZ = -1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuoik.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuoik.f new file mode 100644 index 00000000..3715d6d4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zuoik.f @@ -0,0 +1,194 @@ + SUBROUTINE ZUOIK(ZR, ZI, FNU, KODE, IKFLG, N, YR, YI, NUF, TOL, + * ELIM, ALIM) +C***BEGIN PROLOGUE ZUOIK +C***REFER TO ZBESI,ZBESK,ZBESH +C +C ZUOIK COMPUTES THE LEADING TERMS OF THE UNIFORM ASYMPTOTIC +C EXPANSIONS FOR THE I AND K FUNCTIONS AND COMPARES THEM +C (IN LOGARITHMIC FORM) TO ALIM AND ELIM FOR OVER AND UNDERFLOW +C WHERE ALIM.LT.ELIM. IF THE MAGNITUDE, BASED ON THE LEADING +C EXPONENTIAL, IS LESS THAN ALIM OR GREATER THAN -ALIM, THEN +C THE RESULT IS ON SCALE. IF NOT, THEN A REFINED TEST USING OTHER +C MULTIPLIERS (IN LOGARITHMIC FORM) IS MADE BASED ON ELIM. HERE +C EXP(-ELIM)=SMALLEST MACHINE NUMBER*1.0E+3 AND EXP(-ALIM)= +C EXP(-ELIM)/TOL +C +C IKFLG=1 MEANS THE I SEQUENCE IS TESTED +C =2 MEANS THE K SEQUENCE IS TESTED +C NUF = 0 MEANS THE LAST MEMBER OF THE SEQUENCE IS ON SCALE +C =-1 MEANS AN OVERFLOW WOULD OCCUR +C IKFLG=1 AND NUF.GT.0 MEANS THE LAST NUF Y VALUES WERE SET TO ZERO +C THE FIRST N-NUF VALUES MUST BE SET BY ANOTHER ROUTINE +C IKFLG=2 AND NUF.EQ.N MEANS ALL Y VALUES WERE SET TO ZERO +C IKFLG=2 AND 0.LT.NUF.LT.N NOT CONSIDERED. Y MUST BE SET BY +C ANOTHER ROUTINE +C +C***ROUTINES CALLED ZUCHK,ZUNHJ,ZUNIK,D1MACH,ZABS,ZLOG +C***END PROLOGUE ZUOIK +C COMPLEX ARG,ASUM,BSUM,CWRK,CZ,CZERO,PHI,SUM,Y,Z,ZB,ZETA1,ZETA2,ZN, +C *ZR + DOUBLE PRECISION AARG, AIC, ALIM, APHI, ARGI, ARGR, ASUMI, ASUMR, + * ASCLE, AX, AY, BSUMI, BSUMR, CWRKI, CWRKR, CZI, CZR, ELIM, FNN, + * FNU, GNN, GNU, PHII, PHIR, RCZ, STR, STI, SUMI, SUMR, TOL, YI, + * YR, ZBI, ZBR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI, + * ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IDUM, IFORM, IKFLG, INIT, KODE, N, NN, NUF, NW + DIMENSION YR(N), YI(N), CWRKR(16), CWRKI(16) + DATA ZEROR,ZEROI / 0.0D0, 0.0D0 / + DATA AIC / 1.265512123484645396D+00 / + NUF = 0 + NN = N + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + ZBR = ZRR + ZBI = ZRI + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IFORM = 1 + IF (AY.GT.AX) IFORM = 2 + GNU = DMAX1(FNU,1.0D0) + IF (IKFLG.EQ.1) GO TO 20 + FNN = DBLE(FLOAT(NN)) + GNN = FNU + FNN - 1.0D0 + GNU = DMAX1(GNN,FNN) + 20 CONTINUE +C----------------------------------------------------------------------- +C ONLY THE MAGNITUDE OF ARG AND PHI ARE NEEDED ALONG WITH THE +C REAL PARTS OF ZETA1, ZETA2 AND ZB. NO ATTEMPT IS MADE TO GET +C THE SIGN OF THE IMAGINARY PART CORRECT. +C----------------------------------------------------------------------- + IF (IFORM.EQ.2) GO TO 30 + INIT = 0 + CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + GO TO 50 + 30 CONTINUE + ZNR = ZRI + ZNI = -ZRR + IF (ZI.GT.0.0D0) GO TO 40 + ZNR = -ZNR + 40 CONTINUE + CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + 50 CONTINUE + IF (KODE.EQ.1) GO TO 60 + CZR = CZR - ZBR + CZI = CZI - ZBI + 60 CONTINUE + IF (IKFLG.EQ.1) GO TO 70 + CZR = -CZR + CZI = -CZI + 70 CONTINUE + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RCZ = CZR +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + IF (RCZ.GT.ELIM) GO TO 210 + IF (RCZ.LT.ALIM) GO TO 80 + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.ELIM) GO TO 210 + GO TO 130 + 80 CONTINUE +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + IF (RCZ.LT.(-ELIM)) GO TO 90 + IF (RCZ.GT.(-ALIM)) GO TO 130 + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.(-ELIM)) GO TO 110 + 90 CONTINUE + DO 100 I=1,NN + YR(I) = ZEROR + YI(I) = ZEROI + 100 CONTINUE + NUF = NN + RETURN + 110 CONTINUE + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZLOG(PHIR, PHII, STR, STI, IDUM) + CZR = CZR + STR + CZI = CZI + STI + IF (IFORM.EQ.1) GO TO 120 + CALL ZLOG(ARGR, ARGI, STR, STI, IDUM) + CZR = CZR - 0.25D0*STR - AIC + CZI = CZI - 0.25D0*STI + 120 CONTINUE + AX = DEXP(RCZ)/TOL + AY = CZI + CZR = AX*DCOS(AY) + CZI = AX*DSIN(AY) + CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 90 + 130 CONTINUE + IF (IKFLG.EQ.2) RETURN + IF (N.EQ.1) RETURN +C----------------------------------------------------------------------- +C SET UNDERFLOWS ON I SEQUENCE +C----------------------------------------------------------------------- + 140 CONTINUE + GNU = FNU + DBLE(FLOAT(NN-1)) + IF (IFORM.EQ.2) GO TO 150 + INIT = 0 + CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + GO TO 160 + 150 CONTINUE + CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + 160 CONTINUE + IF (KODE.EQ.1) GO TO 170 + CZR = CZR - ZBR + CZI = CZI - ZBI + 170 CONTINUE + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RCZ = CZR + IF (RCZ.LT.(-ELIM)) GO TO 180 + IF (RCZ.GT.(-ALIM)) RETURN + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.(-ELIM)) GO TO 190 + 180 CONTINUE + YR(NN) = ZEROR + YI(NN) = ZEROI + NN = NN - 1 + NUF = NUF + 1 + IF (NN.EQ.0) RETURN + GO TO 140 + 190 CONTINUE + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZLOG(PHIR, PHII, STR, STI, IDUM) + CZR = CZR + STR + CZI = CZI + STI + IF (IFORM.EQ.1) GO TO 200 + CALL ZLOG(ARGR, ARGI, STR, STI, IDUM) + CZR = CZR - 0.25D0*STR - AIC + CZI = CZI - 0.25D0*STI + 200 CONTINUE + AX = DEXP(RCZ)/TOL + AY = CZI + CZR = AX*DCOS(AY) + CZI = AX*DSIN(AY) + CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 180 + RETURN + 210 CONTINUE + NUF = -1 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zwrsk.f b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zwrsk.f new file mode 100644 index 00000000..37cb8d8c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amoslib/zwrsk.f @@ -0,0 +1,94 @@ + SUBROUTINE ZWRSK(ZRR, ZRI, FNU, KODE, N, YR, YI, NZ, CWR, CWI, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZWRSK +C***REFER TO ZBESI,ZBESK +C +C ZWRSK COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY +C NORMALIZING THE I FUNCTION RATIOS FROM ZRATI BY THE WRONSKIAN +C +C***ROUTINES CALLED D1MACH,ZBKNU,ZRATI,ZABS +C***END PROLOGUE ZWRSK +C COMPLEX CINU,CSCL,CT,CW,C1,C2,RCT,ST,Y,ZR + DOUBLE PRECISION ACT, ACW, ALIM, ASCLE, CINUI, CINUR, CSCLR, CTI, + * CTR, CWI, CWR, C1I, C1R, C2I, C2R, ELIM, FNU, PTI, PTR, RACT, + * STI, STR, TOL, YI, YR, ZRI, ZRR, ZABS, D1MACH + INTEGER I, KODE, N, NW, NZ + DIMENSION YR(N), YI(N), CWR(2), CWI(2) +C----------------------------------------------------------------------- +C I(FNU+I-1,Z) BY BACKWARD RECURRENCE FOR RATIOS +C Y(I)=I(FNU+I,Z)/I(FNU+I-1,Z) FROM CRATI NORMALIZED BY THE +C WRONSKIAN WITH K(FNU,Z) AND K(FNU+1,Z) FROM CBKNU. +C----------------------------------------------------------------------- + NZ = 0 + CALL ZBKNU(ZRR, ZRI, FNU, KODE, 2, CWR, CWI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 50 + CALL ZRATI(ZRR, ZRI, FNU, N, YR, YI, TOL) +C----------------------------------------------------------------------- +C RECUR FORWARD ON I(FNU+1,Z) = R(FNU,Z)*I(FNU,Z), +C R(FNU+J-1,Z)=Y(J), J=1,...,N +C----------------------------------------------------------------------- + CINUR = 1.0D0 + CINUI = 0.0D0 + IF (KODE.EQ.1) GO TO 10 + CINUR = DCOS(ZRI) + CINUI = DSIN(ZRI) + 10 CONTINUE +C----------------------------------------------------------------------- +C ON LOW EXPONENT MACHINES THE K FUNCTIONS CAN BE CLOSE TO BOTH +C THE UNDER AND OVERFLOW LIMITS AND THE NORMALIZATION MUST BE +C SCALED TO PREVENT OVER OR UNDERFLOW. CUOIK HAS DETERMINED THAT +C THE RESULT IS ON SCALE. +C----------------------------------------------------------------------- + ACW = ZABS(CMPLX(CWR(2),CWI(2),kind=KIND(1.0D0))) + ASCLE = 1.0D+3*D1MACH(1)/TOL + CSCLR = 1.0D0 + IF (ACW.GT.ASCLE) GO TO 20 + CSCLR = 1.0D0/TOL + GO TO 30 + 20 CONTINUE + ASCLE = 1.0D0/ASCLE + IF (ACW.LT.ASCLE) GO TO 30 + CSCLR = TOL + 30 CONTINUE + C1R = CWR(1)*CSCLR + C1I = CWI(1)*CSCLR + C2R = CWR(2)*CSCLR + C2I = CWI(2)*CSCLR + STR = YR(1) + STI = YI(1) +C----------------------------------------------------------------------- +C CINU=CINU*(CONJG(CT)/CABS(CT))*(1.0D0/CABS(CT) PREVENTS +C UNDER- OR OVERFLOW PREMATURELY BY SQUARING CABS(CT) +C----------------------------------------------------------------------- + PTR = STR*C1R - STI*C1I + PTI = STR*C1I + STI*C1R + PTR = PTR + C2R + PTI = PTI + C2I + CTR = ZRR*PTR - ZRI*PTI + CTI = ZRR*PTI + ZRI*PTR + ACT = ZABS(CMPLX(CTR,CTI,kind=KIND(1.0D0))) + RACT = 1.0D0/ACT + CTR = CTR*RACT + CTI = -CTI*RACT + PTR = CINUR*RACT + PTI = CINUI*RACT + CINUR = PTR*CTR - PTI*CTI + CINUI = PTR*CTI + PTI*CTR + YR(1) = CINUR*CSCLR + YI(1) = CINUI*CSCLR + IF (N.EQ.1) RETURN + DO 40 I=2,N + PTR = STR*CINUR - STI*CINUI + CINUI = STR*CINUI + STI*CINUR + CINUR = PTR + STR = YR(I) + STI = YI(I) + YR(I) = CINUR*CSCLR + YI(I) = CINUI*CSCLR + 40 CONTINUE + RETURN + 50 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go new file mode 100644 index 00000000..45182541 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 amos implements functions originally in the Netlab code by Donald Amos. +package amos // import "gonum.org/v1/gonum/mathext/internal/amos" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/origcode_test.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/origcode_test.go new file mode 100644 index 00000000..a7d8be8f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/amos/origcode_test.go @@ -0,0 +1,2276 @@ +// Copyright ©2016 The gonum 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 amos + +import ( + "math" + "math/cmplx" +) + +// These routines are the versions directly modified from the Fortran code. +// They are used to ensure that code style improvements do not change the +// code output. + +func iabs(a int) int { + if a >= 0 { + return a + } + return -a +} + +func min0(a, b int) int { + if a < b { + return a + } + return b +} + +func max0(a, b int) int { + if a > b { + return a + } + return b +} + +func zairyOrig(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + // zairy is adapted from the original Netlib code by Donald Amos. + // http://www.netlib.no/netlib/amos/zairy.f + + // Original comment: + /* + C***BEGIN PROLOGUE ZAIRY + C***DATE WRITTEN 830501 (YYMMDD) + C***REVISION DATE 890801 (YYMMDD) + C***CATEGORY NO. B5K + C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD + C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES + C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z + C***DESCRIPTION + C + C ***A DOUBLE PRECISION ROUTINE*** + C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR + C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON + C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* + C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN + C -PI/31.0 FROM THE K BESSEL + C FUNCTIONS BY + C + C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) + C C=1.0/(PI*SQRT(3.0)) + C ZTA=(2/3)*Z**(3/2) + C + C WITH THE POWER SERIES FOR CABS(Z)<=1.0. + C + C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- + C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES + C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF + C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), + C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR + C FLAG IERR=3 IS TRIGGERED WHERE UR=dmax(dmach[4),1.0D-18) IS + C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. + C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN + C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT + C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE + C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA + C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, + C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE + C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE + C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- + C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- + C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN + C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN + C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, + C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE + C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER + C MACHINES. + C + C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX + C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT + C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- + C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE + C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), + C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF + C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY + C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN + C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY + C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER + C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, + C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS + C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER + C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY + C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER + C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE + C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, + C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, + C OR -PI/2+P. + C + C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ + C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF + C COMMERCE, 1955. + C + C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT + C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 + C + C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- + C 1018, MAY, 1985 + C + C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. + C MATH. SOFTWARE, 1986 + */ + var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128 + var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, + CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG, + DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64 + var IERR, IFLAG, K, K1, K2, MR, NN int + var tmp complex128 + + // Extra element for padding. + CYR := []float64{math.NaN(), 0} + CYI := []float64{math.NaN(), 0} + + _ = AI + _ = CONE + _ = CSQ + _ = CY + _ = S1 + _ = S2 + _ = TRM1 + _ = TRM2 + _ = Z + _ = ZTA + _ = Z3 + + TTH = 6.66666666666666667E-01 + C1 = 3.55028053887817240E-01 + C2 = 2.58819403792806799E-01 + COEF = 1.83776298473930683E-01 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + if ID < 0 || ID > 1 { + IERR = 1 + } + if KODE < 1 || KODE > 2 { + IERR = 1 + } + if IERR != 0 { + return + } + AZ = zabs(complex(ZR, ZI)) + TOL = dmax(dmach[4], 1.0E-18) + FID = float64(ID) + if AZ > 1.0E0 { + goto Seventy + } + + // POWER SERIES FOR CABS(Z)<=1. + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + if AZ < TOL { + goto OneSeventy + } + AA = AZ * AZ + if AA < TOL/AZ { + goto Forty + } + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0E0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ * AA + AK = 2.0E0 + FID + BK = 3.0E0 - FID - FID + CK = 4.0E0 - FID + DK = 3.0E0 + FID + FID + D1 = AK * DK + D2 = BK * CK + AD = dmin(D1, D2) + AK = 24.0E0 + 9.0E0*FID + BK = 30.0E0 - 9.0E0*FID + for K = 1; K <= 25; K++ { + STR = (TRM1R*Z3R - TRM1I*Z3I) / D1 + TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R - TRM2I*Z3I) / D2 + TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM * AZ3 / AD + D1 = D1 + AK + D2 = D2 + BK + AD = dmin(D1, D2) + if ATRM < TOL*AD { + goto Forty + } + AK = AK + 18.0E0 + BK = BK + 18.0E0 + } +Forty: + if ID == 1 { + goto Fifty + } + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + if KODE == 1 { + return + } + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = zexp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + return + +Fifty: + AIR = -S2R * C2 + AII = -S2I * C2 + if AZ <= TOL { + goto Sixty + } + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1 / (1.0E0 + FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + +Sixty: + if KODE == 1 { + return + } + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = zexp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + return + + // CASE FOR CABS(Z)>1.0. +Seventy: + FNU = (1.0E0 + FID) / 3.0E0 + + /* + SET PARAMETERS RELATED TO MACHINE CONSTANTS. + TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. + ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT. + EXP(-ELIM)EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR + UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. + RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z. + DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). + */ + K1 = imach[15] + K2 = imach[16] + R1M5 = dmach[5] + + K = min0(iabs(K1), iabs(K2)) + ELIM = 2.303E0 * (float64(K)*R1M5 - 3.0E0) + K1 = imach[14] - 1 + AA = R1M5 * float64(K1) + DIG = dmin(AA, 18.0E0) + AA = AA * 2.303E0 + ALIM = ELIM + dmax(-AA, -41.45E0) + RL = 1.2E0*DIG + 3.0E0 + ALAZ = dlog(AZ) + + // TEST FOR PROPER RANGE. + AA = 0.5E0 / TOL + BB = float64(float32(imach[9])) * 0.5E0 + AA = dmin(AA, BB) + AA = math.Pow(AA, TTH) + if AZ > AA { + goto TwoSixty + } + AA = dsqrt(AA) + if AZ > AA { + IERR = 3 + } + tmp = zsqrt(complex(ZR, ZI)) + CSQR = real(tmp) + CSQI = imag(tmp) + ZTAR = TTH * (ZR*CSQR - ZI*CSQI) + ZTAI = TTH * (ZR*CSQI + ZI*CSQR) + + // RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL. + IFLAG = 0 + SFAC = 1.0E0 + AK = ZTAI + if ZR >= 0.0E0 { + goto Eighty + } + BK = ZTAR + CK = -dabs(BK) + ZTAR = CK + ZTAI = AK + +Eighty: + if ZI != 0.0E0 { + goto Ninety + } + if ZR > 0.0E0 { + goto Ninety + } + ZTAR = 0.0E0 + ZTAI = AK +Ninety: + AA = ZTAR + if AA >= 0.0E0 && ZR > 0.0E0 { + goto OneTen + } + if KODE == 2 { + goto OneHundred + } + + // OVERFLOW TEST. + if AA > (-ALIM) { + goto OneHundred + } + AA = -AA + 0.25E0*ALAZ + IFLAG = 1 + SFAC = TOL + if AA > ELIM { + goto TwoSeventy + } + +OneHundred: + // CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2. + MR = 1 + if ZI < 0.0E0 { + MR = -1 + } + ZTAR, ZTAI, FNU, KODE, MR, _, CYR, CYI, NN, RL, TOL, ELIM, ALIM = zacaiOrig(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, ELIM, ALIM) + if NN < 0 { + goto TwoEighty + } + NZ = NZ + NN + goto OneThirty + +OneTen: + if KODE == 2 { + goto OneTwenty + } + + // UNDERFLOW TEST. + if AA < ALIM { + goto OneTwenty + } + AA = -AA - 0.25E0*ALAZ + IFLAG = 2 + SFAC = 1.0E0 / TOL + if AA < (-ELIM) { + goto TwoTen + } +OneTwenty: + ZTAR, ZTAI, FNU, KODE, _, CYR, CYI, NZ, TOL, ELIM, ALIM = zbknuOrig(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, ALIM) + +OneThirty: + S1R = CYR[1] * COEF + S1I = CYI[1] * COEF + if IFLAG != 0 { + goto OneFifty + } + if ID == 1 { + goto OneFourty + } + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + return +OneFourty: + AIR = -(ZR*S1R - ZI*S1I) + AII = -(ZR*S1I + ZI*S1R) + return +OneFifty: + S1R = S1R * SFAC + S1I = S1I * SFAC + if ID == 1 { + goto OneSixty + } + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSixty: + STR = -(S1R*ZR - S1I*ZI) + S1I = -(S1R*ZI + S1I*ZR) + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSeventy: + AA = 1.0E+3 * dmach[1] + S1R = ZEROR + S1I = ZEROI + if ID == 1 { + goto OneNinety + } + if AZ <= AA { + goto OneEighty + } + S1R = C2 * ZR + S1I = C2 * ZI +OneEighty: + AIR = C1 - S1R + AII = -S1I + return +OneNinety: + AIR = -C2 + AII = 0.0E0 + AA = dsqrt(AA) + if AZ <= AA { + goto TwoHundred + } + S1R = 0.5E0 * (ZR*ZR - ZI*ZI) + S1I = ZR * ZI +TwoHundred: + AIR = AIR + C1*S1R + AII = AII + C1*S1I + return +TwoTen: + NZ = 1 + AIR = ZEROR + AII = ZEROI + return +TwoSeventy: + NZ = 0 + IERR = 2 + return +TwoEighty: + if NN == (-1) { + goto TwoSeventy + } + NZ = 0 + IERR = 5 + return +TwoSixty: + IERR = 4 + NZ = 0 + return +} + +// sbknu computes the k bessel function in the right half z plane. +func zbknuOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + /* Old dimension comment. + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) + */ + + // TODO(btracey): Find which of these are inputs/outputs/both and clean up + // the function call. + // YR and YI have length n (but n+1 with better indexing) + var AA, AK, ASCLE, A1, A2, BB, BK, CAZ, + CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR, + CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS, + FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI, + PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64 + + var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int + + var tmp complex128 + var CSSR, CSRR, BRY [4]float64 + var CYR, CYI [3]float64 + + KMAX = 30 + CZEROR = 0 + CZEROI = 0 + CONER = 1 + CONEI = 0 + CTWOR = 2 + R1 = 2 + + DPI = 3.14159265358979324E0 + RTHPI = 1.25331413731550025E0 + SPI = 1.90985931710274403E0 + HPI = 1.57079632679489662E0 + FPI = 1.89769999331517738E0 + TTH = 6.66666666666666666E-01 + + CC := [9]float64{math.NaN(), 5.77215664901532861E-01, -4.20026350340952355E-02, + -4.21977345555443367E-02, 7.21894324666309954E-03, + -2.15241674114950973E-04, -2.01348547807882387E-05, + 1.13302723198169588E-06, 6.11609510448141582E-09} + + CAZ = zabs(complex(ZR, ZI)) + CSCLR = 1.0E0 / TOL + CRSCR = TOL + CSSR[1] = CSCLR + CSSR[2] = 1.0E0 + CSSR[3] = CRSCR + CSRR[1] = CRSCR + CSRR[2] = 1.0E0 + CSRR[3] = CSCLR + BRY[1] = 1.0E+3 * dmach[1] / TOL + BRY[2] = 1.0E0 / BRY[1] + BRY[3] = dmach[2] + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0E0 / CAZ + STR = ZR * RCAZ + STI = -ZI * RCAZ + RZR = (STR + STR) * RCAZ + RZI = (STI + STI) * RCAZ + INU = int(float32(FNU + 0.5)) + DNU = FNU - float64(INU) + if dabs(DNU) == 0.5E0 { + goto OneTen + } + DNU2 = 0.0E0 + if dabs(DNU) > TOL { + DNU2 = DNU * DNU + } + if CAZ > R1 { + goto OneTen + } + + // SERIES FOR CABS(Z)<=R1. + FC = 1.0E0 + tmp = zlog(complex(RZR, RZI)) + SMUR = real(tmp) + SMUI = imag(tmp) + FMUR = SMUR * DNU + FMUI = SMUI * DNU + FMUR, FMUI, CSHR, CSHI, CCHR, CCHI = zshchOrig(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI) + if DNU == 0.0E0 { + goto Ten + } + FC = DNU * DPI + FC = FC / dsin(FC) + SMUR = CSHR / DNU + SMUI = CSHI / DNU +Ten: + A2 = 1.0E0 + DNU + + // GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU). + T2 = dexp(-dgamln(A2, IDUM)) + T1 = 1.0E0 / (T2 * FC) + if dabs(DNU) > 0.1E0 { + goto Forty + } + + // SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU). + AK = 1.0E0 + S = CC[1] + for K = 2; K <= 8; K++ { + AK = AK * DNU2 + TM = CC[K] * AK + S = S + TM + if dabs(TM) < TOL { + goto Thirty + } + } +Thirty: + G1 = -S + goto Fifty +Forty: + G1 = (T1 - T2) / (DNU + DNU) +Fifty: + G2 = (T1 + T2) * 0.5E0 + FR = FC * (CCHR*G1 + SMUR*G2) + FI = FC * (CCHI*G1 + SMUI*G2) + tmp = zexp(complex(FMUR, FMUI)) + STR = real(tmp) + STI = imag(tmp) + PR = 0.5E0 * STR / T2 + PI = 0.5E0 * STI / T2 + tmp = zdiv(complex(0.5, 0), complex(STR, STI)) + PTR = real(tmp) + PTI = imag(tmp) + QR = PTR / T1 + QI = PTI / T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0E0 + A1 = 1.0E0 + CKR = CONER + CKI = CONEI + BK = 1.0E0 - DNU2 + if INU > 0 || N > 1 { + goto Eighty + } + + // GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1. + if CAZ < TOL { + goto Seventy + } + tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI)) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Sixty: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Sixty + } +Seventy: + YR[1] = S1R + YI[1] = S1I + if KODED == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + tmp = zexp(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(S1R, S1I), complex(STR, STI)) + YR[1] = real(tmp) + YI[1] = imag(tmp) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE. +Eighty: + if CAZ < TOL { + goto OneHundred + } + tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI)) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Ninety: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Ninety + } +OneHundred: + KFLAG = 2 + A1 = FNU + 1.0E0 + AK = A1 * dabs(SMUR) + if AK > ALIM { + KFLAG = 3 + } + STR = CSSR[KFLAG] + P2R = S2R * STR + P2I = S2I * STR + tmp = zmlt(complex(P2R, P2I), complex(RZR, RZI)) + S2R = real(tmp) + S2I = imag(tmp) + S1R = S1R * STR + S1I = S1I * STR + if KODED == 1 { + goto TwoTen + } + tmp = zexp(complex(ZR, ZI)) + FR = real(tmp) + FI = imag(tmp) + tmp = zmlt(complex(S1R, S1I), complex(FR, FI)) + S1R = real(tmp) + S1I = imag(tmp) + tmp = zmlt(complex(S2R, S2I), complex(FR, FI)) + S2R = real(tmp) + S2I = imag(tmp) + goto TwoTen + + // IFLAG=0 MEANS NO UNDERFLOW OCCURRED + // IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH + // KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION +OneTen: + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zdiv(complex(RTHPI, CZEROI), complex(STR, STI)) + COEFR = real(tmp) + COEFI = imag(tmp) + KFLAG = 2 + if KODED == 2 { + goto OneTwenty + } + if ZR > ALIM { + goto TwoNinety + } + + STR = dexp(-ZR) * CSSR[KFLAG] + STI = -STR * dsin(ZI) + STR = STR * dcos(ZI) + tmp = zmlt(complex(COEFR, COEFI), complex(STR, STI)) + COEFR = real(tmp) + COEFI = imag(tmp) +OneTwenty: + if dabs(DNU) == 0.5E0 { + goto ThreeHundred + } + // MILLER ALGORITHM FOR CABS(Z)>R1. + AK = dcos(DPI * DNU) + AK = dabs(AK) + if AK == CZEROR { + goto ThreeHundred + } + FHS = dabs(0.25E0 - DNU2) + if FHS == CZEROR { + goto ThreeHundred + } + + // COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO + // DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON + // 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= + // TOL WHERE B IS THE BASE OF THE ARITHMETIC. + T1 = float64(imach[14] - 1) + T1 = T1 * dmach[5] * 3.321928094E0 + T1 = dmax(T1, 12.0E0) + T1 = dmin(T1, 60.0E0) + T2 = TTH*T1 - 6.0E0 + if ZR != 0.0E0 { + goto OneThirty + } + T1 = HPI + goto OneFourty +OneThirty: + T1 = datan(ZI / ZR) + T1 = dabs(T1) +OneFourty: + if T2 > CAZ { + goto OneSeventy + } + // FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2. + ETEST = AK / (DPI * CAZ * TOL) + FK = CONER + if ETEST < CONER { + goto OneEighty + } + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + for I = 1; I <= KMAX; I++ { + AK = FHS / FKS + CBR = CKR / (FK + CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = dabs(P2R) * FK + if ETEST < STR { + goto OneSixty + } + } + goto ThreeTen +OneSixty: + FK = FK + SPI*T1*dsqrt(T2/CAZ) + FHS = dabs(0.25 - DNU2) + goto OneEighty +OneSeventy: + // COMPUTE BACKWARD INDEX K FOR CABS(Z) 0 || N > 1 { + goto TwoHundred + } + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoHundred: + // COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING. + TM = zabs(complex(P2R, P2I)) + PTR = 1.0E0 / TM + P1R = P1R * PTR + P1I = P1I * PTR + P2R = P2R * PTR + P2I = -P2I * PTR + tmp = zmlt(complex(P1R, P1I), complex(P2R, P2I)) + PTR = real(tmp) + PTI = imag(tmp) + STR = DNU + 0.5E0 - PTR + STI = -PTI + tmp = zdiv(complex(STR, STI), complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + STR = STR + 1.0E0 + tmp = zmlt(complex(STR, STI), complex(S1R, S1I)) + S2R = real(tmp) + S2I = imag(tmp) + + // FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH + // SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +TwoTen: + STR = DNU + 1.0E0 + CKR = STR * RZR + CKI = STR * RZI + if N == 1 { + INU = INU - 1 + } + if INU > 0 { + goto TwoTwenty + } + if N > 1 { + goto TwoFifteen + } + S1R = S2R + S1I = S2I +TwoFifteen: + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoTwenty: + INUB = 1 + if IFLAG == 1 { + goto TwoSixtyOne + } +TwoTwentyFive: + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = INUB; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + if KFLAG >= 3 { + continue + } + P2R = S2R * P1R + P2I = S2I * P1R + STR = dabs(P2R) + STI = dabs(P2I) + P2M = dmax(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I +TwoFourty: + STR = CSRR[KFLAG] + YR[1] = S1R * STR + YI[1] = S1I * STR + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + YR[2] = S2R * STR + YI[2] = S2I * STR + if N == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = 2 +TwoFifty: + KK = KK + 1 + if KK > N { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = KK; I <= N; I++ { + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R * P1R + P2I = S2I * P1R + YR[I] = P2R + YI[I] = P2I + if KFLAG >= 3 { + continue + } + STR = dabs(P2R) + STI = dabs(P2I) + P2M = dmax(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW. +TwoSixtyOne: + HELIM = 0.5E0 * ELIM + ELM = dexp(-ELIM) + CELMR = ELM + ASCLE = BRY[1] + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + for I = 1; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = STR*CKR - STI*CKI + S1R + S2I = STI*CKR + STR*CKI + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + AS = zabs(complex(S2R, S2I)) + ALAS = dlog(AS) + P2R = -ZDR + ALAS + if P2R < (-ELIM) { + goto TwoSixtyThree + } + tmp = zlog(complex(S2R, S2I)) + STR = real(tmp) + STI = imag(tmp) + P2R = -ZDR + STR + P2I = -ZDI + STI + P2M = dexp(P2R) / TOL + P1R = P2M * dcos(P2I) + P1I = P2M * dsin(P2I) + P1R, P1I, NW, ASCLE, TOL = zuchkOrig(P1R, P1I, NW, ASCLE, TOL) + if NW != 0 { + goto TwoSixtyThree + } + J = 3 - J + CYR[J] = P1R + CYI[J] = P1I + if IC == (I - 1) { + goto TwoSixtyFour + } + IC = I + continue + TwoSixtyThree: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + if N != 1 { + goto TwoSeventy + } + S1R = S2R + S1I = S2I + goto TwoSeventy +TwoSixtyFour: + KFLAG = 1 + INUB = I + 1 + S2R = CYR[J] + S2I = CYI[J] + J = 3 - J + S1R = CYR[J] + S1I = CYI[J] + if INUB <= INU { + goto TwoTwentyFive + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I + goto TwoFourty +TwoSeventy: + YR[1] = S1R + YI[1] = S1I + if N == 1 { + goto TwoEighty + } + YR[2] = S2R + YI[2] = S2I +TwoEighty: + ASCLE = BRY[1] + ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM = zksclOrig(ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM) + INU = N - NZ + if INU <= 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 1 + S1R = YR[KK] + S1I = YI[KK] + YR[KK] = S1R * CSRR[1] + YI[KK] = S1I * CSRR[1] + if INU == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 2 + S2R = YR[KK] + S2I = YI[KK] + YR[KK] = S2R * CSRR[1] + YI[KK] = S2I * CSRR[1] + if INU == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + T2 = FNU + float64(float32(KK-1)) + CKR = T2 * RZR + CKI = T2 * RZI + KFLAG = 1 + goto TwoFifty +TwoNinety: + + // SCALE BY dexp(Z), IFLAG = 1 CASES. + + KODED = 2 + IFLAG = 1 + KFLAG = 2 + goto OneTwenty + + // FNU=HALF ODD INTEGER CASE, DNU=-0.5 +ThreeHundred: + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + goto TwoTen + +ThreeTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +func zksclOrig(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I, + S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64 + + var I, IC, KK, NN, NW int + var tmp complex128 + var CYR, CYI [3]float64 + // DIMENSION YR(N), YI(N), CYR(2), CYI(2) + ZEROR = 0 + ZEROI = 0 + NZ = 0 + IC = 0 + NN = min0(2, N) + for I = 1; I <= NN; I++ { + S1R = YR[I] + S1I = YI[I] + CYR[I] = S1R + CYI[I] = S1I + AS = zabs(complex(S1R, S1I)) + ACS = -ZRR + dlog(AS) + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + continue + } + + tmp = zlog(complex(S1R, S1I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = dexp(CSR) / TOL + CSR = STR * dcos(CSI) + CSI = STR * dsin(CSI) + CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL) + if NW != 0 { + continue + } + YR[I] = CSR + YI[I] = CSI + IC = I + NZ = NZ - 1 + } + if N == 1 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if IC > 1 { + goto Twenty + } + YR[1] = ZEROR + YI[1] = ZEROI + NZ = 2 +Twenty: + if N == 2 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if NZ == 0 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + FN = FNU + 1.0E0 + CKR = FN * RZR + CKI = FN * RZI + S1R = CYR[1] + S1I = CYI[1] + S2R = CYR[2] + S2I = CYI[2] + HELIM = 0.5E0 * ELIM + ELM = dexp(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI + + // FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF + // S2 GETS LARGER THAN EXP(ELIM/2) + for I = 3; I <= N; I++ { + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = zabs(complex(S2R, S2I)) + ALAS = dlog(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + goto TwentyFive + } + tmp = zlog(complex(S2R, S2I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = dexp(CSR) / TOL + CSR = STR * dcos(CSI) + CSI = STR * dsin(CSI) + CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL) + if NW != 0 { + goto TwentyFive + } + YR[I] = CSR + YI[I] = CSI + NZ = NZ - 1 + if IC == KK-1 { + goto Forty + } + IC = KK + continue + TwentyFive: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + NZ = N + if IC == N { + NZ = N - 1 + } + goto FourtyFive +Forty: + NZ = KK - 2 +FourtyFive: + for I = 1; I <= NZ; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +// Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN +// EXP(-ALIM)=ASCLE=1.0E+3*dmach[1)/TOL. THE TEST IS MADE TO SEE +// if THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW +// WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED +// if THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE +// OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE +// ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED. +func zuchkOrig(YR, YI float64, NZ int, ASCLE, TOL float64) (YRout, YIout float64, NZout int, ASCLEout, TOLout float64) { + var SS, ST, WR, WI float64 + NZ = 0 + WR = dabs(YR) + WI = dabs(YI) + ST = dmin(WR, WI) + if ST > ASCLE { + return YR, YI, NZ, ASCLE, TOL + } + SS = dmax(WR, WI) + ST = ST / TOL + if SS < ST { + NZ = 1 + } + return YR, YI, NZ, ASCLE, TOL +} + +// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +// +// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +// MP=PI*MR*CMPLX(0.0,1.0) +// +// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON +// IS CALLED FROM ZAIRY. +func zacaiOrig(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI, + SGN, YY, ZNR, ZNI float64 + var INU, IUF, NN, NW int + CYR := []float64{math.NaN(), 0, 0} + CYI := []float64{math.NaN(), 0, 0} + + PI = math.Pi + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = zabs(complex(ZR, ZI)) + NN = N + DFNU = FNU + float64(float32(N-1)) + if AZ <= 2.0E0 { + goto Ten + } + if AZ*AZ*0.25 > DFNU+1.0E0 { + goto Twenty + } +Ten: + // POWER SERIES FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM = zseriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM) + goto Forty +Twenty: + if AZ < RL { + goto Thirty + } + // ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM = zasyiOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM) + if NW < 0 { + goto Eighty + } + goto Forty +Thirty: + // MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL = zmlriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + if NW < 0 { + goto Eighty + } +Forty: + // ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION. + ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = zbknuOrig(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + if NW != 0 { + goto Eighty + } + FMR = float64(float32(MR)) + SGN = -math.Copysign(PI, FMR) + CSGNR = 0.0E0 + CSGNI = SGN + if KODE == 1 { + goto Fifty + } + YY = -ZNI + CSGNR = -CSGNI * dsin(YY) + CSGNI = CSGNI * dcos(YY) +Fifty: + // CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE + // WHEN FNU IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * SGN + CSPNR = dcos(ARG) + CSPNI = dsin(ARG) + if INU%2 == 0 { + goto Sixty + } + CSPNR = -CSPNR + CSPNI = -CSPNI +Sixty: + C1R = CYR[1] + C1I = CYI[1] + C2R = YR[1] + C2I = YI[1] + if KODE == 1 { + goto Seventy + } + IUF = 0 + ASCLE = 1.0E+3 * dmach[1] / TOL + ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF = zs1s2Orig(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW +Seventy: + YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +Eighty: + NZ = -1 + if NW == -2 { + NZ = -2 + } + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return. +// NZ<0 INDICATES AN OVERFLOW ON KODE=1. +func zasyiOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL, + AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I, + P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + S2R, TZI, TZR, ZEROI, ZEROR float64 + + var I, IB, IL, INU, J, JL, K, KODED, M, NN int + var tmp complex128 + + PI = math.Pi + RTPI = 0.159154943091895336E0 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + ARM = 1.0E3 * dmach[1] + RTR1 = dsqrt(ARM) + IL = min0(2, N) + DFNU = FNU + float64(float32(N-IL)) + + // OVERFLOW TEST + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + AK1R = RTPI * STR * RAZ + AK1I = RTPI * STI * RAZ + tmp = zsqrt(complex(AK1R, AK1I)) + AK1R = real(tmp) + AK1I = imag(tmp) + CZR = ZR + CZI = ZI + if KODE != 2 { + goto Ten + } + CZR = ZEROR + CZI = ZI +Ten: + if dabs(CZR) > ELIM { + goto OneHundred + } + DNU2 = DFNU + DFNU + KODED = 1 + if (dabs(CZR) > ALIM) && (N > 2) { + goto Twenty + } + KODED = 0 + tmp = zexp(complex(CZR, CZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(AK1R, AK1I), complex(STR, STI)) + AK1R = real(tmp) + AK1I = imag(tmp) +Twenty: + FDN = 0.0E0 + if DNU2 > RTR1 { + FDN = DNU2 * DNU2 + } + EZR = ZR * 8.0E0 + EZI = ZI * 8.0E0 + + // WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE + // FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE + // EXPANSION FOR THE IMAGINARY PART. + AEZ = 8.0E0 * AZ + S = TOL / AEZ + JL = int(float32(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + if ZI == 0.0E0 { + goto Thirty + } + + // CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF + // SIGNIFICANCE WHEN FNU OR N IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * PI + INU = INU + N - IL + AK = -dsin(ARG) + BK = dcos(ARG) + if ZI < 0.0E0 { + BK = -BK + } + P1R = AK + P1I = BK + if INU%2 == 0 { + goto Thirty + } + P1R = -P1R + P1I = -P1I +Thirty: + for K = 1; K <= IL; K++ { + SQK = FDN - 1.0E0 + ATOL = S * dabs(SQK) + SGN = 1.0E0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0E0 + AA = 1.0E0 + BB = AEZ + DKR = EZR + DKI = EZI + // TODO(btracey): This loop is executed tens of thousands of times. Why? + // is that really necessary? + for J = 1; J <= JL; J++ { + tmp = zdiv(complex(CKR, CKI), complex(DKR, DKI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * SQK + CKI = STI * SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA * dabs(SQK) / BB + BB = BB + AEZ + AK = AK + 8.0E0 + SQK = SQK - AK + if AA <= ATOL { + goto Fifty + } + } + goto OneTen + Fifty: + S2R = CS1R + S2I = CS1I + if ZR+ZR >= ELIM { + goto Sixty + } + TZR = ZR + ZR + TZI = ZI + ZI + tmp = zexp(complex(-TZR, -TZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(STR, STI), complex(P1R, P1I)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(STR, STI), complex(CS2R, CS2I)) + STR = real(tmp) + STI = imag(tmp) + S2R = S2R + STR + S2I = S2I + STI + Sixty: + FDN = FDN + 8.0E0*DFNU + 4.0E0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR[M] = S2R*AK1R - S2I*AK1I + YI[M] = S2R*AK1I + S2I*AK1R + } + if N <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + NN = N + K = NN - 2 + AK = float64(float32(K)) + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + IB = 3 + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + if KODED == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + tmp = zexp(complex(CZR, CZI)) + CKR = real(tmp) + CKI = imag(tmp) + for I = 1; I <= NN; I++ { + STR = YR[I]*CKR - YI[I]*CKI + YI[I] = YR[I]*CKI + YI[I]*CKR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneHundred: + NZ = -1 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE +// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +func zmlriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I, + P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + SUMR, TFNF, TST, ZEROI, ZEROR float64 + var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int + var tmp complex128 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + SCLE = dmach[1] / TOL + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + IAZ = int(float32(AZ)) + IFNU = int(float32(FNU)) + INU = IFNU + N - 1 + AT = float64(float32(IAZ)) + 1.0E0 + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT + 1.0E0) * RAZ + RHO = ACK + dsqrt(ACK*ACK-1.0E0) + RHO2 = RHO * RHO + TST = (RHO2 + RHO2) / ((RHO2 - 1.0E0) * (RHO - 1.0E0)) + TST = TST / TOL + + // COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES. + //fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK) + AK = AT + for I = 1; I <= 80; I++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKI*PTR + CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = zabs(complex(P2R, P2I)) + if AP > TST*AK*AK { + goto Twenty + } + AK = AK + 1.0E0 + } + goto OneTen +Twenty: + I = I + 1 + K = 0 + if INU < IAZ { + goto Forty + } + // COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS. + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = float64(float32(INU)) + 1.0E0 + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + ACK = AT * RAZ + TST = dsqrt(ACK / TOL) + ITIME = 1 + for K = 1; K <= 80; K++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKR*PTI + CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = zabs(complex(P2R, P2I)) + if AP < TST { + continue + } + if ITIME == 2 { + goto Forty + } + ACK = zabs(complex(CKR, CKI)) + FLAM = ACK + dsqrt(ACK*ACK-1.0E0) + FKAP = AP / zabs(complex(P1R, P1I)) + RHO = dmin(FLAM, FKAP) + TST = TST * dsqrt(RHO/(RHO*RHO-1.0E0)) + ITIME = 2 + } + goto OneTen +Forty: + // BACKWARD RECURRENCE AND SUM NORMALIZING RELATION. + K = K + 1 + KK = max0(I+IAZ, K+INU) + FKK = float64(float32(KK)) + P1R = ZEROR + P1I = ZEROI + + // SCALE P2 AND SUM BY SCLE. + P2R = SCLE + P2I = ZEROI + FNF = FNU - float64(float32(IFNU)) + TFNF = FNF + FNF + BK = dgamln(FKK+TFNF+1.0E0, IDUM) - dgamln(FKK+1.0E0, IDUM) - dgamln(TFNF+1.0E0, IDUM) + BK = dexp(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + for I = 1; I <= KM; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } + YR[N] = P2R + YI[N] = P2I + if N == 1 { + goto Seventy + } + for I = 2; I <= N; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + M = N - I + 1 + YR[M] = P2R + YI[M] = P2I + } +Seventy: + if IFNU <= 0 { + goto Ninety + } + for I = 1; I <= IFNU; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } +Ninety: + PTR = ZR + PTI = ZI + if KODE == 2 { + PTR = ZEROR + } + tmp = zlog(complex(RZR, RZI)) + STR = real(tmp) + STI = imag(tmp) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = dgamln(1.0E0+FNF, IDUM) + PTR = P1R - AP + PTI = P1I + + // THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW + // IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES. + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = zabs(complex(P2R, P2I)) + P1R = 1.0E0 / AP + tmp = zexp(complex(PTR, PTI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * P1R + CKI = STI * P1R + PTR = P2R * P1R + PTI = -P2I * P1R + tmp = zmlt(complex(CKR, CKI), complex(PTR, PTI)) + CNORMR = real(tmp) + CNORMI = imag(tmp) + for I = 1; I <= N; I++ { + STR = YR[I]*CNORMR - YI[I]*CNORMI + YI[I] = YR[I]*CNORMI + YI[I]*CNORMR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} + +// ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)<=2*SQRT(FNU+1). NZ=0 IS A NORMAL return. +// NZ>0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO +// DUE TO UNDERFLOW. NZ<0 MEANS UNDERFLOW OCCURRED, BUT THE +// CONDITION CABS(Z)<=2*SQRT(FNU+1) WAS VIOLATED AND THE +// COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ). +func zseriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + var AA, ACZ, AK, AK1I, AK1R, ARM, ASCLE, ATOL, + AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU, + FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI, + STR, S1I, S1R, S2I, S2R, ZEROI, ZEROR float64 + var I, IB, IDUM, IFLAG, IL, K, L, M, NN, NW int + var WR, WI [3]float64 + var tmp complex128 + + CONER = 1.0 + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + if AZ == 0.0E0 { + goto OneSixty + } + // TODO(btracey) + // The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran + // this is interpreted as one to the power of +3*D1MACH(1). While it is possible + // this was intentional, it seems unlikely. + //ARM = 1.0E0 + 3*dmach[1] + //math.Pow(1, 3*dmach[1]) + ARM = 1000 * dmach[1] + RTR1 = dsqrt(ARM) + CRSCR = 1.0E0 + IFLAG = 0 + if AZ < ARM { + goto OneFifty + } + HZR = 0.5E0 * ZR + HZI = 0.5E0 * ZI + CZR = ZEROR + CZI = ZEROI + if AZ <= RTR1 { + goto Ten + } + tmp = zmlt(complex(HZR, HZI), complex(HZR, HZI)) + CZR = real(tmp) + CZI = imag(tmp) +Ten: + ACZ = zabs(complex(CZR, CZI)) + NN = N + tmp = zlog(complex(HZR, HZI)) + CKR = real(tmp) + CKI = imag(tmp) +Twenty: + DFNU = FNU + float64(float32(NN-1)) + FNUP = DFNU + 1.0E0 + + // UNDERFLOW TEST. + AK1R = CKR * DFNU + AK1I = CKI * DFNU + AK = dgamln(FNUP, IDUM) + AK1R = AK1R - AK + if KODE == 2 { + AK1R = AK1R - ZR + } + if AK1R > (-ELIM) { + goto Forty + } +Thirty: + NZ = NZ + 1 + YR[NN] = ZEROR + YI[NN] = ZEROI + if ACZ > DFNU { + goto OneNinety + } + NN = NN - 1 + if NN == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + goto Twenty +Forty: + if AK1R > (-ALIM) { + goto Fifty + } + IFLAG = 1 + SS = 1.0E0 / TOL + CRSCR = TOL + ASCLE = ARM * SS +Fifty: + AA = dexp(AK1R) + if IFLAG == 1 { + AA = AA * SS + } + COEFR = AA * dcos(AK1I) + COEFI = AA * dsin(AK1I) + ATOL = TOL * ACZ / FNUP + IL = min0(2, NN) + for I = 1; I <= IL; I++ { + DFNU = FNU + float64(float32(NN-I)) + FNUP = DFNU + 1.0E0 + S1R = CONER + S1I = CONEI + if ACZ < TOL*FNUP { + goto Seventy + } + AK1R = CONER + AK1I = CONEI + AK = FNUP + 2.0E0 + S = FNUP + AA = 2.0E0 + Sixty: + RS = 1.0E0 / S + STR = AK1R*CZR - AK1I*CZI + STI = AK1R*CZI + AK1I*CZR + AK1R = STR * RS + AK1I = STI * RS + S1R = S1R + AK1R + S1I = S1I + AK1I + S = S + AK + AK = AK + 2.0E0 + AA = AA * ACZ * RS + if AA > ATOL { + goto Sixty + } + Seventy: + S2R = S1R*COEFR - S1I*COEFI + S2I = S1R*COEFI + S1I*COEFR + WR[I] = S2R + WI[I] = S2I + if IFLAG == 0 { + goto Eighty + } + S2R, S2I, NW, ASCLE, TOL = zuchkOrig(S2R, S2I, NW, ASCLE, TOL) + if NW != 0 { + goto Thirty + } + Eighty: + M = NN - I + 1 + YR[M] = S2R * CRSCR + YI[M] = S2I * CRSCR + if I == IL { + continue + } + tmp = zdiv(complex(COEFR, COEFI), complex(HZR, HZI)) + STR = real(tmp) + STI = imag(tmp) + COEFR = STR * DFNU + COEFI = STI * DFNU + } + if NN <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + K = NN - 2 + AK = float64(float32(K)) + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + if IFLAG == 1 { + goto OneTwenty + } + IB = 3 +OneHundred: + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // RECUR BACKWARD WITH SCALED VALUES. +OneTwenty: + // EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE + // UNDERFLOW LIMIT = ASCLE = dmach[1)*SS*1.0D+3. + S1R = WR[1] + S1I = WI[1] + S2R = WR[2] + S2I = WI[2] + for L = 3; L <= NN; L++ { + CKR = S2R + CKI = S2I + S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI) + S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR) + S1R = CKR + S1I = CKI + CKR = S2R * CRSCR + CKI = S2I * CRSCR + YR[K] = CKR + YI[K] = CKI + AK = AK - 1.0E0 + K = K - 1 + if zabs(complex(CKR, CKI)) > ASCLE { + goto OneFourty + } + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +OneFourty: + IB = L + 1 + if IB > NN { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + goto OneHundred +OneFifty: + NZ = N + if FNU == 0.0E0 { + NZ = NZ - 1 + } +OneSixty: + YR[1] = ZEROR + YI[1] = ZEROI + if FNU != 0.0E0 { + goto OneSeventy + } + YR[1] = CONER + YI[1] = CONEI +OneSeventy: + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + for I = 2; I <= N; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // return WITH NZ<0 if CABS(Z*Z/4)>FNU+N-NZ-1 COMPLETE + // THE CALCULATION IN CBINU WITH N=N-IABS(NZ) + +OneNinety: + NZ = -NZ + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE +// ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON- +// TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION. +// ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF +// MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER +// OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE +// PRECISION ABOVE THE UNDERFLOW LIMIT. +func zs1s2Orig(ZRR, ZRI, S1R, S1I, S2R, S2I float64, NZ int, ASCLE, ALIM float64, IUF int) ( + ZRRout, ZRIout, S1Rout, S1Iout, S2Rout, S2Iout float64, NZout int, ASCLEout, ALIMout float64, IUFout int) { + var AA, ALN, AS1, AS2, C1I, C1R, S1DI, S1DR, ZEROI, ZEROR float64 + var tmp complex128 + + ZEROR = 0 + ZEROI = 0 + NZ = 0 + AS1 = zabs(complex(S1R, S1I)) + AS2 = zabs(complex(S2R, S2I)) + if S1R == 0.0E0 && S1I == 0.0E0 { + goto Ten + } + if AS1 == 0.0E0 { + goto Ten + } + ALN = -ZRR - ZRR + dlog(AS1) + S1DR = S1R + S1DI = S1I + S1R = ZEROR + S1I = ZEROI + AS1 = ZEROR + if ALN < (-ALIM) { + goto Ten + } + tmp = zlog(complex(S1DR, S1DI)) + C1R = real(tmp) + C1I = imag(tmp) + + C1R = C1R - ZRR - ZRR + C1I = C1I - ZRI - ZRI + tmp = zexp(complex(C1R, C1I)) + S1R = real(tmp) + S1I = imag(tmp) + AS1 = zabs(complex(S1R, S1I)) + IUF = IUF + 1 +Ten: + AA = dmax(AS1, AS2) + if AA > ASCLE { + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF + } + S1R = ZEROR + S1I = ZEROI + S2R = ZEROR + S2I = ZEROI + NZ = 1 + IUF = 0 + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF +} + +// ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+iY) AND +// CCH=COSH(X+I*Y), WHERE I**2=-1. +// TODO(btracey): use cmplx.Sinh and cmplx.Cosh. +func zshchOrig(ZR, ZI, CSHR, CSHI, CCHR, CCHI float64) (ZRout, ZIout, CSHRout, CSHIout, CCHRout, CCHIout float64) { + var CH, CN, SH, SN float64 + SH = math.Sinh(ZR) + CH = math.Cosh(ZR) + SN = dsin(ZI) + CN = dcos(ZI) + CSHR = SH * CN + CSHI = CH * SN + CCHR = CH * CN + CCHI = SH * SN + return ZR, ZI, CSHR, CSHI, CCHR, CCHI +} + +func dmax(a, b float64) float64 { + return math.Max(a, b) +} + +func dmin(a, b float64) float64 { + return math.Min(a, b) +} + +func dabs(a float64) float64 { + return math.Abs(a) +} + +func datan(a float64) float64 { + return math.Atan(a) +} + +func dtan(a float64) float64 { + return math.Tan(a) +} + +func dlog(a float64) float64 { + return math.Log(a) +} + +func dsin(a float64) float64 { + return math.Sin(a) +} + +func dcos(a float64) float64 { + return math.Cos(a) +} + +func dexp(a float64) float64 { + return math.Exp(a) +} + +func dsqrt(a float64) float64 { + return math.Sqrt(a) +} + +func zmlt(a, b complex128) complex128 { + return a * b +} + +func zdiv(a, b complex128) complex128 { + return a / b +} + +func zabs(a complex128) float64 { + return cmplx.Abs(a) +} + +func zsqrt(a complex128) complex128 { + return cmplx.Sqrt(a) +} + +func zexp(a complex128) complex128 { + return cmplx.Exp(a) +} + +func zlog(a complex128) complex128 { + return cmplx.Log(a) +} + +// Zshch computes the hyperbolic sin and cosine of the input z. +func Zshch(z complex128) (sinh, cosh complex128) { + return cmplx.Sinh(z), cmplx.Cosh(z) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go new file mode 100644 index 00000000..22d26e87 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go @@ -0,0 +1,28 @@ +// Copyright ©2016 The gonum 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 cephes + +import "math" + +/* +Additional copyright information: + +Code in this package is adapted from the Cephes library (http://www.netlib.org/cephes/). +There is no explicit licence on Netlib, but the author has agreed to a BSD release. +See https://github.com/deepmind/torch-cephes/blob/master/LICENSE.txt and +https://lists.debian.org/debian-legal/2004/12/msg00295.html +*/ + +var ( + badParamOutOfBounds = "cephes: parameter out of bounds" + badParamFunctionSingularity = "cephes: function singularity" +) + +const ( + machEp = 1.0 / (1 << 53) + maxLog = 1024 * math.Ln2 + minLog = -1075 * math.Ln2 + maxIter = 2000 +) diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go new file mode 100644 index 00000000..4fe18ba6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 cephes implements functions originally in the Netlib code by Stephen Mosher. +package cephes // import "gonum.org/v1/gonum/mathext/internal/cephes" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go new file mode 100644 index 00000000..0a9732e5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go @@ -0,0 +1,311 @@ +// Derived from SciPy's special/cephes/igam.c and special/cephes/igam.h +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.h +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1985, ©1987 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +const ( + igamDimK = 25 + igamDimN = 25 + igam = 1 + igamC = 0 + igamSmall = 20 + igamLarge = 200 + igamSmallRatio = 0.3 + igamLargeRatio = 4.5 +) + +var igamCoefs = [igamDimK][igamDimN]float64{ + {-3.3333333333333333e-1, 8.3333333333333333e-2, -1.4814814814814815e-2, 1.1574074074074074e-3, 3.527336860670194e-4, -1.7875514403292181e-4, 3.9192631785224378e-5, -2.1854485106799922e-6, -1.85406221071516e-6, 8.296711340953086e-7, -1.7665952736826079e-7, 6.7078535434014986e-9, 1.0261809784240308e-8, -4.3820360184533532e-9, 9.1476995822367902e-10, -2.551419399494625e-11, -5.8307721325504251e-11, 2.4361948020667416e-11, -5.0276692801141756e-12, 1.1004392031956135e-13, 3.3717632624009854e-13, -1.3923887224181621e-13, 2.8534893807047443e-14, -5.1391118342425726e-16, -1.9752288294349443e-15}, + {-1.8518518518518519e-3, -3.4722222222222222e-3, 2.6455026455026455e-3, -9.9022633744855967e-4, 2.0576131687242798e-4, -4.0187757201646091e-7, -1.8098550334489978e-5, 7.6491609160811101e-6, -1.6120900894563446e-6, 4.6471278028074343e-9, 1.378633446915721e-7, -5.752545603517705e-8, 1.1951628599778147e-8, -1.7543241719747648e-11, -1.0091543710600413e-9, 4.1627929918425826e-10, -8.5639070264929806e-11, 6.0672151016047586e-14, 7.1624989648114854e-12, -2.9331866437714371e-12, 5.9966963656836887e-13, -2.1671786527323314e-16, -4.9783399723692616e-14, 2.0291628823713425e-14, -4.13125571381061e-15}, + {4.1335978835978836e-3, -2.6813271604938272e-3, 7.7160493827160494e-4, 2.0093878600823045e-6, -1.0736653226365161e-4, 5.2923448829120125e-5, -1.2760635188618728e-5, 3.4235787340961381e-8, 1.3721957309062933e-6, -6.298992138380055e-7, 1.4280614206064242e-7, -2.0477098421990866e-10, -1.4092529910867521e-8, 6.228974084922022e-9, -1.3670488396617113e-9, 9.4283561590146782e-13, 1.2872252400089318e-10, -5.5645956134363321e-11, 1.1975935546366981e-11, -4.1689782251838635e-15, -1.0940640427884594e-12, 4.6622399463901357e-13, -9.905105763906906e-14, 1.8931876768373515e-17, 8.8592218725911273e-15}, + {6.4943415637860082e-4, 2.2947209362139918e-4, -4.6918949439525571e-4, 2.6772063206283885e-4, -7.5618016718839764e-5, -2.3965051138672967e-7, 1.1082654115347302e-5, -5.6749528269915966e-6, 1.4230900732435884e-6, -2.7861080291528142e-11, -1.6958404091930277e-7, 8.0994649053880824e-8, -1.9111168485973654e-8, 2.3928620439808118e-12, 2.0620131815488798e-9, -9.4604966618551322e-10, 2.1541049775774908e-10, -1.388823336813903e-14, -2.1894761681963939e-11, 9.7909989511716851e-12, -2.1782191880180962e-12, 6.2088195734079014e-17, 2.126978363279737e-13, -9.3446887915174333e-14, 2.0453671226782849e-14}, + {-8.618882909167117e-4, 7.8403922172006663e-4, -2.9907248030319018e-4, -1.4638452578843418e-6, 6.6414982154651222e-5, -3.9683650471794347e-5, 1.1375726970678419e-5, 2.5074972262375328e-10, -1.6954149536558306e-6, 8.9075075322053097e-7, -2.2929348340008049e-7, 2.956794137544049e-11, 2.8865829742708784e-8, -1.4189739437803219e-8, 3.4463580499464897e-9, -2.3024517174528067e-13, -3.9409233028046405e-10, 1.8602338968504502e-10, -4.356323005056618e-11, 1.2786001016296231e-15, 4.6792750266579195e-12, -2.1492464706134829e-12, 4.9088156148096522e-13, -6.3385914848915603e-18, -5.0453320690800944e-14}, + {-3.3679855336635815e-4, -6.9728137583658578e-5, 2.7727532449593921e-4, -1.9932570516188848e-4, 6.7977804779372078e-5, 1.419062920643967e-7, -1.3594048189768693e-5, 8.0184702563342015e-6, -2.2914811765080952e-6, -3.252473551298454e-10, 3.4652846491085265e-7, -1.8447187191171343e-7, 4.8240967037894181e-8, -1.7989466721743515e-14, -6.3061945000135234e-9, 3.1624176287745679e-9, -7.8409242536974293e-10, 5.1926791652540407e-15, 9.3589442423067836e-11, -4.5134262161632782e-11, 1.0799129993116827e-11, -3.661886712685252e-17, -1.210902069055155e-12, 5.6807435849905643e-13, -1.3249659916340829e-13}, + {5.3130793646399222e-4, -5.9216643735369388e-4, 2.7087820967180448e-4, 7.9023532326603279e-7, -8.1539693675619688e-5, 5.6116827531062497e-5, -1.8329116582843376e-5, -3.0796134506033048e-9, 3.4651553688036091e-6, -2.0291327396058604e-6, 5.7887928631490037e-7, 2.338630673826657e-13, -8.8286007463304835e-8, 4.7435958880408128e-8, -1.2545415020710382e-8, 8.6496488580102925e-14, 1.6846058979264063e-9, -8.5754928235775947e-10, 2.1598224929232125e-10, -7.6132305204761539e-16, -2.6639822008536144e-11, 1.3065700536611057e-11, -3.1799163902367977e-12, 4.7109761213674315e-18, 3.6902800842763467e-13}, + {3.4436760689237767e-4, 5.1717909082605922e-5, -3.3493161081142236e-4, 2.812695154763237e-4, -1.0976582244684731e-4, -1.2741009095484485e-7, 2.7744451511563644e-5, -1.8263488805711333e-5, 5.7876949497350524e-6, 4.9387589339362704e-10, -1.0595367014026043e-6, 6.1667143761104075e-7, -1.7562973359060462e-7, -1.2974473287015439e-12, 2.695423606288966e-8, -1.4578352908731271e-8, 3.887645959386175e-9, -3.8810022510194121e-17, -5.3279941738772867e-10, 2.7437977643314845e-10, -6.9957960920705679e-11, 2.5899863874868481e-17, 8.8566890996696381e-12, -4.403168815871311e-12, 1.0865561947091654e-12}, + {-6.5262391859530942e-4, 8.3949872067208728e-4, -4.3829709854172101e-4, -6.969091458420552e-7, 1.6644846642067548e-4, -1.2783517679769219e-4, 4.6299532636913043e-5, 4.5579098679227077e-9, -1.0595271125805195e-5, 6.7833429048651666e-6, -2.1075476666258804e-6, -1.7213731432817145e-11, 3.7735877416110979e-7, -2.1867506700122867e-7, 6.2202288040189269e-8, 6.5977038267330006e-16, -9.5903864974256858e-9, 5.2132144922808078e-9, -1.3991589583935709e-9, 5.382058999060575e-16, 1.9484714275467745e-10, -1.0127287556389682e-10, 2.6077347197254926e-11, -5.0904186999932993e-18, -3.3721464474854592e-12}, + {-5.9676129019274625e-4, -7.2048954160200106e-5, 6.7823088376673284e-4, -6.4014752602627585e-4, 2.7750107634328704e-4, 1.8197008380465151e-7, -8.4795071170685032e-5, 6.105192082501531e-5, -2.1073920183404862e-5, -8.8585890141255994e-10, 4.5284535953805377e-6, -2.8427815022504408e-6, 8.7082341778646412e-7, 3.6886101871706965e-12, -1.5344695190702061e-7, 8.862466778790695e-8, -2.5184812301826817e-8, -1.0225912098215092e-14, 3.8969470758154777e-9, -2.1267304792235635e-9, 5.7370135528051385e-10, -1.887749850169741e-19, -8.0931538694657866e-11, 4.2382723283449199e-11, -1.1002224534207726e-11}, + {1.3324454494800656e-3, -1.9144384985654775e-3, 1.1089369134596637e-3, 9.932404122642299e-7, -5.0874501293093199e-4, 4.2735056665392884e-4, -1.6858853767910799e-4, -8.1301893922784998e-9, 4.5284402370562147e-5, -3.127053674781734e-5, 1.044986828530338e-5, 4.8435226265680926e-11, -2.1482565873456258e-6, 1.329369701097492e-6, -4.0295693092101029e-7, -1.7567877666323291e-13, 7.0145043163668257e-8, -4.040787734999483e-8, 1.1474026743371963e-8, 3.9642746853563325e-18, -1.7804938269892714e-9, 9.7480262548731646e-10, -2.6405338676507616e-10, 5.794875163403742e-18, 3.7647749553543836e-11}, + {1.579727660730835e-3, 1.6251626278391582e-4, -2.0633421035543276e-3, 2.1389686185689098e-3, -1.0108559391263003e-3, -3.9912705529919201e-7, 3.6235025084764691e-4, -2.8143901463712154e-4, 1.0449513336495887e-4, 2.1211418491830297e-9, -2.5779417251947842e-5, 1.7281818956040463e-5, -5.6413773872904282e-6, -1.1024320105776174e-11, 1.1223224418895175e-6, -6.8693396379526735e-7, 2.0653236975414887e-7, 4.6714772409838506e-14, -3.5609886164949055e-8, 2.0470855345905963e-8, -5.8091738633283358e-9, -1.332821287582869e-16, 9.0354604391335133e-10, -4.9598782517330834e-10, 1.3481607129399749e-10}, + {-4.0725121195140166e-3, 6.4033628338080698e-3, -4.0410161081676618e-3, -2.183732802866233e-6, 2.1740441801254639e-3, -1.9700440518418892e-3, 8.3595469747962458e-4, 1.9445447567109655e-8, -2.5779387120421696e-4, 1.9009987368139304e-4, -6.7696499937438965e-5, -1.4440629666426572e-10, 1.5712512518742269e-5, -1.0304008744776893e-5, 3.304517767401387e-6, 7.9829760242325709e-13, -6.4097794149313004e-7, 3.8894624761300056e-7, -1.1618347644948869e-7, -2.816808630596451e-15, 1.9878012911297093e-8, -1.1407719956357511e-8, 3.2355857064185555e-9, 4.1759468293455945e-20, -5.0423112718105824e-10}, + {-5.9475779383993003e-3, -5.4016476789260452e-4, 8.7910413550767898e-3, -9.8576315587856125e-3, 5.0134695031021538e-3, 1.2807521786221875e-6, -2.0626019342754683e-3, 1.7109128573523058e-3, -6.7695312714133799e-4, -6.9011545676562133e-9, 1.8855128143995902e-4, -1.3395215663491969e-4, 4.6263183033528039e-5, 4.0034230613321351e-11, -1.0255652921494033e-5, 6.612086372797651e-6, -2.0913022027253008e-6, -2.0951775649603837e-13, 3.9756029041993247e-7, -2.3956211978815887e-7, 7.1182883382145864e-8, 8.925574873053455e-16, -1.2101547235064676e-8, 6.9350618248334386e-9, -1.9661464453856102e-9}, + {1.7402027787522711e-2, -2.9527880945699121e-2, 2.0045875571402799e-2, 7.0289515966903407e-6, -1.2375421071343148e-2, 1.1976293444235254e-2, -5.4156038466518525e-3, -6.3290893396418616e-8, 1.8855118129005065e-3, -1.473473274825001e-3, 5.5515810097708387e-4, 5.2406834412550662e-10, -1.4357913535784836e-4, 9.9181293224943297e-5, -3.3460834749478311e-5, -3.5755837291098993e-12, 7.1560851960630076e-6, -4.5516802628155526e-6, 1.4236576649271475e-6, 1.8803149082089664e-14, -2.6623403898929211e-7, 1.5950642189595716e-7, -4.7187514673841102e-8, -6.5107872958755177e-17, 7.9795091026746235e-9}, + {3.0249124160905891e-2, 2.4817436002649977e-3, -4.9939134373457022e-2, 5.9915643009307869e-2, -3.2483207601623391e-2, -5.7212968652103441e-6, 1.5085251778569354e-2, -1.3261324005088445e-2, 5.5515262632426148e-3, 3.0263182257030016e-8, -1.7229548406756723e-3, 1.2893570099929637e-3, -4.6845138348319876e-4, -1.830259937893045e-10, 1.1449739014822654e-4, -7.7378565221244477e-5, 2.5625836246985201e-5, 1.0766165333192814e-12, -5.3246809282422621e-6, 3.349634863064464e-6, -1.0381253128684018e-6, -5.608909920621128e-15, 1.9150821930676591e-7, -1.1418365800203486e-7, 3.3654425209171788e-8}, + {-9.9051020880159045e-2, 1.7954011706123486e-1, -1.2989606383463778e-1, -3.1478872752284357e-5, 9.0510635276848131e-2, -9.2828824411184397e-2, 4.4412112839877808e-2, 2.7779236316835888e-7, -1.7229543805449697e-2, 1.4182925050891573e-2, -5.6214161633747336e-3, -2.39598509186381e-9, 1.6029634366079908e-3, -1.1606784674435773e-3, 4.1001337768153873e-4, 1.8365800754090661e-11, -9.5844256563655903e-5, 6.3643062337764708e-5, -2.076250624489065e-5, -1.1806020912804483e-13, 4.2131808239120649e-6, -2.6262241337012467e-6, 8.0770620494930662e-7, 6.0125912123632725e-16, -1.4729737374018841e-7}, + {-1.9994542198219728e-1, -1.5056113040026424e-2, 3.6470239469348489e-1, -4.6435192311733545e-1, 2.6640934719197893e-1, 3.4038266027147191e-5, -1.3784338709329624e-1, 1.276467178337056e-1, -5.6213828755200985e-2, -1.753150885483011e-7, 1.9235592956768113e-2, -1.5088821281095315e-2, 5.7401854451350123e-3, 1.0622382710310225e-9, -1.5335082692563998e-3, 1.0819320643228214e-3, -3.7372510193945659e-4, -6.6170909729031985e-12, 8.4263617380909628e-5, -5.5150706827483479e-5, 1.7769536448348069e-5, 3.8827923210205533e-14, -3.53513697488768e-6, 2.1865832130045269e-6, -6.6812849447625594e-7}, + {7.2438608504029431e-1, -1.3918010932653375, 1.0654143352413968, 1.876173868950258e-4, -8.2705501176152696e-1, 8.9352433347828414e-1, -4.4971003995291339e-1, -1.6107401567546652e-6, 1.9235590165271091e-1, -1.6597702160042609e-1, 6.8882222681814333e-2, 1.3910091724608687e-8, -2.146911561508663e-2, 1.6228980898865892e-2, -5.9796016172584256e-3, -1.1287469112826745e-10, 1.5167451119784857e-3, -1.0478634293553899e-3, 3.5539072889126421e-4, 8.1704322111801517e-13, -7.7773013442452395e-5, 5.0291413897007722e-5, -1.6035083867000518e-5, 1.2469354315487605e-14, 3.1369106244517615e-6}, + {1.6668949727276811, 1.165462765994632e-1, -3.3288393225018906, 4.4692325482864037, -2.6977693045875807, -2.600667859891061e-4, 1.5389017615694539, -1.4937962361134612, 6.8881964633233148e-1, 1.3077482004552385e-6, -2.5762963325596288e-1, 2.1097676102125449e-1, -8.3714408359219882e-2, -7.7920428881354753e-9, 2.4267923064833599e-2, -1.7813678334552311e-2, 6.3970330388900056e-3, 4.9430807090480523e-11, -1.5554602758465635e-3, 1.0561196919903214e-3, -3.5277184460472902e-4, 9.3002334645022459e-14, 7.5285855026557172e-5, -4.8186515569156351e-5, 1.5227271505597605e-5}, + {-6.6188298861372935, 1.3397985455142589e+1, -1.0789350606845146e+1, -1.4352254537875018e-3, 9.2333694596189809, -1.0456552819547769e+1, 5.5105526029033471, 1.2024439690716742e-5, -2.5762961164755816, 2.3207442745387179, -1.0045728797216284, -1.0207833290021914e-7, 3.3975092171169466e-1, -2.6720517450757468e-1, 1.0235252851562706e-1, 8.4329730484871625e-10, -2.7998284958442595e-2, 2.0066274144976813e-2, -7.0554368915086242e-3, 1.9402238183698188e-12, 1.6562888105449611e-3, -1.1082898580743683e-3, 3.654545161310169e-4, -5.1290032026971794e-11, -7.6340103696869031e-5}, + {-1.7112706061976095e+1, -1.1208044642899116, 3.7131966511885444e+1, -5.2298271025348962e+1, 3.3058589696624618e+1, 2.4791298976200222e-3, -2.061089403411526e+1, 2.088672775145582e+1, -1.0045703956517752e+1, -1.2238783449063012e-5, 4.0770134274221141, -3.473667358470195, 1.4329352617312006, 7.1359914411879712e-8, -4.4797257159115612e-1, 3.4112666080644461e-1, -1.2699786326594923e-1, -2.8953677269081528e-10, 3.3125776278259863e-2, -2.3274087021036101e-2, 8.0399993503648882e-3, -1.177805216235265e-9, -1.8321624891071668e-3, 1.2108282933588665e-3, -3.9479941246822517e-4}, + {7.389033153567425e+1, -1.5680141270402273e+2, 1.322177542759164e+2, 1.3692876877324546e-2, -1.2366496885920151e+2, 1.4620689391062729e+2, -8.0365587724865346e+1, -1.1259851148881298e-4, 4.0770132196179938e+1, -3.8210340013273034e+1, 1.719522294277362e+1, 9.3519707955168356e-7, -6.2716159907747034, 5.1168999071852637, -2.0319658112299095, -4.9507215582761543e-9, 5.9626397294332597e-1, -4.4220765337238094e-1, 1.6079998700166273e-1, -2.4733786203223402e-8, -4.0307574759979762e-2, 2.7849050747097869e-2, -9.4751858992054221e-3, 6.419922235909132e-6, 2.1250180774699461e-3}, + {2.1216837098382522e+2, 1.3107863022633868e+1, -4.9698285932871748e+2, 7.3121595266969204e+2, -4.8213821720890847e+2, -2.8817248692894889e-2, 3.2616720302947102e+2, -3.4389340280087117e+2, 1.7195193870816232e+2, 1.4038077378096158e-4, -7.52594195897599e+1, 6.651969984520934e+1, -2.8447519748152462e+1, -7.613702615875391e-7, 9.5402237105304373, -7.5175301113311376, 2.8943997568871961, -4.6612194999538201e-7, -8.0615149598794088e-1, 5.8483006570631029e-1, -2.0845408972964956e-1, 1.4765818959305817e-4, 5.1000433863753019e-2, -3.3066252141883665e-2, 1.5109265210467774e-2}, + {-9.8959643098322368e+2, 2.1925555360905233e+3, -1.9283586782723356e+3, -1.5925738122215253e-1, 1.9569985945919857e+3, -2.4072514765081556e+3, 1.3756149959336496e+3, 1.2920735237496668e-3, -7.525941715948055e+2, 7.3171668742208716e+2, -3.4137023466220065e+2, -9.9857390260608043e-6, 1.3356313181291573e+2, -1.1276295161252794e+2, 4.6310396098204458e+1, -7.9237387133614756e-6, -1.4510726927018646e+1, 1.1111771248100563e+1, -4.1690817945270892, 3.1008219800117808e-3, 1.1220095449981468, -7.6052379926149916e-1, 3.6262236505085254e-1, 2.216867741940747e-1, 4.8683443692930507e-1}, +} + +// Igam computes the incomplete Gamma integral. +// Igam(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or Igam +// will panic. +func Igam(a, x float64) float64 { + // The integral is evaluated by either a power series or continued fraction + // expansion, depending on the relative values of a and x. + // Sources: + // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov + // [2] Maddock et. al., "Incomplete Gamma Functions", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html + + // Check zero integration limit first + if x == 0 { + return 0 + } + + if x < 0 || a <= 0 { + panic(badParamOutOfBounds) + } + + // Asymptotic regime where a ~ x; see [2]. + absxmaA := math.Abs(x-a) / a + if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || + (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { + return asymptoticSeries(a, x, igam) + } + + if x > 1 && x > a { + return 1 - IgamC(a, x) + } + + return igamSeries(a, x) +} + +// IgamC computes the complemented incomplete Gamma integral. +// IgamC(a,x) = 1 - Igam(a,x) +// = (1/ Γ(a)) \int_0^\infty e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or +// IgamC will panic. +func IgamC(a, x float64) float64 { + // The integral is evaluated by either a power series or continued fraction + // expansion, depending on the relative values of a and x. + // Sources: + // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov + // [2] Maddock et. al., "Incomplete Gamma Functions", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html + + switch { + case x < 0, a <= 0: + panic(badParamOutOfBounds) + case x == 0: + return 1 + case math.IsInf(x, 0): + return 0 + } + + // Asymptotic regime where a ~ x; see [2]. + absxmaA := math.Abs(x-a) / a + if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || + (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { + return asymptoticSeries(a, x, igamC) + } + + // Everywhere else; see [2]. + if x > 1.1 { + if x < a { + return 1 - igamSeries(a, x) + } + return igamCContinuedFraction(a, x) + } else if x <= 0.5 { + if -0.4/math.Log(x) < a { + return 1 - igamSeries(a, x) + } + return igamCSeries(a, x) + } + + if x*1.1 < a { + return 1 - igamSeries(a, x) + } + return igamCSeries(a, x) +} + +// igamFac computes +// x^a * e^{-x} / Γ(a) +// corrected from (15) and (16) in [2] by replacing +// e^{x - a} +// with +// e^{a - x} +func igamFac(a, x float64) float64 { + if math.Abs(a-x) > 0.4*math.Abs(a) { + ax := a*math.Log(x) - x - lgam(a) + return math.Exp(ax) + } + + fac := a + lanczosG - 0.5 + res := math.Sqrt(fac/math.Exp(1)) / lanczosSumExpgScaled(a) + + if a < 200 && x < 200 { + res *= math.Exp(a-x) * math.Pow(x/fac, a) + } else { + num := x - a - lanczosG + 0.5 + res *= math.Exp(a*log1pmx(num/fac) + x*(0.5-lanczosG)/fac) + } + + return res +} + +// igamCContinuedFraction computes IgamC using DLMF 8.9.2. +func igamCContinuedFraction(a, x float64) float64 { + ax := igamFac(a, x) + if ax == 0 { + return 0 + } + + // Continued fraction + y := 1 - a + z := x + y + 1 + c := 0.0 + pkm2 := 1.0 + qkm2 := x + pkm1 := x + 1.0 + qkm1 := z * x + ans := pkm1 / qkm1 + + for i := 0; i < maxIter; i++ { + c += 1.0 + y += 1.0 + z += 2.0 + yc := y * c + pk := pkm1*z - pkm2*yc + qk := qkm1*z - qkm2*yc + var t float64 + if qk != 0 { + r := pk / qk + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + if math.Abs(pk) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if t <= machEp { + break + } + } + + return ans * ax +} + +// igamSeries computes Igam using DLMF 8.11.4. +func igamSeries(a, x float64) float64 { + ax := igamFac(a, x) + if ax == 0 { + return 0 + } + + // Power series + r := a + c := 1.0 + ans := 1.0 + + for i := 0; i < maxIter; i++ { + r += 1.0 + c *= x / r + ans += c + if c <= machEp*ans { + break + } + } + + return ans * ax / a +} + +// igamCSeries computes IgamC using DLMF 8.7.3. This is related to the series +// in igamSeries but extra care is taken to avoid cancellation. +func igamCSeries(a, x float64) float64 { + fac := 1.0 + sum := 0.0 + + for n := 1; n < maxIter; n++ { + fac *= -x / float64(n) + term := fac / (a + float64(n)) + sum += term + if math.Abs(term) <= machEp*math.Abs(sum) { + break + } + } + + logx := math.Log(x) + term := -expm1(a*logx - lgam1p(a)) + return term - math.Exp(a*logx-lgam(a))*sum +} + +// asymptoticSeries computes Igam/IgamC using DLMF 8.12.3/8.12.4. +func asymptoticSeries(a, x float64, fun int) float64 { + maxpow := 0 + lambda := x / a + sigma := (x - a) / a + absoldterm := math.MaxFloat64 + etapow := [igamDimN]float64{1} + sum := 0.0 + afac := 1.0 + + var sgn float64 + if fun == igam { + sgn = -1 + } else { + sgn = 1 + } + + var eta float64 + if lambda > 1 { + eta = math.Sqrt(-2 * log1pmx(sigma)) + } else if lambda < 1 { + eta = -math.Sqrt(-2 * log1pmx(sigma)) + } else { + eta = 0 + } + res := 0.5 * math.Erfc(sgn*eta*math.Sqrt(a/2)) + + for k := 0; k < igamDimK; k++ { + ck := igamCoefs[k][0] + for n := 1; n < igamDimN; n++ { + if n > maxpow { + etapow[n] = eta * etapow[n-1] + maxpow++ + } + ckterm := igamCoefs[k][n] * etapow[n] + ck += ckterm + if math.Abs(ckterm) < machEp*math.Abs(ck) { + break + } + } + term := ck * afac + absterm := math.Abs(term) + if absterm > absoldterm { + break + } + sum += term + if absterm < machEp*math.Abs(sum) { + break + } + absoldterm = absterm + afac /= a + } + res += sgn * math.Exp(-0.5*a*eta*eta) * sum / math.Sqrt(2*math.Pi*a) + + return res +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go new file mode 100644 index 00000000..5a8d9a91 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go @@ -0,0 +1,153 @@ +// Derived from SciPy's special/cephes/igami.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igami.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987, ©1995 by Stephen L. Moshier +// Portions Copyright ©2017 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// IgamI computes the inverse of the incomplete Gamma function. That is, it +// returns the x such that: +// IgamC(a, x) = p +// The input argument a must be positive and p must be between 0 and 1 +// inclusive or IgamI will panic. IgamI should return a positive number, but +// can return 0 even with non-zero y due to underflow. +func IgamI(a, p float64) float64 { + // Bound the solution + x0 := math.MaxFloat64 + yl := 0.0 + x1 := 0.0 + yh := 1.0 + dithresh := 5.0 * machEp + + if p < 0 || p > 1 || a <= 0 { + panic(badParamOutOfBounds) + } + + if p == 0 { + return math.Inf(1) + } + + if p == 1 { + return 0.0 + } + + // Starting with the approximate value + // x = a y^3 + // where + // y = 1 - d - ndtri(p) sqrt(d) + // and + // d = 1/9a + // the routine performs up to 10 Newton iterations to find the root of + // IgamC(a, x) - p = 0 + d := 1.0 / (9.0 * a) + y := 1.0 - d - Ndtri(p)*math.Sqrt(d) + x := a * y * y * y + + lgm := lgam(a) + + for i := 0; i < 10; i++ { + if x > x0 || x < x1 { + break + } + + y = IgamC(a, x) + + if y < yl || y > yh { + break + } + + if y < p { + x0 = x + yl = y + } else { + x1 = x + yh = y + } + + // Compute the derivative of the function at this point + d = (a-1)*math.Log(x) - x - lgm + if d < -maxLog { + break + } + d = -math.Exp(d) + + // Compute the step to the next approximation of x + d = (y - p) / d + if math.Abs(d/x) < machEp { + return x + } + x = x - d + } + + d = 0.0625 + if x0 == math.MaxFloat64 { + if x <= 0 { + x = 1 + } + for x0 == math.MaxFloat64 { + x = (1 + d) * x + y = IgamC(a, x) + if y < p { + x0 = x + yl = y + break + } + d = d + d + } + } + + d = 0.5 + dir := 0 + for i := 0; i < 400; i++ { + x = x1 + d*(x0-x1) + y = IgamC(a, x) + + lgm = (x0 - x1) / (x1 + x0) + if math.Abs(lgm) < dithresh { + break + } + + lgm = (y - p) / p + if math.Abs(lgm) < dithresh { + break + } + + if x <= 0 { + break + } + + if y >= p { + x1 = x + yh = y + if dir < 0 { + dir = 0 + d = 0.5 + } else if dir > 1 { + d = 0.5*d + 0.5 + } else { + d = (p - yl) / (yh - yl) + } + dir++ + } else { + x0 = x + yl = y + if dir > 0 { + dir = 0 + d = 0.5 + } else if dir < -1 { + d = 0.5 * d + } else { + d = (p - yl) / (yh - yl) + } + dir-- + } + } + + return x +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go new file mode 100644 index 00000000..cbe46c47 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go @@ -0,0 +1,312 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library, Release 2.3: March, 1995 + * Copyright 1984, 1995 by Stephen L. Moshier + */ + +package cephes + +import ( + "math" + + "gonum.org/v1/gonum/mathext/internal/gonum" +) + +const ( + maxGam = 171.624376956302725 + big = 4.503599627370496e15 + biginv = 2.22044604925031308085e-16 +) + +// Incbet computes the regularized incomplete beta function. +func Incbet(aa, bb, xx float64) float64 { + if aa <= 0 || bb <= 0 { + panic(badParamOutOfBounds) + } + if xx <= 0 || xx >= 1 { + if xx == 0 { + return 0 + } + if xx == 1 { + return 1 + } + panic(badParamOutOfBounds) + } + + var flag int + if bb*xx <= 1 && xx <= 0.95 { + t := pseries(aa, bb, xx) + return transformT(t, flag) + } + + w := 1 - xx + + // Reverse a and b if x is greater than the mean. + var a, b, xc, x float64 + if xx > aa/(aa+bb) { + flag = 1 + a = bb + b = aa + xc = xx + x = w + } else { + a = aa + b = bb + xc = w + x = xx + } + + if flag == 1 && (b*x) <= 1.0 && x <= 0.95 { + t := pseries(a, b, x) + return transformT(t, flag) + } + + // Choose expansion for better convergence. + y := x*(a+b-2.0) - (a - 1.0) + if y < 0.0 { + w = incbcf(a, b, x) + } else { + w = incbd(a, b, x) / xc + } + + // Multiply w by the factor + // x^a * (1-x)^b * Γ(a+b) / (a*Γ(a)*Γ(b)) + var t float64 + y = a * math.Log(x) + t = b * math.Log(xc) + if (a+b) < maxGam && math.Abs(y) < maxLog && math.Abs(t) < maxLog { + t = math.Pow(xc, b) + t *= math.Pow(x, a) + t /= a + t *= w + t *= 1.0 / gonum.Beta(a, b) + return transformT(t, flag) + } + + // Resort to logarithms. + y += t - gonum.Lbeta(a, b) + y += math.Log(w / a) + if y < minLog { + t = 0.0 + } else { + t = math.Exp(y) + } + + return transformT(t, flag) +} + +func transformT(t float64, flag int) float64 { + if flag == 1 { + if t <= machEp { + t = 1.0 - machEp + } else { + t = 1.0 - t + } + } + return t +} + +// incbcf returns the incomplete beta integral evaluated by a continued fraction +// expansion. +func incbcf(a, b, x float64) float64 { + var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 + var k1, k2, k3, k4, k5, k6, k7, k8 float64 + var r, t, ans, thresh float64 + var n int + + k1 = a + k2 = a + b + k3 = a + k4 = a + 1.0 + k5 = 1.0 + k6 = b - 1.0 + k7 = k4 + k8 = a + 2.0 + + pkm2 = 0.0 + qkm2 = 1.0 + pkm1 = 1.0 + qkm1 = 1.0 + ans = 1.0 + r = 1.0 + thresh = 3.0 * machEp + + for n = 0; n <= 300; n++ { + + xk = -(x * k1 * k2) / (k3 * k4) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + xk = (x * k5 * k6) / (k7 * k8) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + if qk != 0 { + r = pk / qk + } + if r != 0 { + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + + if t < thresh { + return ans + } + + k1 += 1.0 + k2 += 1.0 + k3 += 2.0 + k4 += 2.0 + k5 += 1.0 + k6 -= 1.0 + k7 += 2.0 + k8 += 2.0 + + if (math.Abs(qk) + math.Abs(pk)) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { + pkm2 *= big + pkm1 *= big + qkm2 *= big + qkm1 *= big + } + } + + return ans +} + +// incbd returns the incomplete beta integral evaluated by a continued fraction +// expansion. +func incbd(a, b, x float64) float64 { + var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 + var k1, k2, k3, k4, k5, k6, k7, k8 float64 + var r, t, ans, z, thresh float64 + var n int + + k1 = a + k2 = b - 1.0 + k3 = a + k4 = a + 1.0 + k5 = 1.0 + k6 = a + b + k7 = a + 1.0 + k8 = a + 2.0 + + pkm2 = 0.0 + qkm2 = 1.0 + pkm1 = 1.0 + qkm1 = 1.0 + z = x / (1.0 - x) + ans = 1.0 + r = 1.0 + thresh = 3.0 * machEp + for n = 0; n <= 300; n++ { + + xk = -(z * k1 * k2) / (k3 * k4) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + xk = (z * k5 * k6) / (k7 * k8) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + if qk != 0 { + r = pk / qk + } + if r != 0 { + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + + if t < thresh { + return ans + } + + k1 += 1.0 + k2 -= 1.0 + k3 += 2.0 + k4 += 2.0 + k5 += 1.0 + k6 += 1.0 + k7 += 2.0 + k8 += 2.0 + + if (math.Abs(qk) + math.Abs(pk)) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { + pkm2 *= big + pkm1 *= big + qkm2 *= big + qkm1 *= big + } + } + return ans +} + +// pseries returns the incomplete beta integral evaluated by a power series. Use +// when b*x is small and x not too close to 1. +func pseries(a, b, x float64) float64 { + var s, t, u, v, n, t1, z, ai float64 + ai = 1.0 / a + u = (1.0 - b) * x + v = u / (a + 1.0) + t1 = v + t = u + n = 2.0 + s = 0.0 + z = machEp * ai + for math.Abs(v) > z { + u = (n - b) * x / n + t *= u + v = t / (a + n) + s += v + n += 1.0 + } + s += t1 + s += ai + + u = a * math.Log(x) + if (a+b) < maxGam && math.Abs(u) < maxLog { + t = 1.0 / gonum.Beta(a, b) + s = s * t * math.Pow(x, a) + } else { + t = -gonum.Lbeta(a, b) + u + math.Log(s) + if t < minLog { + s = 0.0 + } else { + s = math.Exp(t) + } + } + return (s) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go new file mode 100644 index 00000000..06037867 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go @@ -0,0 +1,248 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library Release 2.4: March,1996 + * Copyright 1984, 1996 by Stephen L. Moshier + */ + +package cephes + +import "math" + +// Incbi computes the inverse of the regularized incomplete beta integral. +func Incbi(aa, bb, yy0 float64) float64 { + var a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh, xt float64 + var i, rflg, dir, nflg int + + i = 0 + if yy0 <= 0 { + return (0.0) + } + if yy0 >= 1.0 { + return (1.0) + } + x0 = 0.0 + yl = 0.0 + x1 = 1.0 + yh = 1.0 + nflg = 0 + + if aa <= 1.0 || bb <= 1.0 { + dithresh = 1.0e-6 + rflg = 0 + a = aa + b = bb + y0 = yy0 + x = a / (a + b) + y = Incbet(a, b, x) + goto ihalve + } else { + dithresh = 1.0e-4 + } + // Approximation to inverse function + yp = -Ndtri(yy0) + + if yy0 > 0.5 { + rflg = 1 + a = bb + b = aa + y0 = 1.0 - yy0 + yp = -yp + } else { + rflg = 0 + a = aa + b = bb + y0 = yy0 + } + + lgm = (yp*yp - 3.0) / 6.0 + x = 2.0 / (1.0/(2.0*a-1.0) + 1.0/(2.0*b-1.0)) + d = yp*math.Sqrt(x+lgm)/x - (1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(lgm+5.0/6.0-2.0/(3.0*x)) + d = 2.0 * d + if d < minLog { + // mtherr("incbi", UNDERFLOW) + x = 0 + goto done + } + x = a / (a + b*math.Exp(d)) + y = Incbet(a, b, x) + yp = (y - y0) / y0 + if math.Abs(yp) < 0.2 { + goto newt + } + + /* Resort to interval halving if not close enough. */ +ihalve: + + dir = 0 + di = 0.5 + for i = 0; i < 100; i++ { + if i != 0 { + x = x0 + di*(x1-x0) + if x == 1.0 { + x = 1.0 - machEp + } + if x == 0.0 { + di = 0.5 + x = x0 + di*(x1-x0) + if x == 0.0 { + // mtherr("incbi", UNDERFLOW) + goto done + } + } + y = Incbet(a, b, x) + yp = (x1 - x0) / (x1 + x0) + if math.Abs(yp) < dithresh { + goto newt + } + yp = (y - y0) / y0 + if math.Abs(yp) < dithresh { + goto newt + } + } + if y < y0 { + x0 = x + yl = y + if dir < 0 { + dir = 0 + di = 0.5 + } else if dir > 3 { + di = 1.0 - (1.0-di)*(1.0-di) + } else if dir > 1 { + di = 0.5*di + 0.5 + } else { + di = (y0 - y) / (yh - yl) + } + dir += 1 + if x0 > 0.75 { + if rflg == 1 { + rflg = 0 + a = aa + b = bb + y0 = yy0 + } else { + rflg = 1 + a = bb + b = aa + y0 = 1.0 - yy0 + } + x = 1.0 - x + y = Incbet(a, b, x) + x0 = 0.0 + yl = 0.0 + x1 = 1.0 + yh = 1.0 + goto ihalve + } + } else { + x1 = x + if rflg == 1 && x1 < machEp { + x = 0.0 + goto done + } + yh = y + if dir > 0 { + dir = 0 + di = 0.5 + } else if dir < -3 { + di = di * di + } else if dir < -1 { + di = 0.5 * di + } else { + di = (y - y0) / (yh - yl) + } + dir -= 1 + } + } + // mtherr("incbi", PLOSS) + if x0 >= 1.0 { + x = 1.0 - machEp + goto done + } + if x <= 0.0 { + // mtherr("incbi", UNDERFLOW) + x = 0.0 + goto done + } + +newt: + if nflg > 0 { + goto done + } + nflg = 1 + lgm = lgam(a+b) - lgam(a) - lgam(b) + + for i = 0; i < 8; i++ { + /* Compute the function at this point. */ + if i != 0 { + y = Incbet(a, b, x) + } + if y < yl { + x = x0 + y = yl + } else if y > yh { + x = x1 + y = yh + } else if y < y0 { + x0 = x + yl = y + } else { + x1 = x + yh = y + } + if x == 1.0 || x == 0.0 { + break + } + /* Compute the derivative of the function at this point. */ + d = (a-1.0)*math.Log(x) + (b-1.0)*math.Log(1.0-x) + lgm + if d < minLog { + goto done + } + if d > maxLog { + break + } + d = math.Exp(d) + /* Compute the step to the next approximation of x. */ + d = (y - y0) / d + xt = x - d + if xt <= x0 { + y = (x - x0) / (x1 - x0) + xt = x0 + 0.5*y*(x-x0) + if xt <= 0.0 { + break + } + } + if xt >= x1 { + y = (x1 - x) / (x1 - x0) + xt = x1 - 0.5*y*(x1-x) + if xt >= 1.0 { + break + } + } + x = xt + if math.Abs(d/x) < 128.0*machEp { + goto done + } + } + /* Did not converge. */ + dithresh = 256.0 * machEp + goto ihalve + +done: + + if rflg > 0 { + if x <= machEp { + x = 1.0 - machEp + } else { + x = 1.0 - x + } + } + return (x) +} + +func lgam(a float64) float64 { + lg, _ := math.Lgamma(a) + return lg +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go new file mode 100644 index 00000000..c32909b5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go @@ -0,0 +1,153 @@ +// Derived from SciPy's special/cephes/lanczos.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/lanczos.c + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©2006 John Maddock +// Portions Copyright ©2003 Boost +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +// Optimal values for G for each N are taken from +// http://web.mala.bc.ca/pughg/phdThesis/phdThesis.pdf, +// as are the theoretical error bounds. + +// Constants calculated using the method described by Godfrey +// http://my.fit.edu/~gabdo/gamma.txt and elaborated by Toth at +// http://www.rskey.org/gamma.htm using NTL::RR at 1000 bit precision. + +var lanczosNum = [...]float64{ + 2.506628274631000270164908177133837338626, + 210.8242777515793458725097339207133627117, + 8071.672002365816210638002902272250613822, + 186056.2653952234950402949897160456992822, + 2876370.628935372441225409051620849613599, + 31426415.58540019438061423162831820536287, + 248874557.8620541565114603864132294232163, + 1439720407.311721673663223072794912393972, + 6039542586.35202800506429164430729792107, + 17921034426.03720969991975575445893111267, + 35711959237.35566804944018545154716670596, + 42919803642.64909876895789904700198885093, + 23531376880.41075968857200767445163675473, +} + +var lanczosDenom = [...]float64{ + 1, + 66, + 1925, + 32670, + 357423, + 2637558, + 13339535, + 45995730, + 105258076, + 150917976, + 120543840, + 39916800, + 0, +} + +var lanczosSumExpgScaledNum = [...]float64{ + 0.006061842346248906525783753964555936883222, + 0.5098416655656676188125178644804694509993, + 19.51992788247617482847860966235652136208, + 449.9445569063168119446858607650988409623, + 6955.999602515376140356310115515198987526, + 75999.29304014542649875303443598909137092, + 601859.6171681098786670226533699352302507, + 3481712.15498064590882071018964774556468, + 14605578.08768506808414169982791359218571, + 43338889.32467613834773723740590533316085, + 86363131.28813859145546927288977868422342, + 103794043.1163445451906271053616070238554, + 56906521.91347156388090791033559122686859, +} + +var lanczosSumExpgScaledDenom = [...]float64{ + 1, + 66, + 1925, + 32670, + 357423, + 2637558, + 13339535, + 45995730, + 105258076, + 150917976, + 120543840, + 39916800, + 0, +} + +var lanczosSumNear1D = [...]float64{ + 0.3394643171893132535170101292240837927725e-9, + -0.2499505151487868335680273909354071938387e-8, + 0.8690926181038057039526127422002498960172e-8, + -0.1933117898880828348692541394841204288047e-7, + 0.3075580174791348492737947340039992829546e-7, + -0.2752907702903126466004207345038327818713e-7, + -0.1515973019871092388943437623825208095123e-5, + 0.004785200610085071473880915854204301886437, + -0.1993758927614728757314233026257810172008, + 1.483082862367253753040442933770164111678, + -3.327150580651624233553677113928873034916, + 2.208709979316623790862569924861841433016, +} + +var lanczosSumNear2D = [...]float64{ + 0.1009141566987569892221439918230042368112e-8, + -0.7430396708998719707642735577238449585822e-8, + 0.2583592566524439230844378948704262291927e-7, + -0.5746670642147041587497159649318454348117e-7, + 0.9142922068165324132060550591210267992072e-7, + -0.8183698410724358930823737982119474130069e-7, + -0.4506604409707170077136555010018549819192e-5, + 0.01422519127192419234315002746252160965831, + -0.5926941084905061794445733628891024027949, + 4.408830289125943377923077727900630927902, + -9.8907772644920670589288081640128194231, + 6.565936202082889535528455955485877361223, +} + +const lanczosG = 6.024680040776729583740234375 + +func lanczosSum(x float64) float64 { + return ratevl(x, + lanczosNum[:], + len(lanczosNum)-1, + lanczosDenom[:], + len(lanczosDenom)-1) +} + +func lanczosSumExpgScaled(x float64) float64 { + return ratevl(x, + lanczosSumExpgScaledNum[:], + len(lanczosSumExpgScaledNum)-1, + lanczosSumExpgScaledDenom[:], + len(lanczosSumExpgScaledDenom)-1) +} + +func lanczosSumNear1(dx float64) float64 { + var result float64 + + for i, val := range lanczosSumNear1D { + k := float64(i + 1) + result += (-val * dx) / (k*dx + k*k) + } + + return result +} + +func lanczosSumNear2(dx float64) float64 { + var result float64 + x := dx + 2 + + for i, val := range lanczosSumNear2D { + k := float64(i + 1) + result += (-val * dx) / (x + k*x + k*k - 1) + } + + return result +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go new file mode 100644 index 00000000..1b26abdc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go @@ -0,0 +1,150 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library Release 2.1: January, 1989 + * Copyright 1984, 1987, 1989 by Stephen L. Moshier + * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 + */ + +package cephes + +import "math" + +// TODO(btracey): There is currently an implementation of this functionality +// in gonum/stat/distuv. Find out which implementation is better, and rectify +// by having distuv call this, or moving this implementation into +// gonum/mathext/internal/gonum. + +// math.Sqrt(2*pi) +const s2pi = 2.50662827463100050242E0 + +// approximation for 0 <= |y - 0.5| <= 3/8 +var P0 = [5]float64{ + -5.99633501014107895267E1, + 9.80010754185999661536E1, + -5.66762857469070293439E1, + 1.39312609387279679503E1, + -1.23916583867381258016E0, +} + +var Q0 = [8]float64{ + /* 1.00000000000000000000E0, */ + 1.95448858338141759834E0, + 4.67627912898881538453E0, + 8.63602421390890590575E1, + -2.25462687854119370527E2, + 2.00260212380060660359E2, + -8.20372256168333339912E1, + 1.59056225126211695515E1, + -1.18331621121330003142E0, +} + +// Approximation for interval z = math.Sqrt(-2 log y ) between 2 and 8 +// i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14. +var P1 = [9]float64{ + 4.05544892305962419923E0, + 3.15251094599893866154E1, + 5.71628192246421288162E1, + 4.40805073893200834700E1, + 1.46849561928858024014E1, + 2.18663306850790267539E0, + -1.40256079171354495875E-1, + -3.50424626827848203418E-2, + -8.57456785154685413611E-4, +} + +var Q1 = [8]float64{ + /* 1.00000000000000000000E0, */ + 1.57799883256466749731E1, + 4.53907635128879210584E1, + 4.13172038254672030440E1, + 1.50425385692907503408E1, + 2.50464946208309415979E0, + -1.42182922854787788574E-1, + -3.80806407691578277194E-2, + -9.33259480895457427372E-4, +} + +// Approximation for interval z = math.Sqrt(-2 log y ) between 8 and 64 +// i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890. +var P2 = [9]float64{ + 3.23774891776946035970E0, + 6.91522889068984211695E0, + 3.93881025292474443415E0, + 1.33303460815807542389E0, + 2.01485389549179081538E-1, + 1.23716634817820021358E-2, + 3.01581553508235416007E-4, + 2.65806974686737550832E-6, + 6.23974539184983293730E-9, +} + +var Q2 = [8]float64{ + /* 1.00000000000000000000E0, */ + 6.02427039364742014255E0, + 3.67983563856160859403E0, + 1.37702099489081330271E0, + 2.16236993594496635890E-1, + 1.34204006088543189037E-2, + 3.28014464682127739104E-4, + 2.89247864745380683936E-6, + 6.79019408009981274425E-9, +} + +// Ndtri returns the argument, x, for which the area under the +// Gaussian probability density function (integrated from +// minus infinity to x) is equal to y. +func Ndtri(y0 float64) float64 { + // For small arguments 0 < y < exp(-2), the program computes + // z = math.Sqrt( -2.0 * math.Log(y) ); then the approximation is + // x = z - math.Log(z)/z - (1/z) P(1/z) / Q(1/z). + // There are two rational functions P/Q, one for 0 < y < exp(-32) + // and the other for y up to exp(-2). For larger arguments, + // w = y - 0.5, and x/math.Sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). + var x, y, z, y2, x0, x1 float64 + var code int + + if y0 <= 0.0 { + if y0 < 0 { + panic(badParamOutOfBounds) + } + return math.Inf(-1) + } + if y0 >= 1.0 { + if y0 > 1 { + panic(badParamOutOfBounds) + } + return math.Inf(1) + } + code = 1 + y = y0 + if y > (1.0 - 0.13533528323661269189) { /* 0.135... = exp(-2) */ + y = 1.0 - y + code = 0 + } + + if y > 0.13533528323661269189 { + y = y - 0.5 + y2 = y * y + x = y + y*(y2*polevl(y2, P0[:], 4)/p1evl(y2, Q0[:], 8)) + x = x * s2pi + return (x) + } + + x = math.Sqrt(-2.0 * math.Log(y)) + x0 = x - math.Log(x)/x + + z = 1.0 / x + if x < 8.0 { /* y > exp(-32) = 1.2664165549e-14 */ + x1 = z * polevl(z, P1[:], 8) / p1evl(z, Q1[:], 8) + } else { + x1 = z * polevl(z, P2[:], 8) / p1evl(z, Q2[:], 8) + } + x = x0 - x1 + if code != 0 { + x = -x + } + return (x) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go new file mode 100644 index 00000000..5cbd8cbb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go @@ -0,0 +1,82 @@ +// Derived from SciPy's special/cephes/polevl.h +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/polevl.h +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987, ©1988 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// polevl evaluates a polynomial of degree N +// y = c_0 + c_1 x_1 + c_2 x_2^2 ... +// where the coefficients are stored in reverse order, i.e. coef[0] = c_n and +// coef[n] = c_0. +func polevl(x float64, coef []float64, n int) float64 { + ans := coef[0] + for i := 1; i <= n; i++ { + ans = ans*x + coef[i] + } + return ans +} + +// p1evl is the same as polevl, except c_n is assumed to be 1 and is not included +// in the slice. +func p1evl(x float64, coef []float64, n int) float64 { + ans := x + coef[0] + for i := 1; i <= n-1; i++ { + ans = ans*x + coef[i] + } + return ans +} + +// ratevl evaluates a rational function +func ratevl(x float64, num []float64, m int, denom []float64, n int) float64 { + // Source: Holin et. al., "Polynomial and Rational Function Evaluation", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/roots/rational.html + absx := math.Abs(x) + + var dir, idx int + var y float64 + if absx > 1 { + // Evaluate as a polynomial in 1/x + dir = -1 + idx = m + y = 1 / x + } else { + dir = 1 + idx = 0 + y = x + } + + // Evaluate the numerator + numAns := num[idx] + idx += dir + for i := 0; i < m; i++ { + numAns = numAns*y + num[idx] + idx += dir + } + + // Evaluate the denominator + if absx > 1 { + idx = n + } else { + idx = 0 + } + + denomAns := denom[idx] + idx += dir + for i := 0; i < n; i++ { + denomAns = denomAns*y + denom[idx] + idx += dir + } + + if absx > 1 { + pow := float64(n - m) + return math.Pow(x, pow) * numAns / denomAns + } + return numAns / denomAns +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go new file mode 100644 index 00000000..1333dd1d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go @@ -0,0 +1,170 @@ +// Derived from SciPy's special/cephes/unity.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/unity.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1996 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// Relative error approximations for function arguments near unity. +// log1p(x) = log(1+x) +// expm1(x) = exp(x) - 1 +// cosm1(x) = cos(x) - 1 +// lgam1p(x) = lgam(1+x) + +const ( + invSqrt2 = 1 / math.Sqrt2 + pi4 = math.Pi / 4 + euler = 0.577215664901532860606512090082402431 // Euler constant +) + +// Coefficients for +// log(1+x) = x - \frac{x^2}{2} + \frac{x^3 lP(x)}{lQ(x)} +// for +// \frac{1}{\sqrt{2}} <= x < \sqrt{2} +// Theoretical peak relative error = 2.32e-20 +var lP = [...]float64{ + 4.5270000862445199635215E-5, + 4.9854102823193375972212E-1, + 6.5787325942061044846969E0, + 2.9911919328553073277375E1, + 6.0949667980987787057556E1, + 5.7112963590585538103336E1, + 2.0039553499201281259648E1, +} + +var lQ = [...]float64{ + 1.5062909083469192043167E1, + 8.3047565967967209469434E1, + 2.2176239823732856465394E2, + 3.0909872225312059774938E2, + 2.1642788614495947685003E2, + 6.0118660497603843919306E1, +} + +// log1p computes +// log(1 + x) +func log1p(x float64) float64 { + z := 1 + x + if z < invSqrt2 || z > math.Sqrt2 { + return math.Log(z) + } + z = x * x + z = -0.5*z + x*(z*polevl(x, lP[:], 6)/p1evl(x, lQ[:], 6)) + return x + z +} + +// log1pmx computes +// log(1 + x) - x +func log1pmx(x float64) float64 { + if math.Abs(x) < 0.5 { + xfac := x + res := 0.0 + + var term float64 + for n := 2; n < maxIter; n++ { + xfac *= -x + term = xfac / float64(n) + res += term + if math.Abs(term) < machEp*math.Abs(res) { + break + } + } + return res + } + return log1p(x) - x +} + +// Coefficients for +// e^x = 1 + \frac{2x eP(x^2)}{eQ(x^2) - eP(x^2)} +// for +// -0.5 <= x <= 0.5 +var eP = [...]float64{ + 1.2617719307481059087798E-4, + 3.0299440770744196129956E-2, + 9.9999999999999999991025E-1, +} + +var eQ = [...]float64{ + 3.0019850513866445504159E-6, + 2.5244834034968410419224E-3, + 2.2726554820815502876593E-1, + 2.0000000000000000000897E0, +} + +// expm1 computes +// expm1(x) = e^x - 1 +func expm1(x float64) float64 { + if math.IsInf(x, 0) { + if math.IsNaN(x) || x > 0 { + return x + } + return -1 + } + if x < -0.5 || x > 0.5 { + return math.Exp(x) - 1 + } + xx := x * x + r := x * polevl(xx, eP[:], 2) + r = r / (polevl(xx, eQ[:], 3) - r) + return r + r +} + +var coscof = [...]float64{ + 4.7377507964246204691685E-14, + -1.1470284843425359765671E-11, + 2.0876754287081521758361E-9, + -2.7557319214999787979814E-7, + 2.4801587301570552304991E-5, + -1.3888888888888872993737E-3, + 4.1666666666666666609054E-2, +} + +// cosm1 computes +// cosm1(x) = cos(x) - 1 +func cosm1(x float64) float64 { + if x < -pi4 || x > pi4 { + return math.Cos(x) - 1 + } + xx := x * x + xx = -0.5*xx + xx*xx*polevl(xx, coscof[:], 6) + return xx +} + +// lgam1pTayler computes +// lgam(x + 1) +//around x = 0 using its Taylor series. +func lgam1pTaylor(x float64) float64 { + if x == 0 { + return 0 + } + res := -euler * x + xfac := -x + for n := 2; n < 42; n++ { + nf := float64(n) + xfac *= -x + coeff := Zeta(nf, 1) * xfac / nf + res += coeff + if math.Abs(coeff) < machEp*math.Abs(res) { + break + } + } + + return res +} + +// lgam1p computes +// lgam(x + 1) +func lgam1p(x float64) float64 { + if math.Abs(x) <= 0.5 { + return lgam1pTaylor(x) + } else if math.Abs(x-1) < 0.5 { + return math.Log(x) + lgam1pTaylor(x-1) + } + return lgam(x + 1) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go new file mode 100644 index 00000000..14a41b6f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go @@ -0,0 +1,110 @@ +// Derived from SciPy's special/cephes/zeta.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/zeta.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// zetaCoegs are the expansion coefficients for Euler-Maclaurin summation +// formula: +// \frac{(2k)!}{B_{2k}} +// where +// B_{2k} +// are Bernoulli numbers. +var zetaCoefs = [...]float64{ + 12.0, + -720.0, + 30240.0, + -1209600.0, + 47900160.0, + -1.307674368e12 / 691, + 7.47242496e10, + -1.067062284288e16 / 3617, + 5.109094217170944e18 / 43867, + -8.028576626982912e20 / 174611, + 1.5511210043330985984e23 / 854513, + -1.6938241367317436694528e27 / 236364091, +} + +// Zeta computes the Riemann zeta function of two arguments. +// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} +// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, +// q is either zero or a negative integer, or q is negative and x is not an +// integer. +// +// Note that: +// zeta(x,1) = zetac(x) + 1 +func Zeta(x, q float64) float64 { + // REFERENCE: Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals, Series, + // and Products, p. 1073; Academic Press, 1980. + if x == 1 { + return math.Inf(1) + } + + if x < 1 { + panic(badParamOutOfBounds) + } + + if q <= 0 { + if q == math.Floor(q) { + panic(badParamFunctionSingularity) + } + if x != math.Floor(x) { + panic(badParamOutOfBounds) // Because q^-x not defined + } + } + + // Asymptotic expansion: http://dlmf.nist.gov/25.11#E43 + if q > 1e8 { + return (1/(x-1) + 1/(2*q)) * math.Pow(q, 1-x) + } + + // The Euler-Maclaurin summation formula is used to obtain the expansion: + // Zeta(x,q) = \sum_{k=1}^n (k+q)^{-x} + \frac{(n+q)^{1-x}}{x-1} - \frac{1}{2(n+q)^x} + \sum_{j=1}^{\infty} \frac{B_{2j}x(x+1)...(x+2j)}{(2j)! (n+q)^{x+2j+1}} + // where + // B_{2j} + // are Bernoulli numbers. + // Permit negative q but continue sum until n+q > 9. This case should be + // handled by a reflection formula. If q<0 and x is an integer, there is a + // relation to the polyGamma function. + s := math.Pow(q, -x) + a := q + i := 0 + b := 0.0 + for i < 9 || a <= 9 { + i++ + a += 1.0 + b = math.Pow(a, -x) + s += b + if math.Abs(b/s) < machEp { + return s + } + } + + w := a + s += b * w / (x - 1) + s -= 0.5 * b + a = 1.0 + k := 0.0 + for _, coef := range zetaCoefs { + a *= x + k + b /= w + t := a * b / coef + s = s + t + t = math.Abs(t / s) + if t < machEp { + return s + } + k += 1.0 + a *= x + k + b /= w + k += 1.0 + } + return s +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go new file mode 100644 index 00000000..7038c08f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go @@ -0,0 +1,52 @@ +// Copyright ©2016 The gonum 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 gonum + +import ( + "math" +) + +// Beta returns the value of the complete beta function B(a, b). It is defined as +// Γ(a)Γ(b) / Γ(a+b) +// Special cases are: +// B(a,b) returns NaN if a or b is Inf +// B(a,b) returns NaN if a and b are 0 +// B(a,b) returns NaN if a or b is NaN +// B(a,b) returns NaN if a or b is < 0 +// B(a,b) returns +Inf if a xor b is 0. +// +// See http://mathworld.wolfram.com/BetaFunction.html for more detailed information. +func Beta(a, b float64) float64 { + return math.Exp(Lbeta(a, b)) +} + +// Lbeta returns the natural logarithm of the complete beta function B(a,b). +// Lbeta is defined as: +// Ln(Γ(a)Γ(b)/Γ(a+b)) +// Special cases are: +// Lbeta(a,b) returns NaN if a or b is Inf +// Lbeta(a,b) returns NaN if a and b are 0 +// Lbeta(a,b) returns NaN if a or b is NaN +// Lbeta(a,b) returns NaN if a or b is < 0 +// Lbeta(a,b) returns +Inf if a xor b is 0. +func Lbeta(a, b float64) float64 { + switch { + case math.IsInf(a, +1) || math.IsInf(b, +1): + return math.NaN() + case a == 0 && b == 0: + return math.NaN() + case a < 0 || b < 0: + return math.NaN() + case math.IsNaN(a) || math.IsNaN(b): + return math.NaN() + case a == 0 || b == 0: + return math.Inf(+1) + } + + la, _ := math.Lgamma(a) + lb, _ := math.Lgamma(b) + lab, _ := math.Lgamma(a + b) + return la + lb - lab +} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go new file mode 100644 index 00000000..a726cfcb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 gonum contains functions implemented by the gonum team. It is here to +// avoid circular imports and/or double coding of functions. +package gonum // import "gonum.org/v1/gonum/mathext/internal/gonum" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go new file mode 100644 index 00000000..eae3e1c4 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go @@ -0,0 +1,5 @@ +// Copyright ©2016 The gonum 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 gonum diff --git a/vendor/gonum.org/v1/gonum/mathext/mvgamma.go b/vendor/gonum.org/v1/gonum/mathext/mvgamma.go new file mode 100644 index 00000000..c18b37ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/mvgamma.go @@ -0,0 +1,32 @@ +// Copyright ©2016 The gonum 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 mathext + +import "math" + +const ( + logPi = 1.14472988584940017414342735135305871164729481 // http://oeis.org/A053510 +) + +// MvLgamma returns the log of the multivariate Gamma function. Dim +// must be greater than zero, and MvLgamma will return NaN if v < (dim-1)/2. +// +// See https://en.wikipedia.org/wiki/Multivariate_gamma_function for more +// information. +func MvLgamma(v float64, dim int) float64 { + if dim < 1 { + panic("mathext: negative dimension") + } + df := float64(dim) + if v < (df-1)*0.5 { + return math.NaN() + } + ans := df * (df - 1) * 0.25 * logPi + for i := 1; i <= dim; i++ { + lg, _ := math.Lgamma(v + float64(1-i)*0.5) + ans += lg + } + return ans +} diff --git a/vendor/gonum.org/v1/gonum/mathext/mvgamma_test.go b/vendor/gonum.org/v1/gonum/mathext/mvgamma_test.go new file mode 100644 index 00000000..f7d309c8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/mvgamma_test.go @@ -0,0 +1,27 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" + "testing" +) + +func TestMvLgamma(t *testing.T) { + // Values compared with scipy + for i, test := range []struct { + v float64 + dim int + ans float64 + }{ + {10, 5, 58.893841851237397}, + {3, 1, 0.69314718055994529}, + } { + ans := MvLgamma(test.v, test.dim) + if math.Abs(test.ans-ans) > 1e-14 { + t.Errorf("Case %v. got=%v want=%v.", i, ans, test.ans) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/mathext/roots.go b/vendor/gonum.org/v1/gonum/mathext/roots.go new file mode 100644 index 00000000..61ff12c6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/roots.go @@ -0,0 +1,178 @@ +// Derived from SciPy's special/c_misc/fsolve.c and special/c_misc/misc.h +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/fsolve.c +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/misc.h + +// Copyright ©2017 The gonum 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 mathext + +import "math" + +type objectiveFunc func(float64, []float64) float64 + +type fSolveResult uint8 + +const ( + // An exact solution was found, in which case the first point on the + // interval is the value + fSolveExact fSolveResult = iota + 1 + // Interval width is less than the tolerance + fSolveConverged + // Root-finding didn't converge in a set number of iterations + fSolveMaxIterations +) + +const ( + machEp = 1.0 / (1 << 53) +) + +// falsePosition uses a combination of bisection and false position to find a +// root of a function within a given interval. This is guaranteed to converge, +// and always keeps a bounding interval, unlike Newton's method. Inputs are: +// x1, x2: initial bounding interval +// f1, f2: value of f() at x1 and x2 +// absErr, relErr: absolute and relative errors on the bounding interval +// bisectTil: if > 0.0, perform bisection until the width of the bounding +// interval is less than this +// f, fExtra: function to find root of is f(x, fExtra) +// Returns: +// result: whether an exact root was found, the process converged to a +// bounding interval small than the required error, or the max number +// of iterations was hit +// bestX: best root approximation +// bestF: function value at bestX +// errEst: error estimation +func falsePosition(x1, x2, f1, f2, absErr, relErr, bisectTil float64, f objectiveFunc, fExtra []float64) (fSolveResult, float64, float64, float64) { + // The false position steps are either unmodified, or modified with the + // Anderson-Bjorck method as appropriate. Theoretically, this has a "speed of + // convergence" of 1.7 (bisection is 1, Newton is 2). + // Note that this routine was designed initially to work with gammaincinv, so + // it may not be tuned right for other problems. Don't use it blindly. + + if f1*f2 >= 0 { + panic("Initial interval is not a bounding interval") + } + + const ( + maxIterations = 100 + bisectIter = 4 + bisectWidth = 4.0 + ) + + const ( + bisect = iota + 1 + falseP + ) + + var state uint8 + if bisectTil > 0 { + state = bisect + } else { + state = falseP + } + + gamma := 1.0 + + w := math.Abs(x2 - x1) + lastBisectWidth := w + + var nFalseP int + var x3, f3, bestX, bestF float64 + for i := 0; i < maxIterations; i++ { + switch state { + case bisect: + x3 = 0.5 * (x1 + x2) + if x3 == x1 || x3 == x2 { + // i.e., x1 and x2 are successive floating-point numbers + bestX = x3 + if x3 == x1 { + bestF = f1 + } else { + bestF = f2 + } + return fSolveConverged, bestX, bestF, w + } + + f3 = f(x3, fExtra) + if f3 == 0 { + return fSolveExact, x3, f3, w + } + + if f3*f2 < 0 { + x1 = x2 + f1 = f2 + } + x2 = x3 + f2 = f3 + w = math.Abs(x2 - x1) + lastBisectWidth = w + if bisectTil > 0 { + if w < bisectTil { + bisectTil = -1.0 + gamma = 1.0 + nFalseP = 0 + state = falseP + } + } else { + gamma = 1.0 + nFalseP = 0 + state = falseP + } + case falseP: + s12 := (f2 - gamma*f1) / (x2 - x1) + x3 = x2 - f2/s12 + f3 = f(x3, fExtra) + if f3 == 0 { + return fSolveExact, x3, f3, w + } + + nFalseP++ + if f3*f2 < 0 { + gamma = 1.0 + x1 = x2 + f1 = f2 + } else { + // Anderson-Bjorck method + g := 1.0 - f3/f2 + if g <= 0 { + g = 0.5 + } + gamma *= g + } + x2 = x3 + f2 = f3 + w = math.Abs(x2 - x1) + + // Sanity check. For every 4 false position checks, see if we really are + // decreasing the interval by comparing to what bisection would have + // achieved (or, rather, a bit more lenient than that -- interval + // decreased by 4 instead of by 16, as the fp could be decreasing gamma + // for a bit). Note that this should guarantee convergence, as it makes + // sure that we always end up decreasing the interval width with a + // bisection. + if nFalseP > bisectIter { + if w*bisectWidth > lastBisectWidth { + state = bisect + } + nFalseP = 0 + lastBisectWidth = w + } + } + + tol := absErr + relErr*math.Max(math.Max(math.Abs(x1), math.Abs(x2)), 1.0) + if w <= tol { + if math.Abs(f1) < math.Abs(f2) { + bestX = x1 + bestF = f1 + } else { + bestX = x2 + bestF = f2 + } + return fSolveConverged, bestX, bestF, w + } + } + + return fSolveMaxIterations, x3, f3, w +} diff --git a/vendor/gonum.org/v1/gonum/mathext/zeta.go b/vendor/gonum.org/v1/gonum/mathext/zeta.go new file mode 100644 index 00000000..920a7e6e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/zeta.go @@ -0,0 +1,20 @@ +// Copyright ©2016 The gonum 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 mathext + +import "gonum.org/v1/gonum/mathext/internal/cephes" + +// Zeta computes the Riemann zeta function of two arguments. +// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} +// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, +// q is either zero or a negative integer, or q is negative and x is not an +// integer. +// +// See http://mathworld.wolfram.com/HurwitzZetaFunction.html +// or https://en.wikipedia.org/wiki/Multiple_zeta_function#Two_parameters_case +// for more detailed information. +func Zeta(x, q float64) float64 { + return cephes.Zeta(x, q) +} diff --git a/vendor/gonum.org/v1/gonum/mathext/zeta_test.go b/vendor/gonum.org/v1/gonum/mathext/zeta_test.go new file mode 100644 index 00000000..e415818f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mathext/zeta_test.go @@ -0,0 +1,42 @@ +// Copyright ©2016 The gonum 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 mathext + +import ( + "math" + "testing" +) + +func TestZeta(t *testing.T) { + for i, test := range []struct { + x, q, want float64 + }{ + // Results computed using scipy.special.zeta + {1, 1, math.Inf(1)}, + {1.00001, 0.5, 100001.96352290553}, + {1.0001, 25, 9996.8017690244506}, + {1.001, 1, 1000.5772884760117}, + {1.01, 10, 97.773405639173305}, + {1.5, 2, 1.6123753486854886}, + {1.5, 20, 0.45287361712938717}, + {2, -0.7, 14.28618087263834}, + {2.5, 0.5, 6.2471106345688137}, + {5, 2.5, 0.013073166646113805}, + {7.5, 5, 7.9463377443314306e-06}, + {10, -0.5, 2048.0174503557578}, + {10, 0.5, 1024.0174503557578}, + {10, 7.5, 2.5578265694201971e-9}, + {12, 2.5, 1.7089167198843551e-5}, + {17, 0.5, 131072.00101513157}, + {20, -2.5, 2097152.0006014798}, + {20, 0.75, 315.3368689825316}, + {25, 0.25, 1125899906842624.0}, + {30, 1, 1.0000000009313275}, + } { + if got := Zeta(test.x, test.q); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d Zeta(%g, %g) failed: got %g want %g", i, test.x, test.q, got, test.want) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/README.md b/vendor/gonum.org/v1/gonum/optimize/README.md new file mode 100644 index 00000000..0067895c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/README.md @@ -0,0 +1,3 @@ +# Gonum optimize [![GoDoc](https://godoc.org/gonum.org/v1/gonum/optimize?status.svg)](https://godoc.org/gonum.org/v1/gonum/optimize) + +Package optimize is an optimization package for the Go language. diff --git a/vendor/gonum.org/v1/gonum/optimize/backtracking.go b/vendor/gonum.org/v1/gonum/optimize/backtracking.go new file mode 100644 index 00000000..313077f3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/backtracking.go @@ -0,0 +1,82 @@ +// Copyright ©2014 The gonum 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 optimize + +const ( + defaultBacktrackingContraction = 0.5 + defaultBacktrackingDecrease = 1e-4 + minimumBacktrackingStepSize = 1e-20 +) + +// Backtracking is a Linesearcher that uses backtracking to find a point that +// satisfies the Armijo condition with the given decrease factor. If the Armijo +// condition has not been met, the step size is decreased by ContractionFactor. +// +// The Armijo condition only requires the gradient at the beginning of each +// major iteration (not at successive step locations), and so Backtracking may +// be a good linesearch for functions with expensive gradients. Backtracking is +// not appropriate for optimizers that require the Wolfe conditions to be met, +// such as BFGS. +// +// Both DecreaseFactor and ContractionFactor must be between zero and one, and +// Backtracking will panic otherwise. If either DecreaseFactor or +// ContractionFactor are zero, it will be set to a reasonable default. +type Backtracking struct { + DecreaseFactor float64 // Constant factor in the sufficient decrease (Armijo) condition. + ContractionFactor float64 // Step size multiplier at each iteration (step *= ContractionFactor). + + stepSize float64 + initF float64 + initG float64 + + lastOp Operation +} + +func (b *Backtracking) Init(f, g float64, step float64) Operation { + if step <= 0 { + panic("backtracking: bad step size") + } + if g >= 0 { + panic("backtracking: initial derivative is non-negative") + } + + if b.ContractionFactor == 0 { + b.ContractionFactor = defaultBacktrackingContraction + } + if b.DecreaseFactor == 0 { + b.DecreaseFactor = defaultBacktrackingDecrease + } + if b.ContractionFactor <= 0 || b.ContractionFactor >= 1 { + panic("backtracking: ContractionFactor must be between 0 and 1") + } + if b.DecreaseFactor <= 0 || b.DecreaseFactor >= 1 { + panic("backtracking: DecreaseFactor must be between 0 and 1") + } + + b.stepSize = step + b.initF = f + b.initG = g + + b.lastOp = FuncEvaluation + return b.lastOp +} + +func (b *Backtracking) Iterate(f, _ float64) (Operation, float64, error) { + if b.lastOp != FuncEvaluation { + panic("backtracking: Init has not been called") + } + + if ArmijoConditionMet(f, b.initF, b.initG, b.stepSize, b.DecreaseFactor) { + b.lastOp = MajorIteration + return b.lastOp, b.stepSize, nil + } + b.stepSize *= b.ContractionFactor + if b.stepSize < minimumBacktrackingStepSize { + b.lastOp = NoOperation + return b.lastOp, b.stepSize, ErrLinesearcherFailure + } + b.lastOp = FuncEvaluation + return b.lastOp, b.stepSize, nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/bfgs.go b/vendor/gonum.org/v1/gonum/optimize/bfgs.go new file mode 100644 index 00000000..997d991b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/bfgs.go @@ -0,0 +1,160 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "math" + + "gonum.org/v1/gonum/mat" +) + +// BFGS implements the Broyden–Fletcher–Goldfarb–Shanno optimization method. It +// is a quasi-Newton method that performs successive rank-one updates to an +// estimate of the inverse Hessian of the objective function. It exhibits +// super-linear convergence when in proximity to a local minimum. It has memory +// cost that is O(n^2) relative to the input dimension. +type BFGS struct { + // Linesearcher selects suitable steps along the descent direction. + // Accepted steps should satisfy the strong Wolfe conditions. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + + ls *LinesearchMethod + + dim int + x mat.VecDense // Location of the last major iteration. + grad mat.VecDense // Gradient at the last major iteration. + s mat.VecDense // Difference between locations in this and the previous iteration. + y mat.VecDense // Difference between gradients in this and the previous iteration. + tmp mat.VecDense + + invHess *mat.SymDense + + first bool // Indicator of the first iteration. +} + +func (b *BFGS) Init(loc *Location) (Operation, error) { + if b.Linesearcher == nil { + b.Linesearcher = &Bisection{} + } + if b.ls == nil { + b.ls = &LinesearchMethod{} + } + b.ls.Linesearcher = b.Linesearcher + b.ls.NextDirectioner = b + + return b.ls.Init(loc) +} + +func (b *BFGS) Iterate(loc *Location) (Operation, error) { + return b.ls.Iterate(loc) +} + +func (b *BFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + b.dim = dim + b.first = true + + x := mat.NewVecDense(dim, loc.X) + grad := mat.NewVecDense(dim, loc.Gradient) + b.x.CloneVec(x) + b.grad.CloneVec(grad) + + b.y.Reset() + b.s.Reset() + b.tmp.Reset() + + if b.invHess == nil || cap(b.invHess.RawSymmetric().Data) < dim*dim { + b.invHess = mat.NewSymDense(dim, nil) + } else { + b.invHess = mat.NewSymDense(dim, b.invHess.RawSymmetric().Data[:dim*dim]) + } + // The values of the inverse Hessian are initialized in the first call to + // NextDirection. + + // Initial direction is just negative of the gradient because the Hessian + // is an identity matrix. + d := mat.NewVecDense(dim, dir) + d.ScaleVec(-1, grad) + return 1 / mat.Norm(d, 2) +} + +func (b *BFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) { + dim := b.dim + if len(loc.X) != dim { + panic("bfgs: unexpected size mismatch") + } + if len(loc.Gradient) != dim { + panic("bfgs: unexpected size mismatch") + } + if len(dir) != dim { + panic("bfgs: unexpected size mismatch") + } + + x := mat.NewVecDense(dim, loc.X) + grad := mat.NewVecDense(dim, loc.Gradient) + + // s = x_{k+1} - x_{k} + b.s.SubVec(x, &b.x) + // y = g_{k+1} - g_{k} + b.y.SubVec(grad, &b.grad) + + sDotY := mat.Dot(&b.s, &b.y) + + if b.first { + // Rescale the initial Hessian. + // From: Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). + // Springer (2006), page 143, eq. 6.20. + yDotY := mat.Dot(&b.y, &b.y) + scale := sDotY / yDotY + for i := 0; i < dim; i++ { + for j := i; j < dim; j++ { + if i == j { + b.invHess.SetSym(i, i, scale) + } else { + b.invHess.SetSym(i, j, 0) + } + } + } + b.first = false + } + + if math.Abs(sDotY) != 0 { + // Update the inverse Hessian according to the formula + // + // B_{k+1}^-1 = B_k^-1 + // + (s_k^T y_k + y_k^T B_k^-1 y_k) / (s_k^T y_k)^2 * (s_k s_k^T) + // - (B_k^-1 y_k s_k^T + s_k y_k^T B_k^-1) / (s_k^T y_k). + // + // Note that y_k^T B_k^-1 y_k is a scalar, and that the third term is a + // rank-two update where B_k^-1 y_k is one vector and s_k is the other. + yBy := mat.Inner(&b.y, b.invHess, &b.y) + b.tmp.MulVec(b.invHess, &b.y) + scale := (1 + yBy/sDotY) / sDotY + b.invHess.SymRankOne(b.invHess, scale, &b.s) + b.invHess.RankTwo(b.invHess, -1/sDotY, &b.tmp, &b.s) + } + + // Update the stored BFGS data. + b.x.CopyVec(x) + b.grad.CopyVec(grad) + + // New direction is stored in dir. + d := mat.NewVecDense(dim, dir) + d.MulVec(b.invHess, grad) + d.ScaleVec(-1, d) + + return 1 +} + +func (*BFGS) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/vendor/gonum.org/v1/gonum/optimize/bisection.go b/vendor/gonum.org/v1/gonum/optimize/bisection.go new file mode 100644 index 00000000..6dfe8652 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/bisection.go @@ -0,0 +1,146 @@ +// Copyright ©2014 The gonum 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 optimize + +import "math" + +const ( + defaultBisectionCurvature = 0.9 +) + +// Bisection is a Linesearcher that uses a bisection to find a point that +// satisfies the strong Wolfe conditions with the given curvature factor and +// a decrease factor of zero. +type Bisection struct { + // CurvatureFactor is the constant factor in the curvature condition. + // Smaller values result in a more exact line search. + // A set value must be in the interval (0, 1), otherwise Init will panic. + // If it is zero, it will be defaulted to 0.9. + CurvatureFactor float64 + + minStep float64 + maxStep float64 + currStep float64 + + initF float64 + minF float64 + maxF float64 + lastF float64 + + initGrad float64 + + lastOp Operation +} + +func (b *Bisection) Init(f, g float64, step float64) Operation { + if step <= 0 { + panic("bisection: bad step size") + } + if g >= 0 { + panic("bisection: initial derivative is non-negative") + } + + if b.CurvatureFactor == 0 { + b.CurvatureFactor = defaultBisectionCurvature + } + if b.CurvatureFactor <= 0 || b.CurvatureFactor >= 1 { + panic("bisection: CurvatureFactor not between 0 and 1") + } + + b.minStep = 0 + b.maxStep = math.Inf(1) + b.currStep = step + + b.initF = f + b.minF = f + b.maxF = math.NaN() + + b.initGrad = g + + // Only evaluate the gradient when necessary. + b.lastOp = FuncEvaluation + return b.lastOp +} + +func (b *Bisection) Iterate(f, g float64) (Operation, float64, error) { + if b.lastOp != FuncEvaluation && b.lastOp != GradEvaluation { + panic("bisection: Init has not been called") + } + minF := b.initF + if b.maxF < minF { + minF = b.maxF + } + if b.minF < minF { + minF = b.minF + } + if b.lastOp == FuncEvaluation { + // See if the function value is good enough to make progress. If it is, + // evaluate the gradient. If not, set it to the upper bound if the bound + // has not yet been found, otherwise iterate toward the minimum location. + if f <= minF { + b.lastF = f + b.lastOp = GradEvaluation + return b.lastOp, b.currStep, nil + } + if math.IsInf(b.maxStep, 1) { + b.maxStep = b.currStep + b.maxF = f + return b.nextStep((b.minStep + b.maxStep) / 2) + } + if b.minF <= b.maxF { + b.maxStep = b.currStep + b.maxF = f + } else { + b.minStep = b.currStep + b.minF = f + } + return b.nextStep((b.minStep + b.maxStep) / 2) + } + f = b.lastF + // The function value was lower. Check if this location is sufficient to + // converge the linesearch, otherwise iterate. + if StrongWolfeConditionsMet(f, g, minF, b.initGrad, b.currStep, 0, b.CurvatureFactor) { + b.lastOp = MajorIteration + return b.lastOp, b.currStep, nil + } + if math.IsInf(b.maxStep, 1) { + // The function value is lower. If the gradient is positive, an upper bound + // of the minimum been found. If the gradient is negative, search farther + // in that direction. + if g > 0 { + b.maxStep = b.currStep + b.maxF = f + return b.nextStep((b.minStep + b.maxStep) / 2) + } + b.minStep = b.currStep + b.minF = f + return b.nextStep(b.currStep * 2) + } + // The interval has been bounded, and we have found a new lowest value. Use + // the gradient to decide which direction. + if g < 0 { + b.minStep = b.currStep + b.minF = f + } else { + b.maxStep = b.currStep + b.maxF = f + } + return b.nextStep((b.minStep + b.maxStep) / 2) +} + +// nextStep checks if the new step is equal to the old step. +// This can happen if min and max are the same, or if the step size is infinity, +// both of which indicate the minimization must stop. If the steps are different, +// it sets the new step size and returns the evaluation type and the step. If the steps +// are the same, it returns an error. +func (b *Bisection) nextStep(step float64) (Operation, float64, error) { + if b.currStep == step { + b.lastOp = NoOperation + return b.lastOp, b.currStep, ErrLinesearcherFailure + } + b.currStep = step + b.lastOp = FuncEvaluation + return b.lastOp, b.currStep, nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/cg.go b/vendor/gonum.org/v1/gonum/optimize/cg.go new file mode 100644 index 00000000..88612d3f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/cg.go @@ -0,0 +1,313 @@ +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +const ( + iterationRestartFactor = 6 + angleRestartThreshold = -0.9 +) + +// CGVariant calculates the scaling parameter, β, used for updating the +// conjugate direction in the nonlinear conjugate gradient (CG) method. +type CGVariant interface { + // Init is called at the first iteration and provides a way to initialize + // any internal state. + Init(loc *Location) + // Beta returns the value of the scaling parameter that is computed + // according to the particular variant of the CG method. + Beta(grad, gradPrev, dirPrev []float64) float64 +} + +// CG implements the nonlinear conjugate gradient method for solving nonlinear +// unconstrained optimization problems. It is a line search method that +// generates the search directions d_k according to the formula +// d_{k+1} = -∇f_{k+1} + β_k*d_k, d_0 = -∇f_0. +// Variants of the conjugate gradient method differ in the choice of the +// parameter β_k. The conjugate gradient method usually requires fewer function +// evaluations than the gradient descent method and no matrix storage, but +// L-BFGS is usually more efficient. +// +// CG implements a restart strategy that takes the steepest descent direction +// (i.e., d_{k+1} = -∇f_{k+1}) whenever any of the following conditions holds: +// +// - A certain number of iterations has elapsed without a restart. This number +// is controllable via IterationRestartFactor and if equal to 0, it is set to +// a reasonable default based on the problem dimension. +// - The angle between the gradients at two consecutive iterations ∇f_k and +// ∇f_{k+1} is too large. +// - The direction d_{k+1} is not a descent direction. +// - β_k returned from CGVariant.Beta is equal to zero. +// +// The line search for CG must yield step sizes that satisfy the strong Wolfe +// conditions at every iteration, otherwise the generated search direction +// might fail to be a descent direction. The line search should be more +// stringent compared with those for Newton-like methods, which can be achieved +// by setting the gradient constant in the strong Wolfe conditions to a small +// value. +// +// See also William Hager, Hongchao Zhang, A survey of nonlinear conjugate +// gradient methods. Pacific Journal of Optimization, 2 (2006), pp. 35-58, and +// references therein. +type CG struct { + // Linesearcher must satisfy the strong Wolfe conditions at every iteration. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + // Variant implements the particular CG formula for computing β_k. + // If Variant is nil, an appropriate default is chosen. + Variant CGVariant + // InitialStep estimates the initial line search step size, because the CG + // method does not generate well-scaled search directions. + // If InitialStep is nil, an appropriate default is chosen. + InitialStep StepSizer + + // IterationRestartFactor determines the frequency of restarts based on the + // problem dimension. The negative gradient direction is taken whenever + // ceil(IterationRestartFactor*(problem dimension)) iterations have elapsed + // without a restart. For medium and large-scale problems + // IterationRestartFactor should be set to 1, low-dimensional problems a + // larger value should be chosen. Note that if the ceil function returns 1, + // CG will be identical to gradient descent. + // If IterationRestartFactor is 0, it will be set to 6. + // CG will panic if IterationRestartFactor is negative. + IterationRestartFactor float64 + // AngleRestartThreshold sets the threshold angle for restart. The method + // is restarted if the cosine of the angle between two consecutive + // gradients is smaller than or equal to AngleRestartThreshold, that is, if + // ∇f_k·∇f_{k+1} / (|∇f_k| |∇f_{k+1}|) <= AngleRestartThreshold. + // A value of AngleRestartThreshold closer to -1 (successive gradients in + // exact opposite directions) will tend to reduce the number of restarts. + // If AngleRestartThreshold is 0, it will be set to -0.9. + // CG will panic if AngleRestartThreshold is not in the interval [-1, 0]. + AngleRestartThreshold float64 + + ls *LinesearchMethod + + restartAfter int + iterFromRestart int + + dirPrev []float64 + gradPrev []float64 + gradPrevNorm float64 +} + +func (cg *CG) Init(loc *Location) (Operation, error) { + if cg.IterationRestartFactor < 0 { + panic("cg: IterationRestartFactor is negative") + } + if cg.AngleRestartThreshold < -1 || cg.AngleRestartThreshold > 0 { + panic("cg: AngleRestartThreshold not in [-1, 0]") + } + + if cg.Linesearcher == nil { + cg.Linesearcher = &MoreThuente{CurvatureFactor: 0.1} + } + if cg.Variant == nil { + cg.Variant = &HestenesStiefel{} + } + if cg.InitialStep == nil { + cg.InitialStep = &FirstOrderStepSize{} + } + + if cg.IterationRestartFactor == 0 { + cg.IterationRestartFactor = iterationRestartFactor + } + if cg.AngleRestartThreshold == 0 { + cg.AngleRestartThreshold = angleRestartThreshold + } + + if cg.ls == nil { + cg.ls = &LinesearchMethod{} + } + cg.ls.Linesearcher = cg.Linesearcher + cg.ls.NextDirectioner = cg + + return cg.ls.Init(loc) +} + +func (cg *CG) Iterate(loc *Location) (Operation, error) { + return cg.ls.Iterate(loc) +} + +func (cg *CG) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + + cg.restartAfter = int(math.Ceil(cg.IterationRestartFactor * float64(dim))) + cg.iterFromRestart = 0 + + // The initial direction is always the negative gradient. + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + + cg.dirPrev = resize(cg.dirPrev, dim) + copy(cg.dirPrev, dir) + cg.gradPrev = resize(cg.gradPrev, dim) + copy(cg.gradPrev, loc.Gradient) + cg.gradPrevNorm = floats.Norm(loc.Gradient, 2) + + cg.Variant.Init(loc) + return cg.InitialStep.Init(loc, dir) +} + +func (cg *CG) NextDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + + cg.iterFromRestart++ + var restart bool + if cg.iterFromRestart == cg.restartAfter { + // Restart because too many iterations have been taken without a restart. + restart = true + } + + gDot := floats.Dot(loc.Gradient, cg.gradPrev) + gNorm := floats.Norm(loc.Gradient, 2) + if gDot <= cg.AngleRestartThreshold*gNorm*cg.gradPrevNorm { + // Restart because the angle between the last two gradients is too large. + restart = true + } + + // Compute the scaling factor β_k even when restarting, because cg.Variant + // may be keeping an inner state that needs to be updated at every iteration. + beta := cg.Variant.Beta(loc.Gradient, cg.gradPrev, cg.dirPrev) + if beta == 0 { + // β_k == 0 means that the steepest descent direction will be taken, so + // indicate that the method is in fact being restarted. + restart = true + } + if !restart { + // The method is not being restarted, so update the descent direction. + floats.AddScaled(dir, beta, cg.dirPrev) + if floats.Dot(loc.Gradient, dir) >= 0 { + // Restart because the new direction is not a descent direction. + restart = true + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + } + } + + // Get the initial line search step size from the StepSizer even if the + // method was restarted, because StepSizers need to see every iteration. + stepSize = cg.InitialStep.StepSize(loc, dir) + if restart { + // The method was restarted and since the steepest descent direction is + // not related to the previous direction, discard the estimated step + // size from cg.InitialStep and use step size of 1 instead. + stepSize = 1 + // Reset to 0 the counter of iterations taken since the last restart. + cg.iterFromRestart = 0 + } + + copy(cg.gradPrev, loc.Gradient) + copy(cg.dirPrev, dir) + cg.gradPrevNorm = gNorm + return stepSize +} + +func (*CG) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} + +// FletcherReeves implements the Fletcher-Reeves variant of the CG method that +// computes the scaling parameter β_k according to the formula +// β_k = |∇f_{k+1}|^2 / |∇f_k|^2. +type FletcherReeves struct { + prevNorm float64 +} + +func (fr *FletcherReeves) Init(loc *Location) { + fr.prevNorm = floats.Norm(loc.Gradient, 2) +} + +func (fr *FletcherReeves) Beta(grad, _, _ []float64) (beta float64) { + norm := floats.Norm(grad, 2) + beta = (norm / fr.prevNorm) * (norm / fr.prevNorm) + fr.prevNorm = norm + return beta +} + +// PolakRibierePolyak implements the Polak-Ribiere-Polyak variant of the CG +// method that computes the scaling parameter β_k according to the formula +// β_k = max(0, ∇f_{k+1}·y_k / |∇f_k|^2), +// where y_k = ∇f_{k+1} - ∇f_k. +type PolakRibierePolyak struct { + prevNorm float64 +} + +func (pr *PolakRibierePolyak) Init(loc *Location) { + pr.prevNorm = floats.Norm(loc.Gradient, 2) +} + +func (pr *PolakRibierePolyak) Beta(grad, gradPrev, _ []float64) (beta float64) { + norm := floats.Norm(grad, 2) + dot := floats.Dot(grad, gradPrev) + beta = (norm*norm - dot) / (pr.prevNorm * pr.prevNorm) + pr.prevNorm = norm + return math.Max(0, beta) +} + +// HestenesStiefel implements the Hestenes-Stiefel variant of the CG method +// that computes the scaling parameter β_k according to the formula +// β_k = max(0, ∇f_{k+1}·y_k / d_k·y_k), +// where y_k = ∇f_{k+1} - ∇f_k. +type HestenesStiefel struct { + y []float64 +} + +func (hs *HestenesStiefel) Init(loc *Location) { + hs.y = resize(hs.y, len(loc.Gradient)) +} + +func (hs *HestenesStiefel) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(hs.y, grad, gradPrev) + beta = floats.Dot(grad, hs.y) / floats.Dot(dirPrev, hs.y) + return math.Max(0, beta) +} + +// DaiYuan implements the Dai-Yuan variant of the CG method that computes the +// scaling parameter β_k according to the formula +// β_k = |∇f_{k+1}|^2 / d_k·y_k, +// where y_k = ∇f_{k+1} - ∇f_k. +type DaiYuan struct { + y []float64 +} + +func (dy *DaiYuan) Init(loc *Location) { + dy.y = resize(dy.y, len(loc.Gradient)) +} + +func (dy *DaiYuan) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(dy.y, grad, gradPrev) + norm := floats.Norm(grad, 2) + return norm * norm / floats.Dot(dirPrev, dy.y) +} + +// HagerZhang implements the Hager-Zhang variant of the CG method that computes the +// scaling parameter β_k according to the formula +// β_k = (y_k - 2 d_k |y_k|^2/(d_k·y_k))·∇f_{k+1} / (d_k·y_k), +// where y_k = ∇f_{k+1} - ∇f_k. +type HagerZhang struct { + y []float64 +} + +func (hz *HagerZhang) Init(loc *Location) { + hz.y = resize(hz.y, len(loc.Gradient)) +} + +func (hz *HagerZhang) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(hz.y, grad, gradPrev) + dirDotY := floats.Dot(dirPrev, hz.y) + gDotY := floats.Dot(grad, hz.y) + gDotDir := floats.Dot(grad, dirPrev) + yNorm := floats.Norm(hz.y, 2) + return (gDotY - 2*gDotDir*yNorm*yNorm/dirDotY) / dirDotY +} diff --git a/vendor/gonum.org/v1/gonum/optimize/convex/lp/convert.go b/vendor/gonum.org/v1/gonum/optimize/convex/lp/convert.go new file mode 100644 index 00000000..66ebe2ea --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/convex/lp/convert.go @@ -0,0 +1,137 @@ +// Copyright ©2016 The gonum 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 lp + +import ( + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// TODO(btracey): Have some sort of preprocessing step for helping to fix A to make it +// full rank? +// TODO(btracey): Reduce rows? Get rid of all zeros, places where only one variable +// is there, etc. Could be implemented with a Reduce function. +// TODO(btracey): Provide method of artificial variables for help when problem +// is infeasible? +// TODO(btracey): Add an lp.Solve that solves an LP in non-standard form. + +// Convert converts a General-form LP into a standard form LP. +// The general form of an LP is: +// minimize c^T * x +// s.t G * x <= h +// A * x = b +// And the standard form is: +// minimize cNew^T * x +// s.t aNew * x = bNew +// x >= 0 +// If there are no constraints of the given type, the inputs may be nil. +func Convert(c []float64, g mat.Matrix, h []float64, a mat.Matrix, b []float64) (cNew []float64, aNew *mat.Dense, bNew []float64) { + nVar := len(c) + nIneq := len(h) + + // Check input sizes. + if g == nil { + if nIneq != 0 { + panic(badShape) + } + } else { + gr, gc := g.Dims() + if gr != nIneq { + panic(badShape) + } + if gc != nVar { + panic(badShape) + } + } + + nEq := len(b) + if a == nil { + if nEq != 0 { + panic(badShape) + } + } else { + ar, ac := a.Dims() + if ar != nEq { + panic(badShape) + } + if ac != nVar { + panic(badShape) + } + } + + // Convert the general form LP. + // Derivation: + // 0. Start with general form + // min. c^T * x + // s.t. G * x <= h + // A * x = b + // 1. Introduce slack variables for each constraint + // min. c^T * x + // s.t. G * x + s = h + // A * x = b + // s >= 0 + // 2. Add non-negativity constraints for x by splitting x + // into positive and negative components. + // x = xp - xn + // xp >= 0, xn >= 0 + // This makes the LP + // min. c^T * xp - c^T xn + // s.t. G * xp - G * xn + s = h + // A * xp - A * xn = b + // xp >= 0, xn >= 0, s >= 0 + // 3. Write the above in standard form: + // xt = [xp + // xn + // s ] + // min. [c^T, -c^T, 0] xt + // s.t. [G, -G, I] xt = h + // [A, -A, 0] xt = b + // x >= 0 + + // In summary: + // Original LP: + // min. c^T * x + // s.t. G * x <= h + // A * x = b + // Standard Form: + // xt = [xp; xn; s] + // min. [c^T, -c^T, 0] xt + // s.t. [G, -G, I] xt = h + // [A, -A, 0] xt = b + // x >= 0 + + // New size of x is [xp, xn, s] + nNewVar := nVar + nVar + nIneq + + // Construct cNew = [c; -c; 0] + cNew = make([]float64, nNewVar) + copy(cNew, c) + copy(cNew[nVar:], c) + floats.Scale(-1, cNew[nVar:2*nVar]) + + // New number of equality constraints is the number of total constraints. + nNewEq := nIneq + nEq + + // Construct bNew = [h, b]. + bNew = make([]float64, nNewEq) + copy(bNew, h) + copy(bNew[nIneq:], b) + + // Construct aNew = [G, -G, I; A, -A, 0]. + aNew = mat.NewDense(nNewEq, nNewVar, nil) + if nIneq != 0 { + aNew.Slice(0, nIneq, 0, nVar).(*mat.Dense).Copy(g) + aNew.Slice(0, nIneq, nVar, 2*nVar).(*mat.Dense).Scale(-1, g) + aView := aNew.Slice(0, nIneq, 2*nVar, 2*nVar+nIneq).(*mat.Dense) + for i := 0; i < nIneq; i++ { + aView.Set(i, i, 1) + } + } + if nEq != 0 { + aNew.Slice(nIneq, nIneq+nEq, 0, nVar).(*mat.Dense).Copy(a) + aNew.Slice(nIneq, nIneq+nEq, nVar, 2*nVar).(*mat.Dense).Scale(-1, a) + } + return cNew, aNew, bNew +} diff --git a/vendor/gonum.org/v1/gonum/optimize/convex/lp/doc.go b/vendor/gonum.org/v1/gonum/optimize/convex/lp/doc.go new file mode 100644 index 00000000..7b084247 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/convex/lp/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 lp implements routines to solve linear programming problems. +package lp // import "gonum.org/v1/gonum/optimize/convex/lp" diff --git a/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex.go b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex.go new file mode 100644 index 00000000..eb7757ff --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex.go @@ -0,0 +1,619 @@ +// Copyright ©2016 The gonum 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 lp implements routines for solving linear programs. +package lp + +import ( + "errors" + "fmt" + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// TODO(btracey): Could have a solver structure with an abstract factorizer. With +// this transformation the same high-level code could handle both Dense and Sparse. +// TODO(btracey): Need to improve error handling. Only want to panic if condition number inf. +// TODO(btracey): Performance enhancements. There are currently lots of linear +// solves that can be improved by doing rank-one updates. For example, the swap +// step is just a rank-one update. +// TODO(btracey): Better handling on the linear solve errors. If the condition +// number is not inf and the equation solved "well", should keep moving. + +var ( + ErrBland = errors.New("lp: bland: all replacements are negative or cause ill-conditioned ab") + ErrInfeasible = errors.New("lp: problem is infeasible") + ErrLinSolve = errors.New("lp: linear solve failure") + ErrUnbounded = errors.New("lp: problem is unbounded") + ErrSingular = errors.New("lp: A is singular") + ErrZeroColumn = errors.New("lp: A has a column of all zeros") + ErrZeroRow = errors.New("lp: A has a row of all zeros") +) + +var ( + badShape = "lp: size mismatch" +) + +// TODO(btracey): Should these tolerances be part of a settings struct? + +const ( + // initPosTol is the tolerance on the initial condition being feasible. Strictly, + // the x should be positive, but instead it must be greater than -initPosTol. + initPosTol = 1e-13 + // blandNegTol is the tolerance on the value being greater than 0 in the bland test. + blandNegTol = 1e-14 + // rRoundTol is the tolerance for rounding values to zero when testing if + // constraints are met. + rRoundTol = 1e-13 + // dRoundTol is the tolerance for testing if values are zero for the problem + // being unbounded. + dRoundTol = 1e-13 + // phaseIZeroTol tests if the Phase I problem returned a feasible solution. + phaseIZeroTol = 1e-12 + // blandZeroTol is the tolerance on testing if the bland solution can move. + blandZeroTol = 1e-12 +) + +// Simplex solves a linear program in standard form using Danzig's Simplex +// algorithm. The standard form of a linear program is: +// minimize c^T x +// s.t. A*x = b +// x >= 0 . +// The input tol sets how close to the optimal solution is found (specifically, +// when the maximal reduced cost is below tol). An error will be returned if the +// problem is infeasible or unbounded. In rare cases, numeric errors can cause +// the Simplex to fail. In this case, an error will be returned along with the +// most recently found feasible solution. +// +// The Convert function can be used to transform a general LP into standard form. +// +// The input matrix A must have full rank and may not contain any columns with +// all zeros. Furthermore, len(c) must equal the number of columns of A, and len(b) +// must equal the number of rows of A. Simplex will panic if these conditions are +// not met. +// +// initialBasic can be used to set the initial set of indices for a feasible +// solution to the LP. If an initial feasible solution is not known, initialBasic +// may be nil. If initialBasic is non-nil, len(initialBasic) must equal the number +// of rows of A and must be an actual feasible solution to the LP, otherwise +// Simplex will panic. +// +// A description of the Simplex algorithm can be found in Ch. 8 of +// Strang, Gilbert. "Linear Algebra and Applications." Academic, New York (1976). +// For a detailed video introduction, see lectures 11-13 of UC Math 352 +// https://www.youtube.com/watch?v=ESzYPFkY3og&index=11&list=PLh464gFUoJWOmBYla3zbZbc4nv2AXez6X. +func Simplex(c []float64, A mat.Matrix, b []float64, tol float64, initialBasic []int) (optF float64, optX []float64, err error) { + ans, x, _, err := simplex(initialBasic, c, A, b, tol) + return ans, x, err +} + +func simplex(initialBasic []int, c []float64, A mat.Matrix, b []float64, tol float64) (float64, []float64, []int, error) { + err := verifyInputs(initialBasic, c, A, b) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + return math.NaN(), nil, nil, err + } + m, n := A.Dims() + + // There is at least one optimal solution to the LP which is at the intersection + // to a set of constraint boundaries. For a standard form LP with m variables + // and n equality constraints, at least m-n elements of x must equal zero + // at optimality. The Simplex algorithm solves the standard-form LP by starting + // at an initial constraint vertex and successively moving to adjacent constraint + // vertices. At every vertex, the set of non-zero x values is the "basic + // feasible solution". The list of non-zero x's are maintained in basicIdxs, + // the respective columns of A are in ab, and the actual non-zero values of + // x are in xb. + // + // The LP is equality constrained such that A * x = b. This can be expanded + // to + // ab * xb + an * xn = b + // where ab are the columns of a in the basic set, and an are all of the + // other columns. Since each element of xn is zero by definition, this means + // that for all feasible solutions xb = ab^-1 * b. + // + // Before the simplex algorithm can start, an initial feasible solution must + // be found. If initialBasic is non-nil a feasible solution has been supplied. + // Otherwise the "Phase I" problem must be solved to find an initial feasible + // solution. + + var basicIdxs []int // The indices of the non-zero x values. + var ab *mat.Dense // The subset of columns of A listed in basicIdxs. + var xb []float64 // The non-zero elements of x. xb = ab^-1 b + + if initialBasic != nil { + // InitialBasic supplied. Panic if incorrect length or infeasible. + if len(initialBasic) != m { + panic("lp: incorrect number of initial vectors") + } + ab = mat.NewDense(m, len(initialBasic), nil) + extractColumns(ab, A, initialBasic) + xb = make([]float64, m) + err = initializeFromBasic(xb, ab, b) + if err != nil { + panic(err) + } + basicIdxs = make([]int, len(initialBasic)) + copy(basicIdxs, initialBasic) + } else { + // No initial basis supplied. Solve the PhaseI problem. + basicIdxs, ab, xb, err = findInitialBasic(A, b) + if err != nil { + return math.NaN(), nil, nil, err + } + } + + // basicIdxs contains the indexes for an initial feasible solution, + // ab contains the extracted columns of A, and xb contains the feasible + // solution. All x not in the basic set are 0 by construction. + + // nonBasicIdx is the set of nonbasic variables. + nonBasicIdx := make([]int, 0, n-m) + inBasic := make(map[int]struct{}) + for _, v := range basicIdxs { + inBasic[v] = struct{}{} + } + for i := 0; i < n; i++ { + _, ok := inBasic[i] + if !ok { + nonBasicIdx = append(nonBasicIdx, i) + } + } + + // cb is the subset of c for the basic variables. an and cn + // are the equivalents to ab and cb but for the nonbasic variables. + cb := make([]float64, len(basicIdxs)) + for i, idx := range basicIdxs { + cb[i] = c[idx] + } + cn := make([]float64, len(nonBasicIdx)) + for i, idx := range nonBasicIdx { + cn[i] = c[idx] + } + an := mat.NewDense(m, len(nonBasicIdx), nil) + extractColumns(an, A, nonBasicIdx) + + bVec := mat.NewVecDense(len(b), b) + cbVec := mat.NewVecDense(len(cb), cb) + + // Temporary data needed each iteration. (Described later) + r := make([]float64, n-m) + move := make([]float64, m) + + // Solve the linear program starting from the initial feasible set. This is + // the "Phase 2" problem. + // + // Algorithm: + // 1) Compute the "reduced costs" for the non-basic variables. The reduced + // costs are the lagrange multipliers of the constraints. + // r = cn - an^T * ab^-T * cb + // 2) If all of the reduced costs are positive, no improvement is possible, + // and the solution is optimal (xn can only increase because of + // non-negativity constraints). Otherwise, the solution can be improved and + // one element will be exchanged in the basic set. + // 3) Choose the x_n with the most negative value of r. Call this value xe. + // This variable will be swapped into the basic set. + // 4) Increase xe until the next constraint boundary is met. This will happen + // when the first element in xb becomes 0. The distance xe can increase before + // a given element in xb becomes negative can be found from + // xb = Ab^-1 b - Ab^-1 An xn + // = Ab^-1 b - Ab^-1 Ae xe + // = bhat + d x_e + // xe = bhat_i / - d_i + // where Ae is the column of A corresponding to xe. + // The constraining basic index is the first index for which this is true, + // so remove the element which is min_i (bhat_i / -d_i), assuming d_i is negative. + // If no d_i is less than 0, then the problem is unbounded. + // 5) If the new xe is 0 (that is, bhat_i == 0), then this location is at + // the intersection of several constraints. Use the Bland rule instead + // of the rule in step 4 to avoid cycling. + for { + // Compute reduced costs -- r = cn - an^T ab^-T cb + var tmp mat.VecDense + err = tmp.SolveVec(ab.T(), cbVec) + if err != nil { + break + } + data := make([]float64, n-m) + tmp2 := mat.NewVecDense(n-m, data) + tmp2.MulVec(an.T(), &tmp) + floats.SubTo(r, cn, data) + + // Replace the most negative element in the simplex. If there are no + // negative entries then the optimal solution has been found. + minIdx := floats.MinIdx(r) + if r[minIdx] >= -tol { + break + } + + for i, v := range r { + if math.Abs(v) < rRoundTol { + r[i] = 0 + } + } + + // Compute the moving distance. + err = computeMove(move, minIdx, A, ab, xb, nonBasicIdx) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + break + } + + // Replace the basic index along the tightest constraint. + replace := floats.MinIdx(move) + if move[replace] <= 0 { + replace, minIdx, err = replaceBland(A, ab, xb, basicIdxs, nonBasicIdx, r, move) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + break + } + } + + // Replace the constrained basicIdx with the newIdx. + basicIdxs[replace], nonBasicIdx[minIdx] = nonBasicIdx[minIdx], basicIdxs[replace] + cb[replace], cn[minIdx] = cn[minIdx], cb[replace] + tmpCol1 := mat.Col(nil, replace, ab) + tmpCol2 := mat.Col(nil, minIdx, an) + ab.SetCol(replace, tmpCol2) + an.SetCol(minIdx, tmpCol1) + + // Compute the new xb. + xbVec := mat.NewVecDense(len(xb), xb) + err = xbVec.SolveVec(ab, bVec) + if err != nil { + break + } + } + // Found the optimum successfully or died trying. The basic variables get + // their values, and the non-basic variables are all zero. + opt := floats.Dot(cb, xb) + xopt := make([]float64, n) + for i, v := range basicIdxs { + xopt[v] = xb[i] + } + return opt, xopt, basicIdxs, err +} + +// computeMove computes how far can be moved replacing each index. The results +// are stored into move. +func computeMove(move []float64, minIdx int, A mat.Matrix, ab *mat.Dense, xb []float64, nonBasicIdx []int) error { + // Find ae. + col := mat.Col(nil, nonBasicIdx[minIdx], A) + aCol := mat.NewVecDense(len(col), col) + + // d = - Ab^-1 Ae + nb, _ := ab.Dims() + d := make([]float64, nb) + dVec := mat.NewVecDense(nb, d) + err := dVec.SolveVec(ab, aCol) + if err != nil { + return ErrLinSolve + } + floats.Scale(-1, d) + + for i, v := range d { + if math.Abs(v) < dRoundTol { + d[i] = 0 + } + } + + // If no di < 0, then problem is unbounded. + if floats.Min(d) >= 0 { + return ErrUnbounded + } + + // move = bhat_i / - d_i, assuming d is negative. + bHat := xb // ab^-1 b + for i, v := range d { + if v >= 0 { + move[i] = math.Inf(1) + } else { + move[i] = bHat[i] / math.Abs(v) + } + } + return nil +} + +// replaceBland uses the Bland rule to find the indices to swap if the minimum +// move is 0. The indices to be swapped are replace and minIdx (following the +// nomenclature in the main routine). +func replaceBland(A mat.Matrix, ab *mat.Dense, xb []float64, basicIdxs, nonBasicIdx []int, r, move []float64) (replace, minIdx int, err error) { + m, _ := A.Dims() + // Use the traditional bland rule, except don't replace a constraint which + // causes the new ab to be singular. + for i, v := range r { + if v > -blandNegTol { + continue + } + minIdx = i + err = computeMove(move, minIdx, A, ab, xb, nonBasicIdx) + if err != nil { + // Either unbounded or something went wrong. + return -1, -1, err + } + replace = floats.MinIdx(move) + if math.Abs(move[replace]) > blandZeroTol { + // Large enough that it shouldn't be a problem + return replace, minIdx, nil + } + // Find a zero index where replacement is non-singular. + biCopy := make([]int, len(basicIdxs)) + for replace, v := range move { + if v > blandZeroTol { + continue + } + copy(biCopy, basicIdxs) + biCopy[replace] = nonBasicIdx[minIdx] + abTmp := mat.NewDense(m, len(biCopy), nil) + extractColumns(abTmp, A, biCopy) + // If the condition number is reasonable, use this index. + if mat.Cond(abTmp, 1) < 1e16 { + return replace, minIdx, nil + } + } + } + return -1, -1, ErrBland +} + +func verifyInputs(initialBasic []int, c []float64, A mat.Matrix, b []float64) error { + m, n := A.Dims() + if len(c) != n { + panic("lp: c vector incorrect length") + } + if len(b) != m { + panic("lp: b vector incorrect length") + } + if len(c) != n { + panic("lp: c vector incorrect length") + } + if len(initialBasic) != 0 && len(initialBasic) != m { + panic("lp: initialBasic incorrect length") + } + + // Do some sanity checks so that ab does not become singular during the + // simplex solution. If the ZeroRow checks are removed then the code for + // finding a set of linearly indepent columns must be improved. + + // Check that if a row of A only has zero elements that corresponding + // element in b is zero, otherwise the problem is infeasible. + // Otherwise return ErrZeroRow. + for i := 0; i < m; i++ { + isZero := true + for j := 0; j < n; j++ { + if A.At(i, j) != 0 { + isZero = false + break + } + } + if isZero && b[i] != 0 { + // Infeasible + return ErrInfeasible + } else if isZero { + return ErrZeroRow + } + } + // Check that if a column only has zero elements that the respective C vector + // is positive (otherwise unbounded). Otherwise return ErrZeroColumn. + for j := 0; j < n; j++ { + isZero := true + for i := 0; i < m; i++ { + if A.At(i, j) != 0 { + isZero = false + break + } + } + if isZero && c[j] < 0 { + return ErrUnbounded + } else if isZero { + return ErrZeroColumn + } + } + return nil +} + +// initializeFromBasic initializes the basic feasible solution given a set of +// basic indices. It extracts the columns of A specified by basicIdxs and finds +// the x values at that location. These are stored into xb. +// +// If the columns of A are not linearly independent or if the initial set is not +// feasible, an error is returned. +func initializeFromBasic(xb []float64, ab *mat.Dense, b []float64) error { + m, _ := ab.Dims() + if len(xb) != m { + panic("simplex: bad xb length") + } + xbMat := mat.NewVecDense(m, xb) + + err := xbMat.SolveVec(ab, mat.NewVecDense(m, b)) + if err != nil { + return errors.New("lp: subcolumns of A for supplied initial basic singular") + } + // The solve ensures that the equality constraints are met (ab * xb = b). + // Thus, the solution is feasible if and only if all of the x's are positive. + allPos := true + for _, v := range xb { + if v < -initPosTol { + allPos = false + break + } + } + if !allPos { + return errors.New("lp: supplied subcolumns not a feasible solution") + } + return nil +} + +// extractColumns copies the columns specified by cols into the columns of dst. +func extractColumns(dst *mat.Dense, A mat.Matrix, cols []int) { + r, c := dst.Dims() + ra, _ := A.Dims() + if ra != r { + panic("simplex: row mismatch") + } + if c != len(cols) { + panic("simplex: column mismatch") + } + col := make([]float64, r) + for j, idx := range cols { + mat.Col(col, idx, A) + dst.SetCol(j, col) + } +} + +// findInitialBasic finds an initial basic solution, and returns the basic +// indices, ab, and xb. +func findInitialBasic(A mat.Matrix, b []float64) ([]int, *mat.Dense, []float64, error) { + m, n := A.Dims() + basicIdxs := findLinearlyIndependent(A) + if len(basicIdxs) != m { + return nil, nil, nil, ErrSingular + } + + // It may be that this linearly independent basis is also a feasible set. If + // so, the Phase I problem can be avoided. + ab := mat.NewDense(m, len(basicIdxs), nil) + extractColumns(ab, A, basicIdxs) + xb := make([]float64, m) + err := initializeFromBasic(xb, ab, b) + if err == nil { + return basicIdxs, ab, xb, nil + } + + // This set was not feasible. Instead the "Phase I" problem must be solved + // to find an initial feasible set of basis. + // + // Method: Construct an LP whose optimal solution is a feasible solution + // to the original LP. + // 1) Introduce an artificial variable x_{n+1}. + // 2) Let x_j be the most negative element of x_b (largest constraint violation). + // 3) Add the artificial variable to A with: + // a_{n+1} = b - \sum_{i in basicIdxs} a_i + a_j + // swap j with n+1 in the basicIdxs. + // 4) Define a new LP: + // minimize x_{n+1} + // subject to [A A_{n+1}][x_1 ... x_{n+1}] = b + // x, x_{n+1} >= 0 + // 5) Solve this LP. If x_{n+1} != 0, then the problem is infeasible, otherwise + // the found basis can be used as an initial basis for phase II. + // + // The extra column in Step 3 is defined such that the vector of 1s is an + // initial feasible solution. + + // Find the largest constraint violator. + // Compute a_{n+1} = b - \sum{i in basicIdxs}a_i + a_j. j is in basicIDx, so + // instead just subtract the basicIdx columns that are not minIDx. + minIdx := floats.MinIdx(xb) + aX1 := make([]float64, m) + copy(aX1, b) + col := make([]float64, m) + for i, v := range basicIdxs { + if i == minIdx { + continue + } + mat.Col(col, v, A) + floats.Sub(aX1, col) + } + + // Construct the new LP. + // aNew = [A, a_{n+1}] + // bNew = b + // cNew = 1 for x_{n+1} + aNew := mat.NewDense(m, n+1, nil) + aNew.Copy(A) + aNew.SetCol(n, aX1) + basicIdxs[minIdx] = n // swap minIdx with n in the basic set. + c := make([]float64, n+1) + c[n] = 1 + + // Solve the Phase I linear program. + _, xOpt, newBasic, err := simplex(basicIdxs, c, aNew, b, 1e-10) + if err != nil { + return nil, nil, nil, fmt.Errorf("lp: error finding feasible basis: %s", err) + } + + // The original LP is infeasible if the added variable has non-zero value + // in the optimal solution to the Phase I problem. + if math.Abs(xOpt[n]) > phaseIZeroTol { + return nil, nil, nil, ErrInfeasible + } + + // The basis found in Phase I is a feasible solution to the original LP if + // the added variable is not in the basis. + addedIdx := -1 + for i, v := range newBasic { + if v == n { + addedIdx = i + } + xb[i] = xOpt[v] + } + if addedIdx == -1 { + extractColumns(ab, A, newBasic) + return newBasic, ab, xb, nil + } + + // The value of the added variable is in the basis, but it has a zero value. + // See if exchanging another variable into the basic set finds a feasible + // solution. + basicMap := make(map[int]struct{}) + for _, v := range newBasic { + basicMap[v] = struct{}{} + } + var set bool + for i := range xOpt { + if _, inBasic := basicMap[i]; inBasic { + continue + } + newBasic[addedIdx] = i + if set { + mat.Col(col, i, A) + ab.SetCol(addedIdx, col) + } else { + extractColumns(ab, A, newBasic) + set = true + } + err := initializeFromBasic(xb, ab, b) + if err == nil { + return newBasic, ab, xb, nil + } + } + return nil, nil, nil, ErrInfeasible +} + +// findLinearlyIndependnt finds a set of linearly independent columns of A, and +// returns the column indexes of the linearly independent columns. +func findLinearlyIndependent(A mat.Matrix) []int { + m, n := A.Dims() + idxs := make([]int, 0, m) + columns := mat.NewDense(m, m, nil) + newCol := make([]float64, m) + // Walk in reverse order because slack variables are typically the last columns + // of A. + for i := n - 1; i >= 0; i-- { + if len(idxs) == m { + break + } + mat.Col(newCol, i, A) + columns.SetCol(len(idxs), newCol) + if len(idxs) == 0 { + // A column is linearly independent from the null set. + // If all-zero column of A are allowed, this code needs to be adjusted. + idxs = append(idxs, i) + continue + } + if mat.Cond(columns.Slice(0, m, 0, len(idxs)+1), 1) > 1e12 { + // Not linearly independent. + continue + } + idxs = append(idxs, i) + } + return idxs +} diff --git a/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex_test.go b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex_test.go new file mode 100644 index 00000000..75c759b5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplex_test.go @@ -0,0 +1,269 @@ +// Copyright ©2016 The gonum 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 lp + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +const convergenceTol = 1e-10 + +func TestSimplex(t *testing.T) { + // First test specific inputs. These were collected from failures + // during randomized testing. + // TODO(btracey): Test specific problems with known solutions. + for _, test := range []struct { + A mat.Matrix + b []float64 + c []float64 + tol float64 + initialBasic []int + }{ + { + // Basic feasible LP + A: mat.NewDense(2, 4, []float64{ + -1, 2, 1, 0, + 3, 1, 0, 1, + }), + b: []float64{4, 9}, + c: []float64{-1, -2, 0, 0}, + //initialBasic: nil, + tol: 0, + }, + { + // Zero row that caused linear solver failure + A: mat.NewDense(3, 5, []float64{0.09917822373225804, 0, 0, -0.2588175087223661, -0.5935518220870567, 1.301111422556007, 0.12220247487326946, 0, 0, -1.9194869979254463, 0, 0, 0, 0, -0.8588221231396473}), + b: []float64{0, 0, 0}, + c: []float64{0, 0.598992624019304, 0, 0, 0}, + }, + { + // Case that caused linear solver failure + A: mat.NewDense(13, 26, []float64{-0.7001209024399848, -0.7027502615621812, -0, 0.7354444798695736, -0, 0.476457578966189, 0.7001209024399848, 0.7027502615621812, 0, -0.7354444798695736, 0, -0.476457578966189, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.8446087238391438, -0, -0, 0.7705609478497938, -0, -0, -2.7311218710244463, 0, 0, -0.7705609478497938, 0, 0, 2.7311218710244463, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, 0.8332519091897401, 0.7762132098737671, -0, -0, -0.052470638647269585, 0, -0.8332519091897401, -0.7762132098737671, 0, 0, 0.052470638647269585, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9898577208292023, 0.31653724289408824, -0, -0, 0.17797227766447388, 1.2702427184954932, -0.7998764021535656, -0.31653724289408824, 0, 0, -0.17797227766447388, -1.2702427184954932, 0.7998764021535656, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0, 0.4206278126213235, -0.7253374879437113, 0, 0, 0, 0, -0.4206278126213235, 0.7253374879437113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0.7567988418466963, 0.3304567624749696, 0.8385927625193501, -0.0021606686026376387, -0, 0, 0.7567988418466963, -0.3304567624749696, -0.8385927625193501, 0.0021606686026376387, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2.230107839590404, -0.9897104202085316, -0, 0.24703471683023603, -0, -2.382860345431941, 0.6206871648345162, 0.9897104202085316, 0, -0.24703471683023603, 0, 2.382860345431941, -0.6206871648345162, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 1.4350469221322282, -0.9730343818431852, -0, 2.326429855201535, -0, -0.14347849887004038, -1.4350469221322282, 0.9730343818431852, 0, -2.326429855201535, 0, 0.14347849887004038, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0.7943912888763849, -0.13735037357335078, -0.5101161104860161, -0, -0, -1.4790634590370297, 0.050911195996747316, 0.13735037357335078, 0.5101161104860161, 0, 0, 1.4790634590370297, -0.050911195996747316, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, -0, -0.2515400440591492, 0.2058339272568599, -0, -0, -1.314023802253438, 0, 0.2515400440591492, -0.2058339272568599, 0, 0, 1.314023802253438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0.08279503413614919, -0.16669071891829756, -0, -0.6208413721884664, -0, -0.6348258970402827, -0.08279503413614919, 0.16669071891829756, 0, 0.6208413721884664, 0, 0.6348258970402827, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -0, -0, 0.49634739711260845, -0, -0, -0, 0, 0, -0.49634739711260845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -0.2797437186631715, -0.8356683570259136, 1.8970426594969672, -0.4095711945594497, 0.45831284820623924, -0.6109615338552246, 0.2797437186631715, 0.8356683570259136, -1.8970426594969672, 0.4095711945594497, -0.45831284820623924, 0.6109615338552246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1}), + b: []float64{-0.8446087238391436, 0, 1.9898577208292023, 0, 0, -2.230107839590404, 0, 0.20560871112361512, 0, 0, 0, 0, 0}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + { + // Phase 1 of the above that panicked + A: mat.NewDense(26, 52, []float64{0.7001209024399848, -0, -0, -0.31653724289408824, -0, -0, 0.9897104202085316, -1.4350469221322282, 0.13735037357335078, -0, -0.08279503413614919, -0, 0.2797437186631715, -0.7001209024399848, 0, 0, 0.31653724289408824, 0, 0, -0.9897104202085316, 1.4350469221322282, -0.13735037357335078, 0, 0.08279503413614919, 0, -0.2797437186631715, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7027502615621812, -0, -0.8332519091897401, -0, -0, 0.7567988418466963, -0, 0.9730343818431852, 0.5101161104860161, 0.2515400440591492, 0.16669071891829756, -0, 0.8356683570259136, -0.7027502615621812, 0, 0.8332519091897401, 0, 0, -0.7567988418466963, 0, -0.9730343818431852, -0.5101161104860161, -0.2515400440591492, -0.16669071891829756, 0, -0.8356683570259136, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0.7705609478497938, -0.7762132098737671, -0, -0, -0.3304567624749696, -0.24703471683023603, -0, -0, -0.2058339272568599, -0, -0.49634739711260845, -1.8970426594969672, 0, 0.7705609478497938, 0.7762132098737671, 0, 0, 0.3304567624749696, 0.24703471683023603, 0, 0, 0.2058339272568599, 0, 0.49634739711260845, 1.8970426594969672, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7354444798695736, -0, -0, -0.17797227766447388, -0, -0.8385927625193501, -0, -2.326429855201535, -0, -0, 0.6208413721884664, -0, 0.4095711945594497, 0.7354444798695736, 0, 0, 0.17797227766447388, 0, 0.8385927625193501, 0, 2.326429855201535, 0, 0, -0.6208413721884664, 0, -0.4095711945594497, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1.2702427184954932, -0.4206278126213235, 0.0021606686026376387, 2.382860345431941, -0, 1.4790634590370297, -0, -0, -0, -0.45831284820623924, 0, 0, 0, 1.2702427184954932, 0.4206278126213235, -0.0021606686026376387, -2.382860345431941, 0, -1.4790634590370297, 0, 0, 0, 0.45831284820623924, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.476457578966189, 2.7311218710244463, 0.052470638647269585, 0.7998764021535656, 0.7253374879437113, -0, -0.6206871648345162, 0.14347849887004038, -0.050911195996747316, 1.314023802253438, 0.6348258970402827, -0, 0.6109615338552246, 0.476457578966189, -2.7311218710244463, -0.052470638647269585, -0.7998764021535656, -0.7253374879437113, 0, 0.6206871648345162, -0.14347849887004038, 0.050911195996747316, -1.314023802253438, -0.6348258970402827, 0, -0.6109615338552246, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7001209024399848, -0, -0, 0.31653724289408824, -0, -0, -0.9897104202085316, 1.4350469221322282, -0.13735037357335078, -0, 0.08279503413614919, -0, -0.2797437186631715, 0.7001209024399848, 0, 0, -0.31653724289408824, 0, 0, 0.9897104202085316, -1.4350469221322282, 0.13735037357335078, 0, -0.08279503413614919, 0, 0.2797437186631715, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7027502615621812, -0, 0.8332519091897401, -0, -0, -0.7567988418466963, -0, -0.9730343818431852, -0.5101161104860161, -0.2515400440591492, -0.16669071891829756, -0, -0.8356683570259136, 0.7027502615621812, 0, -0.8332519091897401, 0, 0, 0.7567988418466963, 0, 0.9730343818431852, 0.5101161104860161, 0.2515400440591492, 0.16669071891829756, 0, 0.8356683570259136, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0.7705609478497938, 0.7762132098737671, -0, -0, 0.3304567624749696, 0.24703471683023603, -0, -0, 0.2058339272568599, -0, 0.49634739711260845, 1.8970426594969672, 0, -0.7705609478497938, -0.7762132098737671, 0, 0, -0.3304567624749696, -0.24703471683023603, 0, 0, -0.2058339272568599, 0, -0.49634739711260845, -1.8970426594969672, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7354444798695736, -0, -0, 0.17797227766447388, -0, 0.8385927625193501, -0, 2.326429855201535, -0, -0, -0.6208413721884664, -0, -0.4095711945594497, -0.7354444798695736, 0, 0, -0.17797227766447388, 0, -0.8385927625193501, 0, -2.326429855201535, 0, 0, 0.6208413721884664, 0, 0.4095711945594497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, 1.2702427184954932, 0.4206278126213235, -0.0021606686026376387, -2.382860345431941, -0, -1.4790634590370297, -0, -0, -0, 0.45831284820623924, 0, 0, 0, -1.2702427184954932, -0.4206278126213235, 0.0021606686026376387, 2.382860345431941, 0, 1.4790634590370297, 0, 0, 0, -0.45831284820623924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.476457578966189, -2.7311218710244463, -0.052470638647269585, -0.7998764021535656, -0.7253374879437113, -0, 0.6206871648345162, -0.14347849887004038, 0.050911195996747316, -1.314023802253438, -0.6348258970402827, -0, -0.6109615338552246, -0.476457578966189, 2.7311218710244463, 0.052470638647269585, 0.7998764021535656, 0.7253374879437113, 0, -0.6206871648345162, 0.14347849887004038, -0.050911195996747316, 1.314023802253438, 0.6348258970402827, 0, 0.6109615338552246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1.8446087238391438, 1, -0.9898577208292023, 1, 1, 2.230107839590404, 1, 0.7943912888763849, 1, 1, 1, 1, 1, -1.8446087238391438, -1, 0.9898577208292023, -1, -1, -2.230107839590404, -1, -0.7943912888763849, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + c: []float64{-0.8446087238391436, 0, 1.9898577208292023, 0, 0, -2.230107839590404, 0, 0.20560871112361512, 0, 0, 0, 0, 0, 0.8446087238391436, -0, -1.9898577208292023, -0, -0, 2.230107839590404, -0, -0.20560871112361512, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + // Dense case that panicked. + A: mat.NewDense(6, 15, []float64{0.3279477313560112, 0.04126296122557327, 0.24121743535067522, -0.8676933623438741, -0.3279477313560112, -0.04126296122557327, -0.24121743535067522, 0.8676933623438741, 1, 0, 0, 0, 0, 0, 1.3702148909442915, 0.43713186538468607, 0.8613818492485417, -0.9298615442657688, -0.037784779008231184, -0.43713186538468607, -0.8613818492485417, 0.9298615442657688, 0.037784779008231184, 0, 1, 0, 0, 0, 0, 0.3478112701177931, -0, 0.748352668598051, -0.4294796840343912, -0, 0, -0.748352668598051, 0.4294796840343912, 0, 0, 0, 1, 0, 0, 0, -1, -0, 1.1913912184457485, 1.732132186658447, 0.4026384828544584, 0, -1.1913912184457485, -1.732132186658447, -0.4026384828544584, 0, 0, 0, 1, 0, 0, -0.4598555419763902, -0, 1.2088959976921831, -0.7297794575275871, 1.9835614149566971, 0, -1.2088959976921831, 0.7297794575275871, -1.9835614149566971, 0, 0, 0, 0, 1, 0, 0.5986809560819324, 0.19738159369304414, -1.0647198575836367, -0, -0.7264943883762761, -0.19738159369304414, 1.0647198575836367, 0, 0.7264943883762761, 0, 0, 0, 0, 0, 1, 0.36269644970561576}), + b: []float64{2.3702148909442915, 1.3478112701177931, 0, -0.4598555419763902, 1.5986809560819324, 1.3626964497056158}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + { + A: mat.NewDense(6, 11, []float64{-0.036551083288733854, -0.8967234664797694, 0.036551083288733854, 0.8967234664797694, 1, 0, 0, 0, 0, 0, -0.719908817815329, -1.9043311904524263, -0, 1.9043311904524263, 0, 0, 1, 0, 0, 0, 0, -1.142213296802784, -0, 0.17584914855696687, 0, -0.17584914855696687, 0, 0, 1, 0, 0, 0, -0.5423586338987796, -0.21663357118058713, -0.4815354890024489, 0.21663357118058713, 0.4815354890024489, 0, 0, 0, 1, 0, 0, -0.6864090947259134, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, 0.4091621839837596, -1.1853040616164046, -0.11374085137543871, 1.1853040616164046, 0.11374085137543871, 0, 0, 0, 0, 0, 1, -1.7416078575675549}), + b: []float64{0.28009118218467105, -0.14221329680278405, 0.4576413661012204, 0.3135909052740866, 1.4091621839837596, -1.7416078575675549}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + initialBasic: []int{10, 8, 7, 6, 5, 4}, + }, + { + A: mat.NewDense(6, 10, []float64{-0.036551083288733854, -0.8967234664797694, 0.036551083288733854, 0.8967234664797694, 1, 0, 0, 0, 0, 0, -1.9043311904524263, -0, 1.9043311904524263, 0, 0, 1, 0, 0, 0, 0, -0, 0.17584914855696687, 0, -0.17584914855696687, 0, 0, 1, 0, 0, 0, -0.21663357118058713, -0.4815354890024489, 0.21663357118058713, 0.4815354890024489, 0, 0, 0, 1, 0, 0, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, -1.1853040616164046, -0.11374085137543871, 1.1853040616164046, 0.11374085137543871, 0, 0, 0, 0, 0, 1}), + b: []float64{0.28009118218467105, -0.14221329680278405, 0.4576413661012204, 0.3135909052740866, 1.4091621839837596, -1.7416078575675549}, + c: []float64{-1.1951160054922971, -1.354633418345746, 1.1951160054922971, 1.354633418345746, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{0, 8, 7, 6, 5, 4}, + }, + { + A: mat.NewDense(6, 14, []float64{-0.4398035705048233, -0, -1.1190414559968929, -0, 0.4398035705048233, 0, 1.1190414559968929, 0, 1, 0, 0, 0, 0, 0, -0, 0.45892918156139395, -0, -0, 0, -0.45892918156139395, 0, 0, 0, 1, 0, 0, 0, 0, -0, -0, -0.3163051515958635, -0, 0, 0, 0.3163051515958635, 0, 0, 0, 1, 0, 0, 0, -0, -0, -1.8226051692445888, -0.8154477101733032, 0, 0, 1.8226051692445888, 0.8154477101733032, 0, 0, 0, 1, 0, 0, -0, 1.0020104354806922, -2.80863692523519, -0.8493721031516384, 0, -1.0020104354806922, 2.80863692523519, 0.8493721031516384, 0, 0, 0, 0, 1, 0, -0.8292937871394104, -1.4615144665021647, -0, -0, 0.8292937871394104, 1.4615144665021647, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, -1.0154749704172474, 0, 0, 0, -1.5002324315812783}, + c: []float64{1.0665389045026794, 0.097366273706136, 0, 2.7928153636989954, -1.0665389045026794, -0.097366273706136, -0, -2.7928153636989954, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{5, 12, 11, 10, 0, 8}, + }, + { + // Bad Phase I setup. + A: mat.NewDense(6, 7, []float64{1.4009742075419371, 0, 0.05737255493210325, -2.5954004393412915, 0, 1.561789236911904, 0, 0.17152506517602673, 0, 0, 0, 0, 0, -0.3458126550149948, 1.900744052464951, -0.32773164134097343, -0.9648201331251137, 0, 0, 0, 0, -1.3229549190526497, 0.0692227703722903, 0, 0, -0.1024297720479933, 0.4550740188869777, 0, 0.013599438965679167, 0, 0, 0, 0, 0, -0.1164365105021209, 0, 0, 0.4077091957443405, 1.5682816151954875, 0.8411734682369051, 0.22379142247562167, 1.2206581060250778}), + b: []float64{0.3293809220378252, 0, -0.5688424847664554, 0, 0, 1.4832526082339592}, + c: []float64{0.5246370956983506, -0.36608819899109946, 1.5854141981237713, 0.5170486527020665, 0, 1.4006819866163691, 0.7733814538809437}, + }, + { + // The problem is feasible, but the PhaseI problem keeps the last + // variable in the basis. + A: mat.NewDense(2, 3, []float64{0.7171320440380402, 0, 0.22818288617480836, 0, -0.10030202006494793, -0.3282372661549324}), + b: []float64{0.8913013436978257, 0}, + c: []float64{0, 0, 1.16796158316812}, + initialBasic: nil, + }, + { + // Case where primal was returned as feasible, but the dual was returned + // as infeasible. This is the dual. + // Here, the phase I problem returns the value in the basis but equal + // to epsilon and not 0. + A: mat.NewDense(5, 11, []float64{0.48619717875196006, 0.5089083769874058, 1.4064796473022745, -0.48619717875196006, -0.5089083769874058, -1.4064796473022745, 1, 0, 0, 0, 0, 1.5169837857318682, -0, -0, -1.5169837857318682, 0, 0, 0, 1, 0, 0, 0, -1.3096160896447528, 0.12600426735917414, 0.296082394213142, 1.3096160896447528, -0.12600426735917414, -0.296082394213142, 0, 0, 1, 0, 0, -0, -0, 1.9870800277141467, 0, 0, -1.9870800277141467, 0, 0, 0, 1, 0, -0.3822356988571877, -0, -0.1793908926957139, 0.3822356988571877, 0, 0.1793908926957139, 0, 0, 0, 0, 1}), + b: []float64{0.6015865977347667, 0, -1.5648780993757594, 0, 0}, + c: []float64{-0.642801659201449, -0.5412741400343285, -1.4634460998530177, 0.642801659201449, 0.5412741400343285, 1.4634460998530177, 0, 0, 0, 0, 0}, + }, + { + // Caused linear solve error. The error is because replacing the minimum + // index in Bland causes the new basis to be singular. This + // necessitates the ending loop in bland over possible moves. + A: mat.NewDense(9, 23, []float64{-0.898219823758102, -0, -0, -0, 1.067555075209233, 1.581598470243863, -1.0656096883610071, 0.898219823758102, 0, 0, 0, -1.067555075209233, -1.581598470243863, 1.0656096883610071, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1.5657353278668433, 0.5798888118401012, -0, 0.14560553520321928, -0, -0, -0, 1.5657353278668433, -0.5798888118401012, 0, -0.14560553520321928, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -0, -0, -1.5572250142582087, -0, -0, -0, -0, 0, 0, 1.5572250142582087, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1.1266215512973428, -0, 1.0661059397023553, -0, 0, 0, 0, 1.1266215512973428, 0, -1.0661059397023553, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, -2.060232129551813, 1.756900609902372, -0, -0, -0, -0, 0, 2.060232129551813, -1.756900609902372, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.0628806512935949, -0, -0, 0.3306985942820342, -0, 0.5013194822231914, -0, -1.0628806512935949, 0, 0, -0.3306985942820342, 0, -0.5013194822231914, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0.02053916418367785, 2.0967009672108627, -0, 1.276296057052031, -0, -0.8396554873675388, -0, 0.02053916418367785, -2.0967009672108627, 0, -1.276296057052031, 0, 0.8396554873675388, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1.5173172721095745, -0, -0, -0, -0, -0.7781977786718928, -0.08927683907374018, 1.5173172721095745, 0, 0, 0, 0, 0.7781977786718928, 0.08927683907374018, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0, -0, -0, -0, -0, 0.39773149008355624, -0, 0, 0, 0, 0, 0, -0.39773149008355624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + c: []float64{0.24547850255842107, -0.9373919913433648, 0, 0, 0, 0.2961224049153204, 0, -0.24547850255842107, 0.9373919913433648, -0, -0, -0, -0.2961224049153204, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + // Caused error because ALL of the possible replacements in Bland cause. + // ab to be singular. This necessitates outer loop in bland over possible + // moves. + A: mat.NewDense(9, 23, []float64{0.6595219196440785, -0, -0, -1.8259394918781682, -0, -0, 0.005457361044175046, -0.6595219196440785, 0, 0, 1.8259394918781682, 0, 0, -0.005457361044175046, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0.10352878714214864, -0, -0, -0, -0, 0.5945016966696087, 0, 0.10352878714214864, 0, 0, 0, 0, -0.5945016966696087, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0.31734882842876444, -0, -0, -0, -0, -0, -0.716633126367685, -0.31734882842876444, 0, 0, 0, 0, 0, 0.716633126367685, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0.7769812182932578, -0, -0.17370050158829553, 0.19405062263734607, -0, 1.1472330031002533, -0.6776631768730962, 0.7769812182932578, 0, 0.17370050158829553, -0.19405062263734607, 0, -1.1472330031002533, 0.6776631768730962, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, 0.8285611486611473, -0, -0, -0, -0, -0, 0, -0.8285611486611473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -2.088953453647358, 1.3286488791152795, -0, -0, -0, -0, 0.9147833235021142, 2.088953453647358, -1.3286488791152795, 0, 0, 0, 0, -0.9147833235021142, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0, -0, -0, -0, 0.6560365621262937, -0, -0, 0, 0, 0, 0, -0.6560365621262937, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0.8957188338098074, -0, -0, -0, -0, -0, -0, -0.8957188338098074, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0.2761381891117365, -0, -0, -0, 1.1154921426237823, 0.06429872020552618, -0, 0.2761381891117365, 0, 0, 0, -1.1154921426237823, -0.06429872020552618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0.5046208538522362, 1.0859412982429362, -2.066283584195025, 0, -0.2604305274353169}, + c: []float64{0, 0, 0, 0, 0, 0, -0.05793762969330718, -0, -0, -0, -0, -0, -0, 0.05793762969330718, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{22, 11, 7, 19, 18, 17, 16, 15, 14}, + }, + { + // Caused initial supplied basis of Phase I to be singular. + A: mat.NewDense(7, 11, []float64{0, 0, 0, 0, 0, 0.6667874223914787, -0.04779440888372957, -0.810020924434026, 0, 1.4190243477163373, 0, 0, 1.0452496826112936, 1.1966134226828076, 0, 0, 0, 0, -0.676136041089015, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.123232807871834, 0.2795467733707712, 0.21997115467272987, 0, -0.1572003980840453, 0, 0, 0, 0, 0.5130196002804861, 0, -0.005957174211761673, 0.3262874931735277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.5582052881594286, 0, 0.3544026193217651, 0, -1.0761986709145068, 0, 0.2438593072108347, 0, 0, 0, 0, 1.387509848081664, 0, 0, 0.3958750570508226, 1.6281679612990678, 0, 0, -0.24638311667922103, 0, 0, 0, 0, 0, 0, -0.628850893994423}), + b: []float64{0.4135281763629115, 0, 0, 0, 0, 0, 0}, + c: []float64{0.5586772876113472, 0, 0.14261332948424457, 0, -0.016394076753000086, -0.506087285562544, 0, 0.37619482505459145, 1.2943822852419233, 0.5887960293578207, 0}, + }, + } { + testSimplex(t, test.initialBasic, test.c, test.A, test.b, convergenceTol) + } + + rnd := rand.New(rand.NewSource(1)) + // Randomized tests + testRandomSimplex(t, 20000, 0.7, 10, rnd) + testRandomSimplex(t, 20000, 0, 10, rnd) + testRandomSimplex(t, 200, 0, 100, rnd) + testRandomSimplex(t, 2, 0, 400, rnd) +} + +func testRandomSimplex(t *testing.T, nTest int, pZero float64, maxN int, rnd *rand.Rand) { + // Try a bunch of random LPs + for i := 0; i < nTest; i++ { + n := rnd.Intn(maxN) + 2 // n must be at least two. + m := rnd.Intn(n-1) + 1 // m must be between 1 and n + if m == 0 || n == 0 { + continue + } + randValue := func() float64 { + //var pZero float64 + v := rnd.Float64() + if v < pZero { + return 0 + } + return rnd.NormFloat64() + } + a := mat.NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, randValue()) + } + } + b := make([]float64, m) + for i := range b { + b[i] = randValue() + } + + c := make([]float64, n) + for i := range c { + c[i] = randValue() + } + + testSimplex(t, nil, c, a, b, convergenceTol) + } +} + +func testSimplex(t *testing.T, initialBasic []int, c []float64, a mat.Matrix, b []float64, convergenceTol float64) error { + primalOpt, primalX, _, errPrimal := simplex(initialBasic, c, a, b, convergenceTol) + if errPrimal == nil { + // No error solving the simplex, check that the solution is feasible. + var bCheck mat.VecDense + bCheck.MulVec(a, mat.NewVecDense(len(primalX), primalX)) + if !mat.EqualApprox(&bCheck, mat.NewVecDense(len(b), b), 1e-10) { + t.Errorf("No error in primal but solution infeasible") + } + } + + primalInfeasible := errPrimal == ErrInfeasible + primalUnbounded := errPrimal == ErrUnbounded + primalBounded := errPrimal == nil + primalASingular := errPrimal == ErrSingular + primalZeroRow := errPrimal == ErrZeroRow + primalZeroCol := errPrimal == ErrZeroColumn + + primalBad := !primalInfeasible && !primalUnbounded && !primalBounded && !primalASingular && !primalZeroRow && !primalZeroCol + + // It's an error if it's not one of the known returned errors. If it's + // singular the problem is undefined and so the result cannot be compared + // to the dual. + if errPrimal == ErrSingular || primalBad { + if primalBad { + t.Errorf("non-known error returned: %s", errPrimal) + } + return errPrimal + } + + // Compare the result to the answer found from solving the dual LP. + + // Construct and solve the dual LP. + // Standard Form: + // minimize c^T * x + // subject to A * x = b, x >= 0 + // The dual of this problem is + // maximize -b^T * nu + // subject to A^T * nu + c >= 0 + // Which is + // minimize b^T * nu + // subject to -A^T * nu <= c + + negAT := &mat.Dense{} + negAT.Clone(a.T()) + negAT.Scale(-1, negAT) + cNew, aNew, bNew := Convert(b, negAT, c, nil, nil) + + dualOpt, dualX, _, errDual := simplex(nil, cNew, aNew, bNew, convergenceTol) + if errDual == nil { + // Check that the dual is feasible + var bCheck mat.VecDense + bCheck.MulVec(aNew, mat.NewVecDense(len(dualX), dualX)) + if !mat.EqualApprox(&bCheck, mat.NewVecDense(len(bNew), bNew), 1e-10) { + t.Errorf("No error in dual but solution infeasible") + } + } + + // Check about the zero status. + if errPrimal == ErrZeroRow || errPrimal == ErrZeroColumn { + return errPrimal + } + + // If the primal problem is feasible, then the primal and the dual should + // be the same answer. We have flopped the sign in the dual (minimizing + // b^T *nu instead of maximizing -b^T*nu), so flip it back. + if errPrimal == nil { + if errDual != nil { + t.Errorf("Primal feasible but dual errored: %s", errDual) + } + dualOpt *= -1 + if !floats.EqualWithinAbsOrRel(dualOpt, primalOpt, convergenceTol, convergenceTol) { + t.Errorf("Primal and dual value mismatch. Primal %v, dual %v.", primalOpt, dualOpt) + } + } + // If the primal problem is unbounded, then the dual should be infeasible. + if errPrimal == ErrUnbounded && errDual != ErrInfeasible { + t.Errorf("Primal unbounded but dual not infeasible. ErrDual = %s", errDual) + } + + // If the dual is unbounded, then the primal should be infeasible. + if errDual == ErrUnbounded && errPrimal != ErrInfeasible { + t.Errorf("Dual unbounded but primal not infeasible. ErrDual = %s", errPrimal) + } + + // If the primal is infeasible, then the dual should be either infeasible + // or unbounded. + if errPrimal == ErrInfeasible { + if errDual != ErrUnbounded && errDual != ErrInfeasible && errDual != ErrZeroColumn { + t.Errorf("Primal infeasible but dual not infeasible or unbounded: %s", errDual) + } + } + + return errPrimal +} diff --git a/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplexexample_test.go b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplexexample_test.go new file mode 100644 index 00000000..b0daa314 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/convex/lp/simplexexample_test.go @@ -0,0 +1,29 @@ +// Copyright ©2016 The gonum 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 lp_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/optimize/convex/lp" +) + +func ExampleSimplex() { + c := []float64{-1, -2, 0, 0} + A := mat.NewDense(2, 4, []float64{-1, 2, 1, 0, 3, 1, 0, 1}) + b := []float64{4, 9} + + opt, x, err := lp.Simplex(c, A, b, 0, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("opt: %v\n", opt) + fmt.Printf("x: %v\n", x) + // Output: + // opt: -8 + // x: [2 3 0 0] +} diff --git a/vendor/gonum.org/v1/gonum/optimize/doc.go b/vendor/gonum.org/v1/gonum/optimize/doc.go new file mode 100644 index 00000000..1b05a639 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2015 The gonum 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 optimize implements algorithms for finding the optimum value of functions. +package optimize // import "gonum.org/v1/gonum/optimize" diff --git a/vendor/gonum.org/v1/gonum/optimize/errors.go b/vendor/gonum.org/v1/gonum/optimize/errors.go new file mode 100644 index 00000000..07bf5df9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/errors.go @@ -0,0 +1,72 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "errors" + "fmt" + "math" +) + +var ( + // ErrZeroDimensional signifies an optimization was called with an input of length 0. + ErrZeroDimensional = errors.New("optimize: zero dimensional input") + + // ErrLinesearcherFailure signifies that a Linesearcher has iterated too + // many times. This may occur if the gradient tolerance is set too low. + ErrLinesearcherFailure = errors.New("linesearch: failed to converge") + + // ErrNonDescentDirection signifies that LinesearchMethod has received a + // search direction from a NextDirectioner in which the function is not + // decreasing. + ErrNonDescentDirection = errors.New("linesearch: non-descent search direction") + + // ErrNoProgress signifies that LinesearchMethod cannot make further + // progress because there is no change in location after Linesearcher step + // due to floating-point arithmetic. + ErrNoProgress = errors.New("linesearch: no change in location after Linesearcher step") + + // ErrLinesearcherBound signifies that a Linesearcher reached a step that + // lies out of allowed bounds. + ErrLinesearcherBound = errors.New("linesearch: step out of bounds") +) + +// ErrFunc is returned when an initial function value is invalid. The error +// state may be either +Inf or NaN. ErrFunc satisfies the error interface. +type ErrFunc float64 + +func (err ErrFunc) Error() string { + switch { + case math.IsInf(float64(err), 1): + return "optimize: initial function value is infinite" + case math.IsNaN(float64(err)): + return "optimize: initial function value is NaN" + default: + panic("optimize: bad ErrFunc") + } +} + +// ErrGrad is returned when an initial gradient is invalid. The error gradient +// may be either ±Inf or NaN. ErrGrad satisfies the error interface. +type ErrGrad struct { + Grad float64 // Grad is the invalid gradient value. + Index int // Index is the position at which the invalid gradient was found. +} + +func (err ErrGrad) Error() string { + switch { + case math.IsInf(err.Grad, 0): + return fmt.Sprintf("optimize: initial gradient is infinite at position %d", err.Index) + case math.IsNaN(err.Grad): + return fmt.Sprintf("optimize: initial gradient is NaN at position %d", err.Index) + default: + panic("optimize: bad ErrGrad") + } +} + +// List of shared panic strings +var ( + badProblem = "optimize: objective function is undefined" +) diff --git a/vendor/gonum.org/v1/gonum/optimize/functionconvergence.go b/vendor/gonum.org/v1/gonum/optimize/functionconvergence.go new file mode 100644 index 00000000..c532072d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functionconvergence.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum 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 optimize + +import "math" + +// FunctionConverge tests for the convergence of function values. See comment +// in Settings. +type FunctionConverge struct { + Absolute float64 + Relative float64 + Iterations int + + best float64 + iter int +} + +func (fc *FunctionConverge) Init(f float64) { + fc.best = f + fc.iter = 0 +} + +func (fc *FunctionConverge) FunctionConverged(f float64) Status { + if fc.Iterations == 0 { + return NotTerminated + } + maxAbs := math.Max(math.Abs(f), math.Abs(fc.best)) + if f < fc.best && fc.best-f > fc.Relative*maxAbs+fc.Absolute { + fc.best = f + fc.iter = 0 + return NotTerminated + } + fc.iter++ + if fc.iter < fc.Iterations { + return NotTerminated + } + return FunctionConvergence +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/doc.go b/vendor/gonum.org/v1/gonum/optimize/functions/doc.go new file mode 100644 index 00000000..3bdfe8bf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/doc.go @@ -0,0 +1,15 @@ +// Copyright ©2017 The Gonum 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 functions provides objective functions for testing optimization +// algorithms. +// +// We encourage outside contributions of additional test functions that exhibit +// properties not already covered in the testing suite or that have +// significance due to prior use as benchmark cases. +package functions // import "gonum.org/v1/gonum/optimize/functions" + +const ( + badInputDim = "functions: wrong input dimension" +) diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/functions.go b/vendor/gonum.org/v1/gonum/optimize/functions/functions.go new file mode 100644 index 00000000..43a4c948 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/functions.go @@ -0,0 +1,1818 @@ +// Copyright ©2015 The gonum 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 functions + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// Beale implements the Beale's function. +// +// Standard starting points: +// Easy: [1, 1] +// Hard: [1, 4] +// +// References: +// - Beale, E.: On an Iterative Method for Finding a Local Minimum of a +// Function of More than One Variable. Technical Report 25, Statistical +// Techniques Research Group, Princeton University (1958) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Beale struct{} + +func (Beale) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := 1.5 - x[0]*(1-x[1]) + f2 := 2.25 - x[0]*(1-x[1]*x[1]) + f3 := 2.625 - x[0]*(1-x[1]*x[1]*x[1]) + return f1*f1 + f2*f2 + f3*f3 +} + +func (Beale) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + t1 := 1 - x[1] + t2 := 1 - x[1]*x[1] + t3 := 1 - x[1]*x[1]*x[1] + + f1 := 1.5 - x[0]*t1 + f2 := 2.25 - x[0]*t2 + f3 := 2.625 - x[0]*t3 + + grad[0] = -2 * (f1*t1 + f2*t2 + f3*t3) + grad[1] = 2 * x[0] * (f1 + 2*f2*x[1] + 3*f3*x[1]*x[1]) +} + +func (Beale) Hess(hess mat.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + t1 := 1 - x[1] + t2 := 1 - x[1]*x[1] + t3 := 1 - x[1]*x[1]*x[1] + f1 := 1.5 - x[1]*t1 + f2 := 2.25 - x[1]*t2 + f3 := 2.625 - x[1]*t3 + + h00 := 2 * (t1*t1 + t2*t2 + t3*t3) + h01 := 2 * (f1 + x[1]*(2*f2+3*x[1]*f3) - x[0]*(t1+x[1]*(2*t2+3*x[1]*t3))) + h11 := 2 * x[0] * (x[0] + 2*f2 + x[1]*(6*f3+x[0]*x[1]*(4+9*x[1]*x[1]))) + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (Beale) Minima() []Minimum { + return []Minimum{ + { + X: []float64{3, 0.5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP2 implements the the Biggs' EXP2 function. +// +// Standard starting point: +// [1, 2] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP2 struct{} + +func (BiggsEXP2) Func(x []float64) (sum float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - 5*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP2) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - 5*math.Exp(-x[1]*z) - y + + dfdx0 := -z * math.Exp(-x[0]*z) + dfdx1 := 5 * z * math.Exp(-x[1]*z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + } +} + +func (BiggsEXP2) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP3 implements the the Biggs' EXP3 function. +// +// Standard starting point: +// [1, 2, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP3 struct{} + +func (BiggsEXP3) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - x[2]*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP3) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - x[2]*math.Exp(-x[1]*z) - y + + dfdx0 := -z * math.Exp(-x[0]*z) + dfdx1 := x[2] * z * math.Exp(-x[1]*z) + dfdx2 := -math.Exp(-x[1] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + } +} + +func (BiggsEXP3) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP4 implements the the Biggs' EXP4 function. +// +// Standard starting point: +// [1, 2, 1, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP4 struct{} + +func (BiggsEXP4) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP4) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + } +} + +func (BiggsEXP4) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP5 implements the the Biggs' EXP5 function. +// +// Standard starting point: +// [1, 2, 1, 1, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP5 struct{} + +func (BiggsEXP5) Func(x []float64) (sum float64) { + if len(x) != 5 { + panic("dimension of the problem must be 5") + } + + for i := 1; i <= 11; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + 3*math.Exp(-x[4]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP5) Grad(grad, x []float64) { + if len(x) != 5 { + panic("dimension of the problem must be 5") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 11; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + 3*math.Exp(-x[4]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + dfdx4 := -3 * z * math.Exp(-x[4]*z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + grad[4] += 2 * f * dfdx4 + } +} + +func (BiggsEXP5) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5, 4}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP6 implements the the Biggs' EXP6 function. +// +// Standard starting point: +// [1, 2, 1, 1, 1, 1] +// +// References: +// - Biggs, M.C.: Minimization algorithms making use of non-quadratic +// properties of the objective function. IMA J Appl Math 8 (1971), 315-327; +// doi:10.1093/imamat/8.3.315 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BiggsEXP6 struct{} + +func (BiggsEXP6) Func(x []float64) (sum float64) { + if len(x) != 6 { + panic("dimension of the problem must be 6") + } + + for i := 1; i <= 13; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + x[5]*math.Exp(-x[4]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP6) Grad(grad, x []float64) { + if len(x) != 6 { + panic("dimension of the problem must be 6") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 13; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + x[5]*math.Exp(-x[4]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + dfdx4 := -z * x[5] * math.Exp(-x[4]*z) + dfdx5 := math.Exp(-x[4] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + grad[4] += 2 * f * dfdx4 + grad[5] += 2 * f * dfdx5 + } +} + +func (BiggsEXP6) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5, 4, 3}, + F: 0, + Global: true, + }, + { + X: []float64{1.7114159947956764, 17.68319817846745, 1.1631436609697268, + 5.1865615510738605, 1.7114159947949301, 1.1631436609697998}, + F: 0.005655649925499929, + Global: false, + }, + { + // X: []float64{1.22755594752403, X[1] >> 0, 0.83270306333466, X[3] << 0, X[4] = X[0], X[5] = X[2]}, + X: []float64{1.22755594752403, 1000, 0.83270306333466, -1000, 1.22755594752403, 0.83270306333466}, + F: 0.306366772624790, + Global: false, + }, + } +} + +// Box3D implements the Box' three-dimensional function. +// +// Standard starting point: +// [0, 10, 20] +// +// References: +// - Box, M.J.: A comparison of several current optimization methods, and the +// use of transformations in constrained problems. Comput J 9 (1966), 67-77 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Box3D struct{} + +func (Box3D) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 10; i++ { + c := -float64(i) / 10 + y := math.Exp(c) - math.Exp(10*c) + f := math.Exp(c*x[0]) - math.Exp(c*x[1]) - x[2]*y + sum += f * f + } + return sum +} + +func (Box3D) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + grad[0] = 0 + grad[1] = 0 + grad[2] = 0 + for i := 1; i <= 10; i++ { + c := -float64(i) / 10 + y := math.Exp(c) - math.Exp(10*c) + f := math.Exp(c*x[0]) - math.Exp(c*x[1]) - x[2]*y + grad[0] += 2 * f * c * math.Exp(c*x[0]) + grad[1] += -2 * f * c * math.Exp(c*x[1]) + grad[2] += -2 * f * y + } +} + +func (Box3D) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1}, + F: 0, + Global: true, + }, + { + X: []float64{10, 1, -1}, + F: 0, + Global: true, + }, + { + // Any point at the line {a, a, 0}. + X: []float64{1, 1, 0}, + F: 0, + Global: true, + }, + } +} + +// BraninHoo implements the Branin-Hoo function. BraninHoo is a 2-dimensional +// test function with three global minima. It is typically evaluated in the domain +// x_0 ∈ [-5, 10], x_1 ∈ [0, 15]. +// f(x) = (x_1 - (5.1/(4π^2))*x_0^2 + (5/π)*x_0 - 6)^2 + 10*(1-1/(8π))cos(x_0) + 10 +// It has a minimum value of 0.397887 at x^* = {(-π, 12.275), (π, 2.275), (9.424778, 2.475)} +// +// Reference: +// https://www.sfu.ca/~ssurjano/branin.html (obtained June 2017) +type BraninHoo struct{} + +func (BraninHoo) Func(x []float64) float64 { + if len(x) != 2 { + panic("functions: dimension of the problem must be 2") + } + a, b, c, r, s, t := 1.0, 5.1/(4*math.Pi*math.Pi), 5/math.Pi, 6.0, 10.0, 1/(8*math.Pi) + + term := x[1] - b*x[0]*x[0] + c*x[0] - r + return a*term*term + s*(1-t)*math.Cos(x[0]) + s +} + +func (BraninHoo) Minima() []Minimum { + return []Minimum{ + { + X: []float64{-math.Pi, 12.275}, + F: 0.397887, + Global: true, + }, + { + X: []float64{math.Pi, 2.275}, + F: 0.397887, + Global: true, + }, + { + X: []float64{9.424778, 2.475}, + F: 0.397887, + Global: true, + }, + } +} + +// BrownBadlyScaled implements the Brown's badly scaled function. +// +// Standard starting point: +// [1, 1] +// +// References: +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BrownBadlyScaled struct{} + +func (BrownBadlyScaled) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := x[0] - 1e6 + f2 := x[1] - 2e-6 + f3 := x[0]*x[1] - 2 + return f1*f1 + f2*f2 + f3*f3 +} + +func (BrownBadlyScaled) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := x[0] - 1e6 + f2 := x[1] - 2e-6 + f3 := x[0]*x[1] - 2 + grad[0] = 2*f1 + 2*f3*x[1] + grad[1] = 2*f2 + 2*f3*x[0] +} + +func (BrownBadlyScaled) Hess(hess mat.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + h00 := 2 + 2*x[1]*x[1] + h01 := 4*x[0]*x[1] - 4 + h11 := 2 + 2*x[0]*x[0] + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (BrownBadlyScaled) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1e6, 2e-6}, + F: 0, + Global: true, + }, + } +} + +// BrownAndDennis implements the Brown and Dennis function. +// +// Standard starting point: +// [25, 5, -5, -1] +// +// References: +// - Brown, K.M., Dennis, J.E.: New computational algorithms for minimizing a +// sum of squares of nonlinear functions. Research Report Number 71-6, Yale +// University (1971) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BrownAndDennis struct{} + +func (BrownAndDennis) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + for i := 1; i <= 20; i++ { + c := float64(i) / 5 + f1 := x[0] + c*x[1] - math.Exp(c) + f2 := x[2] + x[3]*math.Sin(c) - math.Cos(c) + f := f1*f1 + f2*f2 + sum += f * f + } + return sum +} + +func (BrownAndDennis) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 20; i++ { + c := float64(i) / 5 + f1 := x[0] + c*x[1] - math.Exp(c) + f2 := x[2] + x[3]*math.Sin(c) - math.Cos(c) + f := f1*f1 + f2*f2 + grad[0] += 4 * f * f1 + grad[1] += 4 * f * f1 * c + grad[2] += 4 * f * f2 + grad[3] += 4 * f * f2 * math.Sin(c) + } +} + +func (BrownAndDennis) Hess(hess mat.MutableSymmetric, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + for i := 0; i < 4; i++ { + for j := i; j < 4; j++ { + hess.SetSym(i, j, 0) + } + } + for i := 1; i <= 20; i++ { + d1 := float64(i) / 5 + d2 := math.Sin(d1) + t1 := x[0] + d1*x[1] - math.Exp(d1) + t2 := x[2] + d2*x[3] - math.Cos(d1) + t := t1*t1 + t2*t2 + s3 := 2 * t1 * t2 + r1 := t + 2*t1*t1 + r2 := t + 2*t2*t2 + hess.SetSym(0, 0, hess.At(0, 0)+r1) + hess.SetSym(0, 1, hess.At(0, 1)+d1*r1) + hess.SetSym(1, 1, hess.At(1, 1)+d1*d1*r1) + hess.SetSym(0, 2, hess.At(0, 2)+s3) + hess.SetSym(1, 2, hess.At(1, 2)+d1*s3) + hess.SetSym(2, 2, hess.At(2, 2)+r2) + hess.SetSym(0, 3, hess.At(0, 3)+d2*s3) + hess.SetSym(1, 3, hess.At(1, 3)+d1*d2*s3) + hess.SetSym(2, 3, hess.At(2, 3)+d2*r2) + hess.SetSym(3, 3, hess.At(3, 3)+d2*d2*r2) + } + for i := 0; i < 4; i++ { + for j := i; j < 4; j++ { + hess.SetSym(i, j, 4*hess.At(i, j)) + } + } +} + +func (BrownAndDennis) Minima() []Minimum { + return []Minimum{ + { + X: []float64{-11.594439904762162, 13.203630051207202, -0.4034394881768612, 0.2367787744557347}, + F: 85822.20162635634, + Global: true, + }, + } +} + +// ExtendedPowellSingular implements the extended Powell's function. +// Its Hessian matrix is singular at the minimizer. +// +// Standard starting point: +// [3, -1, 0, 3, 3, -1, 0, 3, ..., 3, -1, 0, 3] +// +// References: +// - Spedicato E.: Computational experience with quasi-Newton algorithms for +// minimization problems of moderatly large size. Towards Global +// Optimization 2 (1978), 209-219 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type ExtendedPowellSingular struct{} + +func (ExtendedPowellSingular) Func(x []float64) (sum float64) { + if len(x)%4 != 0 { + panic("dimension of the problem must be a multiple of 4") + } + + for i := 0; i < len(x); i += 4 { + f1 := x[i] + 10*x[i+1] + f2 := x[i+2] - x[i+3] + t := x[i+1] - 2*x[i+2] + f3 := t * t + t = x[i] - x[i+3] + f4 := t * t + sum += f1*f1 + 5*f2*f2 + f3*f3 + 10*f4*f4 + } + return sum +} + +func (ExtendedPowellSingular) Grad(grad, x []float64) { + if len(x)%4 != 0 { + panic("dimension of the problem must be a multiple of 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := 0; i < len(x); i += 4 { + f1 := x[i] + 10*x[i+1] + f2 := x[i+2] - x[i+3] + t1 := x[i+1] - 2*x[i+2] + f3 := t1 * t1 + t2 := x[i] - x[i+3] + f4 := t2 * t2 + grad[i] = 2*f1 + 40*f4*t2 + grad[i+1] = 20*f1 + 4*f3*t1 + grad[i+2] = 10*f2 - 8*f3*t1 + grad[i+3] = -10*f2 - 40*f4*t2 + } +} + +func (ExtendedPowellSingular) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0, 0, 0, 0}, + F: 0, + Global: true, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + F: 0, + Global: true, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 0, + Global: true, + }, + } +} + +// ExtendedRosenbrock implements the extended, multidimensional Rosenbrock +// function. +// +// Standard starting point: +// Easy: [-1.2, 1, -1.2, 1, ...] +// Hard: any point far from the minimum +// +// References: +// - Rosenbrock, H.H.: An Automatic Method for Finding the Greatest or Least +// Value of a Function. Computer J 3 (1960), 175-184 +// - http://en.wikipedia.org/wiki/Rosenbrock_function +type ExtendedRosenbrock struct{} + +func (ExtendedRosenbrock) Func(x []float64) (sum float64) { + for i := 0; i < len(x)-1; i++ { + a := 1 - x[i] + b := x[i+1] - x[i]*x[i] + sum += a*a + 100*b*b + } + return sum +} + +func (ExtendedRosenbrock) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + dim := len(x) + for i := range grad { + grad[i] = 0 + } + for i := 0; i < dim-1; i++ { + grad[i] -= 2 * (1 - x[i]) + grad[i] -= 400 * (x[i+1] - x[i]*x[i]) * x[i] + } + for i := 1; i < dim; i++ { + grad[i] += 200 * (x[i] - x[i-1]*x[i-1]) + } +} + +func (ExtendedRosenbrock) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{-0.7756592265653526, 0.6130933654850433, + 0.38206284633839305, 0.14597201855219452}, + F: 3.701428610430017, + Global: false, + }, + { + X: []float64{1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{-0.9620510206947502, 0.9357393959767103, + 0.8807136041943204, 0.7778776758544063, 0.6050936785926526}, + F: 3.930839434133027, + Global: false, + }, + { + X: []float64{-0.9865749795709938, 0.9833982288361819, 0.972106670053092, + 0.9474374368264362, 0.8986511848517299, 0.8075739520354182}, + F: 3.973940500930295, + Global: false, + }, + { + X: []float64{-0.9917225725614055, 0.9935553935033712, 0.992173321594692, + 0.9868987626903134, 0.975164756608872, 0.9514319827049906, 0.9052228177139495}, + F: 3.9836005364248543, + Global: false, + }, + { + X: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// Gaussian implements the Gaussian function. +// The function has one global minimum and a number of false local minima +// caused by the finite floating point precision. +// +// Standard starting point: +// [0.4, 1, 0] +// +// Reference: +// More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained optimization +// software. ACM Trans Math Softw 7 (1981), 17-41 +type Gaussian struct{} + +func (Gaussian) y(i int) (yi float64) { + switch i { + case 1, 15: + yi = 0.0009 + case 2, 14: + yi = 0.0044 + case 3, 13: + yi = 0.0175 + case 4, 12: + yi = 0.0540 + case 5, 11: + yi = 0.1295 + case 6, 10: + yi = 0.2420 + case 7, 9: + yi = 0.3521 + case 8: + yi = 0.3989 + } + return yi +} + +func (g Gaussian) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 15; i++ { + c := 0.5 * float64(8-i) + b := c - x[2] + d := b * b + e := math.Exp(-0.5 * x[1] * d) + f := x[0]*e - g.y(i) + sum += f * f + } + return sum +} + +func (g Gaussian) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + grad[0] = 0 + grad[1] = 0 + grad[2] = 0 + for i := 1; i <= 15; i++ { + c := 0.5 * float64(8-i) + b := c - x[2] + d := b * b + e := math.Exp(-0.5 * x[1] * d) + f := x[0]*e - g.y(i) + grad[0] += 2 * f * e + grad[1] -= f * e * d * x[0] + grad[2] += 2 * f * e * x[0] * x[1] * b + } +} + +func (Gaussian) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.398956137837997, 1.0000190844805048, 0}, + F: 1.12793276961912e-08, + Global: true, + }, + } +} + +// GulfResearchAndDevelopment implements the Gulf Research and Development function. +// +// Standard starting point: +// [5, 2.5, 0.15] +// +// References: +// - Cox, R.A.: Comparison of the performance of seven optimization algorithms +// on twelve unconstrained minimization problems. Ref. 1335CNO4, Gulf +// Research and Development Company, Pittsburg (1969) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type GulfResearchAndDevelopment struct{} + +func (GulfResearchAndDevelopment) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 99; i++ { + arg := float64(i) / 100 + r := math.Pow(-50*math.Log(arg), 2.0/3.0) + 25 - x[1] + t1 := math.Pow(math.Abs(r), x[2]) / x[0] + t2 := math.Exp(-t1) + t := t2 - arg + sum += t * t + } + return sum +} + +func (GulfResearchAndDevelopment) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 99; i++ { + arg := float64(i) / 100 + r := math.Pow(-50*math.Log(arg), 2.0/3.0) + 25 - x[1] + t1 := math.Pow(math.Abs(r), x[2]) / x[0] + t2 := math.Exp(-t1) + t := t2 - arg + s1 := t1 * t2 * t + grad[0] += s1 + grad[1] += s1 / r + grad[2] -= s1 * math.Log(math.Abs(r)) + } + grad[0] *= 2 / x[0] + grad[1] *= 2 * x[2] + grad[2] *= 2 +} + +func (GulfResearchAndDevelopment) Minima() []Minimum { + return []Minimum{ + { + X: []float64{50, 25, 1.5}, + F: 0, + Global: true, + }, + { + X: []float64{99.89529935174151, 60.61453902799833, 9.161242695144592}, + F: 32.8345, + Global: false, + }, + { + X: []float64{201.662589489426, 60.61633150468155, 10.224891158488965}, + F: 32.8345, + Global: false, + }, + } +} + +// HelicalValley implements the helical valley function of Fletcher and Powell. +// Function is not defined at x[0] = 0. +// +// Standard starting point: +// [-1, 0, 0] +// +// References: +// - Fletcher, R., Powell, M.J.D.: A rapidly convergent descent method for +// minimization. Comput J 6 (1963), 163-168 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type HelicalValley struct{} + +func (HelicalValley) Func(x []float64) float64 { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if x[0] == 0 { + panic("function not defined at x[0] = 0") + } + + theta := 0.5 * math.Atan(x[1]/x[0]) / math.Pi + if x[0] < 0 { + theta += 0.5 + } + f1 := 10 * (x[2] - 10*theta) + f2 := 10 * (math.Hypot(x[0], x[1]) - 1) + f3 := x[2] + return f1*f1 + f2*f2 + f3*f3 +} + +func (HelicalValley) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + if x[0] == 0 { + panic("function not defined at x[0] = 0") + } + + theta := 0.5 * math.Atan(x[1]/x[0]) / math.Pi + if x[0] < 0 { + theta += 0.5 + } + h := math.Hypot(x[0], x[1]) + r := 1 / h + q := r * r / math.Pi + s := x[2] - 10*theta + grad[0] = 200 * (5*s*q*x[1] + (h-1)*r*x[0]) + grad[1] = 200 * (-5*s*q*x[0] + (h-1)*r*x[1]) + grad[2] = 2 * (100*s + x[2]) +} + +func (HelicalValley) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 0, 0}, + F: 0, + Global: true, + }, + } +} + +// Linear implements a linear function. +type Linear struct{} + +func (Linear) Func(x []float64) float64 { + return floats.Sum(x) +} + +func (Linear) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 1 + } +} + +// PenaltyI implements the first penalty function by Gill, Murray and Pitfield. +// +// Standard starting point: +// [1, ..., n] +// +// References: +// - Gill, P.E., Murray, W., Pitfield, R.A.: The implementation of two revised +// quasi-Newton algorithms for unconstrained optimization. Report NAC 11, +// National Phys Lab (1972), 82-83 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PenaltyI struct{} + +func (PenaltyI) Func(x []float64) (sum float64) { + for _, v := range x { + sum += (v - 1) * (v - 1) + } + sum *= 1e-5 + + var s float64 + for _, v := range x { + s += v * v + } + sum += (s - 0.25) * (s - 0.25) + return sum +} + +func (PenaltyI) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + s := -0.25 + for _, v := range x { + s += v * v + } + for i, v := range x { + grad[i] = 2 * (2*s*v + 1e-5*(v-1)) + } +} + +func (PenaltyI) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.2500074995875379, 0.2500074995875379, 0.2500074995875379, 0.2500074995875379}, + F: 2.2499775008999372e-05, + Global: true, + }, + { + X: []float64{0.15812230111311634, 0.15812230111311634, 0.15812230111311634, + 0.15812230111311634, 0.15812230111311634, 0.15812230111311634, + 0.15812230111311634, 0.15812230111311634, 0.15812230111311634, 0.15812230111311634}, + F: 7.087651467090369e-05, + Global: true, + }, + } +} + +// PenaltyII implements the second penalty function by Gill, Murray and Pitfield. +// +// Standard starting point: +// [0.5, ..., 0.5] +// +// References: +// - Gill, P.E., Murray, W., Pitfield, R.A.: The implementation of two revised +// quasi-Newton algorithms for unconstrained optimization. Report NAC 11, +// National Phys Lab (1972), 82-83 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PenaltyII struct{} + +func (PenaltyII) Func(x []float64) (sum float64) { + dim := len(x) + s := -1.0 + for i, v := range x { + s += float64(dim-i) * v * v + } + for i := 1; i < dim; i++ { + yi := math.Exp(float64(i+1)/10) + math.Exp(float64(i)/10) + f := math.Exp(x[i]/10) + math.Exp(x[i-1]/10) - yi + sum += f * f + } + for i := 1; i < dim; i++ { + f := math.Exp(x[i]/10) - math.Exp(-1.0/10) + sum += f * f + } + sum *= 1e-5 + sum += (x[0] - 0.2) * (x[0] - 0.2) + sum += s * s + return sum +} + +func (PenaltyII) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + dim := len(x) + s := -1.0 + for i, v := range x { + s += float64(dim-i) * v * v + } + for i, v := range x { + grad[i] = 4 * s * float64(dim-i) * v + } + for i := 1; i < dim; i++ { + yi := math.Exp(float64(i+1)/10) + math.Exp(float64(i)/10) + f := math.Exp(x[i]/10) + math.Exp(x[i-1]/10) - yi + grad[i] += 1e-5 * f * math.Exp(x[i]/10) / 5 + grad[i-1] += 1e-5 * f * math.Exp(x[i-1]/10) / 5 + } + for i := 1; i < dim; i++ { + f := math.Exp(x[i]/10) - math.Exp(-1.0/10) + grad[i] += 1e-5 * f * math.Exp(x[i]/10) / 5 + } + grad[0] += 2 * (x[0] - 0.2) +} + +func (PenaltyII) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.19999933335, 0.19131670128566283, 0.4801014860897, 0.5188454026659}, + F: 9.376293007355449e-06, + Global: true, + }, + { + X: []float64{0.19998360520892217, 0.010350644318663525, + 0.01960493546891094, 0.03208906550305253, 0.04993267593895693, + 0.07651399534454084, 0.11862407118600789, 0.1921448731780023, + 0.3473205862372022, 0.36916437893066273}, + F: 0.00029366053745674594, + Global: true, + }, + } +} + +// PowellBadlyScaled implements the Powell's badly scaled function. +// The function is very flat near the minimum. A satisfactory solution is one +// that gives f(x) ≅ 1e-13. +// +// Standard starting point: +// [0, 1] +// +// References: +// - Powell, M.J.D.: A Hybrid Method for Nonlinear Equations. Numerical +// Methods for Nonlinear Algebraic Equations, P. Rabinowitz (ed.), Gordon +// and Breach (1970) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PowellBadlyScaled struct{} + +func (PowellBadlyScaled) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := 1e4*x[0]*x[1] - 1 + f2 := math.Exp(-x[0]) + math.Exp(-x[1]) - 1.0001 + return f1*f1 + f2*f2 +} + +func (PowellBadlyScaled) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := 1e4*x[0]*x[1] - 1 + f2 := math.Exp(-x[0]) + math.Exp(-x[1]) - 1.0001 + grad[0] = 2 * (1e4*f1*x[1] - f2*math.Exp(-x[0])) + grad[1] = 2 * (1e4*f1*x[0] - f2*math.Exp(-x[1])) +} + +func (PowellBadlyScaled) Hess(hess mat.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + t1 := 1e4*x[0]*x[1] - 1 + s1 := math.Exp(-x[0]) + s2 := math.Exp(-x[1]) + t2 := s1 + s2 - 1.0001 + + h00 := 2 * (1e8*x[1]*x[1] + s1*(s1+t2)) + h01 := 2 * (1e4*(1+2*t1) + s1*s2) + h11 := 2 * (1e8*x[0]*x[0] + s2*(s2+t2)) + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (PowellBadlyScaled) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1.0981593296997149e-05, 9.106146739867375}, + F: 0, + Global: true, + }, + } +} + +// Trigonometric implements the trigonometric function. +// +// Standard starting point: +// [1/dim, ..., 1/dim] +// +// References: +// - Spedicato E.: Computational experience with quasi-Newton algorithms for +// minimization problems of moderatly large size. Towards Global +// Optimization 2 (1978), 209-219 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Trigonometric struct{} + +func (Trigonometric) Func(x []float64) (sum float64) { + var s1 float64 + for _, v := range x { + s1 += math.Cos(v) + } + for i, v := range x { + f := float64(len(x)+i+1) - float64(i+1)*math.Cos(v) - math.Sin(v) - s1 + sum += f * f + } + return sum +} + +func (Trigonometric) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + var s1 float64 + for _, v := range x { + s1 += math.Cos(v) + } + + var s2 float64 + for i, v := range x { + f := float64(len(x)+i+1) - float64(i+1)*math.Cos(v) - math.Sin(v) - s1 + s2 += f + grad[i] = 2 * f * (float64(i+1)*math.Sin(v) - math.Cos(v)) + } + + for i, v := range x { + grad[i] += 2 * s2 * math.Sin(v) + } +} + +func (Trigonometric) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.04296456438227447, 0.043976287478192246, + 0.045093397949095684, 0.04633891624617569, 0.047744381782831, + 0.04935473251330618, 0.05123734850076505, 0.19520946391410446, + 0.1649776652761741, 0.06014857783799575}, + F: 0, + Global: true, + }, + { + // TODO(vladimir-ch): If we knew the location of this minimum more + // accurately, we could decrease defaultGradTol. + X: []float64{0.05515090434047145, 0.05684061730812344, + 0.05876400231100774, 0.060990608903034337, 0.06362621381044778, + 0.06684318087364617, 0.2081615177172172, 0.16436309604419047, + 0.08500689695564931, 0.09143145386293675}, + F: 2.795056121876575e-05, + Global: false, + }, + } +} + +// VariablyDimensioned implements a variably dimensioned function. +// +// Standard starting point: +// [..., (dim-i)/dim, ...], i=1,...,dim +// +// References: +// More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained optimization +// software. ACM Trans Math Softw 7 (1981), 17-41 +type VariablyDimensioned struct{} + +func (VariablyDimensioned) Func(x []float64) (sum float64) { + for _, v := range x { + t := v - 1 + sum += t * t + } + + var s float64 + for i, v := range x { + s += float64(i+1) * (v - 1) + } + s *= s + sum += s + s *= s + sum += s + return sum +} + +func (VariablyDimensioned) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + var s float64 + for i, v := range x { + s += float64(i+1) * (v - 1) + } + for i, v := range x { + grad[i] = 2 * (v - 1 + s*float64(i+1)*(1+2*s*s)) + } +} + +func (VariablyDimensioned) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// Watson implements the Watson's function. +// Dimension of the problem should be 2 <= dim <= 31. For dim == 9, the problem +// of minimizing the function is very ill conditioned. +// +// Standard starting point: +// [0, ..., 0] +// +// References: +// - Kowalik, J.S., Osborne, M.R.: Methods for Unconstrained Optimization +// Problems. Elsevier North-Holland, New York, 1968 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Watson struct{} + +func (Watson) Func(x []float64) (sum float64) { + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + sum += t * t + } + t := x[1] - x[0]*x[0] - 1 + sum += x[0]*x[0] + t*t + return sum +} + +func (Watson) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + for j := range x { + grad[j] += d2 * (float64(j) - s3) * t + d2 *= d1 + } + } + t := x[1] - x[0]*x[0] - 1 + grad[0] += x[0] * (2 - 4*t) + grad[1] += 2 * t +} + +func (Watson) Hess(hess mat.MutableSymmetric, x []float64) { + dim := len(x) + if dim != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + for j := 0; j < dim; j++ { + for k := j; k < dim; k++ { + hess.SetSym(j, k, 0) + } + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + d2 := 1.0 + var s1 float64 + for j := 1; j < dim; j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + th := 2 * d1 * d1 * t + for j := 0; j < dim; j++ { + v := float64(j) - s3 + d3 := 1 / d1 + for k := 0; k <= j; k++ { + hess.SetSym(k, j, hess.At(k, j)+d2*d3*(v*(float64(k)-s3)-th)) + d3 *= d1 + } + d2 *= d1 + } + } + t1 := x[1] - x[0]*x[0] - 1 + hess.SetSym(0, 0, hess.At(0, 0)+8*x[0]*x[0]+2-4*t1) + hess.SetSym(0, 1, hess.At(0, 1)-4*x[0]) + hess.SetSym(1, 1, hess.At(1, 1)+2) +} + +func (Watson) Minima() []Minimum { + return []Minimum{ + { + X: []float64{-0.01572508644590686, 1.012434869244884, -0.23299162372002916, + 1.2604300800978554, -1.51372891341701, 0.9929964286340117}, + F: 0.0022876700535523838, + Global: true, + }, + { + X: []float64{-1.5307036521992127e-05, 0.9997897039319495, 0.01476396369355022, + 0.14634232829939883, 1.0008211030046426, -2.617731140519101, 4.104403164479245, + -3.1436122785568514, 1.0526264080103074}, + F: 1.399760138096796e-06, + Global: true, + }, + // TODO(vladimir-ch): More, Garbow, Hillstrom list just the value, but + // not the location. Our minimizers find a minimum, but the value is + // different. + // { + // // For dim == 12 + // F: 4.72238e-10, + // Global: true, + // }, + // TODO(vladimir-ch): netlib/uncon report a value of 2.48631d-20 for dim == 20. + } +} + +// Wood implements the Wood's function. +// +// Standard starting point: +// [-3, -1, -3, -1] +// +// References: +// - Colville, A.R.: A comparative study of nonlinear programming codes. +// Report 320-2949, IBM New York Scientific Center (1968) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Wood struct{} + +func (Wood) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + f1 := x[1] - x[0]*x[0] + f2 := 1 - x[0] + f3 := x[3] - x[2]*x[2] + f4 := 1 - x[2] + f5 := x[1] + x[3] - 2 + f6 := x[1] - x[3] + return 100*f1*f1 + f2*f2 + 90*f3*f3 + f4*f4 + 10*f5*f5 + 0.1*f6*f6 +} + +func (Wood) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := x[1] - x[0]*x[0] + f2 := 1 - x[0] + f3 := x[3] - x[2]*x[2] + f4 := 1 - x[2] + f5 := x[1] + x[3] - 2 + f6 := x[1] - x[3] + grad[0] = -2 * (200*f1*x[0] + f2) + grad[1] = 2 * (100*f1 + 10*f5 + 0.1*f6) + grad[2] = -2 * (180*f3*x[2] + f4) + grad[3] = 2 * (90*f3 + 10*f5 - 0.1*f6) +} + +func (Wood) Hess(hess mat.MutableSymmetric, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + hess.SetSym(0, 0, 400*(3*x[0]*x[0]-x[1])+2) + hess.SetSym(0, 1, -400*x[0]) + hess.SetSym(1, 1, 220.2) + hess.SetSym(0, 2, 0) + hess.SetSym(1, 2, 0) + hess.SetSym(2, 2, 360*(3*x[2]*x[2]-x[3])+2) + hess.SetSym(0, 3, 0) + hess.SetSym(1, 3, 19.8) + hess.SetSym(2, 3, -360*x[2]) + hess.SetSym(3, 3, 200.2) +} + +func (Wood) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// ConcaveRight implements an univariate function that is concave to the right +// of the minimizer which is located at x=sqrt(2). +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.1) +type ConcaveRight struct{} + +func (ConcaveRight) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + return -x[0] / (x[0]*x[0] + 2) +} + +func (ConcaveRight) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + xSqr := x[0] * x[0] + grad[0] = (xSqr - 2) / (xSqr + 2) / (xSqr + 2) +} + +// ConcaveLeft implements an univariate function that is concave to the left of +// the minimizer which is located at x=399/250=1.596. +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.2) +type ConcaveLeft struct{} + +func (ConcaveLeft) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + return math.Pow(x[0]+0.004, 4) * (x[0] - 1.996) +} + +func (ConcaveLeft) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + grad[0] = math.Pow(x[0]+0.004, 3) * (5*x[0] - 7.98) +} + +// Plassmann implements an univariate oscillatory function where the value of L +// controls the number of oscillations. The value of Beta controls the size of +// the derivative at zero and the size of the interval where the strong Wolfe +// conditions can hold. For small values of Beta this function represents a +// difficult test problem for linesearchers also because the information based +// on the derivative is unreliable due to the oscillations. +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.3) +type Plassmann struct { + L float64 // Number of oscillations for |x-1| ≥ Beta. + Beta float64 // Size of the derivative at zero, f'(0) = -Beta. +} + +func (f Plassmann) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + a := x[0] + b := f.Beta + l := f.L + r := 2 * (1 - b) / l / math.Pi * math.Sin(l*math.Pi/2*a) + switch { + case a <= 1-b: + r += 1 - a + case 1-b < a && a <= 1+b: + r += 0.5 * ((a-1)*(a-1)/b + b) + default: // a > 1+b + r += a - 1 + } + return r +} + +func (f Plassmann) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + a := x[0] + b := f.Beta + l := f.L + grad[0] = (1 - b) * math.Cos(l*math.Pi/2*a) + switch { + case a <= 1-b: + grad[0]-- + case 1-b < a && a <= 1+b: + grad[0] += (a - 1) / b + default: // a > 1+b + grad[0]++ + } +} + +// YanaiOzawaKaneko is an univariate convex function where the values of Beta1 +// and Beta2 control the curvature around the minimum. Far away from the +// minimum the function approximates an absolute value function. Near the +// minimum, the function can either be sharply curved or flat, controlled by +// the parameter values. +// +// References: +// - More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.4) +// - Yanai, H., Ozawa, M., and Kaneko, S.: Interpolation methods in one dimensional +// optimization. Computing 27 (1981), 155–163 +type YanaiOzawaKaneko struct { + Beta1 float64 + Beta2 float64 +} + +func (f YanaiOzawaKaneko) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + a := x[0] + b1 := f.Beta1 + b2 := f.Beta2 + g1 := math.Sqrt(1+b1*b1) - b1 + g2 := math.Sqrt(1+b2*b2) - b2 + return g1*math.Sqrt((a-1)*(a-1)+b2*b2) + g2*math.Sqrt(a*a+b1*b1) +} + +func (f YanaiOzawaKaneko) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + a := x[0] + b1 := f.Beta1 + b2 := f.Beta2 + g1 := math.Sqrt(1+b1*b1) - b1 + g2 := math.Sqrt(1+b2*b2) - b2 + grad[0] = g1*(a-1)/math.Sqrt(b2*b2+(a-1)*(a-1)) + g2*a/math.Sqrt(b1*b1+a*a) +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/functions_test.go b/vendor/gonum.org/v1/gonum/optimize/functions/functions_test.go new file mode 100644 index 00000000..0912ab96 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/functions_test.go @@ -0,0 +1,326 @@ +// Copyright ©2015 The gonum 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 functions + +import "testing" + +func TestBeale(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 1}, + F: 14.203125, + Gradient: []float64{0, 27.75}, + }, + { + X: []float64{1, 4}, + F: 4624.453125, + Gradient: []float64{8813.25, 6585}, + }, + } + testFunction(Beale{}, tests, t) +} + +func TestBiggsEXP2(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2}, + F: 32.26255055084012, + Gradient: []float64{8.308203800550878, -25.32607145221645}, + }, + } + testFunction(BiggsEXP2{}, tests, t) +} + +func TestBiggsEXP3(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1}, + F: 1.598844540607779, + Gradient: []float64{1.0633795027631927, -0.5196392672262664, -0.3180919155433357}, + }, + } + testFunction(BiggsEXP3{}, tests, t) +} + +func TestBiggsEXP4(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1}, + F: 1.598844540607779, + Gradient: []float64{1.0633795027631927, -0.5196392672262664, + -0.44245622408151464, -0.3180919155433357}, + }, + } + testFunction(BiggsEXP4{}, tests, t) +} + +func TestBiggsEXP5(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1, 1}, + F: 13.386420552801937, + Gradient: []float64{-6.54665204477596, 3.5259856535515293, + 14.36984212995392, -9.522506150695783, -19.639956134327882}, + }, + } + testFunction(BiggsEXP5{}, tests, t) +} + +func TestBiggsEXP6(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1, 1, 1}, + F: 0.77907007565597, + Gradient: []float64{-0.149371887533426, -0.183163468182936, + -1.483958013575642, 1.428277503849742, -0.149371887533426, + -1.483958013575642}, + }, + } + testFunction(BiggsEXP6{}, tests, t) +} + +func TestBox3D(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 10, 20}, + F: 1031.1538106093985, + Gradient: []float64{98.22343149849218, -2.11937420675874, 112.38817362220350}, + }, + } + testFunction(Box3D{}, tests, t) +} + +func TestBrownBadlyScaled(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 1}, + F: 999998000003, + Gradient: []float64{-2e+6, -4e-6}, + }, + } + testFunction(BrownBadlyScaled{}, tests, t) +} + +// TODO(vladimir-ch): The minimum of BrownAndDennis is not known accurately +// enough, which would force defaultGradTol to be unnecessarily large for the +// tests to pass. This is the only function that causes problems, so disable +// this test until the minimum is more accurate. +// func TestBrownAndDennis(t *testing.T) { +// tests := []funcTest{ +// { +// X: []float64{25, 5, -5, -1}, +// F: 7926693.33699744, +// Gradient: []float64{1149322.836365895, 1779291.674339785, -254579.585463521, -173400.429253115}, +// }, +// } +// testFunction(BrownAndDennis{}, tests, t) +// } + +func TestExtendedPowellSingular(t *testing.T) { + tests := []funcTest{ + { + X: []float64{3, -1, 0, 3}, + F: 95, + Gradient: []float64{-14, -144, -22, 30}, + }, + { + X: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + F: 190, + Gradient: []float64{-14, -144, -22, 30, -14, -144, -22, 30}, + }, + } + testFunction(ExtendedPowellSingular{}, tests, t) +} + +func TestExtendedRosenbrock(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-1.2, 1}, + F: 24.2, + Gradient: []float64{-215.6, -88}, + }, + { + X: []float64{-1.2, 1, -1.2}, + F: 508.2, + Gradient: []float64{-215.6, 792, -440}, + }, + { + X: []float64{-1.2, 1, -1.2, 1}, + F: 532.4, + Gradient: []float64{-215.6, 792, -655.6, -88}, + }, + } + testFunction(ExtendedRosenbrock{}, tests, t) +} + +func TestGaussian(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.4, 1, 0}, + F: 3.88810699116688e-06, + Gradient: []float64{7.41428466839991e-03, -7.44126392165149e-04, -5.30189685421989e-20}, + }, + } + testFunction(Gaussian{}, tests, t) +} + +func TestGulfResearchAndDevelopment(t *testing.T) { + tests := []funcTest{ + { + X: []float64{5, 2.5, 0.15}, + F: 12.11070582556949, + Gradient: []float64{2.0879783574289799, 0.0345792619697154, -39.6766801029386400}, + }, + } + testFunction(GulfResearchAndDevelopment{}, tests, t) +} + +func TestHelicalValley(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-1, 0, 0}, + F: 2500, + Gradient: []float64{0, -1.59154943091895e+03, -1e+03}, + }, + } + testFunction(HelicalValley{}, tests, t) +} + +func TestPenaltyI(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 3, 4}, + F: 885.06264, + Gradient: []float64{119, 238.00002, 357.00004, 476.00006}, + }, + { + X: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + F: 148032.56535, + Gradient: []float64{1539, 3078.00002, 4617.00004, 6156.00006, + 7695.00008, 9234.0001, 10773.00012, 12312.00014, 13851.00016, 15390.00018}, + }, + } + testFunction(PenaltyI{}, tests, t) +} + +func TestPenaltyII(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0.5, 0.5, 0.5}, + F: 2.34000880546302, + Gradient: []float64{12.59999952896435, 8.99999885134508, + 5.99999776830493, 2.99999875380719}, + }, + { + X: []float64{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, + F: 162.65277656596712, + Gradient: []float64{255.5999995289644, 229.4999988513451, + 203.9999977683049, 178.4999965713605, 152.9999952485322, + 127.4999937865809, 101.9999921708749, 76.4999903852436, + 50.9999884118158, 25.4999938418451}, + }, + } + testFunction(PenaltyII{}, tests, t) +} + +func TestPowelBadlyScaled(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 1}, + F: 1.13526171734838, + Gradient: []float64{-2.00007355588823e+04, -2.70596990584991e-01}, + }, + } + testFunction(PowellBadlyScaled{}, tests, t) +} + +func TestTrigonometric(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0.5}, + F: 0.0126877761614045, + Gradient: []float64{-0.00840962732040673, -0.09606967736232540}, + }, + { + X: []float64{0.2, 0.2, 0.2, 0.2, 0.2}, + F: 0.0116573789904718, + Gradient: []float64{0.04568602319608119, -0.00896259022885634, + -0.04777056509084983, -0.07073790138989976, -0.07786459912600564}, + }, + { + X: []float64{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, + F: 0.00707575946622261, + Gradient: []float64{0.03562782195259399, 0.01872017956076182, + 0.00380754216611998, -0.00911009023133202, -0.02003271763159338, + -0.02896034003466506, -0.03589295744054654, -0.04083056984923782, + -0.04377317726073873, -0.04472077967504980}, + }, + } + testFunction(Trigonometric{}, tests, t) +} + +func TestVariablyDimensioned(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0}, + F: 46.5625, + Gradient: []float64{-68.5, -137}, + }, + { + X: []float64{2.0 / 3, 1.0 / 3, 0}, + F: 497.60493827160514, + Gradient: []float64{-416.518518518519, -833.037037037037, -1249.555555555556}, + }, + { + X: []float64{0.75, 0.5, 0.25, 0}, + F: 3222.1875, + Gradient: []float64{-1703, -3406, -5109, -6812}, + }, + } + testFunction(VariablyDimensioned{}, tests, t) +} + +func TestWatson(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 0}, + F: 30, + Gradient: []float64{0, -60}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936, -64.172372791012350, + -65.241283655050239, -66.321647802373235}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936, -64.172372791012350, + -65.241283655050239, -66.321647802373235, -67.413448880864095, + -68.516667837400661, -69.631282933991471}, + }, + } + testFunction(Watson{}, tests, t) +} + +func TestWood(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-3, -1, -3, -1}, + F: 19192, + Gradient: []float64{-12008, -2080, -10808, -1880}, + }, + } + testFunction(Wood{}, tests, t) +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/minsurf.go b/vendor/gonum.org/v1/gonum/optimize/functions/minsurf.go new file mode 100644 index 00000000..d975bfdb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/minsurf.go @@ -0,0 +1,252 @@ +// Copyright ©2015 The gonum 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 functions + +import ( + "fmt" + "math" +) + +// MinimalSurface implements a finite element approximation to a minimal +// surface problem: determine the surface with minimal area and given boundary +// values in a unit square centered at the origin. +// +// References: +// Averick, M.B., Carter, R.G., Moré, J.J., Xue, G.-L.: The Minpack-2 Test +// Problem Collection. Preprint MCS-P153-0692, Argonne National Laboratory (1992) +type MinimalSurface struct { + bottom, top []float64 + left, right []float64 + origin, step [2]float64 +} + +// NewMinimalSurface creates a new discrete minimal surface problem and +// precomputes its boundary values. The problem is discretized on a rectilinear +// grid with nx×ny nodes which means that the problem dimension is (nx-2)(ny-2). +func NewMinimalSurface(nx, ny int) *MinimalSurface { + ms := &MinimalSurface{ + bottom: make([]float64, nx), + top: make([]float64, nx), + left: make([]float64, ny), + right: make([]float64, ny), + origin: [2]float64{-0.5, -0.5}, + step: [2]float64{1 / float64(nx-1), 1 / float64(ny-1)}, + } + + ms.initBoundary(ms.bottom, ms.origin[0], ms.origin[1], ms.step[0], 0) + startY := ms.origin[1] + float64(ny-1)*ms.step[1] + ms.initBoundary(ms.top, ms.origin[0], startY, ms.step[0], 0) + ms.initBoundary(ms.left, ms.origin[0], ms.origin[1], 0, ms.step[1]) + startX := ms.origin[0] + float64(nx-1)*ms.step[0] + ms.initBoundary(ms.right, startX, ms.origin[1], 0, ms.step[1]) + + return ms +} + +// Func returns the area of the surface represented by the vector x. +func (ms *MinimalSurface) Func(x []float64) (area float64) { + nx, ny := ms.Dims() + if len(x) != (nx-2)*(ny-2) { + panic("functions: problem size mismatch") + } + + hx, hy := ms.Steps() + for j := 0; j < ny-1; j++ { + for i := 0; i < nx-1; i++ { + vLL := ms.at(i, j, x) + vLR := ms.at(i+1, j, x) + vUL := ms.at(i, j+1, x) + vUR := ms.at(i+1, j+1, x) + + dvLdx := (vLR - vLL) / hx + dvLdy := (vUL - vLL) / hy + dvUdx := (vUR - vUL) / hx + dvUdy := (vUR - vLR) / hy + + fL := math.Sqrt(1 + dvLdx*dvLdx + dvLdy*dvLdy) + fU := math.Sqrt(1 + dvUdx*dvUdx + dvUdy*dvUdy) + area += fL + fU + } + } + area *= 0.5 * hx * hy + return area +} + +// Grad evaluates the area gradient of the surface represented by the vector. +func (ms *MinimalSurface) Grad(grad, x []float64) { + nx, ny := ms.Dims() + if len(x) != (nx-2)*(ny-2) { + panic("functions: problem size mismatch") + } + if grad != nil && len(x) != len(grad) { + panic("functions: unexpected size mismatch") + } + + for i := range grad { + grad[i] = 0 + } + hx, hy := ms.Steps() + for j := 0; j < ny-1; j++ { + for i := 0; i < nx-1; i++ { + vLL := ms.at(i, j, x) + vLR := ms.at(i+1, j, x) + vUL := ms.at(i, j+1, x) + vUR := ms.at(i+1, j+1, x) + + dvLdx := (vLR - vLL) / hx + dvLdy := (vUL - vLL) / hy + dvUdx := (vUR - vUL) / hx + dvUdy := (vUR - vLR) / hy + + fL := math.Sqrt(1 + dvLdx*dvLdx + dvLdy*dvLdy) + fU := math.Sqrt(1 + dvUdx*dvUdx + dvUdy*dvUdy) + + if grad != nil { + if i > 0 { + if j > 0 { + grad[ms.index(i, j)] -= (dvLdx/hx + dvLdy/hy) / fL + } + if j < ny-2 { + grad[ms.index(i, j+1)] += (dvLdy/hy)/fL - (dvUdx/hx)/fU + } + } + if i < nx-2 { + if j > 0 { + grad[ms.index(i+1, j)] += (dvLdx/hx)/fL - (dvUdy/hy)/fU + } + if j < ny-2 { + grad[ms.index(i+1, j+1)] += (dvUdx/hx + dvUdy/hy) / fU + } + } + } + } + + } + cellSize := 0.5 * hx * hy + for i := range grad { + grad[i] *= cellSize + } +} + +// InitX returns a starting location for the minimization problem. Length of +// the returned slice is (nx-2)(ny-2). +func (ms *MinimalSurface) InitX() []float64 { + nx, ny := ms.Dims() + x := make([]float64, (nx-2)*(ny-2)) + for j := 1; j < ny-1; j++ { + for i := 1; i < nx-1; i++ { + x[ms.index(i, j)] = (ms.left[j] + ms.bottom[i]) / 2 + } + } + return x +} + +// ExactX returns the exact solution to the _continuous_ minimization problem +// projected on the interior nodes of the grid. Length of the returned slice is +// (nx-2)(ny-2). +func (ms *MinimalSurface) ExactX() []float64 { + nx, ny := ms.Dims() + v := make([]float64, (nx-2)*(ny-2)) + for j := 1; j < ny-1; j++ { + for i := 1; i < nx-1; i++ { + v[ms.index(i, j)] = ms.ExactSolution(ms.x(i), ms.y(j)) + } + } + return v +} + +// ExactSolution returns the value of the exact solution to the minimal surface +// problem at (x,y). The exact solution is +// F_exact(x,y) = U^2(x,y) - V^2(x,y), +// where U and V are the unique solutions to the equations +// x = u + uv^2 - u^3/3, +// y = -v - u^2v + v^3/3. +func (ms *MinimalSurface) ExactSolution(x, y float64) float64 { + var u = [2]float64{x, -y} + var f [2]float64 + var jac [2][2]float64 + for k := 0; k < 100; k++ { + f[0] = u[0] + u[0]*u[1]*u[1] - u[0]*u[0]*u[0]/3 - x + f[1] = -u[1] - u[0]*u[0]*u[1] + u[1]*u[1]*u[1]/3 - y + fNorm := math.Hypot(f[0], f[1]) + if fNorm < 1e-13 { + break + } + jac[0][0] = 1 + u[1]*u[1] - u[0]*u[0] + jac[0][1] = 2 * u[0] * u[1] + jac[1][0] = -2 * u[0] * u[1] + jac[1][1] = -1 - u[0]*u[0] + u[1]*u[1] + det := jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0] + u[0] -= (jac[1][1]*f[0] - jac[0][1]*f[1]) / det + u[1] -= (jac[0][0]*f[1] - jac[1][0]*f[0]) / det + } + return u[0]*u[0] - u[1]*u[1] +} + +// Dims returns the size of the underlying rectilinear grid. +func (ms *MinimalSurface) Dims() (nx, ny int) { + return len(ms.bottom), len(ms.left) +} + +// Steps returns the spatial step sizes of the underlying rectilinear grid. +func (ms *MinimalSurface) Steps() (hx, hy float64) { + return ms.step[0], ms.step[1] +} + +func (ms *MinimalSurface) x(i int) float64 { + return ms.origin[0] + float64(i)*ms.step[0] +} + +func (ms *MinimalSurface) y(j int) float64 { + return ms.origin[1] + float64(j)*ms.step[1] +} + +func (ms *MinimalSurface) at(i, j int, x []float64) float64 { + nx, ny := ms.Dims() + if i < 0 || i >= nx { + panic(fmt.Sprintf("node [%v,%v] not on grid", i, j)) + } + if j < 0 || j >= ny { + panic(fmt.Sprintf("node [%v,%v] not on grid", i, j)) + } + + if i == 0 { + return ms.left[j] + } + if j == 0 { + return ms.bottom[i] + } + if i == nx-1 { + return ms.right[j] + } + if j == ny-1 { + return ms.top[i] + } + return x[ms.index(i, j)] +} + +// index maps an interior grid node (i, j) to a one-dimensional index and +// returns it. +func (ms *MinimalSurface) index(i, j int) int { + nx, ny := ms.Dims() + if i <= 0 || i >= nx-1 { + panic(fmt.Sprintf("[%v,%v] is not an interior node", i, j)) + } + if j <= 0 || j >= ny-1 { + panic(fmt.Sprintf("[%v,%v] is not an interior node", i, j)) + } + + return i - 1 + (j-1)*(nx-2) +} + +// initBoundary initializes with the exact solution the boundary b whose i-th +// element b[i] is located at [startX+i×hx, startY+i×hy]. +func (ms *MinimalSurface) initBoundary(b []float64, startX, startY, hx, hy float64) { + for i := range b { + x := startX + float64(i)*hx + y := startY + float64(i)*hy + b[i] = ms.ExactSolution(x, y) + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/minsurf_test.go b/vendor/gonum.org/v1/gonum/optimize/functions/minsurf_test.go new file mode 100644 index 00000000..2f123545 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/minsurf_test.go @@ -0,0 +1,48 @@ +// Copyright ©2015 The gonum 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 functions + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +func TestMinimalSurface(t *testing.T) { + for _, size := range [][2]int{ + {20, 30}, + {30, 30}, + {50, 40}, + } { + f := NewMinimalSurface(size[0], size[1]) + x0 := f.InitX() + grad := make([]float64, len(x0)) + f.Grad(grad, x0) + fdGrad := fd.Gradient(nil, f.Func, x0, &fd.Settings{Formula: fd.Central}) + + // Test that the numerical and analytical gradients agree. + dist := floats.Distance(grad, fdGrad, math.Inf(1)) + if dist > 1e-9 { + t.Errorf("grid %v x %v: numerical and analytical gradient do not match. |fdGrad - grad|_∞ = %v", + size[0], size[1], dist) + } + + // Test that the gradient at the minimum is small enough. + // In some sense this test is not completely correct because ExactX + // returns the exact solution to the continuous problem projected on the + // grid, not the exact solution to the discrete problem which we are + // solving. This is the reason why a relatively loose tolerance 1e-4 + // must be used. + xSol := f.ExactX() + f.Grad(grad, xSol) + norm := floats.Norm(grad, math.Inf(1)) + if norm > 1e-4 { + t.Errorf("grid %v x %v: gradient at the minimum not small enough. |grad|_∞ = %v", + size[0], size[1], norm) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/validate.go b/vendor/gonum.org/v1/gonum/optimize/functions/validate.go new file mode 100644 index 00000000..e7c5fee7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/validate.go @@ -0,0 +1,127 @@ +// Copyright ©2015 The gonum 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 functions + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +// function represents an objective function. +type function interface { + Func(x []float64) float64 +} + +type gradient interface { + Grad(grad, x []float64) +} + +// minimumer is an objective function that can also provide information about +// its minima. +type minimumer interface { + function + + // Minima returns _known_ minima of the function. + Minima() []Minimum +} + +// Minimum represents information about an optimal location of a function. +type Minimum struct { + // X is the location of the minimum. X may not be nil. + X []float64 + // F is the value of the objective function at X. + F float64 + // Global indicates if the location is a global minimum. + Global bool +} + +type funcTest struct { + X []float64 + + // F is the expected function value at X. + F float64 + // Gradient is the expected gradient at X. If nil, it is not evaluated. + Gradient []float64 +} + +// TODO(vladimir-ch): Decide and implement an exported testing function: +// func Test(f Function, ??? ) ??? { +// } + +const ( + defaultTol = 1e-12 + defaultGradTol = 1e-9 + defaultFDGradTol = 1e-5 +) + +// testFunction checks that the function can evaluate itself (and its gradient) +// correctly. +func testFunction(f function, ftests []funcTest, t *testing.T) { + // Make a copy of tests because we may append to the slice. + tests := make([]funcTest, len(ftests)) + copy(tests, ftests) + + // Get information about the function. + fMinima, isMinimumer := f.(minimumer) + fGradient, isGradient := f.(gradient) + + // If the function is a Minimumer, append its minima to the tests. + if isMinimumer { + for _, minimum := range fMinima.Minima() { + // Allocate gradient only if the function can evaluate it. + var grad []float64 + if isGradient { + grad = make([]float64, len(minimum.X)) + } + tests = append(tests, funcTest{ + X: minimum.X, + F: minimum.F, + Gradient: grad, + }) + } + } + + for i, test := range tests { + F := f.Func(test.X) + + // Check that the function value is as expected. + if math.Abs(F-test.F) > defaultTol { + t.Errorf("Test #%d: function value given by Func is incorrect. Want: %v, Got: %v", + i, test.F, F) + } + + if test.Gradient == nil { + continue + } + + // Evaluate the finite difference gradient. + fdGrad := fd.Gradient(nil, f.Func, test.X, &fd.Settings{ + Formula: fd.Central, + Step: 1e-6, + }) + + // Check that the finite difference and expected gradients match. + if !floats.EqualApprox(fdGrad, test.Gradient, defaultFDGradTol) { + dist := floats.Distance(fdGrad, test.Gradient, math.Inf(1)) + t.Errorf("Test #%d: numerical and expected gradients do not match. |fdGrad - WantGrad|_∞ = %v", + i, dist) + } + + // If the function is a Gradient, check that it computes the gradient correctly. + if isGradient { + grad := make([]float64, len(test.Gradient)) + fGradient.Grad(grad, test.X) + + if !floats.EqualApprox(grad, test.Gradient, defaultGradTol) { + dist := floats.Distance(grad, test.Gradient, math.Inf(1)) + t.Errorf("Test #%d: gradient given by Grad is incorrect. |grad - WantGrad|_∞ = %v", + i, dist) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/functions/vlse.go b/vendor/gonum.org/v1/gonum/optimize/functions/vlse.go new file mode 100644 index 00000000..83fab95f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/functions/vlse.go @@ -0,0 +1,325 @@ +// Copyright ©2017 The Gonum 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 functions + +import "math" + +// This file implements functions from the Virtual Library of Simulation Experiments. +// https://www.sfu.ca/~ssurjano/optimization.html +// In many cases gradients and Hessians have been added. In some cases, these +// are not defined at certain points or manifolds. The gradient in these locations +// has been set to 0. + +// Ackley implements the Ackley function, a function of arbitrary dimension that +// has many local minima. It has a single global minimum of 0 at 0. Its typical +// domain is the hypercube of [-32.768, 32.768]^d. +// f(x) = -20 * exp(-0.2 sqrt(1/d sum_i x_i^2)) - exp(1/d sum_i cos(2π x_i)) + 20 + exp(1) +// where d is the input dimension. +// +// Reference: +// https://www.sfu.ca/~ssurjano/ackley.html (obtained June 2017) +type Ackley struct{} + +func (Ackley) Func(x []float64) float64 { + var ss, sc float64 + for _, v := range x { + ss += v * v + sc += math.Cos(2 * math.Pi * v) + } + id := 1 / float64(len(x)) + return -20*math.Exp(-0.2*math.Sqrt(id*ss)) - math.Exp(id*sc) + 20 + math.E +} + +// Bukin6 implements Bukin's 6th function. The function is two-dimensional, with +// the typical domain as x_0 ∈ [-15, -5], x_1 ∈ [-3, 3]. The function has a unique +// global minimum at [-10, 1], and many local minima. +// f(x) = 100 * sqrt(|x_1 - 0.01*x_0^2|) + 0.01*|x_0+10| +// Reference: +// https://www.sfu.ca/~ssurjano/bukin6.html (obtained June 2017) +type Bukin6 struct{} + +func (Bukin6) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + return 100*math.Sqrt(math.Abs(x[1]-0.01*x[0]*x[0])) + 0.01*math.Abs(x[0]+10) +} + +// CrossInTray implements the cross-in-tray function. The cross-in-tray function +// is a two-dimensional function with many local minima, and four global minima +// at (±1.3491, ±1.3491). The function is typically evaluated in the square +// [-10,10]^2. +// f(x) = -0.001(|sin(x_0)sin(x_1)exp(|100-sqrt((x_0^2+x_1^2)/π)|)|+1)^0.1 +// Reference: +// https://www.sfu.ca/~ssurjano/crossit.html (obtained June 2017) +type CrossInTray struct{} + +func (CrossInTray) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + exp := math.Abs(100 - math.Sqrt((x0*x0+x1*x1)/math.Pi)) + return -0.0001 * math.Pow(math.Abs(math.Sin(x0)*math.Sin(x1)*math.Exp(exp))+1, 0.1) +} + +// DropWave implements the drop-wave function, a two-dimensional function with +// many local minima and one global minimum at 0. The function is typically evaluated +// in the square [-5.12, 5.12]^2. +// f(x) = - (1+cos(12*sqrt(x0^2+x1^2))) / (0.5*(x0^2+x1^2)+2) +// Reference: +// https://www.sfu.ca/~ssurjano/drop.html (obtained June 2017) +type DropWave struct{} + +func (DropWave) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + num := 1 + math.Cos(12*math.Sqrt(x0*x0+x1*x1)) + den := 0.5*(x0*x0+x1*x1) + 2 + return -num / den +} + +// Eggholder implements the Eggholder function, a two-dimensional function with +// many local minima and one global minimum at [512, 404.2319]. The function +// is typically evaluated in the square [-512, 512]^2. +// f(x) = -(x_1+47)*sin(sqrt(|x_1+x_0/2+47|))-x_1*sin(sqrt(|x_0-(x_1+47)|)) +// Reference: +// https://www.sfu.ca/~ssurjano/egg.html (obtained June 2017) +type Eggholder struct{} + +func (Eggholder) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + return -(x1+47)*math.Sin(math.Sqrt(math.Abs(x1+x0/2+47))) - + x0*math.Sin(math.Sqrt(math.Abs(x0-x1-47))) +} + +// GramacyLee implements the Gramacy-Lee function, a one-dimensional function +// with many local minima. The function is typically evaluated on the domain [0.5, 2.5]. +// f(x) = sin(10πx)/(2x) + (x-1)^4 +// Reference: +// https://www.sfu.ca/~ssurjano/grlee12.html (obtained June 2017) +type GramacyLee struct{} + +func (GramacyLee) Func(x []float64) float64 { + if len(x) != 1 { + panic(badInputDim) + } + x0 := x[0] + return math.Sin(10*math.Pi*x0)/(2*x0) + math.Pow(x0-1, 4) +} + +// Griewank implements the Griewank function, a function of arbitrary dimension that +// has many local minima. It has a single global minimum of 0 at 0. Its typical +// domain is the hypercube of [-600, 600]^d. +// f(x) = \sum_i x_i^2/4000 - \prod_i cos(x_i/sqrt(i)) + 1 +// where d is the input dimension. +// +// Reference: +// https://www.sfu.ca/~ssurjano/griewank.html (obtained June 2017) +type Griewank struct{} + +func (Griewank) Func(x []float64) float64 { + var ss float64 + pc := 1.0 + for i, v := range x { + ss += v * v + pc *= math.Cos(v / math.Sqrt(float64(i+1))) + } + return ss/4000 - pc + 1 +} + +// HolderTable implements the Holder table function. The Holder table function +// is a two-dimensional function with many local minima, and four global minima +// at (±8.05502, ±9.66459). The function is typically evaluated in the square [-10,10]^2. +// f(x) = -|sin(x_0)cos(x1)exp(|1-sqrt(x_0^2+x1^2)/π|)| +// Reference: +// https://www.sfu.ca/~ssurjano/holder.html (obtained June 2017) +type HolderTable struct{} + +func (HolderTable) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + return -math.Abs(math.Sin(x0) * math.Cos(x1) * math.Exp(math.Abs(1-math.Sqrt(x0*x0+x1*x1)/math.Pi))) +} + +// Langermann2 implements the two-dimensional version of the Langermann function. +// The Langermann function has many local minima. The function is typically +// evaluated in the square [0,10]^2. +// f(x) = \sum_1^5 c_i exp(-(1/π)\sum_{j=1}^2(x_j-A_{ij})^2) * cos(π\sum_{j=1}^2 (x_j - A_{ij})^2) +// c = [5]float64{1,2,5,2,3} +// A = [5][2]float64{{3,5},{5,2},{2,1},{1,4},{7,9}} +// Reference: +// https://www.sfu.ca/~ssurjano/langer.html (obtained June 2017) +type Langermann2 struct{} + +func (Langermann2) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + var ( + c = [5]float64{1, 2, 5, 2, 3} + A = [5][2]float64{{3, 5}, {5, 2}, {2, 1}, {1, 4}, {7, 9}} + ) + var f float64 + for i, cv := range c { + var ss float64 + for j, av := range A[i] { + xja := x[j] - av + ss += xja * xja + } + f += cv * math.Exp(-(1/math.Pi)*ss) * math.Cos(math.Pi*ss) + } + return f +} + +// Levy implements the Levy function, a function of arbitrary dimension that +// has many local minima. It has a single global minimum of 0 at 1. Its typical +// domain is the hypercube of [-10, 10]^d. +// f(x) = sin^2(π*w_0) + \sum_{i=0}^{d-2}(w_i-1)^2*[1+10sin^2(π*w_i+1)] + +// (w_{d-1}-1)^2*[1+sin^2(2π*w_{d-1})] +// w_i = 1 + (x_i-1)/4 +// where d is the input dimension. +// +// Reference: +// https://www.sfu.ca/~ssurjano/levy.html (obtained June 2017) +type Levy struct{} + +func (Levy) Func(x []float64) float64 { + w1 := 1 + (x[0]-1)/4 + s1 := math.Sin(math.Pi * w1) + sum := s1 * s1 + for i := 0; i < len(x)-1; i++ { + wi := 1 + (x[i]-1)/4 + s := math.Sin(math.Pi*wi + 1) + sum += (wi - 1) * (wi - 1) * (1 + 10*s*s) + } + wd := 1 + (x[len(x)-1]-1)/4 + sd := math.Sin(2 * math.Pi * wd) + return sum + (wd-1)*(wd-1)*(1+sd*sd) +} + +// Levy13 implements the Levy-13 function, a two-dimensional function +// with many local minima. It has a single global minimum of 0 at 1. Its typical +// domain is the square [-10, 10]^2. +// f(x) = sin^2(3π*x_0) + (x_0-1)^2*[1+sin^2(3π*x_1)] + (x_1-1)^2*[1+sin^2(2π*x_1)] +// Reference: +// https://www.sfu.ca/~ssurjano/levy13.html (obtained June 2017) +type Levy13 struct{} + +func (Levy13) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + s0 := math.Sin(3 * math.Pi * x0) + s1 := math.Sin(3 * math.Pi * x1) + s2 := math.Sin(2 * math.Pi * x1) + return s0*s0 + (x0-1)*(x0-1)*(1+s1*s1) + (x1-1)*(x1-1)*(1+s2*s2) +} + +// Rastrigin implements the Rastrigen function, a function of arbitrary dimension +// that has many local minima. It has a single global minimum of 0 at 0. Its typical +// domain is the hypercube of [-5.12, 5.12]^d. +// f(x) = 10d + \sum_i [x_i^2 - 10cos(2π*x_i)] +// where d is the input dimension. +// +// Reference: +// https://www.sfu.ca/~ssurjano/rastr.html (obtained June 2017) +type Rastrigin struct{} + +func (Rastrigin) Func(x []float64) float64 { + sum := 10 * float64(len(x)) + for _, v := range x { + sum += v*v - 10*math.Cos(2*math.Pi*v) + } + return sum +} + +// Schaffer2 implements the second Schaffer function, a two-dimensional function +// with many local minima. It has a single global minimum of 0 at 0. Its typical +// domain is the square [-100, 100]^2. +// f(x) = 0.5 + (sin^2(x_0^2-x_1^2)-0.5) / (1+0.001*(x_0^2+x_1^2))^2 +// Reference: +// https://www.sfu.ca/~ssurjano/schaffer2.html (obtained June 2017) +type Schaffer2 struct{} + +func (Schaffer2) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + s := math.Sin(x0*x0 - x1*x1) + den := 1 + 0.001*(x0*x0+x1*x1) + return 0.5 + (s*s-0.5)/(den*den) +} + +// Schaffer4 implements the fourth Schaffer function, a two-dimensional function +// with many local minima. Its typical domain is the square [-100, 100]^2. +// f(x) = 0.5 + (cos(sin(|x_0^2-x_1^2|))-0.5) / (1+0.001*(x_0^2+x_1^2))^2 +// Reference: +// https://www.sfu.ca/~ssurjano/schaffer4.html (obtained June 2017) +type Schaffer4 struct{} + +func (Schaffer4) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + den := 1 + 0.001*(x0*x0+x1*x1) + return 0.5 + (math.Cos(math.Sin(math.Abs(x0*x0-x1*x1)))-0.5)/(den*den) +} + +// Schwefel implements the Schwefel function, a function of arbitrary dimension +// that has many local minima. Its typical domain is the hypercube of [-500, 500]^d. +// f(x) = 418.9829*d - \sum_i x_i*sin(sqrt(|x_i|)) +// where d is the input dimension. +// +// Reference: +// https://www.sfu.ca/~ssurjano/schwef.html (obtained June 2017) +type Schwefel struct{} + +func (Schwefel) Func(x []float64) float64 { + var sum float64 + for _, v := range x { + sum += v * math.Sin(math.Sqrt(math.Abs(v))) + } + return 418.9829*float64(len(x)) - sum +} + +// Shubert implements the Shubert function, a two-dimensional function +// with many local minima and many global minima. Its typical domain is the +// square [-10, 10]^2. +// f(x) = (sum_{i=1}^5 i cos((i+1)*x_0+i)) * (\sum_{i=1}^5 i cos((i+1)*x_1+i)) +// Reference: +// https://www.sfu.ca/~ssurjano/shubert.html (obtained June 2017) +type Shubert struct{} + +func (Shubert) Func(x []float64) float64 { + if len(x) != 2 { + panic(badInputDim) + } + x0 := x[0] + x1 := x[1] + var s0, s1 float64 + for i := 1.0; i <= 5.0; i++ { + s0 += i * math.Cos((i+1)*x0+i) + s1 += i * math.Cos((i+1)*x1+i) + } + return s0 * s1 +} diff --git a/vendor/gonum.org/v1/gonum/optimize/global.go b/vendor/gonum.org/v1/gonum/optimize/global.go new file mode 100644 index 00000000..9f73b753 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/global.go @@ -0,0 +1,239 @@ +// Copyright ©2016 The gonum 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 optimize + +import ( + "math" + "sync" + "time" +) + +// GlobalMethod is a global optimizer. Typically will require more function +// evaluations and no sense of local convergence +type GlobalMethod interface { + // Global tells method the max number of tasks, method returns how many it wants. + // This is needed to sync the Global goroutines and inside goroutines. + InitGlobal(dim, tasks int) int + // Global method may assume that the same task id always has the same pointer with it. + IterateGlobal(task int, loc *Location) (Operation, error) + Needser + // Done communicates to the optimization method that the optimization has + // concluded to allow for shutdown. + Done() +} + +// Global uses a global optimizer to search for the global minimum of a +// function. A maximization problem can be transformed into a +// minimization problem by multiplying the function by -1. +// +// The first argument represents the problem to be minimized. Its fields are +// routines that evaluate the objective function, gradient, and other +// quantities related to the problem. The objective function, p.Func, must not +// be nil. The optimization method used may require other fields to be non-nil +// as specified by method.Needs. Global will panic if these are not met. The +// method can be determined automatically from the supplied problem which is +// described below. +// +// If p.Status is not nil, it is called before every evaluation. If the +// returned Status is not NotTerminated or the error is not nil, the +// optimization run is terminated. +// +// The third argument contains the settings for the minimization. The +// DefaultGlobalSettings function can be called for a Settings struct with the +// default values initialized. If settings == nil, the default settings are used. +// Global optimization methods typically do not make assumptions about the number +// and location of local minima. Thus, the only convergence metric used is the +// function values found at major iterations of the optimization. Bounds on the +// length of optimization are obeyed, such as the number of allowed function +// evaluations. +// +// The final argument is the optimization method to use. If method == nil, then +// an appropriate default is chosen based on the properties of the other arguments +// (dimension, gradient-free or gradient-based, etc.). +// +// If method implements Statuser, method.Status is called before every call +// to method.Iterate. If the returned Status is not NotTerminated or the +// error is non-nil, the optimization run is terminated. +// +// Global returns a Result struct and any error that occurred. See the +// documentation of Result for more information. +// +// Be aware that the default behavior of Global is to find the minimum. +// For certain functions and optimization methods, this process can take many +// function evaluations. If you would like to put limits on this, for example +// maximum runtime or maximum function evaluations, modify the Settings +// input struct. +// +// Something about Global cannot guarantee strict bounds on function evaluations, +// iterations, etc. in the precense of concurrency. +func Global(p Problem, dim int, settings *Settings, method GlobalMethod) (*Result, error) { + startTime := time.Now() + if method == nil { + method = &GuessAndCheck{} + } + if settings == nil { + settings = DefaultSettingsGlobal() + } + stats := &Stats{} + err := checkOptimization(p, dim, method, settings.Recorder) + if err != nil { + return nil, err + } + + optLoc := newLocation(dim, method) + optLoc.F = math.Inf(1) + + if settings.FunctionConverge != nil { + settings.FunctionConverge.Init(optLoc.F) + } + + stats.Runtime = time.Since(startTime) + + // Send initial location to Recorder + if settings.Recorder != nil { + err = settings.Recorder.Record(optLoc, InitIteration, stats) + if err != nil { + return nil, err + } + } + + // Run optimization + var status Status + status, err = minimizeGlobal(&p, method, settings, stats, optLoc, startTime) + + // Cleanup and collect results + if settings.Recorder != nil && err == nil { + err = settings.Recorder.Record(optLoc, PostIteration, stats) + } + stats.Runtime = time.Since(startTime) + return &Result{ + Location: *optLoc, + Stats: *stats, + Status: status, + }, err +} + +func minimizeGlobal(p *Problem, method GlobalMethod, settings *Settings, stats *Stats, optLoc *Location, startTime time.Time) (status Status, err error) { + dim := len(optLoc.X) + statuser, _ := method.(Statuser) + gs := &globalStatus{ + mux: &sync.RWMutex{}, + stats: stats, + status: NotTerminated, + p: p, + startTime: startTime, + optLoc: optLoc, + settings: settings, + statuser: statuser, + } + + nTasks := settings.Concurrent + nTasks = method.InitGlobal(dim, nTasks) + + // Launch optimization workers + var wg sync.WaitGroup + for task := 0; task < nTasks; task++ { + wg.Add(1) + go func(task int) { + defer wg.Done() + loc := newLocation(dim, method) + x := make([]float64, dim) + globalWorker(task, method, gs, loc, x) + }(task) + } + wg.Wait() + method.Done() + return gs.status, gs.err +} + +type globalStatus struct { + mux *sync.RWMutex + stats *Stats + status Status + p *Problem + startTime time.Time + optLoc *Location + settings *Settings + statuser Statuser + err error +} + +func globalWorker(task int, m GlobalMethod, g *globalStatus, loc *Location, x []float64) { + for { + // Find Evaluation location + op, err := m.IterateGlobal(task, loc) + if err != nil { + // TODO(btracey): Figure out how to handle errors properly. Shut + // everything down? Pass to globalStatus so it can shut everything down? + g.mux.Lock() + g.err = err + g.status = Failure + g.mux.Unlock() + break + } + + // Evaluate location and/or update stats. + status := g.globalOperation(op, loc, x) + if status != NotTerminated { + break + } + } +} + +// globalOperation updates handles the status received by an individual worker. +// It uses a mutex to protect updates where necessary. +func (g *globalStatus) globalOperation(op Operation, loc *Location, x []float64) Status { + // Do a quick check to see if one of the other workers converged in the meantime. + var status Status + var err error + g.mux.RLock() + status = g.status + g.mux.RUnlock() + if status != NotTerminated { + return status + } + switch op { + case NoOperation: + case InitIteration: + panic("optimize: Method returned InitIteration") + case PostIteration: + panic("optimize: Method returned PostIteration") + case MajorIteration: + g.mux.Lock() + g.stats.MajorIterations++ + copyLocation(g.optLoc, loc) + g.mux.Unlock() + + g.mux.RLock() + status = checkConvergence(g.optLoc, g.settings, false) + g.mux.RUnlock() + default: // Any of the Evaluation operations. + status, err = evaluate(g.p, loc, op, x) + g.mux.Lock() + updateStats(g.stats, op) + g.mux.Unlock() + } + + g.mux.Lock() + status, err = iterCleanup(status, err, g.stats, g.settings, g.statuser, g.startTime, loc, op) + // Update the termination status if it hasn't already terminated. + if g.status == NotTerminated { + g.status = status + g.err = err + } + g.mux.Unlock() + + return status +} + +func DefaultSettingsGlobal() *Settings { + return &Settings{ + FunctionThreshold: math.Inf(-1), + FunctionConverge: &FunctionConverge{ + Absolute: 1e-10, + Iterations: 100, + }, + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/gradientdescent.go b/vendor/gonum.org/v1/gonum/optimize/gradientdescent.go new file mode 100644 index 00000000..292bf5c9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/gradientdescent.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum 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 optimize + +import "gonum.org/v1/gonum/floats" + +// GradientDescent implements the steepest descent optimization method that +// performs successive steps along the direction of the negative gradient. +type GradientDescent struct { + // Linesearcher selects suitable steps along the descent direction. + // If Linesearcher is nil, a reasonable default will be chosen. + Linesearcher Linesearcher + // StepSizer determines the initial step size along each direction. + // If StepSizer is nil, a reasonable default will be chosen. + StepSizer StepSizer + + ls *LinesearchMethod +} + +func (g *GradientDescent) Init(loc *Location) (Operation, error) { + if g.Linesearcher == nil { + g.Linesearcher = &Backtracking{} + } + if g.StepSizer == nil { + g.StepSizer = &QuadraticStepSize{} + } + + if g.ls == nil { + g.ls = &LinesearchMethod{} + } + g.ls.Linesearcher = g.Linesearcher + g.ls.NextDirectioner = g + + return g.ls.Init(loc) +} + +func (g *GradientDescent) Iterate(loc *Location) (Operation, error) { + return g.ls.Iterate(loc) +} + +func (g *GradientDescent) InitDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return g.StepSizer.Init(loc, dir) +} + +func (g *GradientDescent) NextDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return g.StepSizer.StepSize(loc, dir) +} + +func (*GradientDescent) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/vendor/gonum.org/v1/gonum/optimize/guessandcheck.go b/vendor/gonum.org/v1/gonum/optimize/guessandcheck.go new file mode 100644 index 00000000..e08fc4c6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/guessandcheck.go @@ -0,0 +1,60 @@ +// Copyright ©2016 The gonum 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 optimize + +import ( + "math" + "sync" + + "gonum.org/v1/gonum/stat/distmv" +) + +// GuessAndCheck is a global optimizer that evaluates the function at random +// locations. Not a good optimizer, but useful for comparison and debugging. +type GuessAndCheck struct { + Rander distmv.Rander + + eval []bool + + mux *sync.Mutex + bestF float64 + bestX []float64 +} + +func (g *GuessAndCheck) Needs() struct{ Gradient, Hessian bool } { + return struct{ Gradient, Hessian bool }{false, false} +} + +func (g *GuessAndCheck) Done() { + // No cleanup needed +} + +func (g *GuessAndCheck) InitGlobal(dim, tasks int) int { + g.eval = make([]bool, tasks) + g.bestF = math.Inf(1) + g.bestX = resize(g.bestX, dim) + g.mux = &sync.Mutex{} + return tasks +} + +func (g *GuessAndCheck) IterateGlobal(task int, loc *Location) (Operation, error) { + // Task is true if it contains a new function evaluation. + if g.eval[task] { + g.eval[task] = false + g.mux.Lock() + if loc.F < g.bestF { + g.bestF = loc.F + copy(g.bestX, loc.X) + } else { + loc.F = g.bestF + copy(loc.X, g.bestX) + } + g.mux.Unlock() + return MajorIteration, nil + } + g.eval[task] = true + g.Rander.Rand(loc.X) + return FuncEvaluation, nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/guessandcheck_test.go b/vendor/gonum.org/v1/gonum/optimize/guessandcheck_test.go new file mode 100644 index 00000000..d906f907 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/guessandcheck_test.go @@ -0,0 +1,34 @@ +// Copyright ©2016 The gonum 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 optimize + +import ( + "testing" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/optimize/functions" + "gonum.org/v1/gonum/stat/distmv" +) + +func TestGuessAndCheck(t *testing.T) { + dim := 3000 + problem := Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + } + mu := make([]float64, dim) + sigma := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigma.SetSym(i, i, 1) + } + d, ok := distmv.NewNormal(mu, sigma, nil) + if !ok { + panic("bad test") + } + Global(problem, dim, nil, &GuessAndCheck{Rander: d}) + settings := DefaultSettingsGlobal() + settings.Concurrent = 5 + settings.MajorIterations = 15 + Global(problem, dim, settings, &GuessAndCheck{Rander: d}) +} diff --git a/vendor/gonum.org/v1/gonum/optimize/interfaces.go b/vendor/gonum.org/v1/gonum/optimize/interfaces.go new file mode 100644 index 00000000..12544610 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/interfaces.go @@ -0,0 +1,130 @@ +// Copyright ©2014 The gonum 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 optimize + +// A Method can optimize an objective function. +// +// It uses a reverse-communication interface between the optimization method +// and the caller. Method acts as a client that asks the caller to perform +// needed operations via Operation returned from Init and Iterate methods. +// This provides independence of the optimization algorithm on user-supplied +// data and their representation, and enables automation of common operations +// like checking for (various types of) convergence and maintaining statistics. +// +// A Method can command an Evaluation, a MajorIteration or NoOperation operations. +// +// An evaluation operation is one or more of the Evaluation operations +// (FuncEvaluation, GradEvaluation, etc.) which can be combined with +// the bitwise or operator. In an evaluation operation, the requested fields of +// Problem will be evaluated at the point specified in Location.X. +// The corresponding fields of Location will be filled with the results that +// can be retrieved upon the next call to Iterate. The Method interface +// requires that entries of Location are not modified aside from the commanded +// evaluations. Thus, the type implementing Method may use multiple Operations +// to set the Location fields at a particular x value. +// +// Instead of an Evaluation, a Method may declare MajorIteration. In +// a MajorIteration, the values in the fields of Location are treated as +// a potential optimizer. The convergence of the optimization routine +// (GradientThreshold, etc.) is checked at this new best point. In +// a MajorIteration, the fields of Location must be valid and consistent. +// +// A Method must not return InitIteration and PostIteration operations. These are +// reserved for the clients to be passed to Recorders. A Method must also not +// combine the Evaluation operations with the Iteration operations. +type Method interface { + // Init initializes the method based on the initial data in loc, updates it + // and returns the first operation to be carried out by the caller. + // The initial location must be valid as specified by Needs. + Init(loc *Location) (Operation, error) + + // Iterate retrieves data from loc, performs one iteration of the method, + // updates loc and returns the next operation. + Iterate(loc *Location) (Operation, error) + + Needser +} + +type Needser interface { + // Needs specifies information about the objective function needed by the + // optimizer beyond just the function value. The information is used + // internally for initialization and must match evaluation types returned + // by Init and Iterate during the optimization process. + Needs() struct { + Gradient bool + Hessian bool + } +} + +// Statuser can report the status and any error. It is intended for methods as +// an additional error reporting mechanism apart from the errors returned from +// Init and Iterate. +type Statuser interface { + Status() (Status, error) +} + +// Linesearcher is a type that can perform a line search. It tries to find an +// (approximate) minimum of the objective function along the search direction +// dir_k starting at the most recent location x_k, i.e., it tries to minimize +// the function +// φ(step) := f(x_k + step * dir_k) where step > 0. +// Typically, a Linesearcher will be used in conjunction with LinesearchMethod +// for performing gradient-based optimization through sequential line searches. +type Linesearcher interface { + // Init initializes the Linesearcher and a new line search. Value and + // derivative contain φ(0) and φ'(0), respectively, and step contains the + // first trial step length. It returns an Operation that must be one of + // FuncEvaluation, GradEvaluation, FuncEvaluation|GradEvaluation. The + // caller must evaluate φ(step), φ'(step), or both, respectively, and pass + // the result to Linesearcher in value and derivative arguments to Iterate. + Init(value, derivative float64, step float64) Operation + + // Iterate takes in the values of φ and φ' evaluated at the previous step + // and returns the next operation. + // + // If op is one of FuncEvaluation, GradEvaluation, + // FuncEvaluation|GradEvaluation, the caller must evaluate φ(step), + // φ'(step), or both, respectively, and pass the result to Linesearcher in + // value and derivative arguments on the next call to Iterate. + // + // If op is MajorIteration, a sufficiently accurate minimum of φ has been + // found at the previous step and the line search has concluded. Init must + // be called again to initialize a new line search. + // + // If err is nil, op must not specify another operation. If err is not nil, + // the values of op and step are undefined. + Iterate(value, derivative float64) (op Operation, step float64, err error) +} + +// NextDirectioner implements a strategy for computing a new line search +// direction at each major iteration. Typically, a NextDirectioner will be +// used in conjunction with LinesearchMethod for performing gradient-based +// optimization through sequential line searches. +type NextDirectioner interface { + // InitDirection initializes the NextDirectioner at the given starting location, + // putting the initial direction in place into dir, and returning the initial + // step size. InitDirection must not modify Location. + InitDirection(loc *Location, dir []float64) (step float64) + + // NextDirection updates the search direction and step size. Location is + // the location seen at the conclusion of the most recent linesearch. The + // next search direction is put in place into dir, and the next step size + // is returned. NextDirection must not modify Location. + NextDirection(loc *Location, dir []float64) (step float64) +} + +// StepSizer can set the next step size of the optimization given the last Location. +// Returned step size must be positive. +type StepSizer interface { + Init(loc *Location, dir []float64) float64 + StepSize(loc *Location, dir []float64) float64 +} + +// A Recorder can record the progress of the optimization, for example to print +// the progress to StdOut or to a log file. A Recorder must not modify any data. +type Recorder interface { + Init() error + Record(*Location, Operation, *Stats) error +} diff --git a/vendor/gonum.org/v1/gonum/optimize/lbfgs.go b/vendor/gonum.org/v1/gonum/optimize/lbfgs.go new file mode 100644 index 00000000..5c549377 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/lbfgs.go @@ -0,0 +1,167 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "gonum.org/v1/gonum/floats" +) + +// LBFGS implements the limited-memory BFGS method for gradient-based +// unconstrained minimization. +// +// It stores a modified version of the inverse Hessian approximation H +// implicitly from the last Store iterations while the normal BFGS method +// stores and manipulates H directly as a dense matrix. Therefore LBFGS is more +// appropriate than BFGS for large problems as the cost of LBFGS scales as +// O(Store * dim) while BFGS scales as O(dim^2). The "forgetful" nature of +// LBFGS may also make it perform better than BFGS for functions with Hessians +// that vary rapidly spatially. +type LBFGS struct { + // Linesearcher selects suitable steps along the descent direction. + // Accepted steps should satisfy the strong Wolfe conditions. + // If Linesearcher is nil, a reasonable default will be chosen. + Linesearcher Linesearcher + // Store is the size of the limited-memory storage. + // If Store is 0, it will be defaulted to 15. + Store int + + ls *LinesearchMethod + + dim int // Dimension of the problem + x []float64 // Location at the last major iteration + grad []float64 // Gradient at the last major iteration + + // History + oldest int // Index of the oldest element of the history + y [][]float64 // Last Store values of y + s [][]float64 // Last Store values of s + rho []float64 // Last Store values of rho + a []float64 // Cache of Hessian updates +} + +func (l *LBFGS) Init(loc *Location) (Operation, error) { + if l.Linesearcher == nil { + l.Linesearcher = &Bisection{} + } + if l.Store == 0 { + l.Store = 15 + } + + if l.ls == nil { + l.ls = &LinesearchMethod{} + } + l.ls.Linesearcher = l.Linesearcher + l.ls.NextDirectioner = l + + return l.ls.Init(loc) +} + +func (l *LBFGS) Iterate(loc *Location) (Operation, error) { + return l.ls.Iterate(loc) +} + +func (l *LBFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + l.dim = dim + l.oldest = 0 + + l.a = resize(l.a, l.Store) + l.rho = resize(l.rho, l.Store) + l.y = l.initHistory(l.y) + l.s = l.initHistory(l.s) + + l.x = resize(l.x, dim) + copy(l.x, loc.X) + + l.grad = resize(l.grad, dim) + copy(l.grad, loc.Gradient) + + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return 1 / floats.Norm(dir, 2) +} + +func (l *LBFGS) initHistory(hist [][]float64) [][]float64 { + c := cap(hist) + if c < l.Store { + n := make([][]float64, l.Store-c) + hist = append(hist[:c], n...) + } + hist = hist[:l.Store] + for i := range hist { + hist[i] = resize(hist[i], l.dim) + for j := range hist[i] { + hist[i][j] = 0 + } + } + return hist +} + +func (l *LBFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) { + // Uses two-loop correction as described in + // Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). Springer (2006), chapter 7, page 178. + + if len(loc.X) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + if len(loc.Gradient) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + if len(dir) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + + y := l.y[l.oldest] + floats.SubTo(y, loc.Gradient, l.grad) + s := l.s[l.oldest] + floats.SubTo(s, loc.X, l.x) + sDotY := floats.Dot(s, y) + l.rho[l.oldest] = 1 / sDotY + + l.oldest = (l.oldest + 1) % l.Store + + copy(l.x, loc.X) + copy(l.grad, loc.Gradient) + copy(dir, loc.Gradient) + + // Start with the most recent element and go backward, + for i := 0; i < l.Store; i++ { + idx := l.oldest - i - 1 + if idx < 0 { + idx += l.Store + } + l.a[idx] = l.rho[idx] * floats.Dot(l.s[idx], dir) + floats.AddScaled(dir, -l.a[idx], l.y[idx]) + } + + // Scale the initial Hessian. + gamma := sDotY / floats.Dot(y, y) + floats.Scale(gamma, dir) + + // Start with the oldest element and go forward. + for i := 0; i < l.Store; i++ { + idx := i + l.oldest + if idx >= l.Store { + idx -= l.Store + } + beta := l.rho[idx] * floats.Dot(l.y[idx], dir) + floats.AddScaled(dir, l.a[idx]-beta, l.s[idx]) + } + + // dir contains H^{-1} * g, so flip the direction for minimization. + floats.Scale(-1, dir) + + return 1 +} + +func (*LBFGS) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/vendor/gonum.org/v1/gonum/optimize/linesearch.go b/vendor/gonum.org/v1/gonum/optimize/linesearch.go new file mode 100644 index 00000000..37ccb90e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/linesearch.go @@ -0,0 +1,218 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +// LinesearchMethod represents an abstract optimization method in which a +// function is optimized through successive line search optimizations. +type LinesearchMethod struct { + // NextDirectioner specifies the search direction of each linesearch. + NextDirectioner NextDirectioner + // Linesearcher performs a linesearch along the search direction. + Linesearcher Linesearcher + + x []float64 // Starting point for the current iteration. + dir []float64 // Search direction for the current iteration. + + first bool // Indicator of the first iteration. + nextMajor bool // Indicates that MajorIteration must be commanded at the next call to Iterate. + eval Operation // Indicator of valid fields in Location. + + lastStep float64 // Step taken from x in the previous call to Iterate. + lastOp Operation // Operation returned from the previous call to Iterate. +} + +func (ls *LinesearchMethod) Init(loc *Location) (Operation, error) { + if loc.Gradient == nil { + panic("linesearch: gradient is nil") + } + + dim := len(loc.X) + ls.x = resize(ls.x, dim) + ls.dir = resize(ls.dir, dim) + + ls.first = true + ls.nextMajor = false + + // Indicate that all fields of loc are valid. + ls.eval = FuncEvaluation | GradEvaluation + if loc.Hessian != nil { + ls.eval |= HessEvaluation + } + + ls.lastStep = math.NaN() + ls.lastOp = NoOperation + + return ls.initNextLinesearch(loc) +} + +func (ls *LinesearchMethod) Iterate(loc *Location) (Operation, error) { + switch ls.lastOp { + case NoOperation: + // TODO(vladimir-ch): Either Init has not been called, or the caller is + // trying to resume the optimization run after Iterate previously + // returned with an error. Decide what is the proper thing to do. See also #125. + + case MajorIteration: + // The previous updated location did not converge the full + // optimization. Initialize a new Linesearch. + return ls.initNextLinesearch(loc) + + default: + // Update the indicator of valid fields of loc. + ls.eval |= ls.lastOp + + if ls.nextMajor { + ls.nextMajor = false + + // Linesearcher previously finished, and the invalid fields of loc + // have now been validated. Announce MajorIteration. + ls.lastOp = MajorIteration + return ls.lastOp, nil + } + } + + // Continue the linesearch. + + f := math.NaN() + if ls.eval&FuncEvaluation != 0 { + f = loc.F + } + projGrad := math.NaN() + if ls.eval&GradEvaluation != 0 { + projGrad = floats.Dot(loc.Gradient, ls.dir) + } + op, step, err := ls.Linesearcher.Iterate(f, projGrad) + if err != nil { + return ls.error(err) + } + + switch op { + case MajorIteration: + // Linesearch has been finished. + + ls.lastOp = complementEval(loc, ls.eval) + if ls.lastOp == NoOperation { + // loc is complete, MajorIteration can be declared directly. + ls.lastOp = MajorIteration + } else { + // Declare MajorIteration on the next call to Iterate. + ls.nextMajor = true + } + + case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation: + if step != ls.lastStep { + // We are moving to a new location, and not, say, evaluating extra + // information at the current location. + + // Compute the next evaluation point and store it in loc.X. + floats.AddScaledTo(loc.X, ls.x, step, ls.dir) + if floats.Equal(ls.x, loc.X) { + // Step size has become so small that the next evaluation point is + // indistinguishable from the starting point for the current + // iteration due to rounding errors. + return ls.error(ErrNoProgress) + } + ls.lastStep = step + ls.eval = NoOperation // Indicate all invalid fields of loc. + } + ls.lastOp = op + + default: + panic("linesearch: Linesearcher returned invalid operation") + } + + return ls.lastOp, nil +} + +func (ls *LinesearchMethod) error(err error) (Operation, error) { + ls.lastOp = NoOperation + return ls.lastOp, err +} + +// initNextLinesearch initializes the next linesearch using the previous +// complete location stored in loc. It fills loc.X and returns an evaluation +// to be performed at loc.X. +func (ls *LinesearchMethod) initNextLinesearch(loc *Location) (Operation, error) { + copy(ls.x, loc.X) + + var step float64 + if ls.first { + ls.first = false + step = ls.NextDirectioner.InitDirection(loc, ls.dir) + } else { + step = ls.NextDirectioner.NextDirection(loc, ls.dir) + } + + projGrad := floats.Dot(loc.Gradient, ls.dir) + if projGrad >= 0 { + return ls.error(ErrNonDescentDirection) + } + + op := ls.Linesearcher.Init(loc.F, projGrad, step) + switch op { + case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation: + default: + panic("linesearch: Linesearcher returned invalid operation") + } + + floats.AddScaledTo(loc.X, ls.x, step, ls.dir) + if floats.Equal(ls.x, loc.X) { + // Step size is so small that the next evaluation point is + // indistinguishable from the starting point for the current iteration + // due to rounding errors. + return ls.error(ErrNoProgress) + } + + ls.lastStep = step + ls.eval = NoOperation // Invalidate all fields of loc. + + ls.lastOp = op + return ls.lastOp, nil +} + +// ArmijoConditionMet returns true if the Armijo condition (aka sufficient +// decrease) has been met. Under normal conditions, the following should be +// true, though this is not enforced: +// - initGrad < 0 +// - step > 0 +// - 0 < decrease < 1 +func ArmijoConditionMet(currObj, initObj, initGrad, step, decrease float64) bool { + return currObj <= initObj+decrease*step*initGrad +} + +// StrongWolfeConditionsMet returns true if the strong Wolfe conditions have been met. +// The strong Wolfe conditions ensure sufficient decrease in the function +// value, and sufficient decrease in the magnitude of the projected gradient. +// Under normal conditions, the following should be true, though this is not +// enforced: +// - initGrad < 0 +// - step > 0 +// - 0 <= decrease < curvature < 1 +func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool { + if currObj > initObj+decrease*step*initGrad { + return false + } + return math.Abs(currGrad) < curvature*math.Abs(initGrad) +} + +// WeakWolfeConditionsMet returns true if the weak Wolfe conditions have been met. +// The weak Wolfe conditions ensure sufficient decrease in the function value, +// and sufficient decrease in the value of the projected gradient. Under normal +// conditions, the following should be true, though this is not enforced: +// - initGrad < 0 +// - step > 0 +// - 0 <= decrease < curvature< 1 +func WeakWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool { + if currObj > initObj+decrease*step*initGrad { + return false + } + return currGrad >= curvature*initGrad +} diff --git a/vendor/gonum.org/v1/gonum/optimize/linesearcher_test.go b/vendor/gonum.org/v1/gonum/optimize/linesearcher_test.go new file mode 100644 index 00000000..f1def408 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/linesearcher_test.go @@ -0,0 +1,136 @@ +// Copyright ©2015 The gonum 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 optimize + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/optimize/functions" +) + +func TestMoreThuente(t *testing.T) { + d := 0.001 + c := 0.001 + ls := &MoreThuente{ + DecreaseFactor: d, + CurvatureFactor: c, + } + testLinesearcher(t, ls, d, c, true) +} + +func TestBisection(t *testing.T) { + c := 0.1 + ls := &Bisection{ + CurvatureFactor: c, + } + testLinesearcher(t, ls, 0, c, true) +} + +func TestBacktracking(t *testing.T) { + d := 0.001 + ls := &Backtracking{ + DecreaseFactor: d, + } + testLinesearcher(t, ls, d, 0, false) +} + +type funcGrader interface { + Func([]float64) float64 + Grad([]float64, []float64) +} + +type linesearcherTest struct { + name string + f func(float64) float64 + g func(float64) float64 +} + +func newLinesearcherTest(name string, fg funcGrader) linesearcherTest { + grad := make([]float64, 1) + return linesearcherTest{ + name: name, + f: func(x float64) float64 { + return fg.Func([]float64{x}) + }, + g: func(x float64) float64 { + fg.Grad(grad, []float64{x}) + return grad[0] + }, + } +} + +func testLinesearcher(t *testing.T, ls Linesearcher, decrease, curvature float64, strongWolfe bool) { + for i, prob := range []linesearcherTest{ + newLinesearcherTest("Concave-to-the-right function", functions.ConcaveRight{}), + newLinesearcherTest("Concave-to-the-left function", functions.ConcaveLeft{}), + newLinesearcherTest("Plassmann wiggly function (l=39, beta=0.01)", functions.Plassmann{39, 0.01}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.001)", functions.YanaiOzawaKaneko{0.001, 0.001}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.01, beta2=0.001)", functions.YanaiOzawaKaneko{0.01, 0.001}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.01)", functions.YanaiOzawaKaneko{0.001, 0.01}), + } { + for _, initStep := range []float64{0.001, 0.1, 1, 10, 1000} { + prefix := fmt.Sprintf("test %d (%v started from %v)", i, prob.name, initStep) + + f0 := prob.f(0) + g0 := prob.g(0) + if g0 >= 0 { + panic("bad test function") + } + + op := ls.Init(f0, g0, initStep) + if !op.isEvaluation() { + t.Errorf("%v: Linesearcher.Init returned non-evaluating operation %v", prefix, op) + continue + } + + var ( + err error + k int + f, g float64 + step float64 + ) + loop: + for { + switch op { + case MajorIteration: + if f > f0+step*decrease*g0 { + t.Errorf("%v: %v found step %v that does not satisfy the sufficient decrease condition", + prefix, reflect.TypeOf(ls), step) + } + if strongWolfe && math.Abs(g) > curvature*(-g0) { + t.Errorf("%v: %v found step %v that does not satisfy the curvature condition", + prefix, reflect.TypeOf(ls), step) + } + break loop + case FuncEvaluation: + f = prob.f(step) + case GradEvaluation: + g = prob.g(step) + case FuncEvaluation | GradEvaluation: + f = prob.f(step) + g = prob.g(step) + default: + t.Errorf("%v: Linesearcher returned an invalid operation %v", prefix, op) + break loop + } + + k++ + if k == 1000 { + t.Errorf("%v: %v did not finish", prefix, reflect.TypeOf(ls)) + break + } + + op, step, err = ls.Iterate(f, g) + if err != nil { + t.Errorf("%v: %v failed at step %v with %v", prefix, reflect.TypeOf(ls), step, err) + break + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/optimize/local.go b/vendor/gonum.org/v1/gonum/optimize/local.go new file mode 100644 index 00000000..241e80fe --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/local.go @@ -0,0 +1,225 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "math" + "time" +) + +// Local finds a local minimum of a minimization problem using a sequential +// algorithm. A maximization problem can be transformed into a minimization +// problem by multiplying the function by -1. +// +// The first argument represents the problem to be minimized. Its fields are +// routines that evaluate the objective function, gradient, and other +// quantities related to the problem. The objective function, p.Func, must not +// be nil. The optimization method used may require other fields to be non-nil +// as specified by method.Needs. Local will panic if these are not met. The +// method can be determined automatically from the supplied problem which is +// described below. +// +// If p.Status is not nil, it is called before every evaluation. If the +// returned Status is not NotTerminated or the error is not nil, the +// optimization run is terminated. +// +// The second argument is the initial location at which to start the minimization. +// The initial location must be supplied, and must have a length equal to the +// problem dimension. +// +// The third argument contains the settings for the minimization. It is here that +// gradient tolerance, etc. are specified. The DefaultSettings function +// can be called for a Settings struct with the default values initialized. +// If settings == nil, the default settings are used. See the documentation +// for the Settings structure for more information. The optimization Method used +// may also contain settings, see documentation for the appropriate optimizer. +// +// The final argument is the optimization method to use. If method == nil, then +// an appropriate default is chosen based on the properties of the other arguments +// (dimension, gradient-free or gradient-based, etc.). The optimization +// methods in this package are designed such that reasonable defaults occur +// if options are not specified explicitly. For example, the code +// method := &optimize.BFGS{} +// creates a pointer to a new BFGS struct. When Local is called, the settings +// in the method will be populated with default values. The methods are also +// designed such that they can be reused in future calls to Local. +// +// If method implements Statuser, method.Status is called before every call +// to method.Iterate. If the returned Status is not NotTerminated or the +// error is non-nil, the optimization run is terminated. +// +// Local returns a Result struct and any error that occurred. See the +// documentation of Result for more information. +// +// Be aware that the default behavior of Local is to find the minimum. +// For certain functions and optimization methods, this process can take many +// function evaluations. If you would like to put limits on this, for example +// maximum runtime or maximum function evaluations, modify the Settings +// input struct. +func Local(p Problem, initX []float64, settings *Settings, method Method) (*Result, error) { + startTime := time.Now() + dim := len(initX) + if method == nil { + method = getDefaultMethod(&p) + } + if settings == nil { + settings = DefaultSettings() + } + + stats := &Stats{} + + err := checkOptimization(p, dim, method, settings.Recorder) + if err != nil { + return nil, err + } + + optLoc, err := getStartingLocation(&p, method, initX, stats, settings) + if err != nil { + return nil, err + } + + if settings.FunctionConverge != nil { + settings.FunctionConverge.Init(optLoc.F) + } + + stats.Runtime = time.Since(startTime) + + // Send initial location to Recorder + if settings.Recorder != nil { + err = settings.Recorder.Record(optLoc, InitIteration, stats) + if err != nil { + return nil, err + } + } + + // Check if the starting location satisfies the convergence criteria. + status := checkConvergence(optLoc, settings, true) + + // Run optimization + if status == NotTerminated && err == nil { + // The starting location is not good enough, we need to perform a + // minimization. The optimal location will be stored in-place in + // optLoc. + status, err = minimize(&p, method, settings, stats, optLoc, startTime) + } + + // Cleanup and collect results + if settings.Recorder != nil && err == nil { + // Send the optimal location to Recorder. + err = settings.Recorder.Record(optLoc, PostIteration, stats) + } + stats.Runtime = time.Since(startTime) + return &Result{ + Location: *optLoc, + Stats: *stats, + Status: status, + }, err +} + +func minimize(p *Problem, method Method, settings *Settings, stats *Stats, optLoc *Location, startTime time.Time) (status Status, err error) { + loc := &Location{} + copyLocation(loc, optLoc) + x := make([]float64, len(loc.X)) + + statuser, _ := method.(Statuser) + + var op Operation + op, err = method.Init(loc) + if err != nil { + status = Failure + return + } + + for { + // Sequentially call method.Iterate, performing the operations it has + // commanded, until convergence. + + switch op { + case NoOperation: + case InitIteration: + panic("optimize: Method returned InitIteration") + case PostIteration: + panic("optimize: Method returned PostIteration") + case MajorIteration: + copyLocation(optLoc, loc) + stats.MajorIterations++ + status = checkConvergence(optLoc, settings, true) + default: // Any of the Evaluation operations. + status, err = evaluate(p, loc, op, x) + updateStats(stats, op) + } + + status, err = iterCleanup(status, err, stats, settings, statuser, startTime, loc, op) + if status != NotTerminated || err != nil { + return + } + + op, err = method.Iterate(loc) + if err != nil { + status = Failure + return + } + } +} + +func getDefaultMethod(p *Problem) Method { + if p.Grad != nil { + return &BFGS{} + } + return &NelderMead{} +} + +// getStartingLocation allocates and initializes the starting location for the minimization. +func getStartingLocation(p *Problem, method Method, initX []float64, stats *Stats, settings *Settings) (*Location, error) { + dim := len(initX) + loc := newLocation(dim, method) + copy(loc.X, initX) + + if settings.UseInitialData { + loc.F = settings.InitialValue + if loc.Gradient != nil { + initG := settings.InitialGradient + if initG == nil { + panic("optimize: initial gradient is nil") + } + if len(initG) != dim { + panic("optimize: initial gradient size mismatch") + } + copy(loc.Gradient, initG) + } + if loc.Hessian != nil { + initH := settings.InitialHessian + if initH == nil { + panic("optimize: initial Hessian is nil") + } + if initH.Symmetric() != dim { + panic("optimize: initial Hessian size mismatch") + } + loc.Hessian.CopySym(initH) + } + } else { + eval := FuncEvaluation + if loc.Gradient != nil { + eval |= GradEvaluation + } + if loc.Hessian != nil { + eval |= HessEvaluation + } + x := make([]float64, len(loc.X)) + evaluate(p, loc, eval, x) + updateStats(stats, eval) + } + + if math.IsInf(loc.F, 1) || math.IsNaN(loc.F) { + return loc, ErrFunc(loc.F) + } + for i, v := range loc.Gradient { + if math.IsInf(v, 0) || math.IsNaN(v) { + return loc, ErrGrad{Grad: v, Index: i} + } + } + + return loc, nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/local_example_test.go b/vendor/gonum.org/v1/gonum/optimize/local_example_test.go new file mode 100644 index 00000000..64940388 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/local_example_test.go @@ -0,0 +1,43 @@ +// Copyright ©2016 The gonum 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 optimize_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/optimize" + "gonum.org/v1/gonum/optimize/functions" +) + +func ExampleLocal() { + p := optimize.Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + } + + x := []float64{1.3, 0.7, 0.8, 1.9, 1.2} + settings := optimize.DefaultSettings() + settings.Recorder = nil + settings.GradientThreshold = 1e-12 + settings.FunctionConverge = nil + + result, err := optimize.Local(p, x, settings, &optimize.BFGS{}) + if err != nil { + log.Fatal(err) + } + if err = result.Status.Err(); err != nil { + log.Fatal(err) + } + fmt.Printf("result.Status: %v\n", result.Status) + fmt.Printf("result.X: %v\n", result.X) + fmt.Printf("result.F: %v\n", result.F) + fmt.Printf("result.Stats.FuncEvaluations: %d\n", result.Stats.FuncEvaluations) + // Output: + // result.Status: GradientThreshold + // result.X: [1 1 1 1 1] + // result.F: 0 + // result.Stats.FuncEvaluations: 35 +} diff --git a/vendor/gonum.org/v1/gonum/optimize/minimize.go b/vendor/gonum.org/v1/gonum/optimize/minimize.go new file mode 100644 index 00000000..b5373e72 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/minimize.go @@ -0,0 +1,202 @@ +// Copyright ©2016 The gonum 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 optimize + +import ( + "fmt" + "math" + "time" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +// newLocation allocates a new locatian structure of the appropriate size. It +// allocates memory based on the dimension and the values in Needs. The initial +// function value is set to math.Inf(1). +func newLocation(dim int, method Needser) *Location { + // TODO(btracey): combine this with Local. + loc := &Location{ + X: make([]float64, dim), + } + loc.F = math.Inf(1) + if method.Needs().Gradient { + loc.Gradient = make([]float64, dim) + } + if method.Needs().Hessian { + loc.Hessian = mat.NewSymDense(dim, nil) + } + return loc +} + +func copyLocation(dst, src *Location) { + dst.X = resize(dst.X, len(src.X)) + copy(dst.X, src.X) + + dst.F = src.F + + dst.Gradient = resize(dst.Gradient, len(src.Gradient)) + copy(dst.Gradient, src.Gradient) + + if src.Hessian != nil { + if dst.Hessian == nil || dst.Hessian.Symmetric() != len(src.X) { + dst.Hessian = mat.NewSymDense(len(src.X), nil) + } + dst.Hessian.CopySym(src.Hessian) + } +} + +func checkOptimization(p Problem, dim int, method Needser, recorder Recorder) error { + if p.Func == nil { + panic(badProblem) + } + if dim <= 0 { + panic("optimize: impossible problem dimension") + } + if err := p.satisfies(method); err != nil { + return err + } + if p.Status != nil { + _, err := p.Status() + if err != nil { + return err + } + } + if recorder != nil { + err := recorder.Init() + if err != nil { + return err + } + } + return nil +} + +// evaluate evaluates the routines specified by the Operation at loc.X, and stores +// the answer into loc. loc.X is copied into x before +// evaluating in order to prevent the routines from modifying it. +func evaluate(p *Problem, loc *Location, op Operation, x []float64) (Status, error) { + if !op.isEvaluation() { + panic(fmt.Sprintf("optimize: invalid evaluation %v", op)) + } + if p.Status != nil { + status, err := p.Status() + if err != nil || status != NotTerminated { + return status, err + } + } + copy(x, loc.X) + if op&FuncEvaluation != 0 { + loc.F = p.Func(x) + } + if op&GradEvaluation != 0 { + p.Grad(loc.Gradient, x) + } + if op&HessEvaluation != 0 { + p.Hess(loc.Hessian, x) + } + return NotTerminated, nil +} + +// checkConvergence returns NotTerminated if the Location does not satisfy the +// convergence criteria given by settings. Otherwise a corresponding status is +// returned. +// Unlike checkLimits, checkConvergence is called only at MajorIterations. +// +// If local is true, gradient convergence is also checked. +func checkConvergence(loc *Location, settings *Settings, local bool) Status { + if local && loc.Gradient != nil { + norm := floats.Norm(loc.Gradient, math.Inf(1)) + if norm < settings.GradientThreshold { + return GradientThreshold + } + } + if loc.F < settings.FunctionThreshold { + return FunctionThreshold + } + if settings.FunctionConverge != nil { + return settings.FunctionConverge.FunctionConverged(loc.F) + } + return NotTerminated +} + +// updateStats updates the statistics based on the operation. +func updateStats(stats *Stats, op Operation) { + if op&FuncEvaluation != 0 { + stats.FuncEvaluations++ + } + if op&GradEvaluation != 0 { + stats.GradEvaluations++ + } + if op&HessEvaluation != 0 { + stats.HessEvaluations++ + } +} + +// checkLimits returns NotTerminated status if the various limits given by +// settings have not been reached. Otherwise it returns a corresponding status. +// Unlike checkConvergence, checkLimits is called by Local and Global at _every_ +// iteration. +func checkLimits(loc *Location, stats *Stats, settings *Settings) Status { + // Check the objective function value for negative infinity because it + // could break the linesearches and -inf is the best we can do anyway. + if math.IsInf(loc.F, -1) { + return FunctionNegativeInfinity + } + + if settings.MajorIterations > 0 && stats.MajorIterations >= settings.MajorIterations { + return IterationLimit + } + + if settings.FuncEvaluations > 0 && stats.FuncEvaluations >= settings.FuncEvaluations { + return FunctionEvaluationLimit + } + + if settings.GradEvaluations > 0 && stats.GradEvaluations >= settings.GradEvaluations { + return GradientEvaluationLimit + } + + if settings.HessEvaluations > 0 && stats.HessEvaluations >= settings.HessEvaluations { + return HessianEvaluationLimit + } + + // TODO(vladimir-ch): It would be nice to update Runtime here. + if settings.Runtime > 0 && stats.Runtime >= settings.Runtime { + return RuntimeLimit + } + + return NotTerminated +} + +// TODO(btracey): better name +func iterCleanup(status Status, err error, stats *Stats, settings *Settings, statuser Statuser, startTime time.Time, loc *Location, op Operation) (Status, error) { + if status != NotTerminated || err != nil { + return status, err + } + + if settings.Recorder != nil { + stats.Runtime = time.Since(startTime) + err = settings.Recorder.Record(loc, op, stats) + if err != nil { + if status == NotTerminated { + status = Failure + } + return status, err + } + } + + stats.Runtime = time.Since(startTime) + status = checkLimits(loc, stats, settings) + if status != NotTerminated { + return status, nil + } + + if statuser != nil { + status, err = statuser.Status() + if err != nil || status != NotTerminated { + return status, err + } + } + return status, nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/morethuente.go b/vendor/gonum.org/v1/gonum/optimize/morethuente.go new file mode 100644 index 00000000..ec23167b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/morethuente.go @@ -0,0 +1,385 @@ +// Copyright ©2015 The gonum 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 optimize + +import "math" + +// MoreThuente is a Linesearcher that finds steps that satisfy both the +// sufficient decrease and curvature conditions (the strong Wolfe conditions). +// +// References: +// - More, J.J. and D.J. Thuente: Line Search Algorithms with Guaranteed Sufficient +// Decrease. ACM Transactions on Mathematical Software 20(3) (1994), 286-307 +type MoreThuente struct { + // DecreaseFactor is the constant factor in the sufficient decrease + // (Armijo) condition. + // It must be in the interval [0, 1). The default value is 0. + DecreaseFactor float64 + // CurvatureFactor is the constant factor in the Wolfe conditions. Smaller + // values result in a more exact line search. + // A set value must be in the interval (0, 1). If it is zero, it will be + // defaulted to 0.9. + CurvatureFactor float64 + // StepTolerance sets the minimum acceptable width for the linesearch + // interval. If the relative interval length is less than this value, + // ErrLinesearcherFailure is returned. + // It must be non-negative. If it is zero, it will be defaulted to 1e-10. + StepTolerance float64 + + // MinimumStep is the minimum step that the linesearcher will take. + // It must be non-negative and less than MaximumStep. Defaults to no + // minimum (a value of 0). + MinimumStep float64 + // MaximumStep is the maximum step that the linesearcher will take. + // It must be greater than MinimumStep. If it is zero, it will be defaulted + // to 1e20. + MaximumStep float64 + + bracketed bool // Indicates if a minimum has been bracketed. + fInit float64 // Function value at step = 0. + gInit float64 // Derivative value at step = 0. + + // When stage is 1, the algorithm updates the interval given by x and y + // so that it contains a minimizer of the modified function + // psi(step) = f(step) - f(0) - DecreaseFactor * step * f'(0). + // When stage is 2, the interval is updated so that it contains a minimizer + // of f. + stage int + + step float64 // Current step. + lower, upper float64 // Lower and upper bounds on the next step. + x float64 // Endpoint of the interval with a lower function value. + fx, gx float64 // Data at x. + y float64 // The other endpoint. + fy, gy float64 // Data at y. + width [2]float64 // Width of the interval at two previous iterations. +} + +const ( + mtMinGrowthFactor float64 = 1.1 + mtMaxGrowthFactor float64 = 4 +) + +func (mt *MoreThuente) Init(f, g float64, step float64) Operation { + // Based on the original Fortran code that is available, for example, from + // http://ftp.mcs.anl.gov/pub/MINPACK-2/csrch/ + // as part of + // MINPACK-2 Project. November 1993. + // Argonne National Laboratory and University of Minnesota. + // Brett M. Averick, Richard G. Carter, and Jorge J. Moré. + + if g >= 0 { + panic("morethuente: initial derivative is non-negative") + } + if step <= 0 { + panic("morethuente: invalid initial step") + } + + if mt.CurvatureFactor == 0 { + mt.CurvatureFactor = 0.9 + } + if mt.StepTolerance == 0 { + mt.StepTolerance = 1e-10 + } + if mt.MaximumStep == 0 { + mt.MaximumStep = 1e20 + } + + if mt.MinimumStep < 0 { + panic("morethuente: minimum step is negative") + } + if mt.MaximumStep <= mt.MinimumStep { + panic("morethuente: maximum step is not greater than minimum step") + } + if mt.DecreaseFactor < 0 || mt.DecreaseFactor >= 1 { + panic("morethuente: invalid decrease factor") + } + if mt.CurvatureFactor <= 0 || mt.CurvatureFactor >= 1 { + panic("morethuente: invalid curvature factor") + } + if mt.StepTolerance <= 0 { + panic("morethuente: step tolerance is not positive") + } + + if step < mt.MinimumStep { + step = mt.MinimumStep + } + if step > mt.MaximumStep { + step = mt.MaximumStep + } + + mt.bracketed = false + mt.stage = 1 + mt.fInit = f + mt.gInit = g + + mt.x, mt.fx, mt.gx = 0, f, g + mt.y, mt.fy, mt.gy = 0, f, g + + mt.lower = 0 + mt.upper = step + mtMaxGrowthFactor*step + + mt.width[0] = mt.MaximumStep - mt.MinimumStep + mt.width[1] = 2 * mt.width[0] + + mt.step = step + return FuncEvaluation | GradEvaluation +} + +func (mt *MoreThuente) Iterate(f, g float64) (Operation, float64, error) { + if mt.stage == 0 { + panic("morethuente: Init has not been called") + } + + gTest := mt.DecreaseFactor * mt.gInit + fTest := mt.fInit + mt.step*gTest + + if mt.bracketed { + if mt.step <= mt.lower || mt.step >= mt.upper || mt.upper-mt.lower <= mt.StepTolerance*mt.upper { + // step contains the best step found (see below). + return NoOperation, mt.step, ErrLinesearcherFailure + } + } + if mt.step == mt.MaximumStep && f <= fTest && g <= gTest { + return NoOperation, mt.step, ErrLinesearcherBound + } + if mt.step == mt.MinimumStep && (f > fTest || g >= gTest) { + return NoOperation, mt.step, ErrLinesearcherFailure + } + + // Test for convergence. + if f <= fTest && math.Abs(g) <= mt.CurvatureFactor*(-mt.gInit) { + mt.stage = 0 + return MajorIteration, mt.step, nil + } + + if mt.stage == 1 && f <= fTest && g >= 0 { + mt.stage = 2 + } + + if mt.stage == 1 && f <= mt.fx && f > fTest { + // Lower function value but the decrease is not sufficient . + + // Compute values and derivatives of the modified function at step, x, y. + fm := f - mt.step*gTest + fxm := mt.fx - mt.x*gTest + fym := mt.fy - mt.y*gTest + gm := g - gTest + gxm := mt.gx - gTest + gym := mt.gy - gTest + // Update x, y and step. + mt.nextStep(fxm, gxm, fym, gym, fm, gm) + // Recover values and derivates of the non-modified function at x and y. + mt.fx = fxm + mt.x*gTest + mt.fy = fym + mt.y*gTest + mt.gx = gxm + gTest + mt.gy = gym + gTest + } else { + // Update x, y and step. + mt.nextStep(mt.fx, mt.gx, mt.fy, mt.gy, f, g) + } + + if mt.bracketed { + // Monitor the length of the bracketing interval. If the interval has + // not been reduced sufficiently after two steps, use bisection to + // force its length to zero. + width := mt.y - mt.x + if math.Abs(width) >= 2.0/3*mt.width[1] { + mt.step = mt.x + 0.5*width + } + mt.width[0], mt.width[1] = math.Abs(width), mt.width[0] + } + + if mt.bracketed { + mt.lower = math.Min(mt.x, mt.y) + mt.upper = math.Max(mt.x, mt.y) + } else { + mt.lower = mt.step + mtMinGrowthFactor*(mt.step-mt.x) + mt.upper = mt.step + mtMaxGrowthFactor*(mt.step-mt.x) + } + + // Force the step to be in [MinimumStep, MaximumStep]. + mt.step = math.Max(mt.MinimumStep, math.Min(mt.step, mt.MaximumStep)) + + if mt.bracketed { + if mt.step <= mt.lower || mt.step >= mt.upper || mt.upper-mt.lower <= mt.StepTolerance*mt.upper { + // If further progress is not possible, set step to the best step + // obtained during the search. + mt.step = mt.x + } + } + + return FuncEvaluation | GradEvaluation, mt.step, nil +} + +// nextStep computes the next safeguarded step and updates the interval that +// contains a step that satisfies the sufficient decrease and curvature +// conditions. +func (mt *MoreThuente) nextStep(fx, gx, fy, gy, f, g float64) { + x := mt.x + y := mt.y + step := mt.step + + gNeg := g < 0 + if gx < 0 { + gNeg = !gNeg + } + + var next float64 + var bracketed bool + switch { + case f > fx: + // A higher function value. The minimum is bracketed between x and step. + // We want the next step to be closer to x because the function value + // there is lower. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gx/s)*(g/s)) + if step < x { + gamma *= -1 + } + p := gamma - gx + theta + q := gamma - gx + gamma + g + r := p / q + stpc := x + r*(step-x) + stpq := x + gx/((fx-f)/(step-x)+gx)/2*(step-x) + + if math.Abs(stpc-x) < math.Abs(stpq-x) { + // The cubic step is closer to x than the quadratic step. + // Take the cubic step. + next = stpc + } else { + // If f is much larger than fx, then the quadratic step may be too + // close to x. Therefore heuristically take the average of the + // cubic and quadratic steps. + next = stpc + (stpq-stpc)/2 + } + bracketed = true + + case gNeg: + // A lower function value and derivatives of opposite sign. The minimum + // is bracketed between x and step. If we choose a step that is far + // from step, the next iteration will also likely fall in this case. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gx/s)*(g/s)) + if step > x { + gamma *= -1 + } + p := gamma - g + theta + q := gamma - g + gamma + gx + r := p / q + stpc := step + r*(x-step) + stpq := step + g/(g-gx)*(x-step) + + if math.Abs(stpc-step) > math.Abs(stpq-step) { + // The cubic step is farther from x than the quadratic step. + // Take the cubic step. + next = stpc + } else { + // Take the quadratic step. + next = stpq + } + bracketed = true + + case math.Abs(g) < math.Abs(gx): + // A lower function value, derivatives of the same sign, and the + // magnitude of the derivative decreases. Extrapolate function values + // at x and step so that the next step lies between step and y. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt(math.Max(0, (theta/s)*(theta/s)-(gx/s)*(g/s))) + if step > x { + gamma *= -1 + } + p := gamma - g + theta + q := gamma + gx - g + gamma + r := p / q + var stpc float64 + switch { + case r < 0 && gamma != 0: + stpc = step + r*(x-step) + case step > x: + stpc = mt.upper + default: + stpc = mt.lower + } + stpq := step + g/(g-gx)*(x-step) + + if mt.bracketed { + // We are extrapolating so be cautious and take the step that + // is closer to step. + if math.Abs(stpc-step) < math.Abs(stpq-step) { + next = stpc + } else { + next = stpq + } + // Modify next if it is close to or beyond y. + if step > x { + next = math.Min(step+2.0/3*(y-step), next) + } else { + next = math.Max(step+2.0/3*(y-step), next) + } + } else { + // Minimum has not been bracketed so take the larger step... + if math.Abs(stpc-step) > math.Abs(stpq-step) { + next = stpc + } else { + next = stpq + } + // ...but within reason. + next = math.Max(mt.lower, math.Min(next, mt.upper)) + } + + default: + // A lower function value, derivatives of the same sign, and the + // magnitude of the derivative does not decrease. The function seems to + // decrease rapidly in the direction of the step. + + switch { + case mt.bracketed: + theta := 3*(f-fy)/(y-step) + gy + g + s := math.Max(math.Abs(gy), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gy/s)*(g/s)) + if step > y { + gamma *= -1 + } + p := gamma - g + theta + q := gamma - g + gamma + gy + r := p / q + next = step + r*(y-step) + case step > x: + next = mt.upper + default: + next = mt.lower + } + } + + if f > fx { + // x is still the best step. + mt.y = step + mt.fy = f + mt.gy = g + } else { + // step is the new best step. + if gNeg { + mt.y = x + mt.fy = fx + mt.gy = gx + } + mt.x = step + mt.fx = f + mt.gx = g + } + mt.bracketed = bracketed + mt.step = next +} diff --git a/vendor/gonum.org/v1/gonum/optimize/neldermead.go b/vendor/gonum.org/v1/gonum/optimize/neldermead.go new file mode 100644 index 00000000..18964773 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/neldermead.go @@ -0,0 +1,314 @@ +// Copyright ©2015 The gonum 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 optimize + +import ( + "sort" + + "gonum.org/v1/gonum/floats" +) + +// nmIterType is a Nelder-Mead evaluation kind +type nmIterType int + +const ( + nmReflected = iota + nmExpanded + nmContractedInside + nmContractedOutside + nmInitialize + nmShrink + nmMajor +) + +type nmVertexSorter struct { + vertices [][]float64 + values []float64 +} + +func (n nmVertexSorter) Len() int { + return len(n.values) +} + +func (n nmVertexSorter) Less(i, j int) bool { + return n.values[i] < n.values[j] +} + +func (n nmVertexSorter) Swap(i, j int) { + n.values[i], n.values[j] = n.values[j], n.values[i] + n.vertices[i], n.vertices[j] = n.vertices[j], n.vertices[i] +} + +// NelderMead is an implementation of the Nelder-Mead simplex algorithm for +// gradient-free nonlinear optimization (not to be confused with Danzig's +// simplex algorithm for linear programming). The implementation follows the +// algorithm described in +// +// http://epubs.siam.org/doi/pdf/10.1137/S1052623496303470 +// +// If an initial simplex is provided, it is used and initLoc is ignored. If +// InitialVertices and InitialValues are both nil, an initial simplex will be +// generated automatically using the initial location as one vertex, and each +// additional vertex as SimplexSize away in one dimension. +// +// If the simplex update parameters (Reflection, etc.) +// are zero, they will be set automatically based on the dimension according to +// the recommendations in +// +// http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf +type NelderMead struct { + InitialVertices [][]float64 + InitialValues []float64 + Reflection float64 // Reflection parameter (>0) + Expansion float64 // Expansion parameter (>1) + Contraction float64 // Contraction parameter (>0, <1) + Shrink float64 // Shrink parameter (>0, <1) + SimplexSize float64 // size of auto-constructed initial simplex + + reflection float64 + expansion float64 + contraction float64 + shrink float64 + + vertices [][]float64 // location of the vertices sorted in ascending f + values []float64 // function values at the vertices sorted in ascending f + centroid []float64 // centroid of all but the worst vertex + + fillIdx int // index for filling the simplex during initialization and shrinking + lastIter nmIterType // Last iteration + reflectedPoint []float64 // Storage of the reflected point location + reflectedValue float64 // Value at the last reflection point +} + +func (n *NelderMead) Init(loc *Location) (Operation, error) { + dim := len(loc.X) + if cap(n.vertices) < dim+1 { + n.vertices = make([][]float64, dim+1) + } + n.vertices = n.vertices[:dim+1] + for i := range n.vertices { + n.vertices[i] = resize(n.vertices[i], dim) + } + n.values = resize(n.values, dim+1) + n.centroid = resize(n.centroid, dim) + n.reflectedPoint = resize(n.reflectedPoint, dim) + + if n.SimplexSize == 0 { + n.SimplexSize = 0.05 + } + + // Default parameter choices are chosen in a dimension-dependent way + // from http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf + n.reflection = n.Reflection + if n.reflection == 0 { + n.reflection = 1 + } + n.expansion = n.Expansion + if n.expansion == 0 { + n.expansion = 1 + 2/float64(dim) + } + n.contraction = n.Contraction + if n.contraction == 0 { + n.contraction = 0.75 - 1/(2*float64(dim)) + } + n.shrink = n.Shrink + if n.shrink == 0 { + n.shrink = 1 - 1/float64(dim) + } + + if n.InitialVertices != nil { + // Initial simplex provided. Copy the locations and values, and sort them. + if len(n.InitialVertices) != dim+1 { + panic("neldermead: incorrect number of vertices in initial simplex") + } + if len(n.InitialValues) != dim+1 { + panic("neldermead: incorrect number of values in initial simplex") + } + for i := range n.InitialVertices { + if len(n.InitialVertices[i]) != dim { + panic("neldermead: vertex size mismatch") + } + copy(n.vertices[i], n.InitialVertices[i]) + } + copy(n.values, n.InitialValues) + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + } + + // No simplex provided. Begin initializing initial simplex. First simplex + // entry is the initial location, then step 1 in every direction. + copy(n.vertices[dim], loc.X) + n.values[dim] = loc.F + n.fillIdx = 0 + loc.X[n.fillIdx] += n.SimplexSize + n.lastIter = nmInitialize + return FuncEvaluation, nil +} + +// computeCentroid computes the centroid of all the simplex vertices except the +// final one +func computeCentroid(vertices [][]float64, centroid []float64) { + dim := len(centroid) + for i := range centroid { + centroid[i] = 0 + } + for i := 0; i < dim; i++ { + vertex := vertices[i] + for j, v := range vertex { + centroid[j] += v + } + } + for i := range centroid { + centroid[i] /= float64(dim) + } +} + +func (n *NelderMead) Iterate(loc *Location) (Operation, error) { + dim := len(loc.X) + switch n.lastIter { + case nmInitialize: + n.values[n.fillIdx] = loc.F + copy(n.vertices[n.fillIdx], loc.X) + n.fillIdx++ + if n.fillIdx == dim { + // Successfully finished building initial simplex. + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + } + copy(loc.X, n.vertices[dim]) + loc.X[n.fillIdx] += n.SimplexSize + return FuncEvaluation, nil + case nmMajor: + // Nelder Mead iterations start with Reflection step + return n.returnNext(nmReflected, loc) + case nmReflected: + n.reflectedValue = loc.F + switch { + case loc.F >= n.values[0] && loc.F < n.values[dim-1]: + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + case loc.F < n.values[0]: + return n.returnNext(nmExpanded, loc) + default: + if loc.F < n.values[dim] { + return n.returnNext(nmContractedOutside, loc) + } + return n.returnNext(nmContractedInside, loc) + } + case nmExpanded: + if loc.F < n.reflectedValue { + n.replaceWorst(loc.X, loc.F) + } else { + n.replaceWorst(n.reflectedPoint, n.reflectedValue) + } + return n.returnNext(nmMajor, loc) + case nmContractedOutside: + if loc.F <= n.reflectedValue { + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + } + n.fillIdx = 1 + return n.returnNext(nmShrink, loc) + case nmContractedInside: + if loc.F < n.values[dim] { + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + } + n.fillIdx = 1 + return n.returnNext(nmShrink, loc) + case nmShrink: + copy(n.vertices[n.fillIdx], loc.X) + n.values[n.fillIdx] = loc.F + n.fillIdx++ + if n.fillIdx != dim+1 { + return n.returnNext(nmShrink, loc) + } + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + default: + panic("unreachable") + } +} + +// returnNext updates the location based on the iteration type and the current +// simplex, and returns the next operation. +func (n *NelderMead) returnNext(iter nmIterType, loc *Location) (Operation, error) { + n.lastIter = iter + switch iter { + case nmMajor: + // Fill loc with the current best point and value, + // and command a convergence check. + copy(loc.X, n.vertices[0]) + loc.F = n.values[0] + return MajorIteration, nil + case nmReflected, nmExpanded, nmContractedOutside, nmContractedInside: + // x_new = x_centroid + scale * (x_centroid - x_worst) + var scale float64 + switch iter { + case nmReflected: + scale = n.reflection + case nmExpanded: + scale = n.reflection * n.expansion + case nmContractedOutside: + scale = n.reflection * n.contraction + case nmContractedInside: + scale = -n.contraction + } + dim := len(loc.X) + floats.SubTo(loc.X, n.centroid, n.vertices[dim]) + floats.Scale(scale, loc.X) + floats.Add(loc.X, n.centroid) + if iter == nmReflected { + copy(n.reflectedPoint, loc.X) + } + return FuncEvaluation, nil + case nmShrink: + // x_shrink = x_best + delta * (x_i + x_best) + floats.SubTo(loc.X, n.vertices[n.fillIdx], n.vertices[0]) + floats.Scale(n.shrink, loc.X) + floats.Add(loc.X, n.vertices[0]) + return FuncEvaluation, nil + default: + panic("unreachable") + } +} + +// replaceWorst removes the worst location in the simplex and adds the new +// {x, f} pair maintaining sorting. +func (n *NelderMead) replaceWorst(x []float64, f float64) { + dim := len(x) + if f >= n.values[dim] { + panic("increase in simplex value") + } + copy(n.vertices[dim], x) + n.values[dim] = f + + // Sort the newly-added value. + for i := dim - 1; i >= 0; i-- { + if n.values[i] < f { + break + } + n.vertices[i], n.vertices[i+1] = n.vertices[i+1], n.vertices[i] + n.values[i], n.values[i+1] = n.values[i+1], n.values[i] + } + + // Update the location of the centroid. Only one point has been replaced, so + // subtract the worst point and add the new one. + floats.AddScaled(n.centroid, -1/float64(dim), n.vertices[dim]) + floats.AddScaled(n.centroid, 1/float64(dim), x) +} + +func (*NelderMead) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{false, false} +} diff --git a/vendor/gonum.org/v1/gonum/optimize/newton.go b/vendor/gonum.org/v1/gonum/optimize/newton.go new file mode 100644 index 00000000..e87c269f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/newton.go @@ -0,0 +1,147 @@ +// Copyright ©2015 The gonum 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 optimize + +import ( + "math" + + "gonum.org/v1/gonum/mat" +) + +const maxNewtonModifications = 20 + +// Newton implements a modified Newton's method for Hessian-based unconstrained +// minimization. It applies regularization when the Hessian is not positive +// definite, and it can converge to a local minimum from any starting point. +// +// Newton iteratively forms a quadratic model to the objective function f and +// tries to minimize this approximate model. It generates a sequence of +// locations x_k by means of +// solve H_k d_k = -∇f_k for d_k, +// x_{k+1} = x_k + α_k d_k, +// where H_k is the Hessian matrix of f at x_k and α_k is a step size found by +// a line search. +// +// Away from a minimizer H_k may not be positive definite and d_k may not be a +// descent direction. Newton implements a Hessian modification strategy that +// adds successively larger multiples of identity to H_k until it becomes +// positive definite. Note that the repeated trial factorization of the +// modified Hessian involved in this process can be computationally expensive. +// +// If the Hessian matrix cannot be formed explicitly or if the computational +// cost of its factorization is prohibitive, BFGS or L-BFGS quasi-Newton method +// can be used instead. +type Newton struct { + // Linesearcher is used for selecting suitable steps along the descent + // direction d. Accepted steps should satisfy at least one of the Wolfe, + // Goldstein or Armijo conditions. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + // Increase is the factor by which a scalar tau is successively increased + // so that (H + tau*I) is positive definite. Larger values reduce the + // number of trial Hessian factorizations, but also reduce the second-order + // information in H. + // Increase must be greater than 1. If Increase is 0, it is defaulted to 5. + Increase float64 + + ls *LinesearchMethod + + hess *mat.SymDense // Storage for a copy of the Hessian matrix. + chol mat.Cholesky // Storage for the Cholesky factorization. + tau float64 +} + +func (n *Newton) Init(loc *Location) (Operation, error) { + if n.Increase == 0 { + n.Increase = 5 + } + if n.Increase <= 1 { + panic("optimize: Newton.Increase must be greater than 1") + } + if n.Linesearcher == nil { + n.Linesearcher = &Bisection{} + } + if n.ls == nil { + n.ls = &LinesearchMethod{} + } + n.ls.Linesearcher = n.Linesearcher + n.ls.NextDirectioner = n + + return n.ls.Init(loc) +} + +func (n *Newton) Iterate(loc *Location) (Operation, error) { + return n.ls.Iterate(loc) +} + +func (n *Newton) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + n.hess = resizeSymDense(n.hess, dim) + n.tau = 0 + return n.NextDirection(loc, dir) +} + +func (n *Newton) NextDirection(loc *Location, dir []float64) (stepSize float64) { + // This method implements Algorithm 3.3 (Cholesky with Added Multiple of + // the Identity) from Nocedal, Wright (2006), 2nd edition. + + dim := len(loc.X) + d := mat.NewVecDense(dim, dir) + grad := mat.NewVecDense(dim, loc.Gradient) + n.hess.CopySym(loc.Hessian) + + // Find the smallest diagonal entry of the Hessian. + minA := n.hess.At(0, 0) + for i := 1; i < dim; i++ { + a := n.hess.At(i, i) + if a < minA { + minA = a + } + } + // If the smallest diagonal entry is positive, the Hessian may be positive + // definite, and so first attempt to apply the Cholesky factorization to + // the un-modified Hessian. If the smallest entry is negative, use the + // final tau from the last iteration if regularization was needed, + // otherwise guess an appropriate value for tau. + if minA > 0 { + n.tau = 0 + } else if n.tau == 0 { + n.tau = -minA + 0.001 + } + + for k := 0; k < maxNewtonModifications; k++ { + if n.tau != 0 { + // Add a multiple of identity to the Hessian. + for i := 0; i < dim; i++ { + n.hess.SetSym(i, i, loc.Hessian.At(i, i)+n.tau) + } + } + // Try to apply the Cholesky factorization. + pd := n.chol.Factorize(n.hess) + if pd { + // Store the solution in d's backing array, dir. + n.chol.SolveVec(d, grad) + d.ScaleVec(-1, d) + return 1 + } + // Modified Hessian is not PD, so increase tau. + n.tau = math.Max(n.Increase*n.tau, 0.001) + } + + // Hessian modification failed to get a PD matrix. Return the negative + // gradient as the descent direction. + d.ScaleVec(-1, grad) + return 1 +} + +func (n *Newton) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, true} +} diff --git a/vendor/gonum.org/v1/gonum/optimize/printer.go b/vendor/gonum.org/v1/gonum/optimize/printer.go new file mode 100644 index 00000000..56800f3c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/printer.go @@ -0,0 +1,106 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "fmt" + "io" + "math" + "os" + "time" + + "gonum.org/v1/gonum/floats" +) + +var printerHeadings = [...]string{ + "Iter", + "Runtime", + "FuncEvals", + "Func", + "GradEvals", + "|Gradient|∞", + "HessEvals", +} + +const ( + printerBaseTmpl = "%9v %16v %9v %22v" // Base template for headings and values that are always printed. + printerGradTmpl = " %9v %22v" // Appended to base template when loc.Gradient != nil. + printerHessTmpl = " %9v" // Appended to base template when loc.Hessian != nil. +) + +// Printer writes column-format output to the specified writer as the optimization +// progresses. By default, it writes to os.Stdout. +type Printer struct { + Writer io.Writer + HeadingInterval int + ValueInterval time.Duration + + lastHeading int + lastValue time.Time +} + +func NewPrinter() *Printer { + return &Printer{ + Writer: os.Stdout, + HeadingInterval: 30, + ValueInterval: 500 * time.Millisecond, + } +} + +func (p *Printer) Init() error { + p.lastHeading = p.HeadingInterval // So the headings are printed the first time. + p.lastValue = time.Now().Add(-p.ValueInterval) // So the values are printed the first time. + return nil +} + +func (p *Printer) Record(loc *Location, op Operation, stats *Stats) error { + if op != MajorIteration && op != InitIteration && op != PostIteration { + return nil + } + + // Print values always on PostIteration or when ValueInterval has elapsed. + printValues := time.Since(p.lastValue) > p.ValueInterval || op == PostIteration + if !printValues { + // Return early if not printing anything. + return nil + } + + // Print heading when HeadingInterval lines have been printed, but never on PostIteration. + printHeading := p.lastHeading >= p.HeadingInterval && op != PostIteration + if printHeading { + p.lastHeading = 1 + } else { + p.lastHeading++ + } + + if printHeading { + headings := "\n" + fmt.Sprintf(printerBaseTmpl, printerHeadings[0], printerHeadings[1], printerHeadings[2], printerHeadings[3]) + if loc.Gradient != nil { + headings += fmt.Sprintf(printerGradTmpl, printerHeadings[4], printerHeadings[5]) + } + if loc.Hessian != nil { + headings += fmt.Sprintf(printerHessTmpl, printerHeadings[6]) + } + _, err := fmt.Fprintln(p.Writer, headings) + if err != nil { + return err + } + } + + values := fmt.Sprintf(printerBaseTmpl, stats.MajorIterations, stats.Runtime, stats.FuncEvaluations, loc.F) + if loc.Gradient != nil { + values += fmt.Sprintf(printerGradTmpl, stats.GradEvaluations, floats.Norm(loc.Gradient, math.Inf(1))) + } + if loc.Hessian != nil { + values += fmt.Sprintf(printerHessTmpl, stats.HessEvaluations) + } + _, err := fmt.Fprintln(p.Writer, values) + if err != nil { + return err + } + + p.lastValue = time.Now() + return nil +} diff --git a/vendor/gonum.org/v1/gonum/optimize/stepsizers.go b/vendor/gonum.org/v1/gonum/optimize/stepsizers.go new file mode 100644 index 00000000..487c158c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/stepsizers.go @@ -0,0 +1,185 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +const ( + initialStepFactor = 1 + + quadraticMinimumStepSize = 1e-3 + quadraticMaximumStepSize = 1 + quadraticThreshold = 1e-12 + + firstOrderMinimumStepSize = quadraticMinimumStepSize + firstOrderMaximumStepSize = quadraticMaximumStepSize +) + +// ConstantStepSize is a StepSizer that returns the same step size for +// every iteration. +type ConstantStepSize struct { + Size float64 +} + +func (c ConstantStepSize) Init(_ *Location, _ []float64) float64 { + return c.Size +} + +func (c ConstantStepSize) StepSize(_ *Location, _ []float64) float64 { + return c.Size +} + +// QuadraticStepSize estimates the initial line search step size as the minimum +// of a quadratic that interpolates f(x_{k-1}), f(x_k) and ∇f_k⋅p_k. +// This is useful for line search methods that do not produce well-scaled +// descent directions, such as gradient descent or conjugate gradient methods. +// The step size is bounded away from zero. +type QuadraticStepSize struct { + // Threshold determines that the initial step size should be estimated by + // quadratic interpolation when the relative change in the objective + // function is larger than Threshold. Otherwise the initial step size is + // set to 2*previous step size. + // If Threshold is zero, it will be set to 1e-12. + Threshold float64 + // InitialStepFactor sets the step size for the first iteration to be InitialStepFactor / |g|_∞. + // If InitialStepFactor is zero, it will be set to one. + InitialStepFactor float64 + // MinStepSize is the lower bound on the estimated step size. + // MinStepSize times GradientAbsTol should always be greater than machine epsilon. + // If MinStepSize is zero, it will be set to 1e-3. + MinStepSize float64 + // MaxStepSize is the upper bound on the estimated step size. + // If MaxStepSize is zero, it will be set to 1. + MaxStepSize float64 + + fPrev float64 + dirPrevNorm float64 + projGradPrev float64 + xPrev []float64 +} + +func (q *QuadraticStepSize) Init(loc *Location, dir []float64) (stepSize float64) { + if q.Threshold == 0 { + q.Threshold = quadraticThreshold + } + if q.InitialStepFactor == 0 { + q.InitialStepFactor = initialStepFactor + } + if q.MinStepSize == 0 { + q.MinStepSize = quadraticMinimumStepSize + } + if q.MaxStepSize == 0 { + q.MaxStepSize = quadraticMaximumStepSize + } + if q.MaxStepSize <= q.MinStepSize { + panic("optimize: MinStepSize not smaller than MaxStepSize") + } + + gNorm := floats.Norm(loc.Gradient, math.Inf(1)) + stepSize = math.Max(q.MinStepSize, math.Min(q.InitialStepFactor/gNorm, q.MaxStepSize)) + + q.fPrev = loc.F + q.dirPrevNorm = floats.Norm(dir, 2) + q.projGradPrev = floats.Dot(loc.Gradient, dir) + q.xPrev = resize(q.xPrev, len(loc.X)) + copy(q.xPrev, loc.X) + return stepSize +} + +func (q *QuadraticStepSize) StepSize(loc *Location, dir []float64) (stepSize float64) { + stepSizePrev := floats.Distance(loc.X, q.xPrev, 2) / q.dirPrevNorm + projGrad := floats.Dot(loc.Gradient, dir) + + stepSize = 2 * stepSizePrev + if !floats.EqualWithinRel(q.fPrev, loc.F, q.Threshold) { + // Two consecutive function values are not relatively equal, so + // computing the minimum of a quadratic interpolant might make sense + + df := (loc.F - q.fPrev) / stepSizePrev + quadTest := df - q.projGradPrev + if quadTest > 0 { + // There is a chance of approximating the function well by a + // quadratic only if the finite difference (f_k-f_{k-1})/stepSizePrev + // is larger than ∇f_{k-1}⋅p_{k-1} + + // Set the step size to the minimizer of the quadratic function that + // interpolates f_{k-1}, ∇f_{k-1}⋅p_{k-1} and f_k + stepSize = -q.projGradPrev * stepSizePrev / quadTest / 2 + } + } + // Bound the step size to lie in [MinStepSize, MaxStepSize] + stepSize = math.Max(q.MinStepSize, math.Min(stepSize, q.MaxStepSize)) + + q.fPrev = loc.F + q.dirPrevNorm = floats.Norm(dir, 2) + q.projGradPrev = projGrad + copy(q.xPrev, loc.X) + return stepSize +} + +// FirstOrderStepSize estimates the initial line search step size based on the +// assumption that the first-order change in the function will be the same as +// that obtained at the previous iteration. That is, the initial step size s^0_k +// is chosen so that +// s^0_k ∇f_k⋅p_k = s_{k-1} ∇f_{k-1}⋅p_{k-1} +// This is useful for line search methods that do not produce well-scaled +// descent directions, such as gradient descent or conjugate gradient methods. +type FirstOrderStepSize struct { + // InitialStepFactor sets the step size for the first iteration to be InitialStepFactor / |g|_∞. + // If InitialStepFactor is zero, it will be set to one. + InitialStepFactor float64 + // MinStepSize is the lower bound on the estimated step size. + // MinStepSize times GradientAbsTol should always be greater than machine epsilon. + // If MinStepSize is zero, it will be set to 1e-3. + MinStepSize float64 + // MaxStepSize is the upper bound on the estimated step size. + // If MaxStepSize is zero, it will be set to 1. + MaxStepSize float64 + + dirPrevNorm float64 + projGradPrev float64 + xPrev []float64 +} + +func (fo *FirstOrderStepSize) Init(loc *Location, dir []float64) (stepSize float64) { + if fo.InitialStepFactor == 0 { + fo.InitialStepFactor = initialStepFactor + } + if fo.MinStepSize == 0 { + fo.MinStepSize = firstOrderMinimumStepSize + } + if fo.MaxStepSize == 0 { + fo.MaxStepSize = firstOrderMaximumStepSize + } + if fo.MaxStepSize <= fo.MinStepSize { + panic("optimize: MinStepSize not smaller than MaxStepSize") + } + + gNorm := floats.Norm(loc.Gradient, math.Inf(1)) + stepSize = math.Max(fo.MinStepSize, math.Min(fo.InitialStepFactor/gNorm, fo.MaxStepSize)) + + fo.dirPrevNorm = floats.Norm(dir, 2) + fo.projGradPrev = floats.Dot(loc.Gradient, dir) + fo.xPrev = resize(fo.xPrev, len(loc.X)) + copy(fo.xPrev, loc.X) + return stepSize +} + +func (fo *FirstOrderStepSize) StepSize(loc *Location, dir []float64) (stepSize float64) { + stepSizePrev := floats.Distance(loc.X, fo.xPrev, 2) / fo.dirPrevNorm + projGrad := floats.Dot(loc.Gradient, dir) + + stepSize = stepSizePrev * fo.projGradPrev / projGrad + stepSize = math.Max(fo.MinStepSize, math.Min(stepSize, fo.MaxStepSize)) + + fo.dirPrevNorm = floats.Norm(dir, 2) + fo.projGradPrev = floats.Dot(loc.Gradient, dir) + copy(fo.xPrev, loc.X) + return stepSize +} diff --git a/vendor/gonum.org/v1/gonum/optimize/termination.go b/vendor/gonum.org/v1/gonum/optimize/termination.go new file mode 100644 index 00000000..43c2df68 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/termination.go @@ -0,0 +1,119 @@ +// Copyright ©2014 The gonum 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 optimize + +import "errors" + +// Status represents the status of the optimization. Programs +// should not rely on the underlying numeric value of the Status being constant. +type Status int + +const ( + NotTerminated Status = iota + Success + FunctionThreshold + FunctionConvergence + GradientThreshold + StepConvergence + FunctionNegativeInfinity + Failure + IterationLimit + RuntimeLimit + FunctionEvaluationLimit + GradientEvaluationLimit + HessianEvaluationLimit +) + +func (s Status) String() string { + return statuses[s].name +} + +// Early returns true if the status indicates the optimization ended before a +// minimum was found. As an example, if the maximum iterations was reached, a +// minimum was not found, but if the gradient norm was reached then a minimum +// was found. +func (s Status) Early() bool { + return statuses[s].early +} + +// Err returns the error associated with an early ending to the minimization. If +// Early returns false, Err will return nil. +func (s Status) Err() error { + return statuses[s].err +} + +var statuses = []struct { + name string + early bool + err error +}{ + { + name: "NotTerminated", + }, + { + name: "Success", + }, + { + name: "FunctionThreshold", + }, + { + name: "FunctionConvergence", + }, + { + name: "GradientThreshold", + }, + { + name: "StepConvergence", + }, + { + name: "FunctionNegativeInfinity", + }, + { + name: "Failure", + early: true, + err: errors.New("optimize: termination ended in failure"), + }, + { + name: "IterationLimit", + early: true, + err: errors.New("optimize: maximum number of major iterations reached"), + }, + { + name: "RuntimeLimit", + early: true, + err: errors.New("optimize: maximum runtime reached"), + }, + { + name: "FunctionEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of function evaluations reached"), + }, + { + name: "GradientEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of gradient evaluations reached"), + }, + { + name: "HessianEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of Hessian evaluations reached"), + }, +} + +// NewStatus returns a unique Status variable to represent a custom status. +// NewStatus is intended to be called only during package initialization, and +// calls to NewStatus are not thread safe. +// +// NewStatus takes in three arguments, the string that should be output from +// Status.String, a boolean if the status indicates early optimization conclusion, +// and the error to return from Err (if any). +func NewStatus(name string, early bool, err error) Status { + statuses = append(statuses, struct { + name string + early bool + err error + }{name, early, err}) + return Status(len(statuses) - 1) +} diff --git a/vendor/gonum.org/v1/gonum/optimize/types.go b/vendor/gonum.org/v1/gonum/optimize/types.go new file mode 100644 index 00000000..461693ff --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/types.go @@ -0,0 +1,262 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "errors" + "fmt" + "math" + "time" + + "gonum.org/v1/gonum/mat" +) + +const defaultGradientAbsTol = 1e-6 + +// Operation represents the set of operations commanded by Method at each +// iteration. It is a bitmap of various Iteration and Evaluation constants. +// Individual constants must NOT be combined together by the binary OR operator +// except for the Evaluation operations. +type Operation uint64 + +// Supported Operations. +const ( + // NoOperation specifies that no evaluation or convergence check should + // take place. + NoOperation Operation = 0 + // InitIteration is sent to Recorder to indicate the initial location. + // All fields of the location to record must be valid. + // Method must not return it. + InitIteration Operation = 1 << (iota - 1) + // PostIteration is sent to Recorder to indicate the final location + // reached during an optimization run. + // All fields of the location to record must be valid. + // Method must not return it. + PostIteration + // MajorIteration indicates that the next candidate location for + // an optimum has been found and convergence should be checked. + MajorIteration + // FuncEvaluation specifies that the objective function + // should be evaluated. + FuncEvaluation + // GradEvaluation specifies that the gradient + // of the objective function should be evaluated. + GradEvaluation + // HessEvaluation specifies that the Hessian + // of the objective function should be evaluated. + HessEvaluation + + // Mask for the evaluating operations. + evalMask = FuncEvaluation | GradEvaluation | HessEvaluation +) + +func (op Operation) isEvaluation() bool { + return op&evalMask != 0 && op&^evalMask == 0 +} + +func (op Operation) String() string { + if op&evalMask != 0 { + return fmt.Sprintf("Evaluation(Func: %t, Grad: %t, Hess: %t, Extra: 0b%b)", + op&FuncEvaluation != 0, + op&GradEvaluation != 0, + op&HessEvaluation != 0, + op&^(evalMask)) + } + s, ok := operationNames[op] + if ok { + return s + } + return fmt.Sprintf("Operation(%d)", op) +} + +var operationNames = map[Operation]string{ + NoOperation: "NoOperation", + InitIteration: "InitIteration", + MajorIteration: "MajorIteration", + PostIteration: "PostIteration", +} + +// Location represents a location in the optimization procedure. +type Location struct { + X []float64 + F float64 + Gradient []float64 + Hessian *mat.SymDense +} + +// Result represents the answer of an optimization run. It contains the optimum +// location as well as the Status at convergence and Statistics taken during the +// run. +type Result struct { + Location + Stats + Status Status +} + +// Stats contains the statistics of the run. +type Stats struct { + MajorIterations int // Total number of major iterations + FuncEvaluations int // Number of evaluations of Func + GradEvaluations int // Number of evaluations of Grad + HessEvaluations int // Number of evaluations of Hess + Runtime time.Duration // Total runtime of the optimization +} + +// complementEval returns an evaluating operation that evaluates fields of loc +// not evaluated by eval. +func complementEval(loc *Location, eval Operation) (complEval Operation) { + if eval&FuncEvaluation == 0 { + complEval = FuncEvaluation + } + if loc.Gradient != nil && eval&GradEvaluation == 0 { + complEval |= GradEvaluation + } + if loc.Hessian != nil && eval&HessEvaluation == 0 { + complEval |= HessEvaluation + } + return complEval +} + +// Problem describes the optimization problem to be solved. +type Problem struct { + // Func evaluates the objective function at the given location. Func + // must not modify x. + Func func(x []float64) float64 + + // Grad evaluates the gradient at x and stores the result in-place in grad. + // Grad must not modify x. + Grad func(grad []float64, x []float64) + + // Hess evaluates the Hessian at x and stores the result in-place in hess. + // Hess must not modify x. + Hess func(hess mat.MutableSymmetric, x []float64) + + // Status reports the status of the objective function being optimized and any + // error. This can be used to terminate early, for example when the function is + // not able to evaluate itself. The user can use one of the pre-provided Status + // constants, or may call NewStatus to create a custom Status value. + Status func() (Status, error) +} + +// TODO(btracey): Think about making this an exported function when the +// constraint interface is designed. +func (p Problem) satisfies(method Needser) error { + if method.Needs().Gradient && p.Grad == nil { + return errors.New("optimize: problem does not provide needed Grad function") + } + if method.Needs().Hessian && p.Hess == nil { + return errors.New("optimize: problem does not provide needed Hess function") + } + return nil +} + +// Settings represents settings of the optimization run. It contains initial +// settings, convergence information, and Recorder information. In general, users +// should use DefaultSettings rather than constructing a Settings literal. +// +// If UseInitData is true, InitialValue, InitialGradient and InitialHessian +// specify function information at the initial location. +// +// If Recorder is nil, no information will be recorded. +type Settings struct { + UseInitialData bool // Use supplied information about the conditions at the initial x. + InitialValue float64 // Function value at the initial x. + InitialGradient []float64 // Gradient at the initial x. + InitialHessian *mat.SymDense // Hessian at the initial x. + + // FunctionThreshold is the threshold for acceptably small values of the + // objective function. FunctionThreshold status is returned if + // the objective function is less than this value. + // The default value is -inf. + FunctionThreshold float64 + + // GradientThreshold determines the accuracy to which the minimum is found. + // GradientThreshold status is returned if the infinity norm of + // the gradient is less than this value. + // Has no effect if gradient information is not used. + // The default value is 1e-6. + GradientThreshold float64 + + // FunctionConverge tests that the function value decreases by a + // significant amount over the specified number of iterations. + // + // If f < f_best and + // f_best - f > FunctionConverge.Relative * maxabs(f, f_best) + FunctionConverge.Absolute + // then a significant decrease has occurred, and f_best is updated. + // + // If there is no significant decrease for FunctionConverge.Iterations + // major iterations, FunctionConvergence status is returned. + // + // If this is nil or if FunctionConverge.Iterations == 0, it has no effect. + FunctionConverge *FunctionConverge + + // MajorIterations is the maximum number of iterations allowed. + // IterationLimit status is returned if the number of major iterations + // equals or exceeds this value. + // If it equals zero, this setting has no effect. + // The default value is 0. + MajorIterations int + + // Runtime is the maximum runtime allowed. RuntimeLimit status is returned + // if the duration of the run is longer than this value. Runtime is only + // checked at iterations of the Method. + // If it equals zero, this setting has no effect. + // The default value is 0. + Runtime time.Duration + + // FuncEvaluations is the maximum allowed number of function evaluations. + // FunctionEvaluationLimit status is returned if the total number of calls + // to Func equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + FuncEvaluations int + + // GradEvaluations is the maximum allowed number of gradient evaluations. + // GradientEvaluationLimit status is returned if the total number of calls + // to Grad equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + GradEvaluations int + + // HessEvaluations is the maximum allowed number of Hessian evaluations. + // HessianEvaluationLimit status is returned if the total number of calls + // to Hess equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + HessEvaluations int + + Recorder Recorder + + // Concurrent represents how many concurrent evaluations are possible. + Concurrent int +} + +// DefaultSettings returns a new Settings struct containing the default settings. +func DefaultSettings() *Settings { + return &Settings{ + GradientThreshold: defaultGradientAbsTol, + FunctionThreshold: math.Inf(-1), + FunctionConverge: &FunctionConverge{ + Absolute: 1e-10, + Iterations: 20, + }, + } +} + +// resize takes x and returns a slice of length dim. It returns a resliced x +// if cap(x) >= dim, and a new slice otherwise. +func resize(x []float64, dim int) []float64 { + if dim > cap(x) { + return make([]float64, dim) + } + return x[:dim] +} + +func resizeSymDense(m *mat.SymDense, dim int) *mat.SymDense { + if m == nil || cap(m.RawSymmetric().Data) < dim*dim { + return mat.NewSymDense(dim, nil) + } + return mat.NewSymDense(dim, m.RawSymmetric().Data[:dim*dim]) +} diff --git a/vendor/gonum.org/v1/gonum/optimize/unconstrained_test.go b/vendor/gonum.org/v1/gonum/optimize/unconstrained_test.go new file mode 100644 index 00000000..a8cb373f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/optimize/unconstrained_test.go @@ -0,0 +1,1305 @@ +// Copyright ©2014 The gonum 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 optimize + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/optimize/functions" +) + +type unconstrainedTest struct { + // name is the name of the test. + name string + // p is the optimization problem to be solved. + p Problem + // x is the initial guess. + x []float64 + // gradTol is the absolute gradient tolerance for the test. If gradTol == 0, + // the default value of 1e-12 will be used. + gradTol float64 + // fAbsTol is the absolute function convergence for the test. If fAbsTol == 0, + // the default value of 1e-12 will be used. + fAbsTol float64 + // fIter is the number of iterations for function convergence. If fIter == 0, + // the default value of 20 will be used. + fIter int + // long indicates that the test takes long time to finish and will be + // excluded if testing.Short returns true. + long bool +} + +func (t unconstrainedTest) String() string { + dim := len(t.x) + if dim <= 10 { + // Print the initial X only for small-dimensional problems. + return fmt.Sprintf("F: %v\nDim: %v\nInitial X: %v\nGradientThreshold: %v", + t.name, dim, t.x, t.gradTol) + } + return fmt.Sprintf("F: %v\nDim: %v\nGradientThreshold: %v", + t.name, dim, t.gradTol) +} + +var gradFreeTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + }, + x: []float64{1, 1}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + }, + x: []float64{25, 5, -5, -1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + }, + x: []float64{-10, 10}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + }, + x: []float64{-5, 4, 16, 3}, + }, +} + +var gradientDescentTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + }, + x: []float64{1, 1}, + }, + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + }, + x: []float64{3.00001, 0.50001}, + }, + { + name: "BiggsEXP2", + p: Problem{ + Func: functions.BiggsEXP2{}.Func, + Grad: functions.BiggsEXP2{}.Grad, + }, + x: []float64{1, 2}, + }, + { + name: "BiggsEXP2", + p: Problem{ + Func: functions.BiggsEXP2{}.Func, + Grad: functions.BiggsEXP2{}.Grad, + }, + x: []float64{1.00001, 10.00001}, + }, + { + name: "BiggsEXP3", + p: Problem{ + Func: functions.BiggsEXP3{}.Func, + Grad: functions.BiggsEXP3{}.Grad, + }, + x: []float64{1, 2, 1}, + }, + { + name: "BiggsEXP3", + p: Problem{ + Func: functions.BiggsEXP3{}.Func, + Grad: functions.BiggsEXP3{}.Grad, + }, + x: []float64{1.00001, 10.00001, 3.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-120, 100, 50}, + long: true, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1, 1, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001}, + gradTol: 1e-8, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.4, 1, 0}, + gradTol: 1e-9, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.3989561, 1.0000191, 0}, + gradTol: 1e-9, + }, + { + name: "HelicalValley", + p: Problem{ + Func: functions.HelicalValley{}.Func, + Grad: functions.HelicalValley{}.Grad, + }, + x: []float64{-1, 0, 0}, + }, + { + name: "HelicalValley", + p: Problem{ + Func: functions.HelicalValley{}.Func, + Grad: functions.HelicalValley{}.Grad, + }, + x: []float64{1.00001, 0.00001, 0.00001}, + }, + { + name: "Trigonometric", + p: Problem{ + Func: functions.Trigonometric{}.Func, + Grad: functions.Trigonometric{}.Grad, + }, + x: []float64{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, + gradTol: 1e-7, + }, + { + name: "Trigonometric", + p: Problem{ + Func: functions.Trigonometric{}.Func, + Grad: functions.Trigonometric{}.Grad, + }, + x: []float64{0.042964, 0.043976, 0.045093, 0.046338, 0.047744, + 0.049354, 0.051237, 0.195209, 0.164977, 0.060148}, + gradTol: 1e-8, + }, + newVariablyDimensioned(2, 0), + { + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: []float64{1.00001, 1.00001}, + }, + newVariablyDimensioned(10, 0), + { + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001}, + }, +} + +var cgTests = []unconstrainedTest{ + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1, 2, 1, 1}, + }, + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1}, + gradTol: 1e-7, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-7, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{0, 10, 20}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{100.00001, 100.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + gradTol: 1e-8, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e4, 1e4}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, + gradTol: 1e-10, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + gradTol: 1e-9, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, + gradTol: 1e-10, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, + 0.1581, 0.1581, 0.1581, 0.1581}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-8, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, + gradTol: 1e-8, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, + 0.11862, 0.19214, 0.34732, 0.36916}, + gradTol: 1e-6, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{1.09815e-05, 9.10614}, + gradTol: 1e-8, + }, + newVariablyDimensioned(100, 1e-10), + newVariablyDimensioned(1000, 1e-7), + newVariablyDimensioned(10000, 1e-4), + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + gradTol: 1e-6, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, + gradTol: 1e-6, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + gradTol: 1e-6, + long: true, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, + -2.61773, 4.10440, -3.14361, 1.05262}, + gradTol: 1e-6, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + }, + x: []float64{-3, -1, -3, -1}, + gradTol: 1e-6, + }, +} + +var quasiNewtonTests = []unconstrainedTest{ + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1, 2, 1, 1}, + }, + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1}, + gradTol: 1e-10, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-8, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{0, 10, 20}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{100.00001, 100.00001, 0.00001}, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + }, + x: []float64{1, 1}, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + }, + x: []float64{1.000001e6, 2.01e-6}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.4, 1, 0}, + gradTol: 1e-11, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{5, 2.5, 0.15}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{50.00001, 25.00001, 1.50001}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{99.89529, 60.61453, 9.16124}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{201.66258, 60.61633, 10.22489}, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, + gradTol: 1e-9, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, + 0.1581, 0.1581, 0.1581, 0.1581}, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-9, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, + 0.11862, 0.19214, 0.34732, 0.36916}, + gradTol: 1e-9, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{0, 1}, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{1.09815e-05, 9.10614}, + gradTol: 1e-10, + }, + newVariablyDimensioned(100, 1e-10), + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + gradTol: 1e-7, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, + gradTol: 1e-7, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + gradTol: 1e-8, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, + -2.61773, 4.10440, -3.14361, 1.05262}, + gradTol: 1e-8, + }, +} + +var bfgsTests = []unconstrainedTest{ + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-10, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-10, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + }, + x: []float64{25, 5, -5, -1}, + gradTol: 1e-5, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e5, 1e5}, + gradTol: 1e-10, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.398, 1, 0}, + gradTol: 1e-11, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + }, + x: []float64{-3, -1, -3, -1}, + }, +} + +var lbfgsTests = []unconstrainedTest{ + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-8, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e7, 1e6}, + gradTol: 1e-10, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.398, 1, 0}, + gradTol: 1e-10, + }, + newVariablyDimensioned(1000, 1e-8), + newVariablyDimensioned(10000, 1e-5), +} + +var newtonTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + Hess: functions.Beale{}.Hess, + }, + x: []float64{1, 1}, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + Hess: functions.BrownAndDennis{}.Hess, + }, + x: []float64{25, 5, -5, -1}, + gradTol: 1e-10, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + Hess: functions.BrownBadlyScaled{}.Hess, + }, + x: []float64{1, 1}, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + Hess: functions.PowellBadlyScaled{}.Hess, + }, + x: []float64{0, 1}, + gradTol: 1e-10, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + Hess: functions.Watson{}.Hess, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + Hess: functions.Watson{}.Hess, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + Hess: functions.Wood{}.Hess, + }, + x: []float64{-3, -1, -3, -1}, + }, +} + +func newVariablyDimensioned(dim int, gradTol float64) unconstrainedTest { + x := make([]float64, dim) + for i := range x { + x[i] = float64(dim-i-1) / float64(dim) + } + return unconstrainedTest{ + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: x, + gradTol: gradTol, + } +} + +func TestLocal(t *testing.T) { + var tests []unconstrainedTest + // Mix of functions with and without Grad method. + tests = append(tests, gradFreeTests...) + tests = append(tests, gradientDescentTests...) + testLocal(t, tests, nil) +} + +func TestNelderMead(t *testing.T) { + var tests []unconstrainedTest + // Mix of functions with and without Grad method. + tests = append(tests, gradFreeTests...) + tests = append(tests, gradientDescentTests...) + testLocal(t, tests, &NelderMead{}) +} + +func TestGradientDescent(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{}) +} + +func TestGradientDescentBacktracking(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{ + Linesearcher: &Backtracking{ + DecreaseFactor: 0.1, + }, + }) +} + +func TestGradientDescentBisection(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{ + Linesearcher: &Bisection{}, + }) +} + +func TestCG(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{}) +} + +func TestFletcherReevesQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &FletcherReeves{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestFletcherReevesFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &FletcherReeves{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestHestenesStiefelQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HestenesStiefel{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestHestenesStiefelFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HestenesStiefel{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestPolakRibiereQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &PolakRibierePolyak{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestPolakRibiereFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &PolakRibierePolyak{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestDaiYuanQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &DaiYuan{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestDaiYuanFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &DaiYuan{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestHagerZhangQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HagerZhang{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestHagerZhangFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HagerZhang{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestBFGS(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, quasiNewtonTests...) + tests = append(tests, bfgsTests...) + testLocal(t, tests, &BFGS{}) +} + +func TestLBFGS(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, quasiNewtonTests...) + tests = append(tests, lbfgsTests...) + testLocal(t, tests, &LBFGS{}) +} + +func TestNewton(t *testing.T) { + testLocal(t, newtonTests, &Newton{}) +} + +func testLocal(t *testing.T, tests []unconstrainedTest, method Method) { + for _, test := range tests { + if test.long && testing.Short() { + continue + } + + settings := DefaultSettings() + settings.Recorder = nil + if method != nil && method.Needs().Gradient { + // Turn off function convergence checks for gradient-based methods. + settings.FunctionConverge = nil + } else { + if test.fIter == 0 { + test.fIter = 20 + } + settings.FunctionConverge.Iterations = test.fIter + if test.fAbsTol == 0 { + test.fAbsTol = 1e-12 + } + settings.FunctionConverge.Absolute = test.fAbsTol + } + if test.gradTol == 0 { + test.gradTol = 1e-12 + } + settings.GradientThreshold = test.gradTol + + result, err := Local(test.p, test.x, settings, method) + if err != nil { + t.Errorf("error finding minimum (%v) for:\n%v", err, test) + continue + } + if result == nil { + t.Errorf("nil result without error for:\n%v", test) + continue + } + + // Check that the function value at the found optimum location is + // equal to result.F. + optF := test.p.Func(result.X) + if optF != result.F { + t.Errorf("Function value at the optimum location %v not equal to the returned value %v for:\n%v", + optF, result.F, test) + } + if result.Gradient != nil { + // Evaluate the norm of the gradient at the found optimum location. + g := make([]float64, len(test.x)) + test.p.Grad(g, result.X) + + if !floats.Equal(result.Gradient, g) { + t.Errorf("Gradient at the optimum location not equal to the returned value for:\n%v", test) + } + + optNorm := floats.Norm(g, math.Inf(1)) + // Check that the norm of the gradient at the found optimum location is + // smaller than the tolerance. + if optNorm >= settings.GradientThreshold { + t.Errorf("Norm of the gradient at the optimum location %v not smaller than tolerance %v for:\n%v", + optNorm, settings.GradientThreshold, test) + } + } + + if method == nil { + // The tests below make sense only if the method used is known. + continue + } + + if !method.Needs().Gradient && !method.Needs().Hessian { + // Gradient-free tests can correctly terminate only with + // FunctionConvergence status. + if result.Status != FunctionConvergence { + t.Errorf("Status not %v, %v instead", FunctionConvergence, result.Status) + } + } + + // We are going to restart the solution using known initial data, so + // evaluate them. + settings.UseInitialData = true + settings.InitialValue = test.p.Func(test.x) + if method.Needs().Gradient { + settings.InitialGradient = resize(settings.InitialGradient, len(test.x)) + test.p.Grad(settings.InitialGradient, test.x) + } + if method.Needs().Hessian { + settings.InitialHessian = mat.NewSymDense(len(test.x), nil) + test.p.Hess(settings.InitialHessian, test.x) + } + + // Rerun the test again to make sure that it gets the same answer with + // the same starting condition. Moreover, we are using the initial data. + result2, err2 := Local(test.p, test.x, settings, method) + if err2 != nil { + t.Errorf("error finding minimum second time (%v) for:\n%v", err2, test) + continue + } + if result2 == nil { + t.Errorf("second time nil result without error for:\n%v", test) + continue + } + + // At the moment all the optimizers are deterministic, so check that we + // get _exactly_ the same answer second time as well. + if result.F != result2.F || !floats.Equal(result.X, result2.X) { + t.Errorf("Different minimum second time for:\n%v", test) + } + + // Check that providing initial data reduces the number of evaluations exactly by one. + if result.FuncEvaluations != result2.FuncEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Func calls for:\n%v", test) + continue + } + if method.Needs().Gradient { + if result.GradEvaluations != result2.GradEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Grad calls for:\n%v", test) + continue + } + } + if method.Needs().Hessian { + if result.HessEvaluations != result2.HessEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Hess calls for:\n%v", test) + continue + } + } + } +} + +func TestIssue76(t *testing.T) { + p := Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + } + // Location very close to the minimum. + x := []float64{-11.594439904886773, 13.203630051265385, -0.40343948776868443, 0.2367787746745986} + s := &Settings{ + FunctionThreshold: math.Inf(-1), + GradientThreshold: 1e-14, + MajorIterations: 1000000, + } + m := &GradientDescent{ + Linesearcher: &Backtracking{}, + } + // We are not interested in the error, only in the returned status. + r, _ := Local(p, x, s, m) + // With the above stringent tolerance, the optimizer will never + // successfully reach the minimum. Check if it terminated in a finite + // number of steps. + if r.Status == IterationLimit { + t.Error("Issue https://github.com/gonum/optimize/issues/76 not fixed") + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/appengine_test.go b/vendor/gonum.org/v1/gonum/stat/appengine_test.go new file mode 100644 index 00000000..bb2b93c7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/appengine_test.go @@ -0,0 +1,9 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build noasm appengine + +package stat + +func init() { appengine = true } diff --git a/vendor/gonum.org/v1/gonum/stat/boston_data_test.go b/vendor/gonum.org/v1/gonum/stat/boston_data_test.go new file mode 100644 index 00000000..e85a505f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/boston_data_test.go @@ -0,0 +1,531 @@ +// Copyright ©2016 The gonum 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 stat_test + +import "gonum.org/v1/gonum/mat" + +// Boston Housing Data of Harrison and Rubinfeld (1978) +// http://dx.doi.org/10.1016/0095-0696(78)90006-2 +// http://lib.stat.cmu.edu/datasets/boston +// Columns are; +// per capita crime rate by town, +// proportion of non-retail business acres per town, +// nitric oxide concentration (parts per 10 million), +// weighted distances to Boston employment centers, +// index of accessibility to radial highways, +// pupil-teacher ratio by town, +// proportion of blacks by town, +// average number of rooms per dwelling, +// proportion of owner-occupied units built prior to 1940, +// full-value property-tax rate per $10000, +// median value of owner-occupied homes in $1000s. +var bostonData = mat.NewDense(506, 11, []float64{ + 0.00632, 2.31000, 0.53800, 4.09000, 1.00000, 15.30000, 396.90000, 6.57500, 65.20000, 296.00000, 24.00000, + 0.02731, 7.07000, 0.46900, 4.96710, 2.00000, 17.80000, 396.90000, 6.42100, 78.90000, 242.00000, 21.60000, + 0.02729, 7.07000, 0.46900, 4.96710, 2.00000, 17.80000, 392.83000, 7.18500, 61.10000, 242.00000, 34.70000, + 0.03237, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 394.63000, 6.99800, 45.80000, 222.00000, 33.40000, + 0.06905, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 396.90000, 7.14700, 54.20000, 222.00000, 36.20000, + 0.02985, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 394.12000, 6.43000, 58.70000, 222.00000, 28.70000, + 0.08829, 7.87000, 0.52400, 5.56050, 5.00000, 15.20000, 395.60000, 6.01200, 66.60000, 311.00000, 22.90000, + 0.14455, 7.87000, 0.52400, 5.95050, 5.00000, 15.20000, 396.90000, 6.17200, 96.10000, 311.00000, 27.10000, + 0.21124, 7.87000, 0.52400, 6.08210, 5.00000, 15.20000, 386.63000, 5.63100, 100.00000, 311.00000, 16.50000, + 0.17004, 7.87000, 0.52400, 6.59210, 5.00000, 15.20000, 386.71000, 6.00400, 85.90000, 311.00000, 18.90000, + 0.22489, 7.87000, 0.52400, 6.34670, 5.00000, 15.20000, 392.52000, 6.37700, 94.30000, 311.00000, 15.00000, + 0.11747, 7.87000, 0.52400, 6.22670, 5.00000, 15.20000, 396.90000, 6.00900, 82.90000, 311.00000, 18.90000, + 0.09378, 7.87000, 0.52400, 5.45090, 5.00000, 15.20000, 390.50000, 5.88900, 39.00000, 311.00000, 21.70000, + 0.62976, 8.14000, 0.53800, 4.70750, 4.00000, 21.00000, 396.90000, 5.94900, 61.80000, 307.00000, 20.40000, + 0.63796, 8.14000, 0.53800, 4.46190, 4.00000, 21.00000, 380.02000, 6.09600, 84.50000, 307.00000, 18.20000, + 0.62739, 8.14000, 0.53800, 4.49860, 4.00000, 21.00000, 395.62000, 5.83400, 56.50000, 307.00000, 19.90000, + 1.05393, 8.14000, 0.53800, 4.49860, 4.00000, 21.00000, 386.85000, 5.93500, 29.30000, 307.00000, 23.10000, + 0.78420, 8.14000, 0.53800, 4.25790, 4.00000, 21.00000, 386.75000, 5.99000, 81.70000, 307.00000, 17.50000, + 0.80271, 8.14000, 0.53800, 3.79650, 4.00000, 21.00000, 288.99000, 5.45600, 36.60000, 307.00000, 20.20000, + 0.72580, 8.14000, 0.53800, 3.79650, 4.00000, 21.00000, 390.95000, 5.72700, 69.50000, 307.00000, 18.20000, + 1.25179, 8.14000, 0.53800, 3.79790, 4.00000, 21.00000, 376.57000, 5.57000, 98.10000, 307.00000, 13.60000, + 0.85204, 8.14000, 0.53800, 4.01230, 4.00000, 21.00000, 392.53000, 5.96500, 89.20000, 307.00000, 19.60000, + 1.23247, 8.14000, 0.53800, 3.97690, 4.00000, 21.00000, 396.90000, 6.14200, 91.70000, 307.00000, 15.20000, + 0.98843, 8.14000, 0.53800, 4.09520, 4.00000, 21.00000, 394.54000, 5.81300, 100.00000, 307.00000, 14.50000, + 0.75026, 8.14000, 0.53800, 4.39960, 4.00000, 21.00000, 394.33000, 5.92400, 94.10000, 307.00000, 15.60000, + 0.84054, 8.14000, 0.53800, 4.45460, 4.00000, 21.00000, 303.42000, 5.59900, 85.70000, 307.00000, 13.90000, + 0.67191, 8.14000, 0.53800, 4.68200, 4.00000, 21.00000, 376.88000, 5.81300, 90.30000, 307.00000, 16.60000, + 0.95577, 8.14000, 0.53800, 4.45340, 4.00000, 21.00000, 306.38000, 6.04700, 88.80000, 307.00000, 14.80000, + 0.77299, 8.14000, 0.53800, 4.45470, 4.00000, 21.00000, 387.94000, 6.49500, 94.40000, 307.00000, 18.40000, + 1.00245, 8.14000, 0.53800, 4.23900, 4.00000, 21.00000, 380.23000, 6.67400, 87.30000, 307.00000, 21.00000, + 1.13081, 8.14000, 0.53800, 4.23300, 4.00000, 21.00000, 360.17000, 5.71300, 94.10000, 307.00000, 12.70000, + 1.35472, 8.14000, 0.53800, 4.17500, 4.00000, 21.00000, 376.73000, 6.07200, 100.00000, 307.00000, 14.50000, + 1.38799, 8.14000, 0.53800, 3.99000, 4.00000, 21.00000, 232.60000, 5.95000, 82.00000, 307.00000, 13.20000, + 1.15172, 8.14000, 0.53800, 3.78720, 4.00000, 21.00000, 358.77000, 5.70100, 95.00000, 307.00000, 13.10000, + 1.61282, 8.14000, 0.53800, 3.75980, 4.00000, 21.00000, 248.31000, 6.09600, 96.90000, 307.00000, 13.50000, + 0.06417, 5.96000, 0.49900, 3.36030, 5.00000, 19.20000, 396.90000, 5.93300, 68.20000, 279.00000, 18.90000, + 0.09744, 5.96000, 0.49900, 3.37790, 5.00000, 19.20000, 377.56000, 5.84100, 61.40000, 279.00000, 20.00000, + 0.08014, 5.96000, 0.49900, 3.93420, 5.00000, 19.20000, 396.90000, 5.85000, 41.50000, 279.00000, 21.00000, + 0.17505, 5.96000, 0.49900, 3.84730, 5.00000, 19.20000, 393.43000, 5.96600, 30.20000, 279.00000, 24.70000, + 0.02763, 2.95000, 0.42800, 5.40110, 3.00000, 18.30000, 395.63000, 6.59500, 21.80000, 252.00000, 30.80000, + 0.03359, 2.95000, 0.42800, 5.40110, 3.00000, 18.30000, 395.62000, 7.02400, 15.80000, 252.00000, 34.90000, + 0.12744, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 385.41000, 6.77000, 2.90000, 233.00000, 26.60000, + 0.14150, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 383.37000, 6.16900, 6.60000, 233.00000, 25.30000, + 0.15936, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 394.46000, 6.21100, 6.50000, 233.00000, 24.70000, + 0.12269, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 389.39000, 6.06900, 40.00000, 233.00000, 21.20000, + 0.17142, 6.91000, 0.44800, 5.10040, 3.00000, 17.90000, 396.90000, 5.68200, 33.80000, 233.00000, 19.30000, + 0.18836, 6.91000, 0.44800, 5.10040, 3.00000, 17.90000, 396.90000, 5.78600, 33.30000, 233.00000, 20.00000, + 0.22927, 6.91000, 0.44800, 5.68940, 3.00000, 17.90000, 392.74000, 6.03000, 85.50000, 233.00000, 16.60000, + 0.25387, 6.91000, 0.44800, 5.87000, 3.00000, 17.90000, 396.90000, 5.39900, 95.30000, 233.00000, 14.40000, + 0.21977, 6.91000, 0.44800, 6.08770, 3.00000, 17.90000, 396.90000, 5.60200, 62.00000, 233.00000, 19.40000, + 0.08873, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 395.56000, 5.96300, 45.70000, 243.00000, 19.70000, + 0.04337, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 393.97000, 6.11500, 63.00000, 243.00000, 20.50000, + 0.05360, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 396.90000, 6.51100, 21.10000, 243.00000, 25.00000, + 0.04981, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 396.90000, 5.99800, 21.40000, 243.00000, 23.40000, + 0.01360, 4.00000, 0.41000, 7.31970, 3.00000, 21.10000, 396.90000, 5.88800, 47.60000, 469.00000, 18.90000, + 0.01311, 1.22000, 0.40300, 8.69660, 5.00000, 17.90000, 395.93000, 7.24900, 21.90000, 226.00000, 35.40000, + 0.02055, 0.74000, 0.41000, 9.18760, 2.00000, 17.30000, 396.90000, 6.38300, 35.70000, 313.00000, 24.70000, + 0.01432, 1.32000, 0.41100, 8.32480, 5.00000, 15.10000, 392.90000, 6.81600, 40.50000, 256.00000, 31.60000, + 0.15445, 5.13000, 0.45300, 7.81480, 8.00000, 19.70000, 390.68000, 6.14500, 29.20000, 284.00000, 23.30000, + 0.10328, 5.13000, 0.45300, 6.93200, 8.00000, 19.70000, 396.90000, 5.92700, 47.20000, 284.00000, 19.60000, + 0.14932, 5.13000, 0.45300, 7.22540, 8.00000, 19.70000, 395.11000, 5.74100, 66.20000, 284.00000, 18.70000, + 0.17171, 5.13000, 0.45300, 6.81850, 8.00000, 19.70000, 378.08000, 5.96600, 93.40000, 284.00000, 16.00000, + 0.11027, 5.13000, 0.45300, 7.22550, 8.00000, 19.70000, 396.90000, 6.45600, 67.80000, 284.00000, 22.20000, + 0.12650, 5.13000, 0.45300, 7.98090, 8.00000, 19.70000, 395.58000, 6.76200, 43.40000, 284.00000, 25.00000, + 0.01951, 1.38000, 0.41610, 9.22290, 3.00000, 18.60000, 393.24000, 7.10400, 59.50000, 216.00000, 33.00000, + 0.03584, 3.37000, 0.39800, 6.61150, 4.00000, 16.10000, 396.90000, 6.29000, 17.80000, 337.00000, 23.50000, + 0.04379, 3.37000, 0.39800, 6.61150, 4.00000, 16.10000, 396.90000, 5.78700, 31.10000, 337.00000, 19.40000, + 0.05789, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.21000, 5.87800, 21.40000, 345.00000, 22.00000, + 0.13554, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.90000, 5.59400, 36.80000, 345.00000, 17.40000, + 0.12816, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.90000, 5.88500, 33.00000, 345.00000, 20.90000, + 0.08826, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 383.73000, 6.41700, 6.60000, 305.00000, 24.20000, + 0.15876, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 376.94000, 5.96100, 17.50000, 305.00000, 21.70000, + 0.09164, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 390.91000, 6.06500, 7.80000, 305.00000, 22.80000, + 0.19539, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 377.17000, 6.24500, 6.20000, 305.00000, 23.40000, + 0.07896, 12.83000, 0.43700, 4.25150, 5.00000, 18.70000, 394.92000, 6.27300, 6.00000, 398.00000, 24.10000, + 0.09512, 12.83000, 0.43700, 4.50260, 5.00000, 18.70000, 383.23000, 6.28600, 45.00000, 398.00000, 21.40000, + 0.10153, 12.83000, 0.43700, 4.05220, 5.00000, 18.70000, 373.66000, 6.27900, 74.50000, 398.00000, 20.00000, + 0.08707, 12.83000, 0.43700, 4.09050, 5.00000, 18.70000, 386.96000, 6.14000, 45.80000, 398.00000, 20.80000, + 0.05646, 12.83000, 0.43700, 5.01410, 5.00000, 18.70000, 386.40000, 6.23200, 53.70000, 398.00000, 21.20000, + 0.08387, 12.83000, 0.43700, 4.50260, 5.00000, 18.70000, 396.06000, 5.87400, 36.60000, 398.00000, 20.30000, + 0.04113, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 396.90000, 6.72700, 33.50000, 281.00000, 28.00000, + 0.04462, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 395.63000, 6.61900, 70.40000, 281.00000, 23.90000, + 0.03659, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 396.90000, 6.30200, 32.20000, 281.00000, 24.80000, + 0.03551, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 390.64000, 6.16700, 46.70000, 281.00000, 22.90000, + 0.05059, 4.49000, 0.44900, 4.77940, 3.00000, 18.50000, 396.90000, 6.38900, 48.00000, 247.00000, 23.90000, + 0.05735, 4.49000, 0.44900, 4.43770, 3.00000, 18.50000, 392.30000, 6.63000, 56.10000, 247.00000, 26.60000, + 0.05188, 4.49000, 0.44900, 4.42720, 3.00000, 18.50000, 395.99000, 6.01500, 45.10000, 247.00000, 22.50000, + 0.07151, 4.49000, 0.44900, 3.74760, 3.00000, 18.50000, 395.15000, 6.12100, 56.80000, 247.00000, 22.20000, + 0.05660, 3.41000, 0.48900, 3.42170, 2.00000, 17.80000, 396.90000, 7.00700, 86.30000, 270.00000, 23.60000, + 0.05302, 3.41000, 0.48900, 3.41450, 2.00000, 17.80000, 396.06000, 7.07900, 63.10000, 270.00000, 28.70000, + 0.04684, 3.41000, 0.48900, 3.09230, 2.00000, 17.80000, 392.18000, 6.41700, 66.10000, 270.00000, 22.60000, + 0.03932, 3.41000, 0.48900, 3.09210, 2.00000, 17.80000, 393.55000, 6.40500, 73.90000, 270.00000, 22.00000, + 0.04203, 15.04000, 0.46400, 3.66590, 4.00000, 18.20000, 395.01000, 6.44200, 53.60000, 270.00000, 22.90000, + 0.02875, 15.04000, 0.46400, 3.66590, 4.00000, 18.20000, 396.33000, 6.21100, 28.90000, 270.00000, 25.00000, + 0.04294, 15.04000, 0.46400, 3.61500, 4.00000, 18.20000, 396.90000, 6.24900, 77.30000, 270.00000, 20.60000, + 0.12204, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 357.98000, 6.62500, 57.80000, 276.00000, 28.40000, + 0.11504, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 391.83000, 6.16300, 69.60000, 276.00000, 21.40000, + 0.12083, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 396.90000, 8.06900, 76.00000, 276.00000, 38.70000, + 0.08187, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 393.53000, 7.82000, 36.90000, 276.00000, 43.80000, + 0.06860, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 396.90000, 7.41600, 62.50000, 276.00000, 33.20000, + 0.14866, 8.56000, 0.52000, 2.77780, 5.00000, 20.90000, 394.76000, 6.72700, 79.90000, 384.00000, 27.50000, + 0.11432, 8.56000, 0.52000, 2.85610, 5.00000, 20.90000, 395.58000, 6.78100, 71.30000, 384.00000, 26.50000, + 0.22876, 8.56000, 0.52000, 2.71470, 5.00000, 20.90000, 70.80000, 6.40500, 85.40000, 384.00000, 18.60000, + 0.21161, 8.56000, 0.52000, 2.71470, 5.00000, 20.90000, 394.47000, 6.13700, 87.40000, 384.00000, 19.30000, + 0.13960, 8.56000, 0.52000, 2.42100, 5.00000, 20.90000, 392.69000, 6.16700, 90.00000, 384.00000, 20.10000, + 0.13262, 8.56000, 0.52000, 2.10690, 5.00000, 20.90000, 394.05000, 5.85100, 96.70000, 384.00000, 19.50000, + 0.17120, 8.56000, 0.52000, 2.21100, 5.00000, 20.90000, 395.67000, 5.83600, 91.90000, 384.00000, 19.50000, + 0.13117, 8.56000, 0.52000, 2.12240, 5.00000, 20.90000, 387.69000, 6.12700, 85.20000, 384.00000, 20.40000, + 0.12802, 8.56000, 0.52000, 2.43290, 5.00000, 20.90000, 395.24000, 6.47400, 97.10000, 384.00000, 19.80000, + 0.26363, 8.56000, 0.52000, 2.54510, 5.00000, 20.90000, 391.23000, 6.22900, 91.20000, 384.00000, 19.40000, + 0.10793, 8.56000, 0.52000, 2.77780, 5.00000, 20.90000, 393.49000, 6.19500, 54.40000, 384.00000, 21.70000, + 0.10084, 10.01000, 0.54700, 2.67750, 6.00000, 17.80000, 395.59000, 6.71500, 81.60000, 432.00000, 22.80000, + 0.12329, 10.01000, 0.54700, 2.35340, 6.00000, 17.80000, 394.95000, 5.91300, 92.90000, 432.00000, 18.80000, + 0.22212, 10.01000, 0.54700, 2.54800, 6.00000, 17.80000, 396.90000, 6.09200, 95.40000, 432.00000, 18.70000, + 0.14231, 10.01000, 0.54700, 2.25650, 6.00000, 17.80000, 388.74000, 6.25400, 84.20000, 432.00000, 18.50000, + 0.17134, 10.01000, 0.54700, 2.46310, 6.00000, 17.80000, 344.91000, 5.92800, 88.20000, 432.00000, 18.30000, + 0.13158, 10.01000, 0.54700, 2.73010, 6.00000, 17.80000, 393.30000, 6.17600, 72.50000, 432.00000, 21.20000, + 0.15098, 10.01000, 0.54700, 2.74740, 6.00000, 17.80000, 394.51000, 6.02100, 82.60000, 432.00000, 19.20000, + 0.13058, 10.01000, 0.54700, 2.47750, 6.00000, 17.80000, 338.63000, 5.87200, 73.10000, 432.00000, 20.40000, + 0.14476, 10.01000, 0.54700, 2.75920, 6.00000, 17.80000, 391.50000, 5.73100, 65.20000, 432.00000, 19.30000, + 0.06899, 25.65000, 0.58100, 2.25770, 2.00000, 19.10000, 389.15000, 5.87000, 69.70000, 188.00000, 22.00000, + 0.07165, 25.65000, 0.58100, 2.19740, 2.00000, 19.10000, 377.67000, 6.00400, 84.10000, 188.00000, 20.30000, + 0.09299, 25.65000, 0.58100, 2.08690, 2.00000, 19.10000, 378.09000, 5.96100, 92.90000, 188.00000, 20.50000, + 0.15038, 25.65000, 0.58100, 1.94440, 2.00000, 19.10000, 370.31000, 5.85600, 97.00000, 188.00000, 17.30000, + 0.09849, 25.65000, 0.58100, 2.00630, 2.00000, 19.10000, 379.38000, 5.87900, 95.80000, 188.00000, 18.80000, + 0.16902, 25.65000, 0.58100, 1.99290, 2.00000, 19.10000, 385.02000, 5.98600, 88.40000, 188.00000, 21.40000, + 0.38735, 25.65000, 0.58100, 1.75720, 2.00000, 19.10000, 359.29000, 5.61300, 95.60000, 188.00000, 15.70000, + 0.25915, 21.89000, 0.62400, 1.78830, 4.00000, 21.20000, 392.11000, 5.69300, 96.00000, 437.00000, 16.20000, + 0.32543, 21.89000, 0.62400, 1.81250, 4.00000, 21.20000, 396.90000, 6.43100, 98.80000, 437.00000, 18.00000, + 0.88125, 21.89000, 0.62400, 1.97990, 4.00000, 21.20000, 396.90000, 5.63700, 94.70000, 437.00000, 14.30000, + 0.34006, 21.89000, 0.62400, 2.11850, 4.00000, 21.20000, 395.04000, 6.45800, 98.90000, 437.00000, 19.20000, + 1.19294, 21.89000, 0.62400, 2.27100, 4.00000, 21.20000, 396.90000, 6.32600, 97.70000, 437.00000, 19.60000, + 0.59005, 21.89000, 0.62400, 2.32740, 4.00000, 21.20000, 385.76000, 6.37200, 97.90000, 437.00000, 23.00000, + 0.32982, 21.89000, 0.62400, 2.46990, 4.00000, 21.20000, 388.69000, 5.82200, 95.40000, 437.00000, 18.40000, + 0.97617, 21.89000, 0.62400, 2.34600, 4.00000, 21.20000, 262.76000, 5.75700, 98.40000, 437.00000, 15.60000, + 0.55778, 21.89000, 0.62400, 2.11070, 4.00000, 21.20000, 394.67000, 6.33500, 98.20000, 437.00000, 18.10000, + 0.32264, 21.89000, 0.62400, 1.96690, 4.00000, 21.20000, 378.25000, 5.94200, 93.50000, 437.00000, 17.40000, + 0.35233, 21.89000, 0.62400, 1.84980, 4.00000, 21.20000, 394.08000, 6.45400, 98.40000, 437.00000, 17.10000, + 0.24980, 21.89000, 0.62400, 1.66860, 4.00000, 21.20000, 392.04000, 5.85700, 98.20000, 437.00000, 13.30000, + 0.54452, 21.89000, 0.62400, 1.66870, 4.00000, 21.20000, 396.90000, 6.15100, 97.90000, 437.00000, 17.80000, + 0.29090, 21.89000, 0.62400, 1.61190, 4.00000, 21.20000, 388.08000, 6.17400, 93.60000, 437.00000, 14.00000, + 1.62864, 21.89000, 0.62400, 1.43940, 4.00000, 21.20000, 396.90000, 5.01900, 100.00000, 437.00000, 14.40000, + 3.32105, 19.58000, 0.87100, 1.32160, 5.00000, 14.70000, 396.90000, 5.40300, 100.00000, 403.00000, 13.40000, + 4.09740, 19.58000, 0.87100, 1.41180, 5.00000, 14.70000, 396.90000, 5.46800, 100.00000, 403.00000, 15.60000, + 2.77974, 19.58000, 0.87100, 1.34590, 5.00000, 14.70000, 396.90000, 4.90300, 97.80000, 403.00000, 11.80000, + 2.37934, 19.58000, 0.87100, 1.41910, 5.00000, 14.70000, 172.91000, 6.13000, 100.00000, 403.00000, 13.80000, + 2.15505, 19.58000, 0.87100, 1.51660, 5.00000, 14.70000, 169.27000, 5.62800, 100.00000, 403.00000, 15.60000, + 2.36862, 19.58000, 0.87100, 1.46080, 5.00000, 14.70000, 391.71000, 4.92600, 95.70000, 403.00000, 14.60000, + 2.33099, 19.58000, 0.87100, 1.52960, 5.00000, 14.70000, 356.99000, 5.18600, 93.80000, 403.00000, 17.80000, + 2.73397, 19.58000, 0.87100, 1.52570, 5.00000, 14.70000, 351.85000, 5.59700, 94.90000, 403.00000, 15.40000, + 1.65660, 19.58000, 0.87100, 1.61800, 5.00000, 14.70000, 372.80000, 6.12200, 97.30000, 403.00000, 21.50000, + 1.49632, 19.58000, 0.87100, 1.59160, 5.00000, 14.70000, 341.60000, 5.40400, 100.00000, 403.00000, 19.60000, + 1.12658, 19.58000, 0.87100, 1.61020, 5.00000, 14.70000, 343.28000, 5.01200, 88.00000, 403.00000, 15.30000, + 2.14918, 19.58000, 0.87100, 1.62320, 5.00000, 14.70000, 261.95000, 5.70900, 98.50000, 403.00000, 19.40000, + 1.41385, 19.58000, 0.87100, 1.74940, 5.00000, 14.70000, 321.02000, 6.12900, 96.00000, 403.00000, 17.00000, + 3.53501, 19.58000, 0.87100, 1.74550, 5.00000, 14.70000, 88.01000, 6.15200, 82.60000, 403.00000, 15.60000, + 2.44668, 19.58000, 0.87100, 1.73640, 5.00000, 14.70000, 88.63000, 5.27200, 94.00000, 403.00000, 13.10000, + 1.22358, 19.58000, 0.60500, 1.87730, 5.00000, 14.70000, 363.43000, 6.94300, 97.40000, 403.00000, 41.30000, + 1.34284, 19.58000, 0.60500, 1.75730, 5.00000, 14.70000, 353.89000, 6.06600, 100.00000, 403.00000, 24.30000, + 1.42502, 19.58000, 0.87100, 1.76590, 5.00000, 14.70000, 364.31000, 6.51000, 100.00000, 403.00000, 23.30000, + 1.27346, 19.58000, 0.60500, 1.79840, 5.00000, 14.70000, 338.92000, 6.25000, 92.60000, 403.00000, 27.00000, + 1.46336, 19.58000, 0.60500, 1.97090, 5.00000, 14.70000, 374.43000, 7.48900, 90.80000, 403.00000, 50.00000, + 1.83377, 19.58000, 0.60500, 2.04070, 5.00000, 14.70000, 389.61000, 7.80200, 98.20000, 403.00000, 50.00000, + 1.51902, 19.58000, 0.60500, 2.16200, 5.00000, 14.70000, 388.45000, 8.37500, 93.90000, 403.00000, 50.00000, + 2.24236, 19.58000, 0.60500, 2.42200, 5.00000, 14.70000, 395.11000, 5.85400, 91.80000, 403.00000, 22.70000, + 2.92400, 19.58000, 0.60500, 2.28340, 5.00000, 14.70000, 240.16000, 6.10100, 93.00000, 403.00000, 25.00000, + 2.01019, 19.58000, 0.60500, 2.04590, 5.00000, 14.70000, 369.30000, 7.92900, 96.20000, 403.00000, 50.00000, + 1.80028, 19.58000, 0.60500, 2.42590, 5.00000, 14.70000, 227.61000, 5.87700, 79.20000, 403.00000, 23.80000, + 2.30040, 19.58000, 0.60500, 2.10000, 5.00000, 14.70000, 297.09000, 6.31900, 96.10000, 403.00000, 23.80000, + 2.44953, 19.58000, 0.60500, 2.26250, 5.00000, 14.70000, 330.04000, 6.40200, 95.20000, 403.00000, 22.30000, + 1.20742, 19.58000, 0.60500, 2.42590, 5.00000, 14.70000, 292.29000, 5.87500, 94.60000, 403.00000, 17.40000, + 2.31390, 19.58000, 0.60500, 2.38870, 5.00000, 14.70000, 348.13000, 5.88000, 97.30000, 403.00000, 19.10000, + 0.13914, 4.05000, 0.51000, 2.59610, 5.00000, 16.60000, 396.90000, 5.57200, 88.50000, 296.00000, 23.10000, + 0.09178, 4.05000, 0.51000, 2.64630, 5.00000, 16.60000, 395.50000, 6.41600, 84.10000, 296.00000, 23.60000, + 0.08447, 4.05000, 0.51000, 2.70190, 5.00000, 16.60000, 393.23000, 5.85900, 68.70000, 296.00000, 22.60000, + 0.06664, 4.05000, 0.51000, 3.13230, 5.00000, 16.60000, 390.96000, 6.54600, 33.10000, 296.00000, 29.40000, + 0.07022, 4.05000, 0.51000, 3.55490, 5.00000, 16.60000, 393.23000, 6.02000, 47.20000, 296.00000, 23.20000, + 0.05425, 4.05000, 0.51000, 3.31750, 5.00000, 16.60000, 395.60000, 6.31500, 73.40000, 296.00000, 24.60000, + 0.06642, 4.05000, 0.51000, 2.91530, 5.00000, 16.60000, 391.27000, 6.86000, 74.40000, 296.00000, 29.90000, + 0.05780, 2.46000, 0.48800, 2.82900, 3.00000, 17.80000, 396.90000, 6.98000, 58.40000, 193.00000, 37.20000, + 0.06588, 2.46000, 0.48800, 2.74100, 3.00000, 17.80000, 395.56000, 7.76500, 83.30000, 193.00000, 39.80000, + 0.06888, 2.46000, 0.48800, 2.59790, 3.00000, 17.80000, 396.90000, 6.14400, 62.20000, 193.00000, 36.20000, + 0.09103, 2.46000, 0.48800, 2.70060, 3.00000, 17.80000, 394.12000, 7.15500, 92.20000, 193.00000, 37.90000, + 0.10008, 2.46000, 0.48800, 2.84700, 3.00000, 17.80000, 396.90000, 6.56300, 95.60000, 193.00000, 32.50000, + 0.08308, 2.46000, 0.48800, 2.98790, 3.00000, 17.80000, 391.00000, 5.60400, 89.80000, 193.00000, 26.40000, + 0.06047, 2.46000, 0.48800, 3.27970, 3.00000, 17.80000, 387.11000, 6.15300, 68.80000, 193.00000, 29.60000, + 0.05602, 2.46000, 0.48800, 3.19920, 3.00000, 17.80000, 392.63000, 7.83100, 53.60000, 193.00000, 50.00000, + 0.07875, 3.44000, 0.43700, 3.78860, 5.00000, 15.20000, 393.87000, 6.78200, 41.10000, 398.00000, 32.00000, + 0.12579, 3.44000, 0.43700, 4.56670, 5.00000, 15.20000, 382.84000, 6.55600, 29.10000, 398.00000, 29.80000, + 0.08370, 3.44000, 0.43700, 4.56670, 5.00000, 15.20000, 396.90000, 7.18500, 38.90000, 398.00000, 34.90000, + 0.09068, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 377.68000, 6.95100, 21.50000, 398.00000, 37.00000, + 0.06911, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 389.71000, 6.73900, 30.80000, 398.00000, 30.50000, + 0.08664, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 390.49000, 7.17800, 26.30000, 398.00000, 36.40000, + 0.02187, 2.93000, 0.40100, 6.21960, 1.00000, 15.60000, 393.37000, 6.80000, 9.90000, 265.00000, 31.10000, + 0.01439, 2.93000, 0.40100, 6.21960, 1.00000, 15.60000, 376.70000, 6.60400, 18.80000, 265.00000, 29.10000, + 0.01381, 0.46000, 0.42200, 5.64840, 4.00000, 14.40000, 394.23000, 7.87500, 32.00000, 255.00000, 50.00000, + 0.04011, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 396.90000, 7.28700, 34.10000, 329.00000, 33.30000, + 0.04666, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 354.31000, 7.10700, 36.60000, 329.00000, 30.30000, + 0.03768, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 392.20000, 7.27400, 38.30000, 329.00000, 34.60000, + 0.03150, 1.47000, 0.40300, 7.65340, 3.00000, 17.00000, 396.90000, 6.97500, 15.30000, 402.00000, 34.90000, + 0.01778, 1.47000, 0.40300, 7.65340, 3.00000, 17.00000, 384.30000, 7.13500, 13.90000, 402.00000, 32.90000, + 0.03445, 2.03000, 0.41500, 6.27000, 2.00000, 14.70000, 393.77000, 6.16200, 38.40000, 348.00000, 24.10000, + 0.02177, 2.03000, 0.41500, 6.27000, 2.00000, 14.70000, 395.38000, 7.61000, 15.70000, 348.00000, 42.30000, + 0.03510, 2.68000, 0.41610, 5.11800, 4.00000, 14.70000, 392.78000, 7.85300, 33.20000, 224.00000, 48.50000, + 0.02009, 2.68000, 0.41610, 5.11800, 4.00000, 14.70000, 390.55000, 8.03400, 31.90000, 224.00000, 50.00000, + 0.13642, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 396.90000, 5.89100, 22.30000, 277.00000, 22.60000, + 0.22969, 10.59000, 0.48900, 4.35490, 4.00000, 18.60000, 394.87000, 6.32600, 52.50000, 277.00000, 24.40000, + 0.25199, 10.59000, 0.48900, 4.35490, 4.00000, 18.60000, 389.43000, 5.78300, 72.70000, 277.00000, 22.50000, + 0.13587, 10.59000, 0.48900, 4.23920, 4.00000, 18.60000, 381.32000, 6.06400, 59.10000, 277.00000, 24.40000, + 0.43571, 10.59000, 0.48900, 3.87500, 4.00000, 18.60000, 396.90000, 5.34400, 100.00000, 277.00000, 20.00000, + 0.17446, 10.59000, 0.48900, 3.87710, 4.00000, 18.60000, 393.25000, 5.96000, 92.10000, 277.00000, 21.70000, + 0.37578, 10.59000, 0.48900, 3.66500, 4.00000, 18.60000, 395.24000, 5.40400, 88.60000, 277.00000, 19.30000, + 0.21719, 10.59000, 0.48900, 3.65260, 4.00000, 18.60000, 390.94000, 5.80700, 53.80000, 277.00000, 22.40000, + 0.14052, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 385.81000, 6.37500, 32.30000, 277.00000, 28.10000, + 0.28955, 10.59000, 0.48900, 3.58750, 4.00000, 18.60000, 348.93000, 5.41200, 9.80000, 277.00000, 23.70000, + 0.19802, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 393.63000, 6.18200, 42.40000, 277.00000, 25.00000, + 0.04560, 13.89000, 0.55000, 3.11210, 5.00000, 16.40000, 392.80000, 5.88800, 56.00000, 276.00000, 23.30000, + 0.07013, 13.89000, 0.55000, 3.42110, 5.00000, 16.40000, 392.78000, 6.64200, 85.10000, 276.00000, 28.70000, + 0.11069, 13.89000, 0.55000, 2.88930, 5.00000, 16.40000, 396.90000, 5.95100, 93.80000, 276.00000, 21.50000, + 0.11425, 13.89000, 0.55000, 3.36330, 5.00000, 16.40000, 393.74000, 6.37300, 92.40000, 276.00000, 23.00000, + 0.35809, 6.20000, 0.50700, 2.86170, 8.00000, 17.40000, 391.70000, 6.95100, 88.50000, 307.00000, 26.70000, + 0.40771, 6.20000, 0.50700, 3.04800, 8.00000, 17.40000, 395.24000, 6.16400, 91.30000, 307.00000, 21.70000, + 0.62356, 6.20000, 0.50700, 3.27210, 8.00000, 17.40000, 390.39000, 6.87900, 77.70000, 307.00000, 27.50000, + 0.61470, 6.20000, 0.50700, 3.27210, 8.00000, 17.40000, 396.90000, 6.61800, 80.80000, 307.00000, 30.10000, + 0.31533, 6.20000, 0.50400, 2.89440, 8.00000, 17.40000, 385.05000, 8.26600, 78.30000, 307.00000, 44.80000, + 0.52693, 6.20000, 0.50400, 2.89440, 8.00000, 17.40000, 382.00000, 8.72500, 83.00000, 307.00000, 50.00000, + 0.38214, 6.20000, 0.50400, 3.21570, 8.00000, 17.40000, 387.38000, 8.04000, 86.50000, 307.00000, 37.60000, + 0.41238, 6.20000, 0.50400, 3.21570, 8.00000, 17.40000, 372.08000, 7.16300, 79.90000, 307.00000, 31.60000, + 0.29819, 6.20000, 0.50400, 3.37510, 8.00000, 17.40000, 377.51000, 7.68600, 17.00000, 307.00000, 46.70000, + 0.44178, 6.20000, 0.50400, 3.37510, 8.00000, 17.40000, 380.34000, 6.55200, 21.40000, 307.00000, 31.50000, + 0.53700, 6.20000, 0.50400, 3.67150, 8.00000, 17.40000, 378.35000, 5.98100, 68.10000, 307.00000, 24.30000, + 0.46296, 6.20000, 0.50400, 3.67150, 8.00000, 17.40000, 376.14000, 7.41200, 76.90000, 307.00000, 31.70000, + 0.57529, 6.20000, 0.50700, 3.83840, 8.00000, 17.40000, 385.91000, 8.33700, 73.30000, 307.00000, 41.70000, + 0.33147, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 378.95000, 8.24700, 70.40000, 307.00000, 48.30000, + 0.44791, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 360.20000, 6.72600, 66.50000, 307.00000, 29.00000, + 0.33045, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 376.75000, 6.08600, 61.50000, 307.00000, 24.00000, + 0.52058, 6.20000, 0.50700, 4.14800, 8.00000, 17.40000, 388.45000, 6.63100, 76.50000, 307.00000, 25.10000, + 0.51183, 6.20000, 0.50700, 4.14800, 8.00000, 17.40000, 390.07000, 7.35800, 71.60000, 307.00000, 31.50000, + 0.08244, 4.93000, 0.42800, 6.18990, 6.00000, 16.60000, 379.41000, 6.48100, 18.50000, 300.00000, 23.70000, + 0.09252, 4.93000, 0.42800, 6.18990, 6.00000, 16.60000, 383.78000, 6.60600, 42.20000, 300.00000, 23.30000, + 0.11329, 4.93000, 0.42800, 6.33610, 6.00000, 16.60000, 391.25000, 6.89700, 54.30000, 300.00000, 22.00000, + 0.10612, 4.93000, 0.42800, 6.33610, 6.00000, 16.60000, 394.62000, 6.09500, 65.10000, 300.00000, 20.10000, + 0.10290, 4.93000, 0.42800, 7.03550, 6.00000, 16.60000, 372.75000, 6.35800, 52.90000, 300.00000, 22.20000, + 0.12757, 4.93000, 0.42800, 7.03550, 6.00000, 16.60000, 374.71000, 6.39300, 7.80000, 300.00000, 23.70000, + 0.20608, 5.86000, 0.43100, 7.95490, 7.00000, 19.10000, 372.49000, 5.59300, 76.50000, 330.00000, 17.60000, + 0.19133, 5.86000, 0.43100, 7.95490, 7.00000, 19.10000, 389.13000, 5.60500, 70.20000, 330.00000, 18.50000, + 0.33983, 5.86000, 0.43100, 8.05550, 7.00000, 19.10000, 390.18000, 6.10800, 34.90000, 330.00000, 24.30000, + 0.19657, 5.86000, 0.43100, 8.05550, 7.00000, 19.10000, 376.14000, 6.22600, 79.20000, 330.00000, 20.50000, + 0.16439, 5.86000, 0.43100, 7.82650, 7.00000, 19.10000, 374.71000, 6.43300, 49.10000, 330.00000, 24.50000, + 0.19073, 5.86000, 0.43100, 7.82650, 7.00000, 19.10000, 393.74000, 6.71800, 17.50000, 330.00000, 26.20000, + 0.14030, 5.86000, 0.43100, 7.39670, 7.00000, 19.10000, 396.28000, 6.48700, 13.00000, 330.00000, 24.40000, + 0.21409, 5.86000, 0.43100, 7.39670, 7.00000, 19.10000, 377.07000, 6.43800, 8.90000, 330.00000, 24.80000, + 0.08221, 5.86000, 0.43100, 8.90670, 7.00000, 19.10000, 386.09000, 6.95700, 6.80000, 330.00000, 29.60000, + 0.36894, 5.86000, 0.43100, 8.90670, 7.00000, 19.10000, 396.90000, 8.25900, 8.40000, 330.00000, 42.80000, + 0.04819, 3.64000, 0.39200, 9.22030, 1.00000, 16.40000, 392.89000, 6.10800, 32.00000, 315.00000, 21.90000, + 0.03548, 3.64000, 0.39200, 9.22030, 1.00000, 16.40000, 395.18000, 5.87600, 19.10000, 315.00000, 20.90000, + 0.01538, 3.75000, 0.39400, 6.33610, 3.00000, 15.90000, 386.34000, 7.45400, 34.20000, 244.00000, 44.00000, + 0.61154, 3.97000, 0.64700, 1.80100, 5.00000, 13.00000, 389.70000, 8.70400, 86.90000, 264.00000, 50.00000, + 0.66351, 3.97000, 0.64700, 1.89460, 5.00000, 13.00000, 383.29000, 7.33300, 100.00000, 264.00000, 36.00000, + 0.65665, 3.97000, 0.64700, 2.01070, 5.00000, 13.00000, 391.93000, 6.84200, 100.00000, 264.00000, 30.10000, + 0.54011, 3.97000, 0.64700, 2.11210, 5.00000, 13.00000, 392.80000, 7.20300, 81.80000, 264.00000, 33.80000, + 0.53412, 3.97000, 0.64700, 2.13980, 5.00000, 13.00000, 388.37000, 7.52000, 89.40000, 264.00000, 43.10000, + 0.52014, 3.97000, 0.64700, 2.28850, 5.00000, 13.00000, 386.86000, 8.39800, 91.50000, 264.00000, 48.80000, + 0.82526, 3.97000, 0.64700, 2.07880, 5.00000, 13.00000, 393.42000, 7.32700, 94.50000, 264.00000, 31.00000, + 0.55007, 3.97000, 0.64700, 1.93010, 5.00000, 13.00000, 387.89000, 7.20600, 91.60000, 264.00000, 36.50000, + 0.76162, 3.97000, 0.64700, 1.98650, 5.00000, 13.00000, 392.40000, 5.56000, 62.80000, 264.00000, 22.80000, + 0.78570, 3.97000, 0.64700, 2.13290, 5.00000, 13.00000, 384.07000, 7.01400, 84.60000, 264.00000, 30.70000, + 0.57834, 3.97000, 0.57500, 2.42160, 5.00000, 13.00000, 384.54000, 8.29700, 67.00000, 264.00000, 50.00000, + 0.54050, 3.97000, 0.57500, 2.87200, 5.00000, 13.00000, 390.30000, 7.47000, 52.60000, 264.00000, 43.50000, + 0.09065, 6.96000, 0.46400, 3.91750, 3.00000, 18.60000, 391.34000, 5.92000, 61.50000, 223.00000, 20.70000, + 0.29916, 6.96000, 0.46400, 4.42900, 3.00000, 18.60000, 388.65000, 5.85600, 42.10000, 223.00000, 21.10000, + 0.16211, 6.96000, 0.46400, 4.42900, 3.00000, 18.60000, 396.90000, 6.24000, 16.30000, 223.00000, 25.20000, + 0.11460, 6.96000, 0.46400, 3.91750, 3.00000, 18.60000, 394.96000, 6.53800, 58.70000, 223.00000, 24.40000, + 0.22188, 6.96000, 0.46400, 4.36650, 3.00000, 18.60000, 390.77000, 7.69100, 51.80000, 223.00000, 35.20000, + 0.05644, 6.41000, 0.44700, 4.07760, 4.00000, 17.60000, 396.90000, 6.75800, 32.90000, 254.00000, 32.40000, + 0.09604, 6.41000, 0.44700, 4.26730, 4.00000, 17.60000, 396.90000, 6.85400, 42.80000, 254.00000, 32.00000, + 0.10469, 6.41000, 0.44700, 4.78720, 4.00000, 17.60000, 389.25000, 7.26700, 49.00000, 254.00000, 33.20000, + 0.06127, 6.41000, 0.44700, 4.86280, 4.00000, 17.60000, 393.45000, 6.82600, 27.60000, 254.00000, 33.10000, + 0.07978, 6.41000, 0.44700, 4.14030, 4.00000, 17.60000, 396.90000, 6.48200, 32.10000, 254.00000, 29.10000, + 0.21038, 3.33000, 0.44290, 4.10070, 5.00000, 14.90000, 396.90000, 6.81200, 32.20000, 216.00000, 35.10000, + 0.03578, 3.33000, 0.44290, 4.69470, 5.00000, 14.90000, 387.31000, 7.82000, 64.50000, 216.00000, 45.40000, + 0.03705, 3.33000, 0.44290, 5.24470, 5.00000, 14.90000, 392.23000, 6.96800, 37.20000, 216.00000, 35.40000, + 0.06129, 3.33000, 0.44290, 5.21190, 5.00000, 14.90000, 377.07000, 7.64500, 49.70000, 216.00000, 46.00000, + 0.01501, 1.21000, 0.40100, 5.88500, 1.00000, 13.60000, 395.52000, 7.92300, 24.80000, 198.00000, 50.00000, + 0.00906, 2.97000, 0.40000, 7.30730, 1.00000, 15.30000, 394.72000, 7.08800, 20.80000, 285.00000, 32.20000, + 0.01096, 2.25000, 0.38900, 7.30730, 1.00000, 15.30000, 394.72000, 6.45300, 31.90000, 300.00000, 22.00000, + 0.01965, 1.76000, 0.38500, 9.08920, 1.00000, 18.20000, 341.60000, 6.23000, 31.50000, 241.00000, 20.10000, + 0.03871, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 396.90000, 6.20900, 31.30000, 293.00000, 23.20000, + 0.04590, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 396.90000, 6.31500, 45.60000, 293.00000, 22.30000, + 0.04297, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 371.72000, 6.56500, 22.90000, 293.00000, 24.80000, + 0.03502, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 6.86100, 27.90000, 245.00000, 28.50000, + 0.07886, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 7.14800, 27.70000, 245.00000, 37.30000, + 0.03615, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 6.63000, 23.40000, 245.00000, 27.90000, + 0.08265, 13.92000, 0.43700, 5.50270, 4.00000, 16.00000, 396.90000, 6.12700, 18.40000, 289.00000, 23.90000, + 0.08199, 13.92000, 0.43700, 5.50270, 4.00000, 16.00000, 396.90000, 6.00900, 42.30000, 289.00000, 21.70000, + 0.12932, 13.92000, 0.43700, 5.96040, 4.00000, 16.00000, 396.90000, 6.67800, 31.10000, 289.00000, 28.60000, + 0.05372, 13.92000, 0.43700, 5.96040, 4.00000, 16.00000, 392.85000, 6.54900, 51.00000, 289.00000, 27.10000, + 0.14103, 13.92000, 0.43700, 6.32000, 4.00000, 16.00000, 396.90000, 5.79000, 58.00000, 289.00000, 20.30000, + 0.06466, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 368.24000, 6.34500, 20.10000, 358.00000, 22.50000, + 0.05561, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 371.58000, 7.04100, 10.00000, 358.00000, 29.00000, + 0.04417, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 390.86000, 6.87100, 47.40000, 358.00000, 24.80000, + 0.03537, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 395.75000, 6.59000, 40.40000, 329.00000, 22.00000, + 0.09266, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 383.61000, 6.49500, 18.40000, 329.00000, 26.40000, + 0.10000, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 390.43000, 6.98200, 17.70000, 329.00000, 33.10000, + 0.05515, 2.18000, 0.47200, 4.02200, 7.00000, 18.40000, 393.68000, 7.23600, 41.10000, 222.00000, 36.10000, + 0.05479, 2.18000, 0.47200, 3.37000, 7.00000, 18.40000, 393.36000, 6.61600, 58.10000, 222.00000, 28.40000, + 0.07503, 2.18000, 0.47200, 3.09920, 7.00000, 18.40000, 396.90000, 7.42000, 71.90000, 222.00000, 33.40000, + 0.04932, 2.18000, 0.47200, 3.18270, 7.00000, 18.40000, 396.90000, 6.84900, 70.30000, 222.00000, 28.20000, + 0.49298, 9.90000, 0.54400, 3.31750, 4.00000, 18.40000, 396.90000, 6.63500, 82.50000, 304.00000, 22.80000, + 0.34940, 9.90000, 0.54400, 3.10250, 4.00000, 18.40000, 396.24000, 5.97200, 76.70000, 304.00000, 20.30000, + 2.63548, 9.90000, 0.54400, 2.51940, 4.00000, 18.40000, 350.45000, 4.97300, 37.80000, 304.00000, 16.10000, + 0.79041, 9.90000, 0.54400, 2.64030, 4.00000, 18.40000, 396.90000, 6.12200, 52.80000, 304.00000, 22.10000, + 0.26169, 9.90000, 0.54400, 2.83400, 4.00000, 18.40000, 396.30000, 6.02300, 90.40000, 304.00000, 19.40000, + 0.26938, 9.90000, 0.54400, 3.26280, 4.00000, 18.40000, 393.39000, 6.26600, 82.80000, 304.00000, 21.60000, + 0.36920, 9.90000, 0.54400, 3.60230, 4.00000, 18.40000, 395.69000, 6.56700, 87.30000, 304.00000, 23.80000, + 0.25356, 9.90000, 0.54400, 3.94500, 4.00000, 18.40000, 396.42000, 5.70500, 77.70000, 304.00000, 16.20000, + 0.31827, 9.90000, 0.54400, 3.99860, 4.00000, 18.40000, 390.70000, 5.91400, 83.20000, 304.00000, 17.80000, + 0.24522, 9.90000, 0.54400, 4.03170, 4.00000, 18.40000, 396.90000, 5.78200, 71.70000, 304.00000, 19.80000, + 0.40202, 9.90000, 0.54400, 3.53250, 4.00000, 18.40000, 395.21000, 6.38200, 67.20000, 304.00000, 23.10000, + 0.47547, 9.90000, 0.54400, 4.00190, 4.00000, 18.40000, 396.23000, 6.11300, 58.80000, 304.00000, 21.00000, + 0.16760, 7.38000, 0.49300, 4.54040, 5.00000, 19.60000, 396.90000, 6.42600, 52.30000, 287.00000, 23.80000, + 0.18159, 7.38000, 0.49300, 4.54040, 5.00000, 19.60000, 396.90000, 6.37600, 54.30000, 287.00000, 23.10000, + 0.35114, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 396.90000, 6.04100, 49.90000, 287.00000, 20.40000, + 0.28392, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 391.13000, 5.70800, 74.30000, 287.00000, 18.50000, + 0.34109, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 396.90000, 6.41500, 40.10000, 287.00000, 25.00000, + 0.19186, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 393.68000, 6.43100, 14.70000, 287.00000, 24.60000, + 0.30347, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 396.90000, 6.31200, 28.90000, 287.00000, 23.00000, + 0.24103, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 396.90000, 6.08300, 43.70000, 287.00000, 22.20000, + 0.06617, 3.24000, 0.46000, 5.21460, 4.00000, 16.90000, 382.44000, 5.86800, 25.80000, 430.00000, 19.30000, + 0.06724, 3.24000, 0.46000, 5.21460, 4.00000, 16.90000, 375.21000, 6.33300, 17.20000, 430.00000, 22.60000, + 0.04544, 3.24000, 0.46000, 5.87360, 4.00000, 16.90000, 368.57000, 6.14400, 32.20000, 430.00000, 19.80000, + 0.05023, 6.06000, 0.43790, 6.64070, 1.00000, 16.90000, 394.02000, 5.70600, 28.40000, 304.00000, 17.10000, + 0.03466, 6.06000, 0.43790, 6.64070, 1.00000, 16.90000, 362.25000, 6.03100, 23.30000, 304.00000, 19.40000, + 0.05083, 5.19000, 0.51500, 6.45840, 5.00000, 20.20000, 389.71000, 6.31600, 38.10000, 224.00000, 22.20000, + 0.03738, 5.19000, 0.51500, 6.45840, 5.00000, 20.20000, 389.40000, 6.31000, 38.50000, 224.00000, 20.70000, + 0.03961, 5.19000, 0.51500, 5.98530, 5.00000, 20.20000, 396.90000, 6.03700, 34.50000, 224.00000, 21.10000, + 0.03427, 5.19000, 0.51500, 5.23110, 5.00000, 20.20000, 396.90000, 5.86900, 46.30000, 224.00000, 19.50000, + 0.03041, 5.19000, 0.51500, 5.61500, 5.00000, 20.20000, 394.81000, 5.89500, 59.60000, 224.00000, 18.50000, + 0.03306, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.14000, 6.05900, 37.30000, 224.00000, 20.60000, + 0.05497, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.90000, 5.98500, 45.40000, 224.00000, 19.00000, + 0.06151, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.90000, 5.96800, 58.50000, 224.00000, 18.70000, + 0.01301, 1.52000, 0.44200, 7.03790, 1.00000, 15.50000, 394.74000, 7.24100, 49.30000, 284.00000, 32.70000, + 0.02498, 1.89000, 0.51800, 6.26690, 1.00000, 15.90000, 389.96000, 6.54000, 59.70000, 422.00000, 16.50000, + 0.02543, 3.78000, 0.48400, 5.73210, 5.00000, 17.60000, 396.90000, 6.69600, 56.40000, 370.00000, 23.90000, + 0.03049, 3.78000, 0.48400, 6.46540, 5.00000, 17.60000, 387.97000, 6.87400, 28.10000, 370.00000, 31.20000, + 0.03113, 4.39000, 0.44200, 8.01360, 3.00000, 18.80000, 385.64000, 6.01400, 48.50000, 352.00000, 17.50000, + 0.06162, 4.39000, 0.44200, 8.01360, 3.00000, 18.80000, 364.61000, 5.89800, 52.30000, 352.00000, 17.20000, + 0.01870, 4.15000, 0.42900, 8.53530, 4.00000, 17.90000, 392.43000, 6.51600, 27.70000, 351.00000, 23.10000, + 0.01501, 2.01000, 0.43500, 8.34400, 4.00000, 17.00000, 390.94000, 6.63500, 29.70000, 280.00000, 24.50000, + 0.02899, 1.25000, 0.42900, 8.79210, 1.00000, 19.70000, 389.85000, 6.93900, 34.50000, 335.00000, 26.60000, + 0.06211, 1.25000, 0.42900, 8.79210, 1.00000, 19.70000, 396.90000, 6.49000, 44.40000, 335.00000, 22.90000, + 0.07950, 1.69000, 0.41100, 10.71030, 4.00000, 18.30000, 370.78000, 6.57900, 35.90000, 411.00000, 24.10000, + 0.07244, 1.69000, 0.41100, 10.71030, 4.00000, 18.30000, 392.33000, 5.88400, 18.50000, 411.00000, 18.60000, + 0.01709, 2.02000, 0.41000, 12.12650, 5.00000, 17.00000, 384.46000, 6.72800, 36.10000, 187.00000, 30.10000, + 0.04301, 1.91000, 0.41300, 10.58570, 4.00000, 22.00000, 382.80000, 5.66300, 21.90000, 334.00000, 18.20000, + 0.10659, 1.91000, 0.41300, 10.58570, 4.00000, 22.00000, 376.04000, 5.93600, 19.50000, 334.00000, 20.60000, + 8.98296, 18.10000, 0.77000, 2.12220, 24.00000, 20.20000, 377.73000, 6.21200, 97.40000, 666.00000, 17.80000, + 3.84970, 18.10000, 0.77000, 2.50520, 24.00000, 20.20000, 391.34000, 6.39500, 91.00000, 666.00000, 21.70000, + 5.20177, 18.10000, 0.77000, 2.72270, 24.00000, 20.20000, 395.43000, 6.12700, 83.40000, 666.00000, 22.70000, + 4.26131, 18.10000, 0.77000, 2.50910, 24.00000, 20.20000, 390.74000, 6.11200, 81.30000, 666.00000, 22.60000, + 4.54192, 18.10000, 0.77000, 2.51820, 24.00000, 20.20000, 374.56000, 6.39800, 88.00000, 666.00000, 25.00000, + 3.83684, 18.10000, 0.77000, 2.29550, 24.00000, 20.20000, 350.65000, 6.25100, 91.10000, 666.00000, 19.90000, + 3.67822, 18.10000, 0.77000, 2.10360, 24.00000, 20.20000, 380.79000, 5.36200, 96.20000, 666.00000, 20.80000, + 4.22239, 18.10000, 0.77000, 1.90470, 24.00000, 20.20000, 353.04000, 5.80300, 89.00000, 666.00000, 16.80000, + 3.47428, 18.10000, 0.71800, 1.90470, 24.00000, 20.20000, 354.55000, 8.78000, 82.90000, 666.00000, 21.90000, + 4.55587, 18.10000, 0.71800, 1.61320, 24.00000, 20.20000, 354.70000, 3.56100, 87.90000, 666.00000, 27.50000, + 3.69695, 18.10000, 0.71800, 1.75230, 24.00000, 20.20000, 316.03000, 4.96300, 91.40000, 666.00000, 21.90000, + 13.52220, 18.10000, 0.63100, 1.51060, 24.00000, 20.20000, 131.42000, 3.86300, 100.00000, 666.00000, 23.10000, + 4.89822, 18.10000, 0.63100, 1.33250, 24.00000, 20.20000, 375.52000, 4.97000, 100.00000, 666.00000, 50.00000, + 5.66998, 18.10000, 0.63100, 1.35670, 24.00000, 20.20000, 375.33000, 6.68300, 96.80000, 666.00000, 50.00000, + 6.53876, 18.10000, 0.63100, 1.20240, 24.00000, 20.20000, 392.05000, 7.01600, 97.50000, 666.00000, 50.00000, + 9.23230, 18.10000, 0.63100, 1.16910, 24.00000, 20.20000, 366.15000, 6.21600, 100.00000, 666.00000, 50.00000, + 8.26725, 18.10000, 0.66800, 1.12960, 24.00000, 20.20000, 347.88000, 5.87500, 89.60000, 666.00000, 50.00000, + 11.10810, 18.10000, 0.66800, 1.17420, 24.00000, 20.20000, 396.90000, 4.90600, 100.00000, 666.00000, 13.80000, + 18.49820, 18.10000, 0.66800, 1.13700, 24.00000, 20.20000, 396.90000, 4.13800, 100.00000, 666.00000, 13.80000, + 19.60910, 18.10000, 0.67100, 1.31630, 24.00000, 20.20000, 396.90000, 7.31300, 97.90000, 666.00000, 15.00000, + 15.28800, 18.10000, 0.67100, 1.34490, 24.00000, 20.20000, 363.02000, 6.64900, 93.30000, 666.00000, 13.90000, + 9.82349, 18.10000, 0.67100, 1.35800, 24.00000, 20.20000, 396.90000, 6.79400, 98.80000, 666.00000, 13.30000, + 23.64820, 18.10000, 0.67100, 1.38610, 24.00000, 20.20000, 396.90000, 6.38000, 96.20000, 666.00000, 13.10000, + 17.86670, 18.10000, 0.67100, 1.38610, 24.00000, 20.20000, 393.74000, 6.22300, 100.00000, 666.00000, 10.20000, + 88.97620, 18.10000, 0.67100, 1.41650, 24.00000, 20.20000, 396.90000, 6.96800, 91.90000, 666.00000, 10.40000, + 15.87440, 18.10000, 0.67100, 1.51920, 24.00000, 20.20000, 396.90000, 6.54500, 99.10000, 666.00000, 10.90000, + 9.18702, 18.10000, 0.70000, 1.58040, 24.00000, 20.20000, 396.90000, 5.53600, 100.00000, 666.00000, 11.30000, + 7.99248, 18.10000, 0.70000, 1.53310, 24.00000, 20.20000, 396.90000, 5.52000, 100.00000, 666.00000, 12.30000, + 20.08490, 18.10000, 0.70000, 1.43950, 24.00000, 20.20000, 285.83000, 4.36800, 91.20000, 666.00000, 8.80000, + 16.81180, 18.10000, 0.70000, 1.42610, 24.00000, 20.20000, 396.90000, 5.27700, 98.10000, 666.00000, 7.20000, + 24.39380, 18.10000, 0.70000, 1.46720, 24.00000, 20.20000, 396.90000, 4.65200, 100.00000, 666.00000, 10.50000, + 22.59710, 18.10000, 0.70000, 1.51840, 24.00000, 20.20000, 396.90000, 5.00000, 89.50000, 666.00000, 7.40000, + 14.33370, 18.10000, 0.70000, 1.58950, 24.00000, 20.20000, 372.92000, 4.88000, 100.00000, 666.00000, 10.20000, + 8.15174, 18.10000, 0.70000, 1.72810, 24.00000, 20.20000, 396.90000, 5.39000, 98.90000, 666.00000, 11.50000, + 6.96215, 18.10000, 0.70000, 1.92650, 24.00000, 20.20000, 394.43000, 5.71300, 97.00000, 666.00000, 15.10000, + 5.29305, 18.10000, 0.70000, 2.16780, 24.00000, 20.20000, 378.38000, 6.05100, 82.50000, 666.00000, 23.20000, + 11.57790, 18.10000, 0.70000, 1.77000, 24.00000, 20.20000, 396.90000, 5.03600, 97.00000, 666.00000, 9.70000, + 8.64476, 18.10000, 0.69300, 1.79120, 24.00000, 20.20000, 396.90000, 6.19300, 92.60000, 666.00000, 13.80000, + 13.35980, 18.10000, 0.69300, 1.78210, 24.00000, 20.20000, 396.90000, 5.88700, 94.70000, 666.00000, 12.70000, + 8.71675, 18.10000, 0.69300, 1.72570, 24.00000, 20.20000, 391.98000, 6.47100, 98.80000, 666.00000, 13.10000, + 5.87205, 18.10000, 0.69300, 1.67680, 24.00000, 20.20000, 396.90000, 6.40500, 96.00000, 666.00000, 12.50000, + 7.67202, 18.10000, 0.69300, 1.63340, 24.00000, 20.20000, 393.10000, 5.74700, 98.90000, 666.00000, 8.50000, + 38.35180, 18.10000, 0.69300, 1.48960, 24.00000, 20.20000, 396.90000, 5.45300, 100.00000, 666.00000, 5.00000, + 9.91655, 18.10000, 0.69300, 1.50040, 24.00000, 20.20000, 338.16000, 5.85200, 77.80000, 666.00000, 6.30000, + 25.04610, 18.10000, 0.69300, 1.58880, 24.00000, 20.20000, 396.90000, 5.98700, 100.00000, 666.00000, 5.60000, + 14.23620, 18.10000, 0.69300, 1.57410, 24.00000, 20.20000, 396.90000, 6.34300, 100.00000, 666.00000, 7.20000, + 9.59571, 18.10000, 0.69300, 1.63900, 24.00000, 20.20000, 376.11000, 6.40400, 100.00000, 666.00000, 12.10000, + 24.80170, 18.10000, 0.69300, 1.70280, 24.00000, 20.20000, 396.90000, 5.34900, 96.00000, 666.00000, 8.30000, + 41.52920, 18.10000, 0.69300, 1.60740, 24.00000, 20.20000, 329.46000, 5.53100, 85.40000, 666.00000, 8.50000, + 67.92080, 18.10000, 0.69300, 1.42540, 24.00000, 20.20000, 384.97000, 5.68300, 100.00000, 666.00000, 5.00000, + 20.71620, 18.10000, 0.65900, 1.17810, 24.00000, 20.20000, 370.22000, 4.13800, 100.00000, 666.00000, 11.90000, + 11.95110, 18.10000, 0.65900, 1.28520, 24.00000, 20.20000, 332.09000, 5.60800, 100.00000, 666.00000, 27.90000, + 7.40389, 18.10000, 0.59700, 1.45470, 24.00000, 20.20000, 314.64000, 5.61700, 97.90000, 666.00000, 17.20000, + 14.43830, 18.10000, 0.59700, 1.46550, 24.00000, 20.20000, 179.36000, 6.85200, 100.00000, 666.00000, 27.50000, + 51.13580, 18.10000, 0.59700, 1.41300, 24.00000, 20.20000, 2.60000, 5.75700, 100.00000, 666.00000, 15.00000, + 14.05070, 18.10000, 0.59700, 1.52750, 24.00000, 20.20000, 35.05000, 6.65700, 100.00000, 666.00000, 17.20000, + 18.81100, 18.10000, 0.59700, 1.55390, 24.00000, 20.20000, 28.79000, 4.62800, 100.00000, 666.00000, 17.90000, + 28.65580, 18.10000, 0.59700, 1.58940, 24.00000, 20.20000, 210.97000, 5.15500, 100.00000, 666.00000, 16.30000, + 45.74610, 18.10000, 0.69300, 1.65820, 24.00000, 20.20000, 88.27000, 4.51900, 100.00000, 666.00000, 7.00000, + 18.08460, 18.10000, 0.67900, 1.83470, 24.00000, 20.20000, 27.25000, 6.43400, 100.00000, 666.00000, 7.20000, + 10.83420, 18.10000, 0.67900, 1.81950, 24.00000, 20.20000, 21.57000, 6.78200, 90.80000, 666.00000, 7.50000, + 25.94060, 18.10000, 0.67900, 1.64750, 24.00000, 20.20000, 127.36000, 5.30400, 89.10000, 666.00000, 10.40000, + 73.53410, 18.10000, 0.67900, 1.80260, 24.00000, 20.20000, 16.45000, 5.95700, 100.00000, 666.00000, 8.80000, + 11.81230, 18.10000, 0.71800, 1.79400, 24.00000, 20.20000, 48.45000, 6.82400, 76.50000, 666.00000, 8.40000, + 11.08740, 18.10000, 0.71800, 1.85890, 24.00000, 20.20000, 318.75000, 6.41100, 100.00000, 666.00000, 16.70000, + 7.02259, 18.10000, 0.71800, 1.87460, 24.00000, 20.20000, 319.98000, 6.00600, 95.30000, 666.00000, 14.20000, + 12.04820, 18.10000, 0.61400, 1.95120, 24.00000, 20.20000, 291.55000, 5.64800, 87.60000, 666.00000, 20.80000, + 7.05042, 18.10000, 0.61400, 2.02180, 24.00000, 20.20000, 2.52000, 6.10300, 85.10000, 666.00000, 13.40000, + 8.79212, 18.10000, 0.58400, 2.06350, 24.00000, 20.20000, 3.65000, 5.56500, 70.60000, 666.00000, 11.70000, + 15.86030, 18.10000, 0.67900, 1.90960, 24.00000, 20.20000, 7.68000, 5.89600, 95.40000, 666.00000, 8.30000, + 12.24720, 18.10000, 0.58400, 1.99760, 24.00000, 20.20000, 24.65000, 5.83700, 59.70000, 666.00000, 10.20000, + 37.66190, 18.10000, 0.67900, 1.86290, 24.00000, 20.20000, 18.82000, 6.20200, 78.70000, 666.00000, 10.90000, + 7.36711, 18.10000, 0.67900, 1.93560, 24.00000, 20.20000, 96.73000, 6.19300, 78.10000, 666.00000, 11.00000, + 9.33889, 18.10000, 0.67900, 1.96820, 24.00000, 20.20000, 60.72000, 6.38000, 95.60000, 666.00000, 9.50000, + 8.49213, 18.10000, 0.58400, 2.05270, 24.00000, 20.20000, 83.45000, 6.34800, 86.10000, 666.00000, 14.50000, + 10.06230, 18.10000, 0.58400, 2.08820, 24.00000, 20.20000, 81.33000, 6.83300, 94.30000, 666.00000, 14.10000, + 6.44405, 18.10000, 0.58400, 2.20040, 24.00000, 20.20000, 97.95000, 6.42500, 74.80000, 666.00000, 16.10000, + 5.58107, 18.10000, 0.71300, 2.31580, 24.00000, 20.20000, 100.19000, 6.43600, 87.90000, 666.00000, 14.30000, + 13.91340, 18.10000, 0.71300, 2.22220, 24.00000, 20.20000, 100.63000, 6.20800, 95.00000, 666.00000, 11.70000, + 11.16040, 18.10000, 0.74000, 2.12470, 24.00000, 20.20000, 109.85000, 6.62900, 94.60000, 666.00000, 13.40000, + 14.42080, 18.10000, 0.74000, 2.00260, 24.00000, 20.20000, 27.49000, 6.46100, 93.30000, 666.00000, 9.60000, + 15.17720, 18.10000, 0.74000, 1.91420, 24.00000, 20.20000, 9.32000, 6.15200, 100.00000, 666.00000, 8.70000, + 13.67810, 18.10000, 0.74000, 1.82060, 24.00000, 20.20000, 68.95000, 5.93500, 87.90000, 666.00000, 8.40000, + 9.39063, 18.10000, 0.74000, 1.81720, 24.00000, 20.20000, 396.90000, 5.62700, 93.90000, 666.00000, 12.80000, + 22.05110, 18.10000, 0.74000, 1.86620, 24.00000, 20.20000, 391.45000, 5.81800, 92.40000, 666.00000, 10.50000, + 9.72418, 18.10000, 0.74000, 2.06510, 24.00000, 20.20000, 385.96000, 6.40600, 97.20000, 666.00000, 17.10000, + 5.66637, 18.10000, 0.74000, 2.00480, 24.00000, 20.20000, 395.69000, 6.21900, 100.00000, 666.00000, 18.40000, + 9.96654, 18.10000, 0.74000, 1.97840, 24.00000, 20.20000, 386.73000, 6.48500, 100.00000, 666.00000, 15.40000, + 12.80230, 18.10000, 0.74000, 1.89560, 24.00000, 20.20000, 240.52000, 5.85400, 96.60000, 666.00000, 10.80000, + 10.67180, 18.10000, 0.74000, 1.98790, 24.00000, 20.20000, 43.06000, 6.45900, 94.80000, 666.00000, 11.80000, + 6.28807, 18.10000, 0.74000, 2.07200, 24.00000, 20.20000, 318.01000, 6.34100, 96.40000, 666.00000, 14.90000, + 9.92485, 18.10000, 0.74000, 2.19800, 24.00000, 20.20000, 388.52000, 6.25100, 96.60000, 666.00000, 12.60000, + 9.32909, 18.10000, 0.71300, 2.26160, 24.00000, 20.20000, 396.90000, 6.18500, 98.70000, 666.00000, 14.10000, + 7.52601, 18.10000, 0.71300, 2.18500, 24.00000, 20.20000, 304.21000, 6.41700, 98.30000, 666.00000, 13.00000, + 6.71772, 18.10000, 0.71300, 2.32360, 24.00000, 20.20000, 0.32000, 6.74900, 92.60000, 666.00000, 13.40000, + 5.44114, 18.10000, 0.71300, 2.35520, 24.00000, 20.20000, 355.29000, 6.65500, 98.20000, 666.00000, 15.20000, + 5.09017, 18.10000, 0.71300, 2.36820, 24.00000, 20.20000, 385.09000, 6.29700, 91.80000, 666.00000, 16.10000, + 8.24809, 18.10000, 0.71300, 2.45270, 24.00000, 20.20000, 375.87000, 7.39300, 99.30000, 666.00000, 17.80000, + 9.51363, 18.10000, 0.71300, 2.49610, 24.00000, 20.20000, 6.68000, 6.72800, 94.10000, 666.00000, 14.90000, + 4.75237, 18.10000, 0.71300, 2.43580, 24.00000, 20.20000, 50.92000, 6.52500, 86.50000, 666.00000, 14.10000, + 4.66883, 18.10000, 0.71300, 2.58060, 24.00000, 20.20000, 10.48000, 5.97600, 87.90000, 666.00000, 12.70000, + 8.20058, 18.10000, 0.71300, 2.77920, 24.00000, 20.20000, 3.50000, 5.93600, 80.30000, 666.00000, 13.50000, + 7.75223, 18.10000, 0.71300, 2.78310, 24.00000, 20.20000, 272.21000, 6.30100, 83.70000, 666.00000, 14.90000, + 6.80117, 18.10000, 0.71300, 2.71750, 24.00000, 20.20000, 396.90000, 6.08100, 84.40000, 666.00000, 20.00000, + 4.81213, 18.10000, 0.71300, 2.59750, 24.00000, 20.20000, 255.23000, 6.70100, 90.00000, 666.00000, 16.40000, + 3.69311, 18.10000, 0.71300, 2.56710, 24.00000, 20.20000, 391.43000, 6.37600, 88.40000, 666.00000, 17.70000, + 6.65492, 18.10000, 0.71300, 2.73440, 24.00000, 20.20000, 396.90000, 6.31700, 83.00000, 666.00000, 19.50000, + 5.82115, 18.10000, 0.71300, 2.80160, 24.00000, 20.20000, 393.82000, 6.51300, 89.90000, 666.00000, 20.20000, + 7.83932, 18.10000, 0.65500, 2.96340, 24.00000, 20.20000, 396.90000, 6.20900, 65.40000, 666.00000, 21.40000, + 3.16360, 18.10000, 0.65500, 3.06650, 24.00000, 20.20000, 334.40000, 5.75900, 48.20000, 666.00000, 19.90000, + 3.77498, 18.10000, 0.65500, 2.87150, 24.00000, 20.20000, 22.01000, 5.95200, 84.70000, 666.00000, 19.00000, + 4.42228, 18.10000, 0.58400, 2.54030, 24.00000, 20.20000, 331.29000, 6.00300, 94.50000, 666.00000, 19.10000, + 15.57570, 18.10000, 0.58000, 2.90840, 24.00000, 20.20000, 368.74000, 5.92600, 71.00000, 666.00000, 19.10000, + 13.07510, 18.10000, 0.58000, 2.82370, 24.00000, 20.20000, 396.90000, 5.71300, 56.70000, 666.00000, 20.10000, + 4.34879, 18.10000, 0.58000, 3.03340, 24.00000, 20.20000, 396.90000, 6.16700, 84.00000, 666.00000, 19.90000, + 4.03841, 18.10000, 0.53200, 3.09930, 24.00000, 20.20000, 395.33000, 6.22900, 90.70000, 666.00000, 19.60000, + 3.56868, 18.10000, 0.58000, 2.89650, 24.00000, 20.20000, 393.37000, 6.43700, 75.00000, 666.00000, 23.20000, + 4.64689, 18.10000, 0.61400, 2.53290, 24.00000, 20.20000, 374.68000, 6.98000, 67.60000, 666.00000, 29.80000, + 8.05579, 18.10000, 0.58400, 2.42980, 24.00000, 20.20000, 352.58000, 5.42700, 95.40000, 666.00000, 13.80000, + 6.39312, 18.10000, 0.58400, 2.20600, 24.00000, 20.20000, 302.76000, 6.16200, 97.40000, 666.00000, 13.30000, + 4.87141, 18.10000, 0.61400, 2.30530, 24.00000, 20.20000, 396.21000, 6.48400, 93.60000, 666.00000, 16.70000, + 15.02340, 18.10000, 0.61400, 2.10070, 24.00000, 20.20000, 349.48000, 5.30400, 97.30000, 666.00000, 12.00000, + 10.23300, 18.10000, 0.61400, 2.17050, 24.00000, 20.20000, 379.70000, 6.18500, 96.70000, 666.00000, 14.60000, + 14.33370, 18.10000, 0.61400, 1.95120, 24.00000, 20.20000, 383.32000, 6.22900, 88.00000, 666.00000, 21.40000, + 5.82401, 18.10000, 0.53200, 3.42420, 24.00000, 20.20000, 396.90000, 6.24200, 64.70000, 666.00000, 23.00000, + 5.70818, 18.10000, 0.53200, 3.33170, 24.00000, 20.20000, 393.07000, 6.75000, 74.90000, 666.00000, 23.70000, + 5.73116, 18.10000, 0.53200, 3.41060, 24.00000, 20.20000, 395.28000, 7.06100, 77.00000, 666.00000, 25.00000, + 2.81838, 18.10000, 0.53200, 4.09830, 24.00000, 20.20000, 392.92000, 5.76200, 40.30000, 666.00000, 21.80000, + 2.37857, 18.10000, 0.58300, 3.72400, 24.00000, 20.20000, 370.73000, 5.87100, 41.90000, 666.00000, 20.60000, + 3.67367, 18.10000, 0.58300, 3.99170, 24.00000, 20.20000, 388.62000, 6.31200, 51.90000, 666.00000, 21.20000, + 5.69175, 18.10000, 0.58300, 3.54590, 24.00000, 20.20000, 392.68000, 6.11400, 79.80000, 666.00000, 19.10000, + 4.83567, 18.10000, 0.58300, 3.15230, 24.00000, 20.20000, 388.22000, 5.90500, 53.20000, 666.00000, 20.60000, + 0.15086, 27.74000, 0.60900, 1.82090, 4.00000, 20.10000, 395.09000, 5.45400, 92.70000, 711.00000, 15.20000, + 0.18337, 27.74000, 0.60900, 1.75540, 4.00000, 20.10000, 344.05000, 5.41400, 98.30000, 711.00000, 7.00000, + 0.20746, 27.74000, 0.60900, 1.82260, 4.00000, 20.10000, 318.43000, 5.09300, 98.00000, 711.00000, 8.10000, + 0.10574, 27.74000, 0.60900, 1.86810, 4.00000, 20.10000, 390.11000, 5.98300, 98.80000, 711.00000, 13.60000, + 0.11132, 27.74000, 0.60900, 2.10990, 4.00000, 20.10000, 396.90000, 5.98300, 83.50000, 711.00000, 20.10000, + 0.17331, 9.69000, 0.58500, 2.38170, 6.00000, 19.20000, 396.90000, 5.70700, 54.00000, 391.00000, 21.80000, + 0.27957, 9.69000, 0.58500, 2.38170, 6.00000, 19.20000, 396.90000, 5.92600, 42.60000, 391.00000, 24.50000, + 0.17899, 9.69000, 0.58500, 2.79860, 6.00000, 19.20000, 393.29000, 5.67000, 28.80000, 391.00000, 23.10000, + 0.28960, 9.69000, 0.58500, 2.79860, 6.00000, 19.20000, 396.90000, 5.39000, 72.90000, 391.00000, 19.70000, + 0.26838, 9.69000, 0.58500, 2.89270, 6.00000, 19.20000, 396.90000, 5.79400, 70.60000, 391.00000, 18.30000, + 0.23912, 9.69000, 0.58500, 2.40910, 6.00000, 19.20000, 396.90000, 6.01900, 65.30000, 391.00000, 21.20000, + 0.17783, 9.69000, 0.58500, 2.39990, 6.00000, 19.20000, 395.77000, 5.56900, 73.50000, 391.00000, 17.50000, + 0.22438, 9.69000, 0.58500, 2.49820, 6.00000, 19.20000, 396.90000, 6.02700, 79.70000, 391.00000, 16.80000, + 0.06263, 11.93000, 0.57300, 2.47860, 1.00000, 21.00000, 391.99000, 6.59300, 69.10000, 273.00000, 22.40000, + 0.04527, 11.93000, 0.57300, 2.28750, 1.00000, 21.00000, 396.90000, 6.12000, 76.70000, 273.00000, 20.60000, + 0.06076, 11.93000, 0.57300, 2.16750, 1.00000, 21.00000, 396.90000, 6.97600, 91.00000, 273.00000, 23.90000, + 0.10959, 11.93000, 0.57300, 2.38890, 1.00000, 21.00000, 393.45000, 6.79400, 89.30000, 273.00000, 22.00000, + 0.04741, 11.93000, 0.57300, 2.50500, 1.00000, 21.00000, 396.90000, 6.03000, 80.80000, 273.00000, 11.90000, +}) diff --git a/vendor/gonum.org/v1/gonum/stat/car_data_test.go b/vendor/gonum.org/v1/gonum/stat/car_data_test.go new file mode 100644 index 00000000..a3cdabb2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/car_data_test.go @@ -0,0 +1,406 @@ +// Copyright ©2016 The gonum 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 stat_test + +import "gonum.org/v1/gonum/mat" + +// ASA Car Exposition Data of Ramos and Donoho (1983) +// http://lib.stat.cmu.edu/datasets/cars.desc +// http://lib.stat.cmu.edu/datasets/cars.data +// Columns are: displacement, horsepower, weight, acceleration, MPG. +var carData = mat.NewDense(392, 5, []float64{ + 307.0, 130.0, 3504.0, 12.0, 18.0, + 350.0, 165.0, 3693.0, 11.5, 15.0, + 318.0, 150.0, 3436.0, 11.0, 18.0, + 304.0, 150.0, 3433.0, 12.0, 16.0, + 302.0, 140.0, 3449.0, 10.5, 17.0, + 429.0, 198.0, 4341.0, 10.0, 15.0, + 454.0, 220.0, 4354.0, 9.0, 14.0, + 440.0, 215.0, 4312.0, 8.5, 14.0, + 455.0, 225.0, 4425.0, 10.0, 14.0, + 390.0, 190.0, 3850.0, 8.5, 15.0, + 383.0, 170.0, 3563.0, 10.0, 15.0, + 340.0, 160.0, 3609.0, 8.0, 14.0, + 400.0, 150.0, 3761.0, 9.5, 15.0, + 455.0, 225.0, 3086.0, 10.0, 14.0, + 113.0, 95.0, 2372.0, 15.0, 24.0, + 198.0, 95.0, 2833.0, 15.5, 22.0, + 199.0, 97.0, 2774.0, 15.5, 18.0, + 200.0, 85.0, 2587.0, 16.0, 21.0, + 97.0, 88.0, 2130.0, 14.5, 27.0, + 97.0, 46.0, 1835.0, 20.5, 26.0, + 110.0, 87.0, 2672.0, 17.5, 25.0, + 107.0, 90.0, 2430.0, 14.5, 24.0, + 104.0, 95.0, 2375.0, 17.5, 25.0, + 121.0, 113.0, 2234.0, 12.5, 26.0, + 199.0, 90.0, 2648.0, 15.0, 21.0, + 360.0, 215.0, 4615.0, 14.0, 10.0, + 307.0, 200.0, 4376.0, 15.0, 10.0, + 318.0, 210.0, 4382.0, 13.5, 11.0, + 304.0, 193.0, 4732.0, 18.5, 9.0, + 97.0, 88.0, 2130.0, 14.5, 27.0, + 140.0, 90.0, 2264.0, 15.5, 28.0, + 113.0, 95.0, 2228.0, 14.0, 25.0, + 232.0, 100.0, 2634.0, 13.0, 19.0, + 225.0, 105.0, 3439.0, 15.5, 16.0, + 250.0, 100.0, 3329.0, 15.5, 17.0, + 250.0, 88.0, 3302.0, 15.5, 19.0, + 232.0, 100.0, 3288.0, 15.5, 18.0, + 350.0, 165.0, 4209.0, 12.0, 14.0, + 400.0, 175.0, 4464.0, 11.5, 14.0, + 351.0, 153.0, 4154.0, 13.5, 14.0, + 318.0, 150.0, 4096.0, 13.0, 14.0, + 383.0, 180.0, 4955.0, 11.5, 12.0, + 400.0, 170.0, 4746.0, 12.0, 13.0, + 400.0, 175.0, 5140.0, 12.0, 13.0, + 258.0, 110.0, 2962.0, 13.5, 18.0, + 140.0, 72.0, 2408.0, 19.0, 22.0, + 250.0, 100.0, 3282.0, 15.0, 19.0, + 250.0, 88.0, 3139.0, 14.5, 18.0, + 122.0, 86.0, 2220.0, 14.0, 23.0, + 116.0, 90.0, 2123.0, 14.0, 28.0, + 79.0, 70.0, 2074.0, 19.5, 30.0, + 88.0, 76.0, 2065.0, 14.5, 30.0, + 71.0, 65.0, 1773.0, 19.0, 31.0, + 72.0, 69.0, 1613.0, 18.0, 35.0, + 97.0, 60.0, 1834.0, 19.0, 27.0, + 91.0, 70.0, 1955.0, 20.5, 26.0, + 113.0, 95.0, 2278.0, 15.5, 24.0, + 97.5, 80.0, 2126.0, 17.0, 25.0, + 97.0, 54.0, 2254.0, 23.5, 23.0, + 140.0, 90.0, 2408.0, 19.5, 20.0, + 122.0, 86.0, 2226.0, 16.5, 21.0, + 350.0, 165.0, 4274.0, 12.0, 13.0, + 400.0, 175.0, 4385.0, 12.0, 14.0, + 318.0, 150.0, 4135.0, 13.5, 15.0, + 351.0, 153.0, 4129.0, 13.0, 14.0, + 304.0, 150.0, 3672.0, 11.5, 17.0, + 429.0, 208.0, 4633.0, 11.0, 11.0, + 350.0, 155.0, 4502.0, 13.5, 13.0, + 350.0, 160.0, 4456.0, 13.5, 12.0, + 400.0, 190.0, 4422.0, 12.5, 13.0, + 70.0, 97.0, 2330.0, 13.5, 19.0, + 304.0, 150.0, 3892.0, 12.5, 15.0, + 307.0, 130.0, 4098.0, 14.0, 13.0, + 302.0, 140.0, 4294.0, 16.0, 13.0, + 318.0, 150.0, 4077.0, 14.0, 14.0, + 121.0, 112.0, 2933.0, 14.5, 18.0, + 121.0, 76.0, 2511.0, 18.0, 22.0, + 120.0, 87.0, 2979.0, 19.5, 21.0, + 96.0, 69.0, 2189.0, 18.0, 26.0, + 122.0, 86.0, 2395.0, 16.0, 22.0, + 97.0, 92.0, 2288.0, 17.0, 28.0, + 120.0, 97.0, 2506.0, 14.5, 23.0, + 98.0, 80.0, 2164.0, 15.0, 28.0, + 97.0, 88.0, 2100.0, 16.5, 27.0, + 350.0, 175.0, 4100.0, 13.0, 13.0, + 304.0, 150.0, 3672.0, 11.5, 14.0, + 350.0, 145.0, 3988.0, 13.0, 13.0, + 302.0, 137.0, 4042.0, 14.5, 14.0, + 318.0, 150.0, 3777.0, 12.5, 15.0, + 429.0, 198.0, 4952.0, 11.5, 12.0, + 400.0, 150.0, 4464.0, 12.0, 13.0, + 351.0, 158.0, 4363.0, 13.0, 13.0, + 318.0, 150.0, 4237.0, 14.5, 14.0, + 440.0, 215.0, 4735.0, 11.0, 13.0, + 455.0, 225.0, 4951.0, 11.0, 12.0, + 360.0, 175.0, 3821.0, 11.0, 13.0, + 225.0, 105.0, 3121.0, 16.5, 18.0, + 250.0, 100.0, 3278.0, 18.0, 16.0, + 232.0, 100.0, 2945.0, 16.0, 18.0, + 250.0, 88.0, 3021.0, 16.5, 18.0, + 198.0, 95.0, 2904.0, 16.0, 23.0, + 97.0, 46.0, 1950.0, 21.0, 26.0, + 400.0, 150.0, 4997.0, 14.0, 11.0, + 400.0, 167.0, 4906.0, 12.5, 12.0, + 360.0, 170.0, 4654.0, 13.0, 13.0, + 350.0, 180.0, 4499.0, 12.5, 12.0, + 232.0, 100.0, 2789.0, 15.0, 18.0, + 97.0, 88.0, 2279.0, 19.0, 20.0, + 140.0, 72.0, 2401.0, 19.5, 21.0, + 108.0, 94.0, 2379.0, 16.5, 22.0, + 70.0, 90.0, 2124.0, 13.5, 18.0, + 122.0, 85.0, 2310.0, 18.5, 19.0, + 155.0, 107.0, 2472.0, 14.0, 21.0, + 98.0, 90.0, 2265.0, 15.5, 26.0, + 350.0, 145.0, 4082.0, 13.0, 15.0, + 400.0, 230.0, 4278.0, 9.5, 16.0, + 68.0, 49.0, 1867.0, 19.5, 29.0, + 116.0, 75.0, 2158.0, 15.5, 24.0, + 114.0, 91.0, 2582.0, 14.0, 20.0, + 121.0, 112.0, 2868.0, 15.5, 19.0, + 318.0, 150.0, 3399.0, 11.0, 15.0, + 121.0, 110.0, 2660.0, 14.0, 24.0, + 156.0, 122.0, 2807.0, 13.5, 20.0, + 350.0, 180.0, 3664.0, 11.0, 11.0, + 198.0, 95.0, 3102.0, 16.5, 20.0, + 232.0, 100.0, 2901.0, 16.0, 19.0, + 250.0, 100.0, 3336.0, 17.0, 15.0, + 79.0, 67.0, 1950.0, 19.0, 31.0, + 122.0, 80.0, 2451.0, 16.5, 26.0, + 71.0, 65.0, 1836.0, 21.0, 32.0, + 140.0, 75.0, 2542.0, 17.0, 25.0, + 250.0, 100.0, 3781.0, 17.0, 16.0, + 258.0, 110.0, 3632.0, 18.0, 16.0, + 225.0, 105.0, 3613.0, 16.5, 18.0, + 302.0, 140.0, 4141.0, 14.0, 16.0, + 350.0, 150.0, 4699.0, 14.5, 13.0, + 318.0, 150.0, 4457.0, 13.5, 14.0, + 302.0, 140.0, 4638.0, 16.0, 14.0, + 304.0, 150.0, 4257.0, 15.5, 14.0, + 98.0, 83.0, 2219.0, 16.5, 29.0, + 79.0, 67.0, 1963.0, 15.5, 26.0, + 97.0, 78.0, 2300.0, 14.5, 26.0, + 76.0, 52.0, 1649.0, 16.5, 31.0, + 83.0, 61.0, 2003.0, 19.0, 32.0, + 90.0, 75.0, 2125.0, 14.5, 28.0, + 90.0, 75.0, 2108.0, 15.5, 24.0, + 116.0, 75.0, 2246.0, 14.0, 26.0, + 120.0, 97.0, 2489.0, 15.0, 24.0, + 108.0, 93.0, 2391.0, 15.5, 26.0, + 79.0, 67.0, 2000.0, 16.0, 31.0, + 225.0, 95.0, 3264.0, 16.0, 19.0, + 250.0, 105.0, 3459.0, 16.0, 18.0, + 250.0, 72.0, 3432.0, 21.0, 15.0, + 250.0, 72.0, 3158.0, 19.5, 15.0, + 400.0, 170.0, 4668.0, 11.5, 16.0, + 350.0, 145.0, 4440.0, 14.0, 15.0, + 318.0, 150.0, 4498.0, 14.5, 16.0, + 351.0, 148.0, 4657.0, 13.5, 14.0, + 231.0, 110.0, 3907.0, 21.0, 17.0, + 250.0, 105.0, 3897.0, 18.5, 16.0, + 258.0, 110.0, 3730.0, 19.0, 15.0, + 225.0, 95.0, 3785.0, 19.0, 18.0, + 231.0, 110.0, 3039.0, 15.0, 21.0, + 262.0, 110.0, 3221.0, 13.5, 20.0, + 302.0, 129.0, 3169.0, 12.0, 13.0, + 97.0, 75.0, 2171.0, 16.0, 29.0, + 140.0, 83.0, 2639.0, 17.0, 23.0, + 232.0, 100.0, 2914.0, 16.0, 20.0, + 140.0, 78.0, 2592.0, 18.5, 23.0, + 134.0, 96.0, 2702.0, 13.5, 24.0, + 90.0, 71.0, 2223.0, 16.5, 25.0, + 119.0, 97.0, 2545.0, 17.0, 24.0, + 171.0, 97.0, 2984.0, 14.5, 18.0, + 90.0, 70.0, 1937.0, 14.0, 29.0, + 232.0, 90.0, 3211.0, 17.0, 19.0, + 115.0, 95.0, 2694.0, 15.0, 23.0, + 120.0, 88.0, 2957.0, 17.0, 23.0, + 121.0, 98.0, 2945.0, 14.5, 22.0, + 121.0, 115.0, 2671.0, 13.5, 25.0, + 91.0, 53.0, 1795.0, 17.5, 33.0, + 107.0, 86.0, 2464.0, 15.5, 28.0, + 116.0, 81.0, 2220.0, 16.9, 25.0, + 140.0, 92.0, 2572.0, 14.9, 25.0, + 98.0, 79.0, 2255.0, 17.7, 26.0, + 101.0, 83.0, 2202.0, 15.3, 27.0, + 305.0, 140.0, 4215.0, 13.0, 17.5, + 318.0, 150.0, 4190.0, 13.0, 16.0, + 304.0, 120.0, 3962.0, 13.9, 15.5, + 351.0, 152.0, 4215.0, 12.8, 14.5, + 225.0, 100.0, 3233.0, 15.4, 22.0, + 250.0, 105.0, 3353.0, 14.5, 22.0, + 200.0, 81.0, 3012.0, 17.6, 24.0, + 232.0, 90.0, 3085.0, 17.6, 22.5, + 85.0, 52.0, 2035.0, 22.2, 29.0, + 98.0, 60.0, 2164.0, 22.1, 24.5, + 90.0, 70.0, 1937.0, 14.2, 29.0, + 91.0, 53.0, 1795.0, 17.4, 33.0, + 225.0, 100.0, 3651.0, 17.7, 20.0, + 250.0, 78.0, 3574.0, 21.0, 18.0, + 250.0, 110.0, 3645.0, 16.2, 18.5, + 258.0, 95.0, 3193.0, 17.8, 17.5, + 97.0, 71.0, 1825.0, 12.2, 29.5, + 85.0, 70.0, 1990.0, 17.0, 32.0, + 97.0, 75.0, 2155.0, 16.4, 28.0, + 140.0, 72.0, 2565.0, 13.6, 26.5, + 130.0, 102.0, 3150.0, 15.7, 20.0, + 318.0, 150.0, 3940.0, 13.2, 13.0, + 120.0, 88.0, 3270.0, 21.9, 19.0, + 156.0, 108.0, 2930.0, 15.5, 19.0, + 168.0, 120.0, 3820.0, 16.7, 16.5, + 350.0, 180.0, 4380.0, 12.1, 16.5, + 350.0, 145.0, 4055.0, 12.0, 13.0, + 302.0, 130.0, 3870.0, 15.0, 13.0, + 318.0, 150.0, 3755.0, 14.0, 13.0, + 98.0, 68.0, 2045.0, 18.5, 31.5, + 111.0, 80.0, 2155.0, 14.8, 30.0, + 79.0, 58.0, 1825.0, 18.6, 36.0, + 122.0, 96.0, 2300.0, 15.5, 25.5, + 85.0, 70.0, 1945.0, 16.8, 33.5, + 305.0, 145.0, 3880.0, 12.5, 17.5, + 260.0, 110.0, 4060.0, 19.0, 17.0, + 318.0, 145.0, 4140.0, 13.7, 15.5, + 302.0, 130.0, 4295.0, 14.9, 15.0, + 250.0, 110.0, 3520.0, 16.4, 17.5, + 231.0, 105.0, 3425.0, 16.9, 20.5, + 225.0, 100.0, 3630.0, 17.7, 19.0, + 250.0, 98.0, 3525.0, 19.0, 18.5, + 400.0, 180.0, 4220.0, 11.1, 16.0, + 350.0, 170.0, 4165.0, 11.4, 15.5, + 400.0, 190.0, 4325.0, 12.2, 15.5, + 351.0, 149.0, 4335.0, 14.5, 16.0, + 97.0, 78.0, 1940.0, 14.5, 29.0, + 151.0, 88.0, 2740.0, 16.0, 24.5, + 97.0, 75.0, 2265.0, 18.2, 26.0, + 140.0, 89.0, 2755.0, 15.8, 25.5, + 98.0, 63.0, 2051.0, 17.0, 30.5, + 98.0, 83.0, 2075.0, 15.9, 33.5, + 97.0, 67.0, 1985.0, 16.4, 30.0, + 97.0, 78.0, 2190.0, 14.1, 30.5, + 146.0, 97.0, 2815.0, 14.5, 22.0, + 121.0, 110.0, 2600.0, 12.8, 21.5, + 80.0, 110.0, 2720.0, 13.5, 21.5, + 90.0, 48.0, 1985.0, 21.5, 43.1, + 98.0, 66.0, 1800.0, 14.4, 36.1, + 78.0, 52.0, 1985.0, 19.4, 32.8, + 85.0, 70.0, 2070.0, 18.6, 39.4, + 91.0, 60.0, 1800.0, 16.4, 36.1, + 260.0, 110.0, 3365.0, 15.5, 19.9, + 318.0, 140.0, 3735.0, 13.2, 19.4, + 302.0, 139.0, 3570.0, 12.8, 20.2, + 231.0, 105.0, 3535.0, 19.2, 19.2, + 200.0, 95.0, 3155.0, 18.2, 20.5, + 200.0, 85.0, 2965.0, 15.8, 20.2, + 140.0, 88.0, 2720.0, 15.4, 25.1, + 225.0, 100.0, 3430.0, 17.2, 20.5, + 232.0, 90.0, 3210.0, 17.2, 19.4, + 231.0, 105.0, 3380.0, 15.8, 20.6, + 200.0, 85.0, 3070.0, 16.7, 20.8, + 225.0, 110.0, 3620.0, 18.7, 18.6, + 258.0, 120.0, 3410.0, 15.1, 18.1, + 305.0, 145.0, 3425.0, 13.2, 19.2, + 231.0, 165.0, 3445.0, 13.4, 17.7, + 302.0, 139.0, 3205.0, 11.2, 18.1, + 318.0, 140.0, 4080.0, 13.7, 17.5, + 98.0, 68.0, 2155.0, 16.5, 30.0, + 134.0, 95.0, 2560.0, 14.2, 27.5, + 119.0, 97.0, 2300.0, 14.7, 27.2, + 105.0, 75.0, 2230.0, 14.5, 30.9, + 134.0, 95.0, 2515.0, 14.8, 21.1, + 156.0, 105.0, 2745.0, 16.7, 23.2, + 151.0, 85.0, 2855.0, 17.6, 23.8, + 119.0, 97.0, 2405.0, 14.9, 23.9, + 131.0, 103.0, 2830.0, 15.9, 20.3, + 163.0, 125.0, 3140.0, 13.6, 17.0, + 121.0, 115.0, 2795.0, 15.7, 21.6, + 163.0, 133.0, 3410.0, 15.8, 16.2, + 89.0, 71.0, 1990.0, 14.9, 31.5, + 98.0, 68.0, 2135.0, 16.6, 29.5, + 231.0, 115.0, 3245.0, 15.4, 21.5, + 200.0, 85.0, 2990.0, 18.2, 19.8, + 140.0, 88.0, 2890.0, 17.3, 22.3, + 232.0, 90.0, 3265.0, 18.2, 20.2, + 225.0, 110.0, 3360.0, 16.6, 20.6, + 305.0, 130.0, 3840.0, 15.4, 17.0, + 302.0, 129.0, 3725.0, 13.4, 17.6, + 351.0, 138.0, 3955.0, 13.2, 16.5, + 318.0, 135.0, 3830.0, 15.2, 18.2, + 350.0, 155.0, 4360.0, 14.9, 16.9, + 351.0, 142.0, 4054.0, 14.3, 15.5, + 267.0, 125.0, 3605.0, 15.0, 19.2, + 360.0, 150.0, 3940.0, 13.0, 18.5, + 89.0, 71.0, 1925.0, 14.0, 31.9, + 86.0, 65.0, 1975.0, 15.2, 34.1, + 98.0, 80.0, 1915.0, 14.4, 35.7, + 121.0, 80.0, 2670.0, 15.0, 27.4, + 183.0, 77.0, 3530.0, 20.1, 25.4, + 350.0, 125.0, 3900.0, 17.4, 23.0, + 141.0, 71.0, 3190.0, 24.8, 27.2, + 260.0, 90.0, 3420.0, 22.2, 23.9, + 105.0, 70.0, 2200.0, 13.2, 34.2, + 105.0, 70.0, 2150.0, 14.9, 34.5, + 85.0, 65.0, 2020.0, 19.2, 31.8, + 91.0, 69.0, 2130.0, 14.7, 37.3, + 151.0, 90.0, 2670.0, 16.0, 28.4, + 173.0, 115.0, 2595.0, 11.3, 28.8, + 173.0, 115.0, 2700.0, 12.9, 26.8, + 151.0, 90.0, 2556.0, 13.2, 33.5, + 98.0, 76.0, 2144.0, 14.7, 41.5, + 89.0, 60.0, 1968.0, 18.8, 38.1, + 98.0, 70.0, 2120.0, 15.5, 32.1, + 86.0, 65.0, 2019.0, 16.4, 37.2, + 151.0, 90.0, 2678.0, 16.5, 28.0, + 140.0, 88.0, 2870.0, 18.1, 26.4, + 151.0, 90.0, 3003.0, 20.1, 24.3, + 225.0, 90.0, 3381.0, 18.7, 19.1, + 97.0, 78.0, 2188.0, 15.8, 34.3, + 134.0, 90.0, 2711.0, 15.5, 29.8, + 120.0, 75.0, 2542.0, 17.5, 31.3, + 119.0, 92.0, 2434.0, 15.0, 37.0, + 108.0, 75.0, 2265.0, 15.2, 32.2, + 86.0, 65.0, 2110.0, 17.9, 46.6, + 156.0, 105.0, 2800.0, 14.4, 27.9, + 85.0, 65.0, 2110.0, 19.2, 40.8, + 90.0, 48.0, 2085.0, 21.7, 44.3, + 90.0, 48.0, 2335.0, 23.7, 43.4, + 121.0, 67.0, 2950.0, 19.9, 36.4, + 146.0, 67.0, 3250.0, 21.8, 30.0, + 91.0, 67.0, 1850.0, 13.8, 44.6, + 97.0, 67.0, 2145.0, 18.0, 33.8, + 89.0, 62.0, 1845.0, 15.3, 29.8, + 168.0, 132.0, 2910.0, 11.4, 32.7, + 70.0, 100.0, 2420.0, 12.5, 23.7, + 122.0, 88.0, 2500.0, 15.1, 35.0, + 107.0, 72.0, 2290.0, 17.0, 32.4, + 135.0, 84.0, 2490.0, 15.7, 27.2, + 151.0, 84.0, 2635.0, 16.4, 26.6, + 156.0, 92.0, 2620.0, 14.4, 25.8, + 173.0, 110.0, 2725.0, 12.6, 23.5, + 135.0, 84.0, 2385.0, 12.9, 30.0, + 79.0, 58.0, 1755.0, 16.9, 39.1, + 86.0, 64.0, 1875.0, 16.4, 39.0, + 81.0, 60.0, 1760.0, 16.1, 35.1, + 97.0, 67.0, 2065.0, 17.8, 32.3, + 85.0, 65.0, 1975.0, 19.4, 37.0, + 89.0, 62.0, 2050.0, 17.3, 37.7, + 91.0, 68.0, 1985.0, 16.0, 34.1, + 105.0, 63.0, 2215.0, 14.9, 34.7, + 98.0, 65.0, 2045.0, 16.2, 34.4, + 98.0, 65.0, 2380.0, 20.7, 29.9, + 105.0, 74.0, 2190.0, 14.2, 33.0, + 107.0, 75.0, 2210.0, 14.4, 33.7, + 108.0, 75.0, 2350.0, 16.8, 32.4, + 119.0, 100.0, 2615.0, 14.8, 32.9, + 120.0, 74.0, 2635.0, 18.3, 31.6, + 141.0, 80.0, 3230.0, 20.4, 28.1, + 145.0, 76.0, 3160.0, 19.6, 30.7, + 168.0, 116.0, 2900.0, 12.6, 25.4, + 146.0, 120.0, 2930.0, 13.8, 24.2, + 231.0, 110.0, 3415.0, 15.8, 22.4, + 350.0, 105.0, 3725.0, 19.0, 26.6, + 200.0, 88.0, 3060.0, 17.1, 20.2, + 225.0, 85.0, 3465.0, 16.6, 17.6, + 112.0, 88.0, 2605.0, 19.6, 28.0, + 112.0, 88.0, 2640.0, 18.6, 27.0, + 112.0, 88.0, 2395.0, 18.0, 34.0, + 112.0, 85.0, 2575.0, 16.2, 31.0, + 135.0, 84.0, 2525.0, 16.0, 29.0, + 151.0, 90.0, 2735.0, 18.0, 27.0, + 140.0, 92.0, 2865.0, 16.4, 24.0, + 105.0, 74.0, 1980.0, 15.3, 36.0, + 91.0, 68.0, 2025.0, 18.2, 37.0, + 91.0, 68.0, 1970.0, 17.6, 31.0, + 105.0, 63.0, 2125.0, 14.7, 38.0, + 98.0, 70.0, 2125.0, 17.3, 36.0, + 120.0, 88.0, 2160.0, 14.5, 36.0, + 107.0, 75.0, 2205.0, 14.5, 36.0, + 108.0, 70.0, 2245.0, 16.9, 34.0, + 91.0, 67.0, 1965.0, 15.0, 38.0, + 91.0, 67.0, 1965.0, 15.7, 32.0, + 91.0, 67.0, 1995.0, 16.2, 38.0, + 181.0, 110.0, 2945.0, 16.4, 25.0, + 262.0, 85.0, 3015.0, 17.0, 38.0, + 156.0, 92.0, 2585.0, 14.5, 26.0, + 232.0, 112.0, 2835.0, 14.7, 22.0, + 144.0, 96.0, 2665.0, 13.9, 32.0, + 135.0, 84.0, 2370.0, 13.0, 36.0, + 151.0, 90.0, 2950.0, 17.3, 27.0, + 140.0, 86.0, 2790.0, 15.6, 27.0, + 97.0, 52.0, 2130.0, 24.6, 44.0, + 135.0, 84.0, 2295.0, 11.6, 32.0, + 120.0, 79.0, 2625.0, 18.6, 28.0, + 119.0, 82.0, 2720.0, 19.4, 31.0, +}) diff --git a/vendor/gonum.org/v1/gonum/stat/cca_example_test.go b/vendor/gonum.org/v1/gonum/stat/cca_example_test.go new file mode 100644 index 00000000..f053e5ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/cca_example_test.go @@ -0,0 +1,165 @@ +// Copyright ©2016 The gonum 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 stat_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +// symView is a helper for getting a View of a SymDense. +type symView struct { + sym *mat.SymDense + + i, j, r, c int +} + +func (s symView) Dims() (r, c int) { return s.r, s.c } + +func (s symView) At(i, j int) float64 { + if i < 0 || s.r <= i { + panic("i out of bounds") + } + if j < 0 || s.c <= j { + panic("j out of bounds") + } + return s.sym.At(s.i+i, s.j+j) +} + +func (s symView) T() mat.Matrix { return mat.Transpose{s} } + +func ExampleCC() { + // This example is directly analogous to Example 3.5 on page 87 of + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + + // bostonData is the Boston Housing Data of Harrison and Rubinfeld (1978) + n, _ := bostonData.Dims() + var xd, yd = 7, 4 + // The variables (columns) of bostonData can be partitioned into two sets: + // those that deal with environmental/social variables (xdata), and those + // that contain information regarding the individual (ydata). Because the + // variables can be naturally partitioned in this way, these data are + // appropriate for canonical correlation analysis. The columns (variables) + // of xdata are, in order: + // per capita crime rate by town, + // proportion of non-retail business acres per town, + // nitric oxide concentration (parts per 10 million), + // weighted distances to Boston employment centres, + // index of accessibility to radial highways, + // pupil-teacher ratio by town, and + // proportion of blacks by town. + xdata := bostonData.Slice(0, n, 0, xd) + + // The columns (variables) of ydata are, in order: + // average number of rooms per dwelling, + // proportion of owner-occupied units built prior to 1940, + // full-value property-tax rate per $10000, and + // median value of owner-occupied homes in $1000s. + ydata := bostonData.Slice(0, n, xd, xd+yd) + + // For comparison, calculate the correlation matrix for the original data. + var cor mat.SymDense + stat.CorrelationMatrix(&cor, bostonData, nil) + + // Extract just those correlations that are between xdata and ydata. + var corRaw = symView{sym: &cor, i: 0, j: xd, r: xd, c: yd} + + // Note that the strongest correlation between individual variables is 0.91 + // between the 5th variable of xdata (index of accessibility to radial + // highways) and the 3rd variable of ydata (full-value property-tax rate per + // $10000). + fmt.Printf("corRaw = %.4f", mat.Formatted(corRaw, mat.Prefix(" "))) + + // Calculate the canonical correlations. + var cc stat.CC + err := cc.CanonicalCorrelations(xdata, ydata, nil) + if err != nil { + log.Fatal(err) + } + + // Unpack cc. + ccors := cc.CorrsTo(nil) + pVecs := cc.LeftTo(nil, true) + qVecs := cc.RightTo(nil, true) + phiVs := cc.LeftTo(nil, false) + psiVs := cc.RightTo(nil, false) + + // Canonical Correlation Matrix, or the correlations between the sphered + // data. + var corSph mat.Dense + corSph.Clone(pVecs) + col := make([]float64, xd) + for j := 0; j < yd; j++ { + mat.Col(col, j, &corSph) + floats.Scale(ccors[j], col) + corSph.SetCol(j, col) + } + corSph.Product(&corSph, qVecs.T()) + fmt.Printf("\n\ncorSph = %.4f", mat.Formatted(&corSph, mat.Prefix(" "))) + + // Canonical Correlations. Note that the first canonical correlation is + // 0.95, stronger than the greatest correlation in the original data, and + // much stronger than the greatest correlation in the sphered data. + fmt.Printf("\n\nccors = %.4f", ccors) + + // Left and right eigenvectors of the canonical correlation matrix. + fmt.Printf("\n\npVecs = %.4f", mat.Formatted(pVecs, mat.Prefix(" "))) + fmt.Printf("\n\nqVecs = %.4f", mat.Formatted(qVecs, mat.Prefix(" "))) + + // Canonical Correlation Transforms. These can be useful as they represent + // the canonical variables as linear combinations of the original variables. + fmt.Printf("\n\nphiVs = %.4f", mat.Formatted(phiVs, mat.Prefix(" "))) + fmt.Printf("\n\npsiVs = %.4f", mat.Formatted(psiVs, mat.Prefix(" "))) + + // Output: + // corRaw = ⎡-0.2192 0.3527 0.5828 -0.3883⎤ + // ⎢-0.3917 0.6448 0.7208 -0.4837⎥ + // ⎢-0.3022 0.7315 0.6680 -0.4273⎥ + // ⎢ 0.2052 -0.7479 -0.5344 0.2499⎥ + // ⎢-0.2098 0.4560 0.9102 -0.3816⎥ + // ⎢-0.3555 0.2615 0.4609 -0.5078⎥ + // ⎣ 0.1281 -0.2735 -0.4418 0.3335⎦ + // + // corSph = ⎡ 0.0118 0.0525 0.2300 -0.1363⎤ + // ⎢-0.1810 0.3213 0.3814 -0.1412⎥ + // ⎢ 0.0166 0.2241 0.0104 -0.2235⎥ + // ⎢ 0.0346 -0.5481 -0.0034 -0.1994⎥ + // ⎢ 0.0303 -0.0956 0.7152 0.2039⎥ + // ⎢-0.0298 -0.0022 0.0739 -0.3703⎥ + // ⎣-0.1226 -0.0746 -0.3899 0.1541⎦ + // + // ccors = [0.9451 0.6787 0.5714 0.2010] + // + // pVecs = ⎡-0.2574 0.0158 0.2122 -0.0946⎤ + // ⎢-0.4837 0.3837 0.1474 0.6597⎥ + // ⎢-0.0801 0.3494 0.3287 -0.2862⎥ + // ⎢ 0.1278 -0.7337 0.4851 0.2248⎥ + // ⎢-0.6969 -0.4342 -0.3603 0.0291⎥ + // ⎢-0.0991 0.0503 0.6384 0.1022⎥ + // ⎣ 0.4260 0.0323 -0.2290 0.6419⎦ + // + // qVecs = ⎡ 0.0182 -0.1583 -0.0067 -0.9872⎤ + // ⎢-0.2348 0.9483 -0.1462 -0.1554⎥ + // ⎢-0.9701 -0.2406 -0.0252 0.0209⎥ + // ⎣ 0.0593 -0.1330 -0.9889 0.0291⎦ + // + // phiVs = ⎡-0.0027 0.0093 0.0490 -0.0155⎤ + // ⎢-0.0429 -0.0242 0.0361 0.1839⎥ + // ⎢-1.2248 5.6031 5.8094 -4.7927⎥ + // ⎢-0.0044 -0.3424 0.4470 0.1150⎥ + // ⎢-0.0742 -0.1193 -0.1116 0.0022⎥ + // ⎢-0.0233 0.1046 0.3853 -0.0161⎥ + // ⎣ 0.0001 0.0005 -0.0030 0.0082⎦ + // + // psiVs = ⎡ 0.0302 -0.3002 0.0878 -1.9583⎤ + // ⎢-0.0065 0.0392 -0.0118 -0.0061⎥ + // ⎢-0.0052 -0.0046 -0.0023 0.0008⎥ + // ⎣ 0.0020 0.0037 -0.1293 0.1038⎦ +} diff --git a/vendor/gonum.org/v1/gonum/stat/cca_test.go b/vendor/gonum.org/v1/gonum/stat/cca_test.go new file mode 100644 index 00000000..117ae5f2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/cca_test.go @@ -0,0 +1,191 @@ +// Copyright ©2016 The gonum 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 stat_test + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +func TestCanonicalCorrelations(t *testing.T) { +tests: + for i, test := range []struct { + xdata mat.Matrix + ydata mat.Matrix + weights []float64 + wantCorrs []float64 + wantpVecs *mat.Dense + wantqVecs *mat.Dense + wantphiVs *mat.Dense + wantpsiVs *mat.Dense + epsilon float64 + }{ + // Test results verified using R. + { // Truncated iris data, Sepal vs Petal measurements. + xdata: mat.NewDense(10, 2, []float64{ + 5.1, 3.5, + 4.9, 3.0, + 4.7, 3.2, + 4.6, 3.1, + 5.0, 3.6, + 5.4, 3.9, + 4.6, 3.4, + 5.0, 3.4, + 4.4, 2.9, + 4.9, 3.1, + }), + ydata: mat.NewDense(10, 2, []float64{ + 1.4, 0.2, + 1.4, 0.2, + 1.3, 0.2, + 1.5, 0.2, + 1.4, 0.2, + 1.7, 0.4, + 1.4, 0.3, + 1.5, 0.2, + 1.4, 0.2, + 1.5, 0.1, + }), + wantCorrs: []float64{0.7250624174504773, 0.5547679185730191}, + wantpVecs: mat.NewDense(2, 2, []float64{ + 0.0765914610875867, 0.9970625597666721, + 0.9970625597666721, -0.0765914610875868, + }), + wantqVecs: mat.NewDense(2, 2, []float64{ + 0.3075184850910837, 0.9515421069649439, + 0.9515421069649439, -0.3075184850910837, + }), + wantphiVs: mat.NewDense(2, 2, []float64{ + -1.9794877596804641, 5.2016325219025124, + 4.5211829944066553, -2.7263663170835697, + }), + wantpsiVs: mat.NewDense(2, 2, []float64{ + -0.0613084818030103, 10.8514169865438941, + 12.7209032660734298, -7.6793888180353775, + }), + epsilon: 1e-12, + }, + // Test results compared to those results presented in examples by + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + { // ASA Car Exposition Data of Ramos and Donoho (1983) + // Displacement, Horsepower, Weight + xdata: carData.Slice(0, 392, 0, 3), + // Acceleration, MPG + ydata: carData.Slice(0, 392, 3, 5), + wantCorrs: []float64{0.8782187384352336, 0.6328187219216761}, + wantpVecs: mat.NewDense(3, 2, []float64{ + 0.3218296374829181, 0.3947540257657075, + 0.4162807660635797, 0.7573719053303306, + 0.8503740401982725, -0.5201509936144236, + }), + wantqVecs: mat.NewDense(2, 2, []float64{ + -0.5161984172278830, -0.8564690269072364, + -0.8564690269072364, 0.5161984172278830, + }), + wantphiVs: mat.NewDense(3, 2, []float64{ + 0.0025033152994308, 0.0047795464118615, + 0.0201923608080173, 0.0409150208725958, + -0.0000247374128745, -0.0026766435161875, + }), + wantpsiVs: mat.NewDense(2, 2, []float64{ + -0.1666196759760772, -0.3637393866139658, + -0.0915512109649727, 0.1077863777929168, + }), + epsilon: 1e-12, + }, + // Test results compared to those results presented in examples by + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + { // Boston Housing Data of Harrison and Rubinfeld (1978) + // Per capita crime rate by town, + // Proportion of non-retail business acres per town, + // Nitric oxide concentration (parts per 10 million), + // Weighted distances to Boston employment centres, + // Index of accessibility to radial highways, + // Pupil-teacher ratio by town, Proportion of blacks by town + xdata: bostonData.Slice(0, 506, 0, 7), + // Average number of rooms per dwelling, + // Proportion of owner-occupied units built prior to 1940, + // Full-value property-tax rate per $10000, + // Median value of owner-occupied homes in $1000s + ydata: bostonData.Slice(0, 506, 7, 11), + wantCorrs: []float64{0.9451239443886021, 0.6786622733370654, 0.5714338361583764, 0.2009739704710440}, + wantpVecs: mat.NewDense(7, 4, []float64{ + -0.2574391924541903, 0.0158477516621194, 0.2122169934631024, -0.0945733803894706, + -0.4836594430018478, 0.3837101908138468, 0.1474448317415911, 0.6597324886718275, + -0.0800776365873296, 0.3493556742809252, 0.3287336458109373, -0.2862040444334655, + 0.1277586360386374, -0.7337427663667596, 0.4851134819037011, 0.2247964865970192, + -0.6969432006136684, -0.4341748776002893, -0.3602872887636357, 0.0290661608626292, + -0.0990903250057199, 0.0503411215453873, 0.6384330631742202, 0.1022367136218303, + 0.4260459963765036, 0.0323334351308141, -0.2289527516030810, 0.6419232947608805, + }), + wantqVecs: mat.NewDense(4, 4, []float64{ + 0.0181660502363264, -0.1583489460479038, -0.0066723577642883, -0.9871935400650649, + -0.2347699045986119, 0.9483314614936594, -0.1462420505631345, -0.1554470767919033, + -0.9700704038477141, -0.2406071741000039, -0.0251838984227037, 0.0209134074358349, + 0.0593000682318482, -0.1330460003097728, -0.9889057151969489, 0.0291161494720761, + }), + wantphiVs: mat.NewDense(7, 4, []float64{ + -0.0027462234108197, 0.0093444513500898, 0.0489643932714296, -0.0154967189805819, + -0.0428564455279537, -0.0241708702119420, 0.0360723472093996, 0.1838983230588095, + -1.2248435648802380, 5.6030921364723980, 5.8094144583797025, -4.7926812190419676, + -0.0043684825094649, -0.3424101164977618, 0.4469961215717917, 0.1150161814353696, + -0.0741534069521954, -0.1193135794923700, -0.1115518305471460, 0.0021638758323088, + -0.0233270323101624, 0.1046330818178399, 0.3853045975077387, -0.0160927870102877, + 0.0001293051387859, 0.0004540746921446, -0.0030296315865440, 0.0081895477974654, + }), + wantpsiVs: mat.NewDense(4, 4, []float64{ + 0.0301593362017375, -0.3002219289647127, 0.0878217377593682, -1.9583226531517062, + -0.0065483104073892, 0.0392212086716247, -0.0117570776209991, -0.0061113064481860, + -0.0052075523350125, -0.0045770200452960, -0.0022762313289592, 0.0008441873006821, + 0.0020111735096327, 0.0037352799829930, -0.1292578071621794, 0.1037709056329765, + }), + epsilon: 1e-12, + }, + } { + var cc stat.CC + var corrs []float64 + var pVecs, qVecs *mat.Dense + var phiVs, psiVs *mat.Dense + for j := 0; j < 2; j++ { + err := cc.CanonicalCorrelations(test.xdata, test.ydata, test.weights) + if err != nil { + t.Errorf("%d use %d: unexpected error: %v", i, j, err) + continue tests + } + + corrs = cc.CorrsTo(corrs) + pVecs = cc.LeftTo(pVecs, true) + qVecs = cc.RightTo(qVecs, true) + phiVs = cc.LeftTo(phiVs, false) + psiVs = cc.RightTo(psiVs, false) + + if !floats.EqualApprox(corrs, test.wantCorrs, test.epsilon) { + t.Errorf("%d use %d: unexpected variance result got:%v, want:%v", + i, j, corrs, test.wantCorrs) + } + if !mat.EqualApprox(pVecs, test.wantpVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat.Formatted(pVecs), mat.Formatted(test.wantpVecs)) + } + if !mat.EqualApprox(qVecs, test.wantqVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat.Formatted(qVecs), mat.Formatted(test.wantqVecs)) + } + if !mat.EqualApprox(phiVs, test.wantphiVs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat.Formatted(phiVs), mat.Formatted(test.wantphiVs)) + } + if !mat.EqualApprox(psiVs, test.wantpsiVs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat.Formatted(psiVs), mat.Formatted(test.wantpsiVs)) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/combin/combin.go b/vendor/gonum.org/v1/gonum/stat/combin/combin.go new file mode 100644 index 00000000..d4e1f6e6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/combin/combin.go @@ -0,0 +1,181 @@ +// Copyright ©2016 The gonum 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 combin + +import "math" + +const ( + badNegInput = "combin: negative input" + badSetSize = "combin: n < k" + badInput = "combin: wrong input slice length" +) + +// Binomial returns the binomial coefficient of (n,k), also commonly referred to +// as "n choose k". +// +// The binomial coefficient, C(n,k), is the number of unordered combinations of +// k elements in a set that is n elements big, and is defined as +// +// C(n,k) = n!/((n-k)!k!) +// +// n and k must be non-negative with n >= k, otherwise Binomial will panic. +// No check is made for overflow. +func Binomial(n, k int) int { + if n < 0 || k < 0 { + panic(badNegInput) + } + if n < k { + panic(badSetSize) + } + // (n,k) = (n, n-k) + if k > n/2 { + k = n - k + } + b := 1 + for i := 1; i <= k; i++ { + b = (n - k + i) * b / i + } + return b +} + +// GeneralizedBinomial returns the generalized binomial coefficient of (n, k), +// defined as +// Γ(n+1) / (Γ(k+1) Γ(n-k+1)) +// where Γ is the Gamma function. GeneralizedBinomial is useful for continuous +// relaxations of the binomial coefficient, or when the binomial coefficient value +// may overflow int. In the latter case, one may use math/big for an exact +// computation. +// +// n and k must be non-negative with n >= k, otherwise GeneralizedBinomial will panic. +func GeneralizedBinomial(n, k float64) float64 { + return math.Exp(LogGeneralizedBinomial(n, k)) +} + +// LogGeneralizedBinomial returns the log of the generalized binomial coefficient. +// See GeneralizedBinomial for more information. +func LogGeneralizedBinomial(n, k float64) float64 { + if n < 0 || k < 0 { + panic(badNegInput) + } + if n < k { + panic(badSetSize) + } + a, _ := math.Lgamma(n + 1) + b, _ := math.Lgamma(k + 1) + c, _ := math.Lgamma(n - k + 1) + return a - b - c +} + +// CombinationGenerator generates combinations iteratively. Combinations may be +// called to generate all combinations collectively. +type CombinationGenerator struct { + n int + k int + previous []int + remaining int +} + +// NewCombinationGenerator returns a CombinationGenerator for generating the +// combinations of k elements from a set of size n. +// +// n and k must be non-negative with n >= k, otherwise NewCombinationGenerator +// will panic. +func NewCombinationGenerator(n, k int) *CombinationGenerator { + return &CombinationGenerator{ + n: n, + k: k, + remaining: Binomial(n, k), + } +} + +// Next advances the iterator if there are combinations remaining to be generated, +// and returns false if all combinations have been generated. Next must be called +// to initialize the first value before calling Combination or Combination will +// panic. The value returned by Combination is only changed during calls to Next. +func (c *CombinationGenerator) Next() bool { + if c.remaining <= 0 { + // Next is called before combination, so c.remaining is set to zero before + // Combination is called. Thus, Combination cannot panic on zero, and a + // second sentinel value is needed. + c.remaining = -1 + return false + } + if c.previous == nil { + c.previous = make([]int, c.k) + for i := range c.previous { + c.previous[i] = i + } + } else { + nextCombination(c.previous, c.n, c.k) + } + c.remaining-- + return true +} + +// Combination generates the next combination. If next is non-nil, it must have +// length k and the result will be stored in-place into combination. If combination +// is nil a new slice will be allocated and returned. If all of the combinations +// have already been constructed (Next() returns false), Combination will panic. +// +// Next must be called to initialize the first value before calling Combination +// or Combination will panic. The value returned by Combination is only changed +// during calls to Next. +func (c *CombinationGenerator) Combination(combination []int) []int { + if c.remaining == -1 { + panic("combin: all combinations have been generated") + } + if c.previous == nil { + panic("combin: Combination called before Next") + } + if combination == nil { + combination = make([]int, c.k) + } + if len(combination) != c.k { + panic(badInput) + } + copy(combination, c.previous) + return combination +} + +// Combinations generates all of the combinations of k elements from a +// set of size n. The returned slice has length Binomial(n,k) and each inner slice +// has length k. +// +// n and k must be non-negative with n >= k, otherwise Combinations will panic. +// +// CombinationGenerator may alternatively be used to generate the combinations +// iteratively instead of collectively. +func Combinations(n, k int) [][]int { + combins := Binomial(n, k) + data := make([][]int, combins) + if len(data) == 0 { + return data + } + data[0] = make([]int, k) + for i := range data[0] { + data[0][i] = i + } + for i := 1; i < combins; i++ { + next := make([]int, k) + copy(next, data[i-1]) + nextCombination(next, n, k) + data[i] = next + } + return data +} + +// nextCombination generates the combination after s, overwriting the input value. +func nextCombination(s []int, n, k int) { + for j := k - 1; j >= 0; j-- { + if s[j] == n+j-k { + continue + } + s[j]++ + for l := j + 1; l < k; l++ { + s[l] = s[j] + l - j + } + break + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/combin/combin_test.go b/vendor/gonum.org/v1/gonum/stat/combin/combin_test.go new file mode 100644 index 00000000..8226a675 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/combin/combin_test.go @@ -0,0 +1,181 @@ +// Copyright ©2016 The gonum 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 combin + +import ( + "math/big" + "testing" + + "gonum.org/v1/gonum/floats" +) + +// intSosMatch returns true if the two slices of slices are equal. +func intSosMatch(a, b [][]int) bool { + if len(a) != len(b) { + return false + } + for i, s := range a { + if len(s) != len(b[i]) { + return false + } + for j, v := range s { + if v != b[i][j] { + return false + } + } + } + return true +} + +var binomialTests = []struct { + n, k, ans int +}{ + {0, 0, 1}, + {5, 0, 1}, + {5, 1, 5}, + {5, 2, 10}, + {5, 3, 10}, + {5, 4, 5}, + {5, 5, 1}, + + {6, 0, 1}, + {6, 1, 6}, + {6, 2, 15}, + {6, 3, 20}, + {6, 4, 15}, + {6, 5, 6}, + {6, 6, 1}, + + {20, 0, 1}, + {20, 1, 20}, + {20, 2, 190}, + {20, 3, 1140}, + {20, 4, 4845}, + {20, 5, 15504}, + {20, 6, 38760}, + {20, 7, 77520}, + {20, 8, 125970}, + {20, 9, 167960}, + {20, 10, 184756}, + {20, 11, 167960}, + {20, 12, 125970}, + {20, 13, 77520}, + {20, 14, 38760}, + {20, 15, 15504}, + {20, 16, 4845}, + {20, 17, 1140}, + {20, 18, 190}, + {20, 19, 20}, + {20, 20, 1}, +} + +func TestBinomial(t *testing.T) { + for cas, test := range binomialTests { + ans := Binomial(test.n, test.k) + if ans != test.ans { + t.Errorf("Case %v: Binomial mismatch. Got %v, want %v.", cas, ans, test.ans) + } + } + var ( + n = 61 + want big.Int + got big.Int + ) + for k := 0; k <= n; k++ { + want.Binomial(int64(n), int64(k)) + got.SetInt64(int64(Binomial(n, k))) + if want.Cmp(&got) != 0 { + t.Errorf("Case n=%v,k=%v: Binomial mismatch for large n. Got %v, want %v.", n, k, got, want) + } + } +} + +func TestGeneralizedBinomial(t *testing.T) { + for cas, test := range binomialTests { + ans := GeneralizedBinomial(float64(test.n), float64(test.k)) + if !floats.EqualWithinAbsOrRel(ans, float64(test.ans), 1e-14, 1e-14) { + t.Errorf("Case %v: Binomial mismatch. Got %v, want %v.", cas, ans, test.ans) + } + } +} + +func TestCombinations(t *testing.T) { + for cas, test := range []struct { + n, k int + data [][]int + }{ + { + n: 1, + k: 1, + data: [][]int{{0}}, + }, + { + n: 2, + k: 1, + data: [][]int{{0}, {1}}, + }, + { + n: 2, + k: 2, + data: [][]int{{0, 1}}, + }, + { + n: 3, + k: 1, + data: [][]int{{0}, {1}, {2}}, + }, + { + n: 3, + k: 2, + data: [][]int{{0, 1}, {0, 2}, {1, 2}}, + }, + { + n: 3, + k: 3, + data: [][]int{{0, 1, 2}}, + }, + { + n: 4, + k: 1, + data: [][]int{{0}, {1}, {2}, {3}}, + }, + { + n: 4, + k: 2, + data: [][]int{{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}}, + }, + { + n: 4, + k: 3, + data: [][]int{{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}}, + }, + { + n: 4, + k: 4, + data: [][]int{{0, 1, 2, 3}}, + }, + } { + data := Combinations(test.n, test.k) + if !intSosMatch(data, test.data) { + t.Errorf("Cas %v: Generated combinations mismatch. Got %v, want %v.", cas, data, test.data) + } + } +} + +func TestCombinationGenerator(t *testing.T) { + for n := 0; n <= 10; n++ { + for k := 1; k <= n; k++ { + combinations := Combinations(n, k) + cg := NewCombinationGenerator(n, k) + genCombs := make([][]int, 0, len(combinations)) + for cg.Next() { + genCombs = append(genCombs, cg.Combination(nil)) + } + if !intSosMatch(combinations, genCombs) { + t.Errorf("Combinations and generated combinations do not match. n = %v, k = %v", n, k) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/combin/doc.go b/vendor/gonum.org/v1/gonum/stat/combin/doc.go new file mode 100644 index 00000000..935ccdb8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/combin/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2017 The gonum 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 combin implements routines involving combinatorics (permutations, +// combinations, etc.). +package combin // import "gonum.org/v1/gonum/stat/combin" diff --git a/vendor/gonum.org/v1/gonum/stat/distmat/doc.go b/vendor/gonum.org/v1/gonum/stat/distmat/doc.go new file mode 100644 index 00000000..baca067d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmat/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 distmat provides probability distributions over matrices. +package distmat // import "gonum.org/v1/gonum/stat/distmat" diff --git a/vendor/gonum.org/v1/gonum/stat/distmat/general.go b/vendor/gonum.org/v1/gonum/stat/distmat/general.go new file mode 100644 index 00000000..21bbc95d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmat/general.go @@ -0,0 +1,7 @@ +// Copyright ©2016 The gonum 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 distmat + +var badDim = "distmat: dimension mismatch" diff --git a/vendor/gonum.org/v1/gonum/stat/distmat/wishart.go b/vendor/gonum.org/v1/gonum/stat/distmat/wishart.go new file mode 100644 index 00000000..97992ce0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmat/wishart.go @@ -0,0 +1,209 @@ +// Copyright ©2016 The gonum 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 distmat + +import ( + "math" + "math/rand" + "sync" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/mathext" + "gonum.org/v1/gonum/stat/distuv" +) + +// Wishart is a distribution over d×d positive symmetric definite matrices. It +// is parametrized by a scalar degrees of freedom parameter ν and a d×d positive +// definite matrix V. +// +// The Wishart PDF is given by +// p(X) = [|X|^((ν-d-1)/2) * exp(-tr(V^-1 * X)/2)] / [2^(ν*d/2) * |V|^(ν/2) * Γ_d(ν/2)] +// where X is a d×d PSD matrix, ν > d-1, |·| denotes the determinant, tr is the +// trace and Γ_d is the multivariate gamma function. +// +// See https://en.wikipedia.org/wiki/Wishart_distribution for more information. +type Wishart struct { + nu float64 + src *rand.Rand + + dim int + cholv mat.Cholesky + logdetv float64 + upper mat.TriDense + + once sync.Once + v *mat.SymDense // only stored if needed +} + +// NewWishart returns a new Wishart distribution with the given shape matrix and +// degrees of freedom parameter. NewWishart returns whether the creation was +// successful. +// +// NewWishart panics if nu <= d - 1 where d is the order of v. +func NewWishart(v mat.Symmetric, nu float64, src *rand.Rand) (*Wishart, bool) { + dim := v.Symmetric() + if nu <= float64(dim-1) { + panic("wishart: nu must be greater than dim-1") + } + var chol mat.Cholesky + ok := chol.Factorize(v) + if !ok { + return nil, false + } + + var u mat.TriDense + chol.UTo(&u) + + w := &Wishart{ + nu: nu, + src: src, + + dim: dim, + cholv: chol, + logdetv: chol.LogDet(), + upper: u, + } + return w, true +} + +// MeanSym returns the mean matrix of the distribution as a symmetric matrix. +// If x is nil, a new matrix is allocated and returned. If x is not nil, the +// result is stored in-place into x and MeanSym will panic if the order of x +// is not equal to the order of the receiver. +func (w *Wishart) MeanSym(x *mat.SymDense) *mat.SymDense { + if x == nil { + x = mat.NewSymDense(w.dim, nil) + } + d := x.Symmetric() + if d != w.dim { + panic(badDim) + } + w.setV() + x.CopySym(w.v) + x.ScaleSym(w.nu, x) + return x +} + +// ProbSym returns the probability of the symmetric matrix x. If x is not positive +// definite (the Cholesky decomposition fails), it has 0 probability. +func (w *Wishart) ProbSym(x mat.Symmetric) float64 { + return math.Exp(w.LogProbSym(x)) +} + +// LogProbSym returns the log of the probability of the input symmetric matrix. +// +// LogProbSym returns -∞ if the input matrix is not positive definite (the Cholesky +// decomposition fails). +func (w *Wishart) LogProbSym(x mat.Symmetric) float64 { + dim := x.Symmetric() + if dim != w.dim { + panic(badDim) + } + var chol mat.Cholesky + ok := chol.Factorize(x) + if !ok { + return math.Inf(-1) + } + return w.logProbSymChol(&chol) +} + +// LogProbSymChol returns the log of the probability of the input symmetric matrix +// given its Cholesky decomposition. +func (w *Wishart) LogProbSymChol(cholX *mat.Cholesky) float64 { + dim := cholX.Size() + if dim != w.dim { + panic(badDim) + } + return w.logProbSymChol(cholX) +} + +func (w *Wishart) logProbSymChol(cholX *mat.Cholesky) float64 { + // The PDF is + // p(X) = [|X|^((ν-d-1)/2) * exp(-tr(V^-1 * X)/2)] / [2^(ν*d/2) * |V|^(ν/2) * Γ_d(ν/2)] + // The LogPDF is thus + // (ν-d-1)/2 * log(|X|) - tr(V^-1 * X)/2 - (ν*d/2)*log(2) - ν/2 * log(|V|) - log(Γ_d(ν/2)) + logdetx := cholX.LogDet() + + // Compute tr(V^-1 * X), using the fact that X = U^T * U. + var u mat.TriDense + cholX.UTo(&u) + + var vinvx mat.Dense + err := w.cholv.Solve(&vinvx, u.T()) + if err != nil { + return math.Inf(-1) + } + vinvx.Mul(&vinvx, &u) + tr := mat.Trace(&vinvx) + + fnu := float64(w.nu) + fdim := float64(w.dim) + + return 0.5*((fnu-fdim-1)*logdetx-tr-fnu*fdim*math.Ln2-fnu*w.logdetv) - mathext.MvLgamma(0.5*fnu, w.dim) +} + +// RandSym generates a random symmetric matrix from the distribution. +func (w *Wishart) RandSym(x *mat.SymDense) *mat.SymDense { + if x == nil { + x = &mat.SymDense{} + } + var c mat.Cholesky + w.RandChol(&c) + c.To(x) + return x +} + +// RandChol generates the Cholesky decomposition of a random matrix from the distribution. +func (w *Wishart) RandChol(c *mat.Cholesky) *mat.Cholesky { + // TODO(btracey): Modify the code if the underlying data from c is exposed + // to avoid the dim^2 allocation here. + + // Use the Bartlett Decomposition, which says that + // X ~ L A A^T L^T + // Where A is a lower triangular matrix in which the diagonal of A is + // generated from the square roots of χ^2 random variables, and the + // off-diagonals are generated from standard normal variables. + // The above gives the cholesky decomposition of X, where L_x = L A. + // + // mat64 works with the upper triagular decomposition, so we would like to do + // the same. We can instead say that + // U_x = L_x^T = (L * A)^T = A^T * L^T = A^T * U + // Instead, generate A^T, by using the procedure above, except as an upper + // triangular matrix. + norm := distuv.Normal{ + Mu: 0, + Sigma: 1, + Source: w.src, + } + + t := mat.NewTriDense(w.dim, mat.Upper, nil) + for i := 0; i < w.dim; i++ { + v := distuv.ChiSquared{ + K: w.nu - float64(i), + Src: w.src, + }.Rand() + t.SetTri(i, i, math.Sqrt(v)) + } + for i := 0; i < w.dim; i++ { + for j := i + 1; j < w.dim; j++ { + t.SetTri(i, j, norm.Rand()) + } + } + + t.MulTri(t, &w.upper) + if c == nil { + c = &mat.Cholesky{} + } + c.SetFromU(t) + return c +} + +// setV computes and stores the covariance matrix of the distribution. +func (w *Wishart) setV() { + w.once.Do(func() { + w.v = mat.NewSymDense(w.dim, nil) + w.cholv.To(w.v) + }) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmat/wishart_test.go b/vendor/gonum.org/v1/gonum/stat/distmat/wishart_test.go new file mode 100644 index 00000000..96350c64 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmat/wishart_test.go @@ -0,0 +1,129 @@ +// Copyright ©2016 The gonum 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 distmat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func TestWishart(t *testing.T) { + for c, test := range []struct { + v *mat.SymDense + nu float64 + xs []*mat.SymDense + lps []float64 + }{ + // Logprob data compared with scipy. + { + v: mat.NewSymDense(2, []float64{1, 0, 0, 1}), + nu: 4, + xs: []*mat.SymDense{ + mat.NewSymDense(2, []float64{0.9, 0.1, 0.1, 0.9}), + }, + lps: []float64{-4.2357432031863409}, + }, + { + v: mat.NewSymDense(2, []float64{0.8, -0.2, -0.2, 0.7}), + nu: 5, + xs: []*mat.SymDense{ + mat.NewSymDense(2, []float64{0.9, 0.1, 0.1, 0.9}), + mat.NewSymDense(2, []float64{0.3, -0.1, -0.1, 0.7}), + }, + lps: []float64{-4.2476495605333575, -4.9993285370378633}, + }, + { + v: mat.NewSymDense(3, []float64{0.8, 0.3, 0.1, 0.3, 0.7, -0.1, 0.1, -0.1, 7}), + nu: 5, + xs: []*mat.SymDense{ + mat.NewSymDense(3, []float64{1, 0.2, -0.3, 0.2, 0.6, -0.2, -0.3, -0.2, 6}), + }, + lps: []float64{-11.010982249229421}, + }, + } { + w, ok := NewWishart(test.v, test.nu, nil) + if !ok { + panic("bad test") + } + for i, x := range test.xs { + lp := w.LogProbSym(x) + + var chol mat.Cholesky + ok := chol.Factorize(x) + if !ok { + panic("bad test") + } + lpc := w.LogProbSymChol(&chol) + + if math.Abs(lp-lpc) > 1e-14 { + t.Errorf("Case %d, test %d: probability mismatch between chol and not", c, i) + } + if !floats.EqualWithinAbsOrRel(lp, test.lps[i], 1e-14, 1e-14) { + t.Errorf("Case %d, test %d: got %v, want %v", c, i, lp, test.lps[i]) + } + } + + ch := w.RandChol(nil) + w.RandChol(ch) + + s := w.RandSym(nil) + w.RandSym(s) + + } +} + +func TestWishartRand(t *testing.T) { + for c, test := range []struct { + v *mat.SymDense + nu float64 + samples int + tol float64 + }{ + { + v: mat.NewSymDense(2, []float64{0.8, -0.2, -0.2, 0.7}), + nu: 5, + samples: 30000, + tol: 3e-2, + }, + { + v: mat.NewSymDense(3, []float64{0.8, 0.3, 0.1, 0.3, 0.7, -0.1, 0.1, -0.1, 7}), + nu: 5, + samples: 30000, + tol: 3e-2, + }, + { + v: mat.NewSymDense(4, []float64{ + 0.8, 0.3, 0.1, -0.2, + 0.3, 0.7, -0.1, 0.4, + 0.1, -0.1, 7, 1, + -0.2, -0.1, 1, 6}), + nu: 6, + samples: 30000, + tol: 1e-1, + }, + } { + rnd := rand.New(rand.NewSource(1)) + dim := test.v.Symmetric() + w, ok := NewWishart(test.v, test.nu, rnd) + if !ok { + panic("bad test") + } + mean := mat.NewSymDense(dim, nil) + x := mat.NewSymDense(dim, nil) + for i := 0; i < test.samples; i++ { + w.RandSym(x) + x.ScaleSym(1/float64(test.samples), x) + mean.AddSym(mean, x) + } + trueMean := w.MeanSym(nil) + if !mat.EqualApprox(trueMean, mean, test.tol) { + t.Errorf("Case %d: Mismatch between estimated and true mean. Got\n%0.4v\nWant\n%0.4v\n", c, mat.Formatted(mean), mat.Formatted(trueMean)) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet.go b/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet.go new file mode 100644 index 00000000..fbf2128f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet.go @@ -0,0 +1,144 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/distuv" +) + +// Dirichlet implements the Dirichlet probability distribution. +// +// The Dirichlet distribution is a continuous probability distribution that +// generates elements over the probability simplex, i.e. ||x||_1 = 1. The Dirichlet +// distribution is the conjugate prior to the categorical distribution and the +// multivariate version of the beta distribution. The probability of a point x is +// 1/Beta(α) \prod_i x_i^(α_i - 1) +// where Beta(α) is the multivariate Beta function (see the mathext package). +// +// For more information see https://en.wikipedia.org/wiki/Dirichlet_distribution +type Dirichlet struct { + alpha []float64 + dim int + src *rand.Rand + + lbeta float64 + sumAlpha float64 +} + +// NewDirichlet creates a new dirichlet distribution with the given parameters alpha. +// NewDirichlet will panic if len(alpha) == 0, or if any alpha is <= 0. +func NewDirichlet(alpha []float64, src *rand.Rand) *Dirichlet { + dim := len(alpha) + if dim == 0 { + panic(badZeroDimension) + } + for _, v := range alpha { + if v <= 0 { + panic("dirichlet: non-positive alpha") + } + } + a := make([]float64, len(alpha)) + copy(a, alpha) + d := &Dirichlet{ + alpha: a, + dim: dim, + src: src, + } + d.lbeta, d.sumAlpha = d.genLBeta(a) + return d +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (d *Dirichlet) CovarianceMatrix(cov *mat.SymDense) *mat.SymDense { + if cov == nil { + cov = mat.NewSymDense(d.Dim(), nil) + } else if cov.Symmetric() == 0 { + *cov = *(cov.GrowSquare(d.dim).(*mat.SymDense)) + } else if cov.Symmetric() != d.dim { + panic("normal: input matrix size mismatch") + } + scale := 1 / (d.sumAlpha * d.sumAlpha * (d.sumAlpha + 1)) + for i := 0; i < d.dim; i++ { + ai := d.alpha[i] + v := ai * (d.sumAlpha - ai) * scale + cov.SetSym(i, i, v) + for j := i + 1; j < d.dim; j++ { + aj := d.alpha[j] + v := -ai * aj * scale + cov.SetSym(i, j, v) + } + } + return cov +} + +// genLBeta computes the generalized LBeta function. +func (d *Dirichlet) genLBeta(alpha []float64) (lbeta, sumAlpha float64) { + for _, alpha := range d.alpha { + lg, _ := math.Lgamma(alpha) + lbeta += lg + sumAlpha += alpha + } + lg, _ := math.Lgamma(sumAlpha) + return lbeta - lg, sumAlpha +} + +// Dim returns the dimension of the distribution. +func (d *Dirichlet) Dim() int { + return d.dim +} + +// LogProb computes the log of the pdf of the point x. +// +// It does not check that ||x||_1 = 1. +func (d *Dirichlet) LogProb(x []float64) float64 { + dim := d.dim + if len(x) != dim { + panic(badSizeMismatch) + } + var lprob float64 + for i, x := range x { + lprob += (d.alpha[i] - 1) * math.Log(x) + } + lprob -= d.lbeta + return lprob +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (d *Dirichlet) Mean(x []float64) []float64 { + x = reuseAs(x, d.dim) + copy(x, d.alpha) + floats.Scale(1/d.sumAlpha, x) + return x +} + +// Prob computes the value of the probability density function at x. +func (d *Dirichlet) Prob(x []float64) float64 { + return math.Exp(d.LogProb(x)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (d *Dirichlet) Rand(x []float64) []float64 { + x = reuseAs(x, d.dim) + for i := range x { + x[i] = distuv.Gamma{Alpha: d.alpha[i], Beta: 1, Source: d.src}.Rand() + } + sum := floats.Sum(x) + floats.Scale(1/sum, x) + return x +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet_test.go new file mode 100644 index 00000000..43f77007 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/dirichlet_test.go @@ -0,0 +1,67 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/mat" +) + +func TestDirichlet(t *testing.T) { + // Data from Scipy. + for cas, test := range []struct { + Dir *Dirichlet + x []float64 + prob float64 + }{ + { + NewDirichlet([]float64{1, 1, 1}, nil), + []float64{0.2, 0.3, 0.5}, + 2.0, + }, + { + NewDirichlet([]float64{0.6, 10, 8.7}, nil), + []float64{0.2, 0.3, 0.5}, + 0.24079612737071665, + }, + } { + p := test.Dir.Prob(test.x) + if math.Abs(p-test.prob) > 1e-14 { + t.Errorf("Probablility mismatch. Case %v. Got %v, want %v", cas, p, test.prob) + } + } + + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + Dir *Dirichlet + }{ + { + NewDirichlet([]float64{1, 1, 1}, rnd), + }, + { + NewDirichlet([]float64{2, 3}, rnd), + }, + { + NewDirichlet([]float64{0.2, 0.3}, rnd), + }, + { + NewDirichlet([]float64{0.2, 4}, rnd), + }, + { + NewDirichlet([]float64{0.1, 4, 20}, rnd), + }, + } { + const n = 1e5 + d := test.Dir + dim := d.Dim() + x := mat.NewDense(n, dim, nil) + generateSamples(x, d) + checkMean(t, cas, x, d, 1e-2) + checkCov(t, cas, x, d, 1e-2) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/doc.go b/vendor/gonum.org/v1/gonum/stat/distmv/doc.go new file mode 100644 index 00000000..c126be97 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 distmv provides multivariate random distribution types. +package distmv // import "gonum.org/v1/gonum/stat/distmv" diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/general.go b/vendor/gonum.org/v1/gonum/stat/distmv/general.go new file mode 100644 index 00000000..f473efdf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/general.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum 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 distmv + +var ( + badQuantile = "distmv: quantile not between 0 and 1" + badReceiver = "distmv: input slice is not nil or the correct length" + badSizeMismatch = "distmv: size mismatch" + badZeroDimension = "distmv: zero dimensional input" + nonPosDimension = "distmv: non-positive dimension input" +) + +const logTwoPi = 1.8378770664093454835606594728112352797227949472755668 + +// useAs gets a slice of size n. If len(x) == n, x is returned, if len(x) == 0 +// then a slice is returned of length n. +func reuseAs(x []float64, n int) []float64 { + if len(x) == n { + return x + } + if len(x) == 0 { + if cap(x) >= n { + return x[:n] + } + return make([]float64, n) + } + panic(badReceiver) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/general_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/general_test.go new file mode 100644 index 00000000..05e65f7b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/general_test.go @@ -0,0 +1,96 @@ +// Copyright ©2015 The gonum 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 distmv + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +type prober interface { + Prob(x []float64) float64 + LogProb(x []float64) float64 +} + +type probCase struct { + dist prober + loc []float64 + logProb float64 +} + +func testProbability(t *testing.T, cases []probCase) { + for _, test := range cases { + logProb := test.dist.LogProb(test.loc) + if math.Abs(logProb-test.logProb) > 1e-14 { + t.Errorf("LogProb mismatch: want: %v, got: %v", test.logProb, logProb) + } + prob := test.dist.Prob(test.loc) + if math.Abs(prob-math.Exp(test.logProb)) > 1e-14 { + t.Errorf("Prob mismatch: want: %v, got: %v", math.Exp(test.logProb), prob) + } + } +} + +func generateSamples(x *mat.Dense, r Rander) { + n, _ := x.Dims() + for i := 0; i < n; i++ { + r.Rand(x.RawRowView(i)) + } +} + +type Meaner interface { + Mean([]float64) []float64 +} + +func checkMean(t *testing.T, cas int, x *mat.Dense, m Meaner, tol float64) { + mean := m.Mean(nil) + + // Check that the answer is identical when using nil or non-nil. + mean2 := make([]float64, len(mean)) + m.Mean(mean2) + if !floats.Equal(mean, mean2) { + t.Errorf("Mean mismatch when providing nil and slice. Case %v", cas) + } + + // Check that the mean matches the samples. + r, _ := x.Dims() + col := make([]float64, r) + meanEst := make([]float64, len(mean)) + for i := range meanEst { + meanEst[i] = stat.Mean(mat.Col(col, i, x), nil) + } + if !floats.EqualApprox(mean, meanEst, tol) { + t.Errorf("Returned mean and sample mean mismatch. Case %v. Empirical %v, returned %v", cas, meanEst, mean) + } +} + +type Cover interface { + CovarianceMatrix(*mat.SymDense) *mat.SymDense +} + +func checkCov(t *testing.T, cas int, x *mat.Dense, c Cover, tol float64) { + cov := c.CovarianceMatrix(nil) + n := cov.Symmetric() + cov2 := mat.NewSymDense(n, nil) + c.CovarianceMatrix(cov2) + if !mat.Equal(cov, cov2) { + t.Errorf("Cov mismatch when providing nil and matrix. Case %v", cas) + } + var cov3 mat.SymDense + c.CovarianceMatrix(&cov3) + if !mat.Equal(cov, &cov3) { + t.Errorf("Cov mismatch when providing zero matrix. Case %v", cas) + } + + // Check that the covariance matrix matches the samples + covEst := stat.CovarianceMatrix(nil, x, nil) + if !mat.EqualApprox(covEst, cov, tol) { + t.Errorf("Return cov and sample cov mismatch. Cas %v.\nGot:\n%0.4v\nWant:\n%0.4v", cas, mat.Formatted(cov), mat.Formatted(covEst)) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/interfaces.go b/vendor/gonum.org/v1/gonum/stat/distmv/interfaces.go new file mode 100644 index 00000000..57411933 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/interfaces.go @@ -0,0 +1,33 @@ +// Copyright ©2016 The gonum 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 distmv + +// Quantiler returns the multi-dimensional inverse cumulative distribution function. +// len(x) must equal len(p), and if x is non-nil, len(x) must also equal len(p). +// If x is nil, a new slice will be allocated and returned, otherwise the quantile +// will be stored in-place into x. All of the values of p must be between 0 and 1, +// or Quantile will panic. +type Quantiler interface { + Quantile(x, p []float64) []float64 +} + +// LogProber computes the log of the probability of the point x. +type LogProber interface { + LogProb(x []float64) float64 +} + +// Rander generates a random number according to the distributon. +// If the input is non-nil, len(x) must equal len(p) and the dimension of the distribution, +// otherwise Quantile will panic. +// If the input is nil, a new slice will be allocated and returned. +type Rander interface { + Rand(x []float64) []float64 +} + +// RandLogProber is both a Rander and a LogProber. +type RandLogProber interface { + Rander + LogProber +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/normal.go b/vendor/gonum.org/v1/gonum/stat/distmv/normal.go new file mode 100644 index 00000000..1d5098fd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/normal.go @@ -0,0 +1,345 @@ +// Copyright ©2015 The gonum 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 distmv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +var ( + badInputLength = "distmv: input slice length mismatch" +) + +// Normal is a multivariate normal distribution (also known as the multivariate +// Gaussian distribution). Its pdf in k dimensions is given by +// (2 π)^(-k/2) |Σ|^(-1/2) exp(-1/2 (x-μ)'Σ^-1(x-μ)) +// where μ is the mean vector and Σ the covariance matrix. Σ must be symmetric +// and positive definite. Use NewNormal to construct. +type Normal struct { + mu []float64 + + sigma mat.SymDense + + chol mat.Cholesky + lower mat.TriDense + logSqrtDet float64 + dim int + + src *rand.Rand +} + +// NewNormal creates a new Normal with the given mean and covariance matrix. +// NewNormal panics if len(mu) == 0, or if len(mu) != sigma.N. If the covariance +// matrix is not positive-definite, the returned boolean is false. +func NewNormal(mu []float64, sigma mat.Symmetric, src *rand.Rand) (*Normal, bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := sigma.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + n := &Normal{ + src: src, + dim: dim, + mu: make([]float64, dim), + } + copy(n.mu, mu) + ok := n.chol.Factorize(sigma) + if !ok { + return nil, false + } + n.sigma = *mat.NewSymDense(dim, nil) + n.sigma.CopySym(sigma) + n.chol.LTo(&n.lower) + n.logSqrtDet = 0.5 * n.chol.LogDet() + return n, true +} + +// NewNormalChol creates a new Normal distribution with the given mean and +// covariance matrix represented by its Cholesky decomposition. NewNormalChol +// panics if len(mu) is not equal to chol.Size(). +func NewNormalChol(mu []float64, chol *mat.Cholesky, src *rand.Rand) *Normal { + dim := len(mu) + if dim != chol.Size() { + panic(badSizeMismatch) + } + n := &Normal{ + src: src, + dim: dim, + mu: make([]float64, dim), + } + n.chol.Clone(chol) + copy(n.mu, mu) + chol.LTo(&n.lower) + n.logSqrtDet = 0.5 * n.chol.LogDet() + return n +} + +// NewNormalPrecision creates a new Normal distribution with the given mean and +// precision matrix (inverse of the covariance matrix). NewNormalPrecision +// panics if len(mu) is not equal to prec.Symmetric(). If the precision matrix +// is not positive-definite, NewNormalPrecision returns nil for norm and false +// for ok. +func NewNormalPrecision(mu []float64, prec *mat.SymDense, src *rand.Rand) (norm *Normal, ok bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := prec.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + // TODO(btracey): Computing a matrix inverse is generally numerically instable. + // This only has to compute the inverse of a positive definite matrix, which + // is much better, but this still loses precision. It is worth considering if + // instead the precision matrix should be stored explicitly and used instead + // of the Cholesky decomposition of the covariance matrix where appropriate. + var chol mat.Cholesky + ok = chol.Factorize(prec) + if !ok { + return nil, false + } + var sigma mat.SymDense + chol.InverseTo(&sigma) + return NewNormal(mu, &sigma, src) +} + +// ConditionNormal returns the Normal distribution that is the receiver conditioned +// on the input evidence. The returned multivariate normal has dimension +// n - len(observed), where n is the dimension of the original receiver. The updated +// mean and covariance are +// mu = mu_un + sigma_{ob,un}^T * sigma_{ob,ob}^-1 (v - mu_ob) +// sigma = sigma_{un,un} - sigma_{ob,un}^T * sigma_{ob,ob}^-1 * sigma_{ob,un} +// where mu_un and mu_ob are the original means of the unobserved and observed +// variables respectively, sigma_{un,un} is the unobserved subset of the covariance +// matrix, sigma_{ob,ob} is the observed subset of the covariance matrix, and +// sigma_{un,ob} are the cross terms. The elements of x_2 have been observed with +// values v. The dimension order is preserved during conditioning, so if the value +// of dimension 1 is observed, the returned normal represents dimensions {0, 2, ...} +// of the original Normal distribution. +// +// ConditionNormal returns {nil, false} if there is a failure during the update. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (n *Normal) ConditionNormal(observed []int, values []float64, src *rand.Rand) (*Normal, bool) { + if len(observed) == 0 { + panic("normal: no observed value") + } + if len(observed) != len(values) { + panic(badInputLength) + } + for _, v := range observed { + if v < 0 || v >= n.Dim() { + panic("normal: observed value out of bounds") + } + } + + _, mu1, sigma11 := studentsTConditional(observed, values, math.Inf(1), n.mu, &n.sigma) + if mu1 == nil { + return nil, false + } + return NewNormal(mu1, sigma11, src) +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (n *Normal) CovarianceMatrix(s *mat.SymDense) *mat.SymDense { + if s == nil { + s = mat.NewSymDense(n.Dim(), nil) + } + sn := s.Symmetric() + if sn != n.Dim() { + panic("normal: input matrix size mismatch") + } + s.CopySym(&n.sigma) + return s +} + +// Dim returns the dimension of the distribution. +func (n *Normal) Dim() int { + return n.dim +} + +// Entropy returns the differential entropy of the distribution. +func (n *Normal) Entropy() float64 { + return float64(n.dim)/2*(1+logTwoPi) + n.logSqrtDet +} + +// LogProb computes the log of the pdf of the point x. +func (n *Normal) LogProb(x []float64) float64 { + dim := n.dim + if len(x) != dim { + panic(badSizeMismatch) + } + c := -0.5*float64(dim)*logTwoPi - n.logSqrtDet + dst := stat.Mahalanobis(mat.NewVecDense(dim, x), mat.NewVecDense(dim, n.mu), &n.chol) + return c - 0.5*dst*dst +} + +// MarginalNormal returns the marginal distribution of the given input variables. +// That is, MarginalNormal returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where x_i are the dimensions in the input, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the call to NewNormal. +func (n *Normal) MarginalNormal(vars []int, src *rand.Rand) (*Normal, bool) { + newMean := make([]float64, len(vars)) + for i, v := range vars { + newMean[i] = n.mu[v] + } + var s mat.SymDense + s.SubsetSym(&n.sigma, vars) + return NewNormal(newMean, &s, src) +} + +// MarginalNormalSingle returns the marginal of the given input variable. +// That is, MarginalNormal returns +// p(x_i) = \int_{x_¬i} p(x_i | x_¬i) p(x_¬i) dx_¬i +// where i is the input index. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the constructed distuv.Normal. +func (n *Normal) MarginalNormalSingle(i int, src *rand.Rand) distuv.Normal { + return distuv.Normal{ + Mu: n.mu[i], + Sigma: math.Sqrt(n.sigma.At(i, i)), + Source: src, + } +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (n *Normal) Mean(x []float64) []float64 { + x = reuseAs(x, n.dim) + copy(x, n.mu) + return x +} + +// Prob computes the value of the probability density function at x. +func (n *Normal) Prob(x []float64) float64 { + return math.Exp(n.LogProb(x)) +} + +// Quantile returns the multi-dimensional inverse cumulative distribution function. +// If x is nil, a new slice will be allocated and returned. If x is non-nil, +// len(x) must equal len(p) and the quantile will be stored in-place into x. +// All of the values of p must be between 0 and 1, inclusive, or Quantile will panic. +func (n *Normal) Quantile(x, p []float64) []float64 { + dim := n.Dim() + if len(p) != dim { + panic(badInputLength) + } + if x == nil { + x = make([]float64, dim) + } + if len(x) != len(p) { + panic(badInputLength) + } + + // Transform to a standard normal and then transform to a multivariate Gaussian. + tmp := make([]float64, len(x)) + for i, v := range p { + tmp[i] = distuv.UnitNormal.Quantile(v) + } + n.TransformNormal(x, tmp) + return x +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (n *Normal) Rand(x []float64) []float64 { + x = reuseAs(x, n.dim) + tmp := make([]float64, n.dim) + if n.src == nil { + for i := range x { + tmp[i] = rand.NormFloat64() + } + } else { + for i := range x { + tmp[i] = n.src.NormFloat64() + } + } + n.transformNormal(x, tmp) + return x +} + +// ScoreInput returns the gradient of the log-probability with respect to the +// input x. That is, ScoreInput computes +// ∇_x log(p(x)) +// If score is nil, a new slice will be allocated and returned. If score is of +// length the dimension of Normal, then the result will be put in-place into score. +// If neither of these is true, ScoreInput will panic. +func (n *Normal) ScoreInput(score, x []float64) []float64 { + // Normal log probability is + // c - 0.5*(x-μ)' Σ^-1 (x-μ). + // So the derivative is just + // -Σ^-1 (x-μ). + if len(x) != n.Dim() { + panic(badInputLength) + } + if score == nil { + score = make([]float64, len(x)) + } + if len(score) != len(x) { + panic(badSizeMismatch) + } + tmp := make([]float64, len(x)) + copy(tmp, x) + floats.Sub(tmp, n.mu) + + n.chol.SolveVec(mat.NewVecDense(len(score), score), mat.NewVecDense(len(tmp), tmp)) + floats.Scale(-1, score) + return score +} + +// SetMean changes the mean of the normal distribution. SetMean panics if len(mu) +// does not equal the dimension of the normal distribution. +func (n *Normal) SetMean(mu []float64) { + if len(mu) != n.Dim() { + panic(badSizeMismatch) + } + copy(n.mu, mu) +} + +// TransformNormal transforms the vector, normal, generated from a standard +// multidimensional normal into a vector that has been generated under the +// distribution of the receiver. +// +// If dst is non-nil, the result will be stored into dst, otherwise a new slice +// will be allocated. TransformNormal will panic if the length of normal is not +// the dimension of the receiver, or if dst is non-nil and len(dist) != len(normal). +func (n *Normal) TransformNormal(dst, normal []float64) []float64 { + if len(normal) != n.dim { + panic(badInputLength) + } + dst = reuseAs(dst, n.dim) + if len(dst) != len(normal) { + panic(badInputLength) + } + n.transformNormal(dst, normal) + return dst +} + +// transformNormal performs the same operation as TransformNormal except no +// safety checks are performed and both input slices must be non-nil. +func (n *Normal) transformNormal(dst, normal []float64) []float64 { + srcVec := mat.NewVecDense(n.dim, normal) + dstVec := mat.NewVecDense(n.dim, dst) + dstVec.MulVec(&n.lower, srcVec) + floats.Add(dst, n.mu) + return dst +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/normal_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/normal_test.go new file mode 100644 index 00000000..88ac12b9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/normal_test.go @@ -0,0 +1,573 @@ +// Copyright ©2015 The gonum 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 distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +type mvTest struct { + Mu []float64 + Sigma *mat.SymDense + Loc []float64 + Logprob float64 + Prob float64 +} + +func TestNormProbs(t *testing.T) { + dist1, ok := NewNormal([]float64{0, 0}, mat.NewSymDense(2, []float64{1, 0, 0, 1}), nil) + if !ok { + t.Errorf("bad test") + } + dist2, ok := NewNormal([]float64{6, 7}, mat.NewSymDense(2, []float64{8, 2, 0, 4}), nil) + if !ok { + t.Errorf("bad test") + } + testProbability(t, []probCase{ + { + dist: dist1, + loc: []float64{0, 0}, + logProb: -1.837877066409345, + }, + { + dist: dist2, + loc: []float64{6, 7}, + logProb: -3.503979321496947, + }, + { + dist: dist2, + loc: []float64{1, 2}, + logProb: -7.075407892925519, + }, + }) +} + +func TestNewNormalChol(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov *mat.SymDense + }{ + { + mean: []float64{2, 3}, + cov: mat.NewSymDense(2, []float64{1, 0.1, 0.1, 1}), + }, + } { + var chol mat.Cholesky + ok := chol.Factorize(test.cov) + if !ok { + panic("bad test") + } + n := NewNormalChol(test.mean, &chol, nil) + // Generate a random number and calculate probability to ensure things + // have been set properly. See issue #426. + x := n.Rand(nil) + _ = n.Prob(x) + } +} + +func TestNormRand(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov []float64 + }{ + { + mean: []float64{0, 0}, + cov: []float64{ + 1, 0, + 0, 1, + }, + }, + { + mean: []float64{0, 0}, + cov: []float64{ + 1, 0.9, + 0.9, 1, + }, + }, + { + mean: []float64{6, 7}, + cov: []float64{ + 5, 0.9, + 0.9, 2, + }, + }, + } { + dim := len(test.mean) + cov := mat.NewSymDense(dim, test.cov) + n, ok := NewNormal(test.mean, cov, nil) + if !ok { + t.Errorf("bad covariance matrix") + } + + nSamples := 1000000 + samps := mat.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + n.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat.Col(nil, i, samps), nil) + } + if !floats.EqualApprox(estMean, test.mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat.EqualApprox(estCov, cov, 1e-2) { + t.Errorf("Cov mismatch: want: %v, got %v", cov, estCov) + } + } +} + +func TestNormalQuantile(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov []float64 + }{ + { + mean: []float64{6, 7}, + cov: []float64{ + 5, 0.9, + 0.9, 2, + }, + }, + } { + dim := len(test.mean) + cov := mat.NewSymDense(dim, test.cov) + n, ok := NewNormal(test.mean, cov, nil) + if !ok { + t.Errorf("bad covariance matrix") + } + + nSamples := 1000000 + rnd := rand.New(rand.NewSource(1)) + samps := mat.NewDense(nSamples, dim, nil) + tmp := make([]float64, dim) + for i := 0; i < nSamples; i++ { + for j := range tmp { + tmp[j] = rnd.Float64() + } + n.Quantile(samps.RawRowView(i), tmp) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat.Col(nil, i, samps), nil) + } + if !floats.EqualApprox(estMean, test.mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat.EqualApprox(estCov, cov, 1e-2) { + t.Errorf("Cov mismatch: want: %v, got %v", cov, estCov) + } + } +} + +func TestConditionNormal(t *testing.T) { + // Uncorrelated values shouldn't influence the updated values. + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + observed []int + values []float64 + + newMu []float64 + newSigma *mat.SymDense + }{ + { + mu: []float64{2, 3}, + sigma: mat.NewSymDense(2, []float64{2, 0, 0, 5}), + observed: []int{0}, + values: []float64{10}, + + newMu: []float64{3}, + newSigma: mat.NewSymDense(1, []float64{5}), + }, + { + mu: []float64{2, 3}, + sigma: mat.NewSymDense(2, []float64{2, 0, 0, 5}), + observed: []int{1}, + values: []float64{10}, + + newMu: []float64{2}, + newSigma: mat.NewSymDense(1, []float64{2}), + }, + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0, 0, 0, 5, 0, 0, 0, 10}), + observed: []int{1}, + values: []float64{10}, + + newMu: []float64{2, 4}, + newSigma: mat.NewSymDense(2, []float64{2, 0, 0, 10}), + }, + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0, 0, 0, 5, 0, 0, 0, 10}), + observed: []int{0, 1}, + values: []float64{10, 15}, + + newMu: []float64{4}, + newSigma: mat.NewSymDense(1, []float64{10}), + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 0, 0, 0.5, 5, 0, 0, 0, 0, 10, 2, 0, 0, 2, 3}), + observed: []int{0, 1}, + values: []float64{10, 15}, + + newMu: []float64{4, 5}, + newSigma: mat.NewSymDense(2, []float64{10, 2, 2, 3}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, original sigma not positive definite") + } + newNormal, ok := normal.ConditionNormal(test.observed, test.values, nil) + if !ok { + t.Fatalf("Bad test, update failure") + } + + if !floats.EqualApprox(test.newMu, newNormal.mu, 1e-12) { + t.Errorf("Updated mean mismatch. Want %v, got %v.", test.newMu, newNormal.mu) + } + + var sigma mat.SymDense + newNormal.chol.To(&sigma) + if !mat.EqualApprox(test.newSigma, &sigma, 1e-12) { + t.Errorf("Updated sigma mismatch\n.Want:\n% v\nGot:\n% v\n", test.newSigma, sigma) + } + } + + // Test bivariate case where the update rule is analytic + for _, test := range []struct { + mu []float64 + std []float64 + rho float64 + value float64 + }{ + { + mu: []float64{2, 3}, + std: []float64{3, 5}, + rho: 0.9, + value: 1000, + }, + { + mu: []float64{2, 3}, + std: []float64{3, 5}, + rho: -0.9, + value: 1000, + }, + } { + std := test.std + rho := test.rho + sigma := mat.NewSymDense(2, []float64{std[0] * std[0], std[0] * std[1] * rho, std[0] * std[1] * rho, std[1] * std[1]}) + normal, ok := NewNormal(test.mu, sigma, nil) + if !ok { + t.Fatalf("Bad test, original sigma not positive definite") + } + newNormal, ok := normal.ConditionNormal([]int{1}, []float64{test.value}, nil) + if !ok { + t.Fatalf("Bad test, update failed") + } + var newSigma mat.SymDense + newNormal.chol.To(&newSigma) + trueMean := test.mu[0] + rho*(std[0]/std[1])*(test.value-test.mu[1]) + if math.Abs(trueMean-newNormal.mu[0]) > 1e-14 { + t.Errorf("Mean mismatch. Want %v, got %v", trueMean, newNormal.mu[0]) + } + trueVar := (1 - rho*rho) * std[0] * std[0] + if math.Abs(trueVar-newSigma.At(0, 0)) > 1e-14 { + t.Errorf("Std mismatch. Want %v, got %v", trueMean, newNormal.mu[0]) + } + } + + // Test via sampling. + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + observed []int + unobserved []int + value []float64 + }{ + // The indices in unobserved must be in ascending order for this test. + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + + observed: []int{0}, + unobserved: []int{1, 2}, + value: []float64{1.9}, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + + observed: []int{0, 3}, + unobserved: []int{1, 2}, + value: []float64{1.9, 2.9}, + }, + } { + totalSamp := 4000000 + var nSamp int + samples := mat.NewDense(totalSamp, len(test.mu), nil) + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Errorf("bad test") + } + sample := make([]float64, len(test.mu)) + for i := 0; i < totalSamp; i++ { + normal.Rand(sample) + isClose := true + for i, v := range test.observed { + if math.Abs(sample[v]-test.value[i]) > 1e-1 { + isClose = false + break + } + } + if isClose { + samples.SetRow(nSamp, sample) + nSamp++ + } + } + + if nSamp < 100 { + t.Errorf("bad test, not enough samples") + continue + } + samples = samples.Slice(0, nSamp, 0, len(test.mu)).(*mat.Dense) + + // Compute mean and covariance matrix. + estMean := make([]float64, len(test.mu)) + for i := range estMean { + estMean[i] = stat.Mean(mat.Col(nil, i, samples), nil) + } + estCov := stat.CovarianceMatrix(nil, samples, nil) + + // Compute update rule. + newNormal, ok := normal.ConditionNormal(test.observed, test.value, nil) + if !ok { + t.Fatalf("Bad test, update failure") + } + + var subEstMean []float64 + for _, v := range test.unobserved { + + subEstMean = append(subEstMean, estMean[v]) + } + subEstCov := mat.NewSymDense(len(test.unobserved), nil) + for i := 0; i < len(test.unobserved); i++ { + for j := i; j < len(test.unobserved); j++ { + subEstCov.SetSym(i, j, estCov.At(test.unobserved[i], test.unobserved[j])) + } + } + + for i, v := range subEstMean { + if math.Abs(newNormal.mu[i]-v) > 5e-2 { + t.Errorf("Mean mismatch. Want %v, got %v.", newNormal.mu[i], v) + } + } + var sigma mat.SymDense + newNormal.chol.To(&sigma) + if !mat.EqualApprox(&sigma, subEstCov, 1e-1) { + t.Errorf("Covariance mismatch. Want:\n%0.8v\nGot:\n%0.8v\n", subEstCov, sigma) + } + } +} + +func TestCovarianceMatrix(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{1, 0.5, 3, 0.5, 8, -1, 3, -1, 15}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + cov := normal.CovarianceMatrix(nil) + if !mat.EqualApprox(cov, test.sigma, 1e-14) { + t.Errorf("Covariance mismatch with nil input") + } + dim := test.sigma.Symmetric() + cov = mat.NewSymDense(dim, nil) + normal.CovarianceMatrix(cov) + if !mat.EqualApprox(cov, test.sigma, 1e-14) { + t.Errorf("Covariance mismatch with supplied input") + } + } +} + +func TestMarginal(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + marginal []int + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + marginal: []int{0}, + }, + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + marginal: []int{0, 2}, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + + marginal: []int{0, 3}, + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + marginal, ok := normal.MarginalNormal(test.marginal, nil) + if !ok { + t.Fatalf("Bad test, marginal matrix not positive definite") + } + dim := normal.Dim() + nSamples := 1000000 + samps := mat.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + normal.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat.Col(nil, i, samps), nil) + } + for i, v := range test.marginal { + if math.Abs(marginal.mu[i]-estMean[v]) > 1e-2 { + t.Errorf("Mean mismatch: want: %v, got %v", estMean[v], marginal.mu[i]) + } + } + + marginalCov := marginal.CovarianceMatrix(nil) + estCov := stat.CovarianceMatrix(nil, samps, nil) + for i, v1 := range test.marginal { + for j, v2 := range test.marginal { + c := marginalCov.At(i, j) + ec := estCov.At(v1, v2) + if math.Abs(c-ec) > 5e-2 { + t.Errorf("Cov mismatch element i = %d, j = %d: want: %v, got %v", i, j, c, ec) + } + } + } + } +} + +func TestMarginalSingle(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + for i, mean := range test.mu { + norm := normal.MarginalNormalSingle(i, nil) + if norm.Mean() != mean { + t.Errorf("Mean mismatch nil Sigma, idx %v: want %v, got %v.", i, mean, norm.Mean()) + } + std := math.Sqrt(test.sigma.At(i, i)) + if math.Abs(norm.StdDev()-std) > 1e-14 { + t.Errorf("StdDev mismatch nil Sigma, idx %v: want %v, got %v.", i, std, norm.StdDev()) + } + } + } + + // Test matching with TestMarginal. + rnd := rand.New(rand.NewSource(1)) + for cas := 0; cas < 10; cas++ { + dim := rnd.Intn(10) + 1 + mu := make([]float64, dim) + for i := range mu { + mu[i] = rnd.Float64() + } + x := make([]float64, dim*dim) + for i := range x { + x[i] = rnd.Float64() + } + matrix := mat.NewDense(dim, dim, x) + var sigma mat.SymDense + sigma.SymOuterK(1, matrix) + + normal, ok := NewNormal(mu, &sigma, nil) + if !ok { + t.Fatal("bad test") + } + for i := 0; i < dim; i++ { + single := normal.MarginalNormalSingle(i, nil) + mult, ok := normal.MarginalNormal([]int{i}, nil) + if !ok { + t.Fatal("bad test") + } + if math.Abs(single.Mean()-mult.Mean(nil)[0]) > 1e-14 { + t.Errorf("Mean mismatch") + } + if math.Abs(single.Variance()-mult.CovarianceMatrix(nil).At(0, 0)) > 1e-14 { + t.Errorf("Variance mismatch") + } + } + } +} + +func TestNormalScoreInput(t *testing.T) { + for cas, test := range []struct { + mu []float64 + sigma *mat.SymDense + x []float64 + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + x: []float64{1, 3.1, -2}, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + x: []float64{1, 3.1, -2, 5}, + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + x := make([]float64, len(test.x)) + copy(x, test.x) + score := normal.ScoreInput(nil, x) + if !floats.Equal(x, test.x) { + t.Errorf("x modified during call to ScoreInput") + } + scoreFD := fd.Gradient(nil, normal.LogProb, x, nil) + if !floats.EqualApprox(score, scoreFD, 1e-4) { + t.Errorf("Case %d: derivative mismatch. Got %v, want %v", cas, score, scoreFD) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/normalbench_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/normalbench_test.go new file mode 100644 index 00000000..a8890439 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/normalbench_test.go @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "log" + "math/rand" + "testing" + + "gonum.org/v1/gonum/mat" +) + +func BenchmarkMarginalNormal10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + _ = normal.CovarianceMatrix(nil) // pre-compute sigma + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg, ok := normal.MarginalNormal([]int{1}, nil) + if !ok { + b.Error("bad test") + } + _ = marg + } +} + +func BenchmarkMarginalNormalReset10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg, ok := normal.MarginalNormal([]int{1}, nil) + if !ok { + b.Error("bad test") + } + _ = marg + } +} + +func BenchmarkMarginalNormalSingle10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg := normal.MarginalNormalSingle(1, nil) + _ = marg + } +} + +func randomNormal(sz int, rnd *rand.Rand) *Normal { + mu := make([]float64, sz) + for i := range mu { + mu[i] = rnd.Float64() + } + data := make([]float64, sz*sz) + for i := range data { + data[i] = rnd.Float64() + } + dM := mat.NewDense(sz, sz, data) + var sigma mat.SymDense + sigma.SymOuterK(1, dM) + + normal, ok := NewNormal(mu, &sigma, nil) + if !ok { + log.Fatal("bad test, not pos def") + } + return normal +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/statdist.go b/vendor/gonum.org/v1/gonum/stat/distmv/statdist.go new file mode 100644 index 00000000..9a2f3bd7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/statdist.go @@ -0,0 +1,320 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +// Bhattacharyya is a type for computing the Bhattacharyya distance between +// probability distributions. +// +// The Bhattacharyya distance is defined as +// D_B = -ln(BC(l,r)) +// BC = \int_-∞^∞ (p(x)q(x))^(1/2) dx +// Where BC is known as the Bhattacharyya coefficient. +// The Bhattacharyya distance is related to the Hellinger distance by +// H = sqrt(1-BC) +// For more information, see +// https://en.wikipedia.org/wiki/Bhattacharyya_distance +type Bhattacharyya struct{} + +// DistNormal computes the Bhattacharyya distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// For Normal distributions, the Bhattacharyya distance is +// Σ = (Σ_l + Σ_r)/2 +// D_B = (1/8)*(μ_l - μ_r)^T*Σ^-1*(μ_l - μ_r) + (1/2)*ln(det(Σ)/(det(Σ_l)*det(Σ_r))^(1/2)) +func (Bhattacharyya) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + var sigma mat.SymDense + sigma.AddSym(&l.sigma, &r.sigma) + sigma.ScaleSym(0.5, &sigma) + + var chol mat.Cholesky + chol.Factorize(&sigma) + + mahalanobis := stat.Mahalanobis(mat.NewVecDense(dim, l.mu), mat.NewVecDense(dim, r.mu), &chol) + mahalanobisSq := mahalanobis * mahalanobis + + dl := l.chol.LogDet() + dr := r.chol.LogDet() + ds := chol.LogDet() + + return 0.125*mahalanobisSq + 0.5*ds - 0.25*dl - 0.25*dr +} + +// DistUniform computes the Bhattacharyya distance between uniform distributions l and r. +// The dimensions of the input distributions must match or DistUniform will panic. +func (Bhattacharyya) DistUniform(l, r *Uniform) float64 { + if len(l.bounds) != len(r.bounds) { + panic(badSizeMismatch) + } + // BC = \int \sqrt(p(x)q(x)), which for uniform distributions is a constant + // over the volume where both distributions have positive probability. + // Compute the overlap and the value of sqrt(p(x)q(x)). The entropy is the + // negative log probability of the distribution (use instead of LogProb so + // it is not necessary to construct an x value). + // + // BC = volume * sqrt(p(x)q(x)) + // logBC = log(volume) + 0.5*(logP + logQ) + // D_B = -logBC + return -unifLogVolOverlap(l.bounds, r.bounds) + 0.5*(l.Entropy()+r.Entropy()) +} + +// unifLogVolOverlap computes the log of the volume of the hyper-rectangle where +// both uniform distributions have positive probability. +func unifLogVolOverlap(b1, b2 []Bound) float64 { + var logVolOverlap float64 + for dim, v1 := range b1 { + v2 := b2[dim] + // If the surfaces don't overlap, then the volume is 0 + if v1.Max <= v2.Min || v2.Max <= v1.Min { + return math.Inf(-1) + } + vol := math.Min(v1.Max, v2.Max) - math.Max(v1.Min, v2.Min) + logVolOverlap += math.Log(vol) + } + return logVolOverlap +} + +// CrossEntropy is a type for computing the cross-entropy between probability +// distributions. +// +// The cross-entropy is defined as +// - \int_x l(x) log(r(x)) dx = KL(l || r) + H(l) +// where KL is the Kullback-Leibler divergence and H is the entropy. +// For more information, see +// https://en.wikipedia.org/wiki/Cross_entropy +type CrossEntropy struct{} + +// DistNormal returns the cross-entropy between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +func (CrossEntropy) DistNormal(l, r *Normal) float64 { + if l.Dim() != r.Dim() { + panic(badSizeMismatch) + } + kl := KullbackLeibler{}.DistNormal(l, r) + return kl + l.Entropy() +} + +// Hellinger is a type for computing the Hellinger distance between probability +// distributions. +// +// The Hellinger distance is defined as +// H^2(l,r) = 1/2 * int_x (\sqrt(l(x)) - \sqrt(r(x)))^2 dx +// and is bounded between 0 and 1. +// The Hellinger distance is related to the Bhattacharyya distance by +// H^2 = 1 - exp(-Db) +// For more information, see +// https://en.wikipedia.org/wiki/Hellinger_distance +type Hellinger struct{} + +// DistNormal returns the Hellinger distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// See the documentation of Bhattacharyya.DistNormal for the formula for Normal +// distributions. +func (Hellinger) DistNormal(l, r *Normal) float64 { + if l.Dim() != r.Dim() { + panic(badSizeMismatch) + } + db := Bhattacharyya{}.DistNormal(l, r) + bc := math.Exp(-db) + return math.Sqrt(1 - bc) +} + +// KullbackLiebler is a type for computing the Kullback-Leibler divergence from l to r. +// +// The Kullback-Liebler divergence is defined as +// D_KL(l || r ) = \int_x p(x) log(p(x)/q(x)) dx +// Note that the Kullback-Liebler divergence is not symmetric with respect to +// the order of the input arguments. +type KullbackLeibler struct{} + +// DistNormal returns the KullbackLeibler distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// For two normal distributions, the KL divergence is computed as +// D_KL(l || r) = 0.5*[ln(|Σ_r|) - ln(|Σ_l|) + (μ_l - μ_r)^T*Σ_r^-1*(μ_l - μ_r) + tr(Σ_r^-1*Σ_l)-d] +func (KullbackLeibler) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + mahalanobis := stat.Mahalanobis(mat.NewVecDense(dim, l.mu), mat.NewVecDense(dim, r.mu), &r.chol) + mahalanobisSq := mahalanobis * mahalanobis + + // TODO(btracey): Optimize where there is a SolveCholeskySym + // TODO(btracey): There may be a more efficient way to just compute the trace + // Compute tr(Σ_r^-1*Σ_l) using the fact that Σ_l = U^T * U + var u mat.TriDense + l.chol.UTo(&u) + var m mat.Dense + err := r.chol.Solve(&m, u.T()) + if err != nil { + return math.NaN() + } + m.Mul(&m, &u) + tr := mat.Trace(&m) + + return r.logSqrtDet - l.logSqrtDet + 0.5*(mahalanobisSq+tr-float64(l.dim)) +} + +// DistUniform returns the KullbackLeibler distance between uniform distributions +// l and r. The dimensions of the input distributions must match or DistUniform +// will panic. +func (KullbackLeibler) DistUniform(l, r *Uniform) float64 { + bl := l.Bounds(nil) + br := r.Bounds(nil) + if len(bl) != len(br) { + panic(badSizeMismatch) + } + + // The KL is ∞ if l is not completely contained within r, because then + // r(x) is zero when l(x) is non-zero for some x. + contained := true + for i, v := range bl { + if v.Min < br[i].Min || br[i].Max < v.Max { + contained = false + break + } + } + if !contained { + return math.Inf(1) + } + + // The KL divergence is finite. + // + // KL defines 0*ln(0) = 0, so there is no contribution to KL where l(x) = 0. + // Inside the region, l(x) and r(x) are constant (uniform distribution), and + // this constant is integrated over l(x), which integrates out to one. + // The entropy is -log(p(x)). + logPx := -l.Entropy() + logQx := -r.Entropy() + return logPx - logQx +} + +// Renyi is a type for computing the Rényi divergence of order α from l to r. +// +// The Rényi divergence with α > 0, α ≠ 1 is defined as +// D_α(l || r) = 1/(α-1) log(\int_-∞^∞ l(x)^α r(x)^(1-α)dx) +// The Rényi divergence has special forms for α = 0 and α = 1. This type does +// not implement α = ∞. For α = 0, +// D_0(l || r) = -log \int_-∞^∞ r(x)1{p(x)>0} dx +// that is, the negative log probability under r(x) that l(x) > 0. +// When α = 1, the Rényi divergence is equal to the Kullback-Leibler divergence. +// The Rényi divergence is also equal to half the Bhattacharyya distance when α = 0.5. +// +// The parameter α must be in 0 ≤ α < ∞ or the distance functions will panic. +type Renyi struct { + Alpha float64 +} + +// DistNormal returns the Rényi divergence between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// For two normal distributions, the Rényi divergence is computed as +// Σ_α = (1-α) Σ_l + αΣ_r +// D_α(l||r) = α/2 * (μ_l - μ_r)'*Σ_α^-1*(μ_l - μ_r) + 1/(2(α-1))*ln(|Σ_λ|/(|Σ_l|^(1-α)*|Σ_r|^α)) +// +// For a more nicely formatted version of the formula, see Eq. 15 of +// Kolchinsky, Artemy, and Brendan D. Tracey. "Estimating Mixture Entropy +// with Pairwise Distances." arXiv preprint arXiv:1706.02419 (2017). +// Note that the this formula is for Chernoff divergence, which differs from +// Rényi divergence by a factor of 1-α. Also be aware that most sources in +// the literature report this formula incorrectly. +func (renyi Renyi) DistNormal(l, r *Normal) float64 { + if renyi.Alpha < 0 { + panic("renyi: alpha < 0") + } + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + if renyi.Alpha == 0 { + return 0 + } + if renyi.Alpha == 1 { + return KullbackLeibler{}.DistNormal(l, r) + } + + logDetL := l.chol.LogDet() + logDetR := r.chol.LogDet() + + // Σ_α = (1-α)Σ_l + αΣ_r. + sigA := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + for j := i; j < dim; j++ { + v := (1-renyi.Alpha)*l.sigma.At(i, j) + renyi.Alpha*r.sigma.At(i, j) + sigA.SetSym(i, j, v) + } + } + + var chol mat.Cholesky + ok := chol.Factorize(sigA) + if !ok { + return math.NaN() + } + logDetA := chol.LogDet() + + mahalanobis := stat.Mahalanobis(mat.NewVecDense(dim, l.mu), mat.NewVecDense(dim, r.mu), &chol) + mahalanobisSq := mahalanobis * mahalanobis + + return (renyi.Alpha/2)*mahalanobisSq + 1/(2*(1-renyi.Alpha))*(logDetA-(1-renyi.Alpha)*logDetL-renyi.Alpha*logDetR) +} + +// Wasserstein is a type for computing the Wasserstein distance between two +// probability distributions. +// +// The Wasserstein distance is defined as +// W(l,r) := inf 𝔼(||X-Y||_2^2)^1/2 +// For more information, see +// https://en.wikipedia.org/wiki/Wasserstein_metric +type Wasserstein struct{} + +// DistNormal returns the Wasserstein distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// The Wasserstein distance for Normal distributions is +// d^2 = ||m_l - m_r||_2^2 + Tr(Σ_l + Σ_r - 2(Σ_l^(1/2)*Σ_r*Σ_l^(1/2))^(1/2)) +// For more information, see +// http://djalil.chafai.net/blog/2010/04/30/wasserstein-distance-between-two-gaussians/ +func (Wasserstein) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + d := floats.Distance(l.mu, r.mu, 2) + d = d * d + + // Compute Σ_l^(1/2) + var ssl mat.SymDense + ssl.PowPSD(&l.sigma, 0.5) + // Compute Σ_l^(1/2)*Σ_r*Σ_l^(1/2) + var mean mat.Dense + mean.Mul(&ssl, &r.sigma) + mean.Mul(&mean, &ssl) + + // Reinterpret as symdense, and take Σ^(1/2) + meanSym := mat.NewSymDense(dim, mean.RawMatrix().Data) + ssl.PowPSD(meanSym, 0.5) + + tr := mat.Trace(&r.sigma) + tl := mat.Trace(&l.sigma) + tm := mat.Trace(&ssl) + + return d + tl + tr - 2*tm +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/statdist_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/statdist_test.go new file mode 100644 index 00000000..a3d1d9c2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/statdist_test.go @@ -0,0 +1,329 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func TestBhattacharyyaNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + want := bhattacharyyaSample(a.Dim(), test.samples, a, b) + got := Bhattacharyya{}.DistNormal(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Bhattacharyya mismatch, case %d: got %v, want %v", cas, got, want) + } + + // Bhattacharyya should by symmetric + got2 := Bhattacharyya{}.DistNormal(b, a) + if math.Abs(got-got2) > 1e-14 { + t.Errorf("Bhattacharyya distance not symmetric") + } + } +} + +func TestBhattacharyyaUniform(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + a, b *Uniform + samples int + tol float64 + }{ + { + a: NewUniform([]Bound{{-3, 2}, {-5, 8}}, rnd), + b: NewUniform([]Bound{{-4, 1}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + { + a: NewUniform([]Bound{{-3, 2}, {-5, 8}}, rnd), + b: NewUniform([]Bound{{-5, -4}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + } { + a, b := test.a, test.b + want := bhattacharyyaSample(a.Dim(), test.samples, a, b) + got := Bhattacharyya{}.DistUniform(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Bhattacharyya mismatch, case %d: got %v, want %v", cas, got, want) + } + // Bhattacharyya should by symmetric + got2 := Bhattacharyya{}.DistUniform(b, a) + if math.Abs(got-got2) > 1e-14 { + t.Errorf("Bhattacharyya distance not symmetric") + } + } +} + +// bhattacharyyaSample finds an estimate of the Bhattacharyya coefficient through +// sampling. +func bhattacharyyaSample(dim, samples int, l RandLogProber, r LogProber) float64 { + lBhatt := make([]float64, samples) + x := make([]float64, dim) + for i := 0; i < samples; i++ { + // Do importance sampling over a: \int sqrt(a*b)/a * a dx + l.Rand(x) + pa := l.LogProb(x) + pb := r.LogProb(x) + lBhatt[i] = 0.5*pb - 0.5*pa + } + logBc := floats.LogSumExp(lBhatt) - math.Log(float64(samples)) + return -logBc +} + +func TestCrossEntropyNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + var ce float64 + x := make([]float64, a.Dim()) + for i := 0; i < test.samples; i++ { + a.Rand(x) + ce -= b.LogProb(x) + } + ce /= float64(test.samples) + got := CrossEntropy{}.DistNormal(a, b) + if math.Abs(ce-got) > test.tol { + t.Errorf("CrossEntropy mismatch, case %d: got %v, want %v", cas, got, ce) + } + } +} + +func TestHellingerNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 5e-1, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + lAitchEDoubleHockeySticks := make([]float64, test.samples) + x := make([]float64, a.Dim()) + for i := 0; i < test.samples; i++ { + // Do importance sampling over a: \int (\sqrt(a)-\sqrt(b))^2/a * a dx + a.Rand(x) + pa := a.LogProb(x) + pb := b.LogProb(x) + d := math.Exp(0.5*pa) - math.Exp(0.5*pb) + d = d * d + lAitchEDoubleHockeySticks[i] = math.Log(d) - pa + } + want := math.Sqrt(0.5 * math.Exp(floats.LogSumExp(lAitchEDoubleHockeySticks)-math.Log(float64(test.samples)))) + got := Hellinger{}.DistNormal(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Hellinger mismatch, case %d: got %v, want %v", cas, got, want) + } + } +} + +func TestKullbackLeiblerNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 10000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + want := klSample(a.Dim(), test.samples, a, b) + got := KullbackLeibler{}.DistNormal(a, b) + if !floats.EqualWithinAbsOrRel(want, got, test.tol, test.tol) { + t.Errorf("Case %d, KL mismatch: got %v, want %v", cas, got, want) + } + } +} + +func TestKullbackLeiblerUniform(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + a, b *Uniform + samples int + tol float64 + }{ + { + a: NewUniform([]Bound{{-5, 2}, {-7, 12}}, rnd), + b: NewUniform([]Bound{{-4, 1}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + { + a: NewUniform([]Bound{{-5, 2}, {-7, 12}}, rnd), + b: NewUniform([]Bound{{-9, -6}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + } { + a, b := test.a, test.b + want := klSample(a.Dim(), test.samples, a, b) + got := KullbackLeibler{}.DistUniform(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Kullback-Leibler mismatch, case %d: got %v, want %v", cas, got, want) + } + } +} + +// klSample finds an estimate of the Kullback-Leibler divergence through sampling. +func klSample(dim, samples int, l RandLogProber, r LogProber) float64 { + var klmc float64 + x := make([]float64, dim) + for i := 0; i < samples; i++ { + l.Rand(x) + pa := l.LogProb(x) + pb := r.LogProb(x) + klmc += pa - pb + } + return klmc / float64(samples) +} + +func TestRenyiNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat.SymDense + alpha float64 + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + alpha: 0.3, + samples: 10000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + want := renyiSample(a.Dim(), test.samples, test.alpha, a, b) + got := Renyi{Alpha: test.alpha}.DistNormal(a, b) + if !floats.EqualWithinAbsOrRel(want, got, test.tol, test.tol) { + t.Errorf("Case %d: Renyi sampling mismatch: got %v, want %v", cas, got, want) + } + + // Compare with Bhattacharyya. + want = 2 * Bhattacharyya{}.DistNormal(a, b) + got = Renyi{Alpha: 0.5}.DistNormal(a, b) + if math.Abs(want-got) > 1e-10 { + t.Errorf("Case %d: Renyi mismatch with Bhattacharyya: got %v, want %v", cas, got, want) + } + + // Compare with KL in both directions. + want = KullbackLeibler{}.DistNormal(a, b) + got = Renyi{Alpha: 0.9999999}.DistNormal(a, b) // very close to 1 but not equal to 1. + if math.Abs(want-got) > 1e-6 { + t.Errorf("Case %d: Renyi mismatch with KL(a||b): got %v, want %v", cas, got, want) + } + want = KullbackLeibler{}.DistNormal(b, a) + got = Renyi{Alpha: 0.9999999}.DistNormal(b, a) // very close to 1 but not equal to 1. + if math.Abs(want-got) > 1e-6 { + t.Errorf("Case %d: Renyi mismatch with KL(b||a): got %v, want %v", cas, got, want) + } + } +} + +// renyiSample finds an estimate of the Rényi divergence through sampling. +// Note that this sampling procedure only works if l has broader support than r. +func renyiSample(dim, samples int, alpha float64, l RandLogProber, r LogProber) float64 { + rmcs := make([]float64, samples) + x := make([]float64, dim) + for i := 0; i < samples; i++ { + l.Rand(x) + pa := l.LogProb(x) + pb := r.LogProb(x) + rmcs[i] = (alpha-1)*pa + (1-alpha)*pb + } + return 1 / (alpha - 1) * (floats.LogSumExp(rmcs) - math.Log(float64(samples))) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/studentst.go b/vendor/gonum.org/v1/gonum/stat/distmv/studentst.go new file mode 100644 index 00000000..041b1369 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/studentst.go @@ -0,0 +1,354 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/distuv" +) + +// StudentsT is a multivariate Student's T distribution. It is a distribution over +// ℝ^n with the probability density +// p(y) = (Γ((ν+n)/2) / Γ(ν/2)) * (νπ)^(-n/2) * |Ʃ|^(-1/2) * +// (1 + 1/ν * (y-μ)^T * Ʃ^-1 * (y-μ))^(-(ν+n)/2) +// where ν is a scalar greater than 2, μ is a vector in ℝ^n, and Ʃ is an n×n +// symmetric positive definite matrix. +// +// In this distribution, ν sets the spread of the distribution, similar to +// the degrees of freedom in a univariate Student's T distribution. As ν → ∞, +// the distribution approaches a multi-variate normal distribution. +// μ is the mean of the distribution, and the covariance is ν/(ν-2)*Ʃ. +// +// See https://en.wikipedia.org/wiki/Student%27s_t-distribution and +// http://users.isy.liu.se/en/rt/roth/student.pdf for more information. +type StudentsT struct { + nu float64 + mu []float64 + src *rand.Rand + + sigma mat.SymDense // only stored if needed + + chol mat.Cholesky + lower mat.TriDense + logSqrtDet float64 + dim int +} + +// NewStudentsT creates a new StudentsT with the given nu, mu, and sigma +// parameters. +// +// NewStudentsT panics if len(mu) == 0, or if len(mu) != sigma.Symmetric(). If +// the covariance matrix is not positive-definite, nil is returned and ok is false. +func NewStudentsT(mu []float64, sigma mat.Symmetric, nu float64, src *rand.Rand) (dist *StudentsT, ok bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := sigma.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + + s := &StudentsT{ + nu: nu, + mu: make([]float64, dim), + dim: dim, + src: src, + } + copy(s.mu, mu) + + ok = s.chol.Factorize(sigma) + if !ok { + return nil, false + } + s.sigma = *mat.NewSymDense(dim, nil) + s.sigma.CopySym(sigma) + s.chol.LTo(&s.lower) + s.logSqrtDet = 0.5 * s.chol.LogDet() + return s, true +} + +// ConditionStudentsT returns the Student's T distribution that is the receiver +// conditioned on the input evidence, and the success of the operation. +// The returned Student's T has dimension +// n - len(observed), where n is the dimension of the original receiver. +// The dimension order is preserved during conditioning, so if the value +// of dimension 1 is observed, the returned normal represents dimensions {0, 2, ...} +// of the original Student's T distribution. +// +// ok indicates whether there was a failure during the update. If ok is false +// the operation failed and dist is not usable. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (s *StudentsT) ConditionStudentsT(observed []int, values []float64, src *rand.Rand) (dist *StudentsT, ok bool) { + if len(observed) == 0 { + panic("studentst: no observed value") + } + if len(observed) != len(values) { + panic(badInputLength) + } + + for _, v := range observed { + if v < 0 || v >= s.dim { + panic("studentst: observed value out of bounds") + } + } + + newNu, newMean, newSigma := studentsTConditional(observed, values, s.nu, s.mu, &s.sigma) + if newMean == nil { + return nil, false + } + + return NewStudentsT(newMean, newSigma, newNu, src) + +} + +// studentsTConditional updates a Student's T distribution based on the observed samples +// (see documentation for the public function). The Gaussian conditional update +// is treated as a special case when nu == math.Inf(1). +func studentsTConditional(observed []int, values []float64, nu float64, mu []float64, sigma mat.Symmetric) (newNu float64, newMean []float64, newSigma *mat.SymDense) { + dim := len(mu) + ob := len(observed) + + unobserved := findUnob(observed, dim) + + unob := len(unobserved) + if unob == 0 { + panic("stat: all dimensions observed") + } + + mu1 := make([]float64, unob) + for i, v := range unobserved { + mu1[i] = mu[v] + } + mu2 := make([]float64, ob) // really v - mu2 + for i, v := range observed { + mu2[i] = values[i] - mu[v] + } + + var sigma11, sigma22 mat.SymDense + sigma11.SubsetSym(sigma, unobserved) + sigma22.SubsetSym(sigma, observed) + + sigma21 := mat.NewDense(ob, unob, nil) + for i, r := range observed { + for j, c := range unobserved { + v := sigma.At(r, c) + sigma21.Set(i, j, v) + } + } + + var chol mat.Cholesky + ok := chol.Factorize(&sigma22) + if !ok { + return math.NaN(), nil, nil + } + + // Compute mu_1 + sigma_{2,1}^T * sigma_{2,2}^-1 (v - mu_2). + v := mat.NewVecDense(ob, mu2) + var tmp, tmp2 mat.VecDense + err := chol.SolveVec(&tmp, v) + if err != nil { + return math.NaN(), nil, nil + } + tmp2.MulVec(sigma21.T(), &tmp) + + for i := range mu1 { + mu1[i] += tmp2.At(i, 0) + } + + // Compute tmp4 = sigma_{2,1}^T * sigma_{2,2}^-1 * sigma_{2,1}. + // TODO(btracey): Should this be a method of SymDense? + var tmp3, tmp4 mat.Dense + err = chol.Solve(&tmp3, sigma21) + if err != nil { + return math.NaN(), nil, nil + } + tmp4.Mul(sigma21.T(), &tmp3) + + // Compute sigma_{1,1} - tmp4 + // TODO(btracey): If tmp4 can constructed with a method, then this can be + // replaced with SubSym. + for i := 0; i < len(unobserved); i++ { + for j := i; j < len(unobserved); j++ { + v := sigma11.At(i, j) + sigma11.SetSym(i, j, v-tmp4.At(i, j)) + } + } + + // The computed variables are accurate for a Normal. + if math.IsInf(nu, 1) { + return nu, mu1, &sigma11 + } + + // Compute beta = (v - mu_2)^T * sigma_{2,2}^-1 * (v - mu_2)^T + beta := mat.Dot(v, &tmp) + + // Scale the covariance matrix + sigma11.ScaleSym((nu+beta)/(nu+float64(ob)), &sigma11) + + return nu + float64(ob), mu1, &sigma11 +} + +// findUnob returns the unobserved variables (the complementary set to observed). +// findUnob panics if any value repeated in observed. +func findUnob(observed []int, dim int) (unobserved []int) { + var setOb intsets.Sparse + for _, v := range observed { + setOb.Insert(v) + } + var setAll intsets.Sparse + for i := 0; i < dim; i++ { + setAll.Insert(i) + } + var setUnob intsets.Sparse + setUnob.Difference(&setAll, &setOb) + unobserved = setUnob.AppendTo(nil) + sort.Ints(unobserved) + return unobserved +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (st *StudentsT) CovarianceMatrix(s *mat.SymDense) *mat.SymDense { + if s == nil { + s = mat.NewSymDense(st.dim, nil) + } + sn := s.Symmetric() + if sn != st.dim { + panic("normal: input matrix size mismatch") + } + s.CopySym(&st.sigma) + s.ScaleSym(st.nu/(st.nu-2), s) + return s +} + +// Dim returns the dimension of the distribution. +func (s *StudentsT) Dim() int { + return s.dim +} + +// LogProb computes the log of the pdf of the point x. +func (s *StudentsT) LogProb(y []float64) float64 { + if len(y) != s.dim { + panic(badInputLength) + } + + nu := s.nu + n := float64(s.dim) + lg1, _ := math.Lgamma((nu + n) / 2) + lg2, _ := math.Lgamma(nu / 2) + + t1 := lg1 - lg2 - n/2*math.Log(nu*math.Pi) - s.logSqrtDet + + shift := make([]float64, len(y)) + copy(shift, y) + floats.Sub(shift, s.mu) + + x := mat.NewVecDense(s.dim, shift) + + var tmp mat.VecDense + s.chol.SolveVec(&tmp, x) + + dot := mat.Dot(&tmp, x) + + return t1 - ((nu+n)/2)*math.Log(1+dot/nu) +} + +// MarginalStudentsT returns the marginal distribution of the given input variables, +// and the success of the operation. +// That is, MarginalStudentsT returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where x_i are the dimensions in the input, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the created StudentsT. +// +// ok indicates whether there was a failure during the marginalization. If ok is false +// the operation failed and dist is not usable. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (s *StudentsT) MarginalStudentsT(vars []int, src *rand.Rand) (dist *StudentsT, ok bool) { + newMean := make([]float64, len(vars)) + for i, v := range vars { + newMean[i] = s.mu[v] + } + var newSigma mat.SymDense + newSigma.SubsetSym(&s.sigma, vars) + return NewStudentsT(newMean, &newSigma, s.nu, src) +} + +// MarginalStudentsT returns the marginal distribution of the given input variable. +// That is, MarginalStudentsT returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where i is the input index, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the call to NewStudentsT. +func (s *StudentsT) MarginalStudentsTSingle(i int, src *rand.Rand) distuv.StudentsT { + return distuv.StudentsT{ + Mu: s.mu[i], + Sigma: math.Sqrt(s.sigma.At(i, i)), + Nu: s.nu, + Src: src, + } +} + +// TODO(btracey): Implement marginal single. Need to modify univariate StudentsT +// to be three-parameter. + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (s *StudentsT) Mean(x []float64) []float64 { + x = reuseAs(x, s.dim) + copy(x, s.mu) + return x +} + +// Prob computes the value of the probability density function at x. +func (s *StudentsT) Prob(y []float64) float64 { + return math.Exp(s.LogProb(y)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (s *StudentsT) Rand(x []float64) []float64 { + // If Y is distributed according to N(0,Sigma), and U is chi^2 with + // parameter ν, then + // X = mu + Y * sqrt(nu / U) + // X is distributed according to this distribution. + + // Generate Y. + x = reuseAs(x, s.dim) + tmp := make([]float64, s.dim) + if s.src == nil { + for i := range x { + tmp[i] = rand.NormFloat64() + } + } else { + for i := range x { + tmp[i] = s.src.NormFloat64() + } + } + xVec := mat.NewVecDense(s.dim, x) + tmpVec := mat.NewVecDense(s.dim, tmp) + xVec.MulVec(&s.lower, tmpVec) + + u := distuv.ChiSquared{K: s.nu, Src: s.src}.Rand() + floats.Scale(math.Sqrt(s.nu/u), x) + + floats.Add(x, s.mu) + return x +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/studentst_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/studentst_test.go new file mode 100644 index 00000000..b21a07f8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/studentst_test.go @@ -0,0 +1,265 @@ +// Copyright ©2016 The gonum 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 distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +func TestStudentTProbs(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for _, test := range []struct { + nu float64 + mu []float64 + sigma *mat.SymDense + + x [][]float64 + probs []float64 + }{ + { + nu: 3, + mu: []float64{0, 0}, + sigma: mat.NewSymDense(2, []float64{1, 0, 0, 1}), + + x: [][]float64{ + {0, 0}, + {1, -1}, + {3, 4}, + {-1, -2}, + }, + // Outputs compared with WolframAlpha. + probs: []float64{ + 0.159154943091895335768883, + 0.0443811199724279860006777747927, + 0.0005980371870904696541052658, + 0.01370560783418571283428283, + }, + }, + { + nu: 4, + mu: []float64{2, -3}, + sigma: mat.NewSymDense(2, []float64{8, -1, -1, 5}), + + x: [][]float64{ + {0, 0}, + {1, -1}, + {3, 4}, + {-1, -2}, + {2, -3}, + }, + // Outputs compared with WolframAlpha. + probs: []float64{ + 0.007360810111491788657953608191001, + 0.0143309905845607117740440592999, + 0.0005307774290578041397794096037035009801668903, + 0.0115657422475668739943625904793879, + 0.0254851872062589062995305736215, + }, + }, + } { + s, ok := NewStudentsT(test.mu, test.sigma, test.nu, src) + if !ok { + t.Fatal("bad test") + } + for i, x := range test.x { + xcpy := make([]float64, len(x)) + copy(xcpy, x) + p := s.Prob(x) + if !floats.Same(x, xcpy) { + t.Errorf("X modified during call to prob, %v, %v", x, xcpy) + } + if !floats.EqualWithinAbsOrRel(p, test.probs[i], 1e-10, 1e-10) { + t.Errorf("Probability mismatch. X = %v. Got %v, want %v.", x, p, test.probs[i]) + } + } + } +} + +func TestStudentsTRand(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + mean []float64 + cov *mat.SymDense + nu float64 + tolcov float64 + }{ + { + mean: []float64{0, 0}, + cov: mat.NewSymDense(2, []float64{1, 0, 0, 1}), + nu: 4, + tolcov: 1e-2, + }, + { + mean: []float64{3, 4}, + cov: mat.NewSymDense(2, []float64{5, 1.2, 1.2, 6}), + nu: 8, + tolcov: 1e-2, + }, + { + mean: []float64{3, 4, -2}, + cov: mat.NewSymDense(3, []float64{5, 1.2, -0.8, 1.2, 6, 0.4, -0.8, 0.4, 2}), + nu: 8, + tolcov: 1e-2, + }, + } { + s, ok := NewStudentsT(test.mean, test.cov, test.nu, src) + if !ok { + t.Fatal("bad test") + } + const nSamples = 1e6 + dim := len(test.mean) + samps := mat.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + s.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat.Col(nil, i, samps), nil) + } + mean := s.Mean(nil) + if !floats.EqualApprox(estMean, mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + cov := s.CovarianceMatrix(nil) + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat.EqualApprox(estCov, cov, test.tolcov) { + t.Errorf("Case %d: Cov mismatch: want: %v, got %v", cas, cov, estCov) + } + } +} + +func TestStudentsTConditional(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for _, test := range []struct { + mean []float64 + cov *mat.SymDense + nu float64 + + idx []int + value []float64 + tolcov float64 + }{ + { + mean: []float64{3, 4, -2}, + cov: mat.NewSymDense(3, []float64{5, 1.2, -0.8, 1.2, 6, 0.4, -0.8, 0.4, 2}), + nu: 8, + idx: []int{0}, + value: []float64{6}, + + tolcov: 1e-2, + }, + } { + s, ok := NewStudentsT(test.mean, test.cov, test.nu, src) + if !ok { + t.Fatal("bad test") + } + + sUp, ok := s.ConditionStudentsT(test.idx, test.value, src) + if !ok { + t.Error("unexpected failure of ConditionStudentsT") + } + + // Compute the other values by hand the inefficient way to compare + newNu := test.nu + float64(len(test.idx)) + if newNu != sUp.nu { + t.Errorf("Updated nu mismatch. Got %v, want %v", s.nu, newNu) + } + dim := len(test.mean) + unob := findUnob(test.idx, dim) + ob := test.idx + + muUnob := make([]float64, len(unob)) + for i, v := range unob { + muUnob[i] = test.mean[v] + } + muOb := make([]float64, len(ob)) + for i, v := range ob { + muOb[i] = test.mean[v] + } + + var sig11, sig22 mat.SymDense + sig11.SubsetSym(&s.sigma, unob) + sig22.SubsetSym(&s.sigma, ob) + + sig12 := mat.NewDense(len(unob), len(ob), nil) + for i := range unob { + for j := range ob { + sig12.Set(i, j, s.sigma.At(unob[i], ob[j])) + } + } + + shift := make([]float64, len(ob)) + copy(shift, test.value) + floats.Sub(shift, muOb) + + newMu := make([]float64, len(muUnob)) + newMuVec := mat.NewVecDense(len(muUnob), newMu) + shiftVec := mat.NewVecDense(len(shift), shift) + var tmp mat.VecDense + tmp.SolveVec(&sig22, shiftVec) + newMuVec.MulVec(sig12, &tmp) + floats.Add(newMu, muUnob) + + if !floats.EqualApprox(newMu, sUp.mu, 1e-10) { + t.Errorf("Mu mismatch. Got %v, want %v", sUp.mu, newMu) + } + + var tmp2 mat.Dense + tmp2.Solve(&sig22, sig12.T()) + + var tmp3 mat.Dense + tmp3.Mul(sig12, &tmp2) + tmp3.Sub(&sig11, &tmp3) + + dot := mat.Dot(shiftVec, &tmp) + tmp3.Scale((test.nu+dot)/(test.nu+float64(len(ob))), &tmp3) + if !mat.EqualApprox(&tmp3, &sUp.sigma, 1e-10) { + t.Errorf("Sigma mismatch") + } + } +} + +func TestStudentsTMarginalSingle(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat.SymDense + nu float64 + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + nu: 5, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + nu: 6, + }, + } { + studentst, ok := NewStudentsT(test.mu, test.sigma, test.nu, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + for i, mean := range test.mu { + st := studentst.MarginalStudentsTSingle(i, nil) + if st.Mean() != mean { + t.Errorf("Mean mismatch nil Sigma, idx %v: want %v, got %v.", i, mean, st.Mean()) + } + std := math.Sqrt(test.sigma.At(i, i)) + if math.Abs(st.Sigma-std) > 1e-14 { + t.Errorf("StdDev mismatch nil Sigma, idx %v: want %v, got %v.", i, std, st.StdDev()) + } + if st.Nu != test.nu { + t.Errorf("Nu mismatch nil Sigma, idx %v: want %v, got %v ", i, test.nu, st.Nu) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/uniform.go b/vendor/gonum.org/v1/gonum/stat/distmv/uniform.go new file mode 100644 index 00000000..c28a0232 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/uniform.go @@ -0,0 +1,196 @@ +// Copyright ©2015 The gonum 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 distmv + +import ( + "math" + "math/rand" +) + +type Bound struct { + Min float64 + Max float64 +} + +// Uniform represents a multivariate uniform distribution. +type Uniform struct { + bounds []Bound + dim int + src *rand.Rand +} + +// NewUniform creates a new uniform distribution with the given bounds. +func NewUniform(bnds []Bound, src *rand.Rand) *Uniform { + dim := len(bnds) + if dim == 0 { + panic(badZeroDimension) + } + for _, b := range bnds { + if b.Max < b.Min { + panic("uniform: maximum less than minimum") + } + } + u := &Uniform{ + bounds: make([]Bound, dim), + dim: dim, + src: src, + } + for i, b := range bnds { + u.bounds[i].Min = b.Min + u.bounds[i].Max = b.Max + } + return u +} + +// NewUnitUniform creates a new Uniform distribution over the dim-dimensional +// unit hypercube. That is, a uniform distribution where each dimension has +// Min = 0 and Max = 1. +func NewUnitUniform(dim int, src *rand.Rand) *Uniform { + if dim <= 0 { + panic(nonPosDimension) + } + bounds := make([]Bound, dim) + for i := range bounds { + bounds[i].Min = 0 + bounds[i].Max = 1 + } + return &Uniform{ + bounds: bounds, + dim: dim, + src: src, + } +} + +// Bounds returns the bounds on the variables of the distribution. If the input +// is nil, a new slice is allocated and returned. If the input is non-nil, then +// the bounds are stored in-place into the input argument, and Bounds will panic +// if len(bounds) != u.Dim(). +func (u *Uniform) Bounds(bounds []Bound) []Bound { + if bounds == nil { + bounds = make([]Bound, u.Dim()) + } + if len(bounds) != u.Dim() { + panic(badInputLength) + } + copy(bounds, u.bounds) + return bounds +} + +// CDF returns the multidimensional cumulative distribution function of the +// probability distribution at the point x. If p is non-nil, the CDF is stored +// in-place into the first argument, otherwise a new slice is allocated and +// returned. +// +// CDF will panic if len(x) is not equal to the dimension of the distribution, +// or if p is non-nil and len(p) is not equal to the dimension of the distribution. +func (u *Uniform) CDF(p, x []float64) []float64 { + if len(x) != u.dim { + panic(badSizeMismatch) + } + if p == nil { + p = make([]float64, u.dim) + } + if len(p) != u.dim { + panic(badSizeMismatch) + } + for i, v := range x { + if v < u.bounds[i].Min { + p[i] = 0 + } else if v > u.bounds[i].Max { + p[i] = 1 + } else { + p[i] = (v - u.bounds[i].Min) / (u.bounds[i].Max - u.bounds[i].Min) + } + } + return p +} + +// Dim returns the dimension of the distribution. +func (u *Uniform) Dim() int { + return u.dim +} + +// Entropy returns the differential entropy of the distribution. +func (u *Uniform) Entropy() float64 { + // Entropy is log of the volume. + var logVol float64 + for _, b := range u.bounds { + logVol += math.Log(b.Max - b.Min) + } + return logVol +} + +// LogProb computes the log of the pdf of the point x. +func (u *Uniform) LogProb(x []float64) float64 { + dim := u.dim + if len(x) != dim { + panic(badSizeMismatch) + } + var logprob float64 + for i, b := range u.bounds { + if x[i] < b.Min || x[i] > b.Max { + return math.Inf(-1) + } + logprob -= math.Log(b.Max - b.Min) + } + return logprob +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (u *Uniform) Mean(x []float64) []float64 { + x = reuseAs(x, u.dim) + for i, b := range u.bounds { + x[i] = (b.Max + b.Min) / 2 + } + return x +} + +// Prob computes the value of the probability density function at x. +func (u *Uniform) Prob(x []float64) float64 { + return math.Exp(u.LogProb(x)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (u *Uniform) Rand(x []float64) []float64 { + x = reuseAs(x, u.dim) + if u.src == nil { + for i, b := range u.bounds { + x[i] = rand.Float64()*(b.Max-b.Min) + b.Min + } + return x + } + for i, b := range u.bounds { + x[i] = rand.Float64()*(b.Max-b.Min) + b.Min + } + return x +} + +// Quantile returns the multi-dimensional inverse cumulative distribution function. +// len(x) must equal len(p), and if x is non-nil, len(x) must also equal len(p). +// If x is nil, a new slice will be allocated and returned, otherwise the quantile +// will be stored in-place into x. All of the values of p must be between 0 and 1, +// or Quantile will panic. +func (u *Uniform) Quantile(x, p []float64) []float64 { + if len(p) != u.dim { + panic(badSizeMismatch) + } + if x == nil { + x = make([]float64, u.dim) + } + if len(x) != u.dim { + panic(badSizeMismatch) + } + for i, v := range p { + if v < 0 || v > 1 { + panic(badQuantile) + } + x[i] = v*(u.bounds[i].Max-u.bounds[i].Min) + u.bounds[i].Min + } + return x +} diff --git a/vendor/gonum.org/v1/gonum/stat/distmv/uniform_test.go b/vendor/gonum.org/v1/gonum/stat/distmv/uniform_test.go new file mode 100644 index 00000000..c52e09a9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distmv/uniform_test.go @@ -0,0 +1,31 @@ +// Copyright ©2017 The gonum 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 distmv + +import ( + "math" + "testing" +) + +func TestUniformEntropy(t *testing.T) { + for _, test := range []struct { + Uniform *Uniform + Entropy float64 + }{ + { + NewUniform([]Bound{{0, 1}, {0, 1}}, nil), + 0, + }, + { + NewUniform([]Bound{{-1, 3}, {2, 8}, {-5, -3}}, nil), + math.Log(48), + }, + } { + ent := test.Uniform.Entropy() + if math.Abs(ent-test.Entropy) > 1e-14 { + t.Errorf("Entropy mismatch. Got %v, want %v", ent, test.Entropy) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go b/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go new file mode 100644 index 00000000..c03578f1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go @@ -0,0 +1,131 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" +) + +// Bernoulli represents a random variable whose value is 1 with probability p and +// value of zero with probability 1-P. The value of P must be between 0 and 1. +// More information at https://en.wikipedia.org/wiki/Bernoulli_distribution. +type Bernoulli struct { + P float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (b Bernoulli) CDF(x float64) float64 { + if x < 0 { + return 0 + } + if x < 1 { + return 1 - b.P + } + return 1 +} + +// Entropy returns the entropy of the distribution. +func (b Bernoulli) Entropy() float64 { + if b.P == 0 { + return 0 + } + if b.P == 1 { + return 1 + } + q := 1 - b.P + return -b.P*math.Log(b.P) - q*math.Log(q) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (b Bernoulli) ExKurtosis() float64 { + pq := b.P * (1 - b.P) + return (1 - 6*pq) / pq +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (b Bernoulli) LogProb(x float64) float64 { + if x == 0 { + return math.Log(1 - b.P) + } + if x == 1 { + return math.Log(b.P) + } + return math.Inf(-1) +} + +// Mean returns the mean of the probability distribution. +func (b Bernoulli) Mean() float64 { + return b.P +} + +// Median returns the median of the probability distribution. +func (b Bernoulli) Median() float64 { + p := b.P + switch { + case p < 0.5: + return 0 + case p > 0.5: + return 1 + default: + return 0.5 + } +} + +// NumParameters returns the number of parameters in the distribution. +func (Bernoulli) NumParameters() int { + return 1 +} + +// Prob computes the value of the probability distribution at x. +func (b Bernoulli) Prob(x float64) float64 { + return math.Exp(b.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (b Bernoulli) Quantile(p float64) float64 { + if p < 0 || 1 < p { + panic(badPercentile) + } + if p < 1-b.P { + return 0 + } + return 1 +} + +// Rand returns a random sample drawn from the distribution. +func (b Bernoulli) Rand() float64 { + var rnd float64 + if b.Source == nil { + rnd = rand.Float64() + } else { + rnd = b.Source.Float64() + } + if rnd < b.P { + return 1 + } + return 0 +} + +// Skewness returns the skewness of the distribution. +func (b Bernoulli) Skewness() float64 { + return (1 - 2*b.P) / math.Sqrt(b.P*(1-b.P)) +} + +// StdDev returns the standard deviation of the probability distribution. +func (b Bernoulli) StdDev() float64 { + return math.Sqrt(b.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (b Bernoulli) Survival(x float64) float64 { + return 1 - b.CDF(x) +} + +// Variance returns the variance of the probability distribution. +func (b Bernoulli) Variance() float64 { + return b.P * (1 - b.P) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli_test.go new file mode 100644 index 00000000..107135ec --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli_test.go @@ -0,0 +1,23 @@ +// Copyright ©2016 The gonum 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 distuv + +import "testing" + +func TestBernoulli(t *testing.T) { + for i, dist := range []Bernoulli{ + { + P: 0.5, + }, + { + P: 0.9, + }, + { + P: 0.2, + }, + } { + testFullDist(t, dist, i, false) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/beta.go b/vendor/gonum.org/v1/gonum/stat/distuv/beta.go new file mode 100644 index 00000000..7c456009 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/beta.go @@ -0,0 +1,126 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// Beta implements the Beta distribution, a two-parameter continuous distribution +// with support between 0 and 1. +// +// The beta distribution has density function +// x^(α-1) * (1-x)^(β-1) * Γ(α+β) / (Γ(α)*Γ(β)) +// +// For more information, see https://en.wikipedia.org/wiki/Beta_distribution +type Beta struct { + // Alpha is the left shape parameter of the distribution. Alpha must be greater + // than 0. + Alpha float64 + // Beta is the right shape parameter of the distribution. Beta must be greater + // than 0. + Beta float64 + + Source *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (b Beta) CDF(x float64) float64 { + if x <= 0 { + return 0 + } + if x >= 1 { + return 1 + } + return mathext.RegIncBeta(b.Alpha, b.Beta, x) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (b Beta) ExKurtosis() float64 { + num := 6 * ((b.Alpha-b.Beta)*(b.Alpha-b.Beta)*(b.Alpha+b.Beta+1) - b.Alpha*b.Beta*(b.Alpha+b.Beta+2)) + den := b.Alpha * b.Beta * (b.Alpha + b.Beta + 2) * (b.Alpha + b.Beta + 3) + return num / den +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (b Beta) LogProb(x float64) float64 { + if x < 0 || x > 1 { + return math.Inf(-1) + } + + if b.Alpha <= 0 || b.Beta <= 0 { + panic("beta: negative parameters") + } + + lab, _ := math.Lgamma(b.Alpha + b.Beta) + la, _ := math.Lgamma(b.Alpha) + lb, _ := math.Lgamma(b.Beta) + return lab - la - lb + (b.Alpha-1)*math.Log(x) + (b.Beta-1)*math.Log(1-x) +} + +// Mean returns the mean of the probability distribution. +func (b Beta) Mean() float64 { + return b.Alpha / (b.Alpha + b.Beta) +} + +// Mode returns the mode of the distribution. +// +// Mode returns NaN if either parameter is less than or equal to 1 as a special case. +func (b Beta) Mode() float64 { + if b.Alpha <= 1 || b.Beta <= 1 { + return math.NaN() + } + return (b.Alpha - 1) / (b.Alpha + b.Beta - 2) +} + +// NumParameters returns the number of parameters in the distribution. +func (b Beta) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (b Beta) Prob(x float64) float64 { + return math.Exp(b.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (b Beta) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.InvRegIncBeta(b.Alpha, b.Beta, p) +} + +// Rand returns a random sample drawn from the distribution. +func (b Beta) Rand() float64 { + ga := Gamma{Alpha: b.Alpha, Beta: 1, Source: b.Source}.Rand() + gb := Gamma{Alpha: b.Beta, Beta: 1, Source: b.Source}.Rand() + return ga / (ga + gb) +} + +// StdDev returns the standard deviation of the probability distribution. +func (b Beta) StdDev() float64 { + return math.Sqrt(b.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (b Beta) Survival(x float64) float64 { + switch { + case x <= 0: + return 1 + case x >= 1: + return 0 + } + return mathext.RegIncBeta(b.Beta, b.Alpha, 1-x) +} + +// Variance returns the variance of the probability distribution. +func (b Beta) Variance() float64 { + return b.Alpha * b.Beta / ((b.Alpha + b.Beta) * (b.Alpha + b.Beta) * (b.Alpha + b.Beta + 1)) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/beta_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/beta_test.go new file mode 100644 index 00000000..ffa1c25b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/beta_test.go @@ -0,0 +1,61 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestBetaProb(t *testing.T) { + // Values a comparison with scipy + for _, test := range []struct { + x, alpha, beta, want float64 + }{ + {0.1, 2, 0.5, 0.079056941504209499}, + {0.5, 1, 5.1, 0.29740426605235754}, + {0.1, 0.5, 0.5, 1.0610329539459691}, + {1, 0.5, 0.5, math.Inf(1)}, + {-1, 0.5, 0.5, 0}, + } { + pdf := Beta{Alpha: test.alpha, Beta: test.beta}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch. Got %v, want %v", pdf, test.want) + } + } +} + +func TestBetaRand(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []Beta{ + {Alpha: 0.5, Beta: 0.5, Source: src}, + {Alpha: 5, Beta: 1, Source: src}, + {Alpha: 2, Beta: 2, Source: src}, + {Alpha: 2, Beta: 5, Source: src}, + } { + testBeta(t, b, i) + } +} + +func testBeta(t *testing.T, b Beta, i int) { + tol := 1e-2 + const n = 5e4 + const bins = 10 + x := make([]float64, n) + generateSamples(x, b) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, b, tol, bins) + checkMean(t, i, x, b, tol) + checkVarAndStd(t, i, x, b, tol) + checkExKurtosis(t, i, x, b, 5e-2) + checkProbContinuous(t, i, x, b, 1e-3) + checkQuantileCDFSurvival(t, i, x, b, tol) + checkProbQuantContinuous(t, i, x, b, tol) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go b/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go new file mode 100644 index 00000000..d2053e93 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go @@ -0,0 +1,184 @@ +// Copyright ©2015 The gonum 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 distuv + +import ( + "math" + "math/rand" +) + +// Categorical is an extension of the Bernoulli distribution where x takes +// values {0, 1, ..., len(w)-1} where w is the weight vector. Categorical must +// be initialized with NewCategorical. +type Categorical struct { + weights []float64 + + // heap is a weight heap. + // + // It keeps a heap-organised sum of remaining + // index weights that are available to be taken + // from. + // + // Each element holds the sum of weights for + // the corresponding index, plus the sum of + // of its children's weights; the children + // of an element i can be found at positions + // 2*(i+1)-1 and 2*(i+1). The root of the + // weight heap is at element 0. + // + // See comments in container/heap for an + // explanation of the layout of a heap. + heap []float64 + + src *rand.Rand +} + +// NewCategorical constructs a new categorical distribution where the probability +// that x equals i is proportional to w[i]. All of the weights must be +// nonnegative, and at least one of the weights must be positive. +func NewCategorical(w []float64, src *rand.Rand) Categorical { + c := Categorical{ + weights: make([]float64, len(w)), + heap: make([]float64, len(w)), + src: src, + } + c.ReweightAll(w) + return c +} + +// CDF computes the value of the cumulative density function at x. +func (c Categorical) CDF(x float64) float64 { + var cdf float64 + for i, w := range c.weights { + if x < float64(i) { + break + } + cdf += w + } + return cdf / c.heap[0] +} + +// Entropy returns the entropy of the distribution. +func (c Categorical) Entropy() float64 { + var ent float64 + for _, w := range c.weights { + if w == 0 { + continue + } + p := w / c.heap[0] + ent += p * math.Log(p) + } + return -ent +} + +// Len returns the number of values x could possibly take (the length of the +// initial supplied weight vector). +func (c Categorical) Len() int { + return len(c.weights) +} + +// Mean returns the mean of the probability distribution. +func (c Categorical) Mean() float64 { + var mean float64 + for i, v := range c.weights { + mean += float64(i) * v + } + return mean / c.heap[0] +} + +// Prob computes the value of the probability density function at x. +func (c Categorical) Prob(x float64) float64 { + xi := int(x) + if float64(xi) != x { + return 0 + } + if xi < 0 || xi > len(c.weights)-1 { + return 0 + } + return c.weights[xi] / c.heap[0] +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (c Categorical) LogProb(x float64) float64 { + return math.Log(c.Prob(x)) +} + +// Rand returns a random draw from the categorical distribution. +func (c Categorical) Rand() float64 { + var r float64 + if c.src == nil { + r = c.heap[0] * rand.Float64() + } else { + r = c.heap[0] * c.src.Float64() + } + i := 1 + last := -1 + left := len(c.weights) + for { + if r -= c.weights[i-1]; r <= 0 { + break // Fall within item i-1. + } + i <<= 1 // Move to left child. + if d := c.heap[i-1]; r > d { + r -= d + // If enough r to pass left child, + // move to right child state will + // be caught at break above. + i++ + } + if i == last || left < 0 { + panic("categorical: bad sample") + } + last = i + left-- + } + return float64(i - 1) +} + +// Reweight sets the weight of item idx to w. The input weight must be +// non-negative, and after reweighting at least one of the weights must be +// positive. +func (c Categorical) Reweight(idx int, w float64) { + if w < 0 { + panic("categorical: negative weight") + } + w, c.weights[idx] = c.weights[idx]-w, w + idx++ + for idx > 0 { + c.heap[idx-1] -= w + idx >>= 1 + } + if c.heap[0] <= 0 { + panic("categorical: sum of the weights non-positive") + } +} + +// ReweightAll resets the weights of the distribution. ReweightAll panics if +// len(w) != c.Len. All of the weights must be nonnegative, and at least one of +// the weights must be positive. +func (c Categorical) ReweightAll(w []float64) { + if len(w) != c.Len() { + panic("categorical: length of the slices do not match") + } + for _, v := range w { + if v < 0 { + panic("categorical: negative weight") + } + } + copy(c.weights, w) + c.reset() +} + +func (c Categorical) reset() { + copy(c.heap, c.weights) + for i := len(c.heap) - 1; i > 0; i-- { + // Sometimes 1-based counting makes sense. + c.heap[((i+1)>>1)-1] += c.heap[i] + } + // TODO(btracey): Renormalization for weird weights? + if c.heap[0] <= 0 { + panic("categorical: sum of the weights non-positive") + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/categorical_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/categorical_test.go new file mode 100644 index 00000000..decd181d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/categorical_test.go @@ -0,0 +1,196 @@ +// Copyright ©2015 The gonum 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 distuv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestCategoricalProb(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0}, + } { + dist := NewCategorical(test, nil) + norm := make([]float64, len(test)) + floats.Scale(1/floats.Sum(norm), norm) + for i, v := range norm { + p := dist.Prob(float64(i)) + if math.Abs(p-v) > 1e-14 { + t.Errorf("Probability mismatch element %d", i) + } + p = dist.Prob(float64(i) + 0.5) + if p != 0 { + t.Errorf("Non-zero probability for non-integer x") + } + } + p := dist.Prob(-1) + if p != 0 { + t.Errorf("Non-zero probability for -1") + } + p = dist.Prob(float64(len(test))) + if p != 0 { + t.Errorf("Non-zero probability for len(test)") + } + } +} + +func TestCategoricalRand(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0}, + } { + dist := NewCategorical(test, nil) + nSamples := 2000000 + counts := sampleCategorical(t, dist, nSamples) + + probs := make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same := samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch. Want %v, got %v", probs, counts) + } + + dist.Reweight(len(test)-1, 10) + counts = sampleCategorical(t, dist, nSamples) + probs = make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same = samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch after Reweight. Want %v, got %v", probs, counts) + } + + w := make([]float64, len(test)) + for i := range w { + w[i] = rand.Float64() + } + + dist.ReweightAll(w) + counts = sampleCategorical(t, dist, nSamples) + probs = make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same = samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch after ReweightAll. Want %v, got %v", probs, counts) + } + } +} + +func sampleCategorical(t *testing.T, dist Categorical, nSamples int) []float64 { + counts := make([]float64, dist.Len()) + for i := 0; i < nSamples; i++ { + v := dist.Rand() + if float64(int(v)) != v { + t.Fatalf("Random number is not an integer") + } + counts[int(v)]++ + } + sum := floats.Sum(counts) + floats.Scale(1/sum, counts) + return counts +} + +func samedDistCategorical(dist Categorical, counts, probs []float64, tol float64) bool { + same := true + for i, prob := range probs { + if prob == 0 && counts[i] != 0 { + same = false + break + } + if !floats.EqualWithinAbsOrRel(prob, counts[i], tol, tol) { + same = false + break + } + } + return same +} + +func TestCategoricalCDF(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0, 4}, + } { + c := make([]float64, len(test)) + copy(c, test) + floats.Scale(1/floats.Sum(c), c) + sum := make([]float64, len(test)) + floats.CumSum(sum, c) + + dist := NewCategorical(test, nil) + cdf := dist.CDF(-0.5) + if cdf != 0 { + t.Errorf("CDF of negative number not zero") + } + for i := range c { + cdf := dist.CDF(float64(i)) + if math.Abs(cdf-sum[i]) > 1e-14 { + t.Errorf("CDF mismatch %v. Want %v, got %v.", float64(i), sum[i], cdf) + } + cdfp := dist.CDF(float64(i) + 0.5) + if cdfp != cdf { + t.Errorf("CDF mismatch for non-integer input") + } + } + } +} + +func TestCategoricalEntropy(t *testing.T) { + for _, test := range []struct { + weights []float64 + entropy float64 + }{ + { + weights: []float64{1, 1}, + entropy: math.Ln2, + }, + { + weights: []float64{1, 1, 1, 1}, + entropy: math.Log(4), + }, + { + weights: []float64{0, 0, 1, 1, 0, 0}, + entropy: math.Ln2, + }, + } { + dist := NewCategorical(test.weights, nil) + entropy := dist.Entropy() + if math.IsNaN(entropy) || math.Abs(entropy-test.entropy) > 1e-14 { + t.Errorf("Entropy mismatch. Want %v, got %v.", test.entropy, entropy) + } + } +} + +func TestCategoricalMean(t *testing.T) { + for _, test := range []struct { + weights []float64 + mean float64 + }{ + { + weights: []float64{10, 0, 0, 0}, + mean: 0, + }, + { + weights: []float64{0, 10, 0, 0}, + mean: 1, + }, + { + weights: []float64{1, 2, 3, 4}, + mean: 2, + }, + } { + dist := NewCategorical(test.weights, nil) + mean := dist.Mean() + if math.IsNaN(mean) || math.Abs(mean-test.mean) > 1e-14 { + t.Errorf("Entropy mismatch. Want %v, got %v.", test.mean, mean) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go b/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go new file mode 100644 index 00000000..2c9827b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// ChiSquared implements the χ² distribution, a one parameter distribution +// with support on the positive numbers. +// +// The density function is given by +// 1/(2^{k/2} * Γ(k/2)) * x^{k/2 - 1} * e^{-x/2} +// It is a special case of the Gamma distribution, Γ(k/2, 1/2). +// +// For more information, see https://en.wikipedia.org/wiki/Chi-squared_distribution. +type ChiSquared struct { + // K is the shape parameter, corresponding to the degrees of freedom. Must + // be greater than 0. + K float64 + + Src *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (c ChiSquared) CDF(x float64) float64 { + return mathext.GammaInc(c.K/2, x/2) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (c ChiSquared) ExKurtosis() float64 { + return 12 / c.K +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (c ChiSquared) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + lg, _ := math.Lgamma(c.K / 2) + return (c.K/2-1)*math.Log(x) - x/2 - (c.K/2)*math.Ln2 - lg +} + +// Mean returns the mean of the probability distribution. +func (c ChiSquared) Mean() float64 { + return c.K +} + +// Mode returns the mode of the distribution. +func (c ChiSquared) Mode() float64 { + return math.Min(c.K-2, 0) +} + +// NumParameters returns the number of parameters in the distribution. +func (c ChiSquared) NumParameters() int { + return 1 +} + +// Prob computes the value of the probability density function at x. +func (c ChiSquared) Prob(x float64) float64 { + return math.Exp(c.LogProb(x)) +} + +// Rand returns a random sample drawn from the distribution. +func (c ChiSquared) Rand() float64 { + return Gamma{c.K / 2, 0.5, c.Src}.Rand() +} + +// Quantile returns the inverse of the cumulative distribution function. +func (c ChiSquared) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.GammaIncInv(0.5*c.K, p) * 2 +} + +// StdDev returns the standard deviation of the probability distribution. +func (c ChiSquared) StdDev() float64 { + return math.Sqrt(c.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (c ChiSquared) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return mathext.GammaIncComp(0.5*c.K, 0.5*x) +} + +// Variance returns the variance of the probability distribution. +func (c ChiSquared) Variance() float64 { + return 2 * c.K +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/chisquared_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/chisquared_test.go new file mode 100644 index 00000000..56941cd0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/chisquared_test.go @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestChiSquaredProb(t *testing.T) { + for _, test := range []struct { + x, k, want float64 + }{ + {10, 3, 0.0085003666025203432}, + {2.3, 3, 0.19157345407042367}, + {0.8, 0.2, 0.080363259903912673}, + } { + pdf := ChiSquared{test.k, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch, x = %v, K = %v. Got %v, want %v", test.x, test.k, pdf, test.want) + } + } +} + +func TestChiSquaredCDF(t *testing.T) { + for _, test := range []struct { + x, k, want float64 + }{ + // Values calculated with scipy.stats.chi2.cdf + {0, 1, 0}, + {0.01, 5, 5.3002700426865167e-07}, + {0.05, 3, 0.002929332764619924}, + {0.5, 2, 0.22119921692859512}, + {0.95, 3, 0.1866520918701263}, + {0.99, 5, 0.036631697220869196}, + {1, 1, 0.68268949213708596}, + {1.5, 4, 0.17335853270322427}, + {10, 10, 0.55950671493478743}, + {25, 15, 0.95005656637357172}, + } { + cdf := ChiSquared{test.k, nil}.CDF(test.x) + if !floats.EqualWithinAbsOrRel(cdf, test.want, 1e-10, 1e-10) { + t.Errorf("CDF mismatch, x = %v, K = %v. Got %v, want %v", test.x, test.k, cdf, test.want) + } + } +} + +func TestChiSquared(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []ChiSquared{ + {3, src}, + {1.5, src}, + {0.9, src}, + } { + testChiSquared(t, b, i) + } +} + +func testChiSquared(t *testing.T, c ChiSquared, i int) { + tol := 1e-2 + const n = 1e5 + const bins = 50 + x := make([]float64, n) + generateSamples(x, c) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, c, tol, bins) + checkMean(t, i, x, c, tol) + checkVarAndStd(t, i, x, c, tol) + checkExKurtosis(t, i, x, c, 7e-2) + checkProbContinuous(t, i, x, c, 1e-3) + checkQuantileCDFSurvival(t, i, x, c, 1e-2) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/constants.go b/vendor/gonum.org/v1/gonum/stat/distuv/constants.go new file mode 100644 index 00000000..9de7d4dc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/constants.go @@ -0,0 +1,24 @@ +// Copyright ©2014 The gonum 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 distuv + +const ( + // oneOverRoot2Pi is the value of 1/(2Pi)^(1/2) + // http://www.wolframalpha.com/input/?i=1%2F%282+*+pi%29%5E%281%2F2%29 + oneOverRoot2Pi = 0.39894228040143267793994605993438186847585863116493465766592582967065792589930183850125233390730693643030255886263518268 + + //LogRoot2Pi is the value of log(sqrt(2*Pi)) + logRoot2Pi = 0.91893853320467274178032973640561763986139747363778341281715154048276569592726039769474329863595419762200564662463433744 + negLogRoot2Pi = -logRoot2Pi + log2Pi = 1.8378770664093454835606594728112352797227949472755668 + ln2 = 0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023 + + // Euler–Mascheroni constant. + eulerGamma = 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495146314472498070824809605 +) + +const ( + panicNameMismatch = "parameter name mismatch" +) diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/distribution_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/distribution_test.go new file mode 100644 index 00000000..722c438a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/distribution_test.go @@ -0,0 +1,293 @@ +// Copyright ©2015 The gonum 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 distuv + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/integrate/quad" + "gonum.org/v1/gonum/stat" +) + +type meaner interface { + Mean() float64 +} + +type quantiler interface { + Quantile(float64) float64 +} + +type medianer interface { + quantiler + Median() float64 +} + +type varStder interface { + StdDev() float64 + Variance() float64 +} + +type entropyer interface { + LogProber + Entropy() float64 +} + +type exKurtosiser interface { + ExKurtosis() float64 + Mean() float64 +} + +type skewnesser interface { + StdDev() float64 + Mean() float64 + Skewness() float64 +} + +type cumulanter interface { + Quantiler + CDF(x float64) float64 + Survival(x float64) float64 +} + +func generateSamples(x []float64, r Rander) { + for i := range x { + x[i] = r.Rand() + } +} + +type probLogprober interface { + Prob(x float64) float64 + LogProb(x float64) float64 +} + +type cumulantProber interface { + cumulanter + probLogprober +} + +func checkMean(t *testing.T, i int, x []float64, m meaner, tol float64) { + mean := stat.Mean(x, nil) + if !floats.EqualWithinAbsOrRel(mean, m.Mean(), tol, tol) { + t.Errorf("Mean mismatch case %v: want: %v, got: %v", i, mean, m.Mean()) + } +} + +func checkMedian(t *testing.T, i int, x []float64, m medianer, tol float64) { + median := stat.Quantile(0.5, stat.Empirical, x, nil) + if !floats.EqualWithinAbsOrRel(median, m.Median(), tol, tol) { + t.Errorf("Median mismatch case %v: want: %v, got: %v", i, median, m.Median()) + } +} + +func checkVarAndStd(t *testing.T, i int, x []float64, v varStder, tol float64) { + variance := stat.Variance(x, nil) + if !floats.EqualWithinAbsOrRel(variance, v.Variance(), tol, tol) { + t.Errorf("Variance mismatch case %v: want: %v, got: %v", i, variance, v.Variance()) + } + std := math.Sqrt(variance) + if !floats.EqualWithinAbsOrRel(std, v.StdDev(), tol, tol) { + t.Errorf("StdDev mismatch case %v: want: %v, got: %v", i, std, v.StdDev()) + } +} + +func checkEntropy(t *testing.T, i int, x []float64, e entropyer, tol float64) { + tmp := make([]float64, len(x)) + for i, v := range x { + tmp[i] = -e.LogProb(v) + } + entropy := stat.Mean(tmp, nil) + if !floats.EqualWithinAbsOrRel(entropy, e.Entropy(), tol, tol) { + t.Errorf("Entropy mismatch case %v: want: %v, got: %v", i, entropy, e.Entropy()) + } +} + +func checkExKurtosis(t *testing.T, i int, x []float64, e exKurtosiser, tol float64) { + mean := e.Mean() + tmp := make([]float64, len(x)) + for i, x := range x { + tmp[i] = math.Pow(x-mean, 4) + } + variance := stat.Variance(x, nil) + mu4 := stat.Mean(tmp, nil) + kurtosis := mu4/(variance*variance) - 3 + if !floats.EqualWithinAbsOrRel(kurtosis, e.ExKurtosis(), tol, tol) { + t.Errorf("ExKurtosis mismatch case %v: want: %v, got: %v", i, kurtosis, e.ExKurtosis()) + } +} + +func checkSkewness(t *testing.T, i int, x []float64, s skewnesser, tol float64) { + mean := s.Mean() + std := s.StdDev() + tmp := make([]float64, len(x)) + for i, v := range x { + tmp[i] = math.Pow(v-mean, 3) + } + mu3 := stat.Mean(tmp, nil) + skewness := mu3 / math.Pow(std, 3) + if !floats.EqualWithinAbsOrRel(skewness, s.Skewness(), tol, tol) { + t.Errorf("Skewness mismatch case %v: want: %v, got: %v", i, skewness, s.Skewness()) + } +} + +func checkQuantileCDFSurvival(t *testing.T, i int, xs []float64, c cumulanter, tol float64) { + // Quantile, CDF, and survival check. + for i, p := range []float64{0.1, 0.25, 0.5, 0.75, 0.9} { + x := c.Quantile(p) + cdf := c.CDF(x) + estCDF := stat.CDF(x, stat.Empirical, xs, nil) + if !floats.EqualWithinAbsOrRel(cdf, estCDF, tol, tol) { + t.Errorf("CDF mismatch case %v: want: %v, got: %v", i, estCDF, cdf) + } + if !floats.EqualWithinAbsOrRel(cdf, p, tol, tol) { + t.Errorf("Quantile/CDF mismatch case %v: want: %v, got: %v", i, p, cdf) + } + if math.Abs(1-cdf-c.Survival(x)) > 1e-14 { + t.Errorf("Survival/CDF mismatch case %v: want: %v, got: %v", i, 1-cdf, c.Survival(x)) + } + } +} + +func checkProbContinuous(t *testing.T, i int, x []float64, p probLogprober, tol float64) { + // Check that the PDF is consistent (integrates to 1). + q := quad.Fixed(p.Prob, math.Inf(-1), math.Inf(1), 1000000, nil, 0) + if math.Abs(q-1) > tol { + t.Errorf("Probability distribution doesn't integrate to 1. Case %v: Got %v", i, q) + } + + // Check that PDF and LogPDF are consistent. + for i, v := range x { + if math.Abs(math.Log(p.Prob(v))-p.LogProb(v)) > 1e-14 { + t.Errorf("Prob and LogProb mismatch case %v at %v: want %v, got %v", i, v, math.Log(v), p.LogProb(v)) + break + } + } +} + +// checkProbQuantContinuous checks that the Prob, Rand, and Quantile are all consistent. +// checkProbContinuous only checks that Prob is a valid distribution (integrates +// to 1 and greater than 0). However, this is also true if the PDF of a different +// distribution is used. This checks that PDF is also consistent with the +// CDF implementation and the random samples. +func checkProbQuantContinuous(t *testing.T, i int, xs []float64, c cumulantProber, tol float64) { + ps := make([]float64, 101) + floats.Span(ps, 0, 1) + + var xp, x float64 + for i, p := range ps { + x = c.Quantile(p) + if p == 0 { + xp = x + if floats.Min(xs) < x { + t.Errorf("Sample of x less than Quantile(0). Case %v.", i) + break + } + continue + } + if p == 1 { + if floats.Max(xs) > x { + t.Errorf("Sample of x greater than Quantile(1). Case %v.", i) + break + } + } + + // The integral of the PDF between xp and x should be the difference in + // the quantiles. + q := quad.Fixed(c.Prob, xp, x, 1000, nil, 0) + if math.Abs(q-(p-ps[i-1])) > 1e-5 { + t.Errorf("Integral of PDF doesn't match quantile. Case %v. Want %v, got %v.", i, p-ps[i-1], q) + break + } + + pEst := stat.CDF(x, stat.Empirical, xs, nil) + if math.Abs(pEst-p) > tol { + t.Errorf("Empirical CDF doesn't match quantile. Case %v.", i) + } + xp = x + } +} + +// checkProbDiscrete confirms that PDF and Rand are consistent for discrete distributions. +func checkProbDiscrete(t *testing.T, i int, xs []float64, p probLogprober, tol float64) { + // Make a map of all of the unique samples. + m := make(map[float64]int) + for _, v := range xs { + m[v]++ + } + for x, count := range m { + prob := float64(count) / float64(len(xs)) + if math.Abs(prob-p.Prob(x)) > tol { + t.Errorf("PDF mismatch case %v at %v: want %v, got %v", i, x, prob, p.Prob(x)) + } + if math.Abs(math.Log(p.Prob(x))-p.LogProb(x)) > 1e-14 { + t.Errorf("Prob and LogProb mismatch case %v at %v: want %v, got %v", i, x, math.Log(x), p.LogProb(x)) + } + } +} + +// dist is a type that implements the standard set of routines. +type fullDist interface { + CDF(x float64) float64 + Entropy() float64 + ExKurtosis() float64 + LogProb(x float64) float64 + Mean() float64 + Median() float64 + NumParameters() int + Prob(x float64) float64 + Quantile(p float64) float64 + Rand() float64 + Skewness() float64 + StdDev() float64 + Survival(x float64) float64 + Variance() float64 +} + +// testFullDist tests all of the functions of a fullDist. +func testFullDist(t *testing.T, f fullDist, i int, continuous bool) { + tol := 1e-2 + const n = 1e6 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkEntropy(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, tol) + checkSkewness(t, i, x, f, tol) + if continuous { + // In a discrete distribution, the median may not have positive probability. + checkMedian(t, i, x, f, tol) + // In a discrete distribution, the CDF and Quantile may not be perfect mappings. + checkQuantileCDFSurvival(t, i, x, f, tol) + // Integrate over the PDF + checkProbContinuous(t, i, x, f, 1e-10) + checkProbQuantContinuous(t, i, x, f, tol) + } else { + // Check against empirical PDF. + checkProbDiscrete(t, i, x, f, tol) + } +} + +// testRandLogProb tests that LogProb and Rand give consistent results. This +// can be used when the distribution does not implement CDF. +func testRandLogProbContinuous(t *testing.T, i int, min float64, x []float64, f LogProber, tol float64, bins int) { + for cdf := 1 / float64(bins); cdf <= 1-1/float64(bins); cdf += 1 / float64(bins) { + // Get the estimated CDF from the samples + pt := stat.Quantile(cdf, stat.Empirical, x, nil) + + prob := func(x float64) float64 { + return math.Exp(f.LogProb(x)) + } + // Integrate the PDF to find the CDF + estCDF := quad.Fixed(prob, min, pt, 1000, nil, 0) + if !floats.EqualWithinAbsOrRel(cdf, estCDF, tol, tol) { + t.Errorf("Mismatch between integral of PDF and empirical CDF. Case %v. Want %v, got %v", i, cdf, estCDF) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/doc.go b/vendor/gonum.org/v1/gonum/stat/distuv/doc.go new file mode 100644 index 00000000..bdf073f5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 distuv provides univariate random distribution types. +package distuv // import "gonum.org/v1/gonum/stat/distuv" diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go b/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go new file mode 100644 index 00000000..c29f9fef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go @@ -0,0 +1,259 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat" +) + +// Exponential represents the exponential distribution (https://en.wikipedia.org/wiki/Exponential_distribution). +type Exponential struct { + Rate float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (e Exponential) CDF(x float64) float64 { + if x < 0 { + return 0 + } + return 1 - math.Exp(-e.Rate*x) +} + +// ConjugateUpdate updates the parameters of the distribution from the sufficient +// statistics of a set of samples. The sufficient statistics, suffStat, have been +// observed with nSamples observations. The prior values of the distribution are those +// currently in the distribution, and have been observed with priorStrength samples. +// +// For the exponential distribution, the sufficient statistic is the inverse of +// the mean of the samples. +// The prior is having seen priorStrength[0] samples with inverse mean Exponential.Rate +// As a result of this function, Exponential.Rate is updated based on the weighted +// samples, and priorStrength is modified to include the new number of samples observed. +// +// This function panics if len(suffStat) != 1 or len(priorStrength) != 1. +func (e *Exponential) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { + if len(suffStat) != 1 { + panic("exponential: incorrect suffStat length") + } + if len(priorStrength) != 1 { + panic("exponential: incorrect priorStrength length") + } + + totalSamples := nSamples + priorStrength[0] + + totalSum := nSamples / suffStat[0] + if !(priorStrength[0] == 0) { + totalSum += priorStrength[0] / e.Rate + } + e.Rate = totalSamples / totalSum + priorStrength[0] = totalSamples +} + +// Entropy returns the entropy of the distribution. +func (e Exponential) Entropy() float64 { + return 1 - math.Log(e.Rate) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Exponential) ExKurtosis() float64 { + return 6 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. +// If weights is nil, then all the weights are 1. +// If weights is not nil, then the len(weights) must equal len(samples). +func (e *Exponential) Fit(samples, weights []float64) { + suffStat := make([]float64, e.NumSuffStat()) + nSamples := e.SuffStat(suffStat, samples, weights) + e.ConjugateUpdate(suffStat, nSamples, make([]float64, e.NumSuffStat())) +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (e Exponential) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + return math.Log(e.Rate) - e.Rate*x +} + +// Mean returns the mean of the probability distribution. +func (e Exponential) Mean() float64 { + return 1 / e.Rate +} + +// Median returns the median of the probability distribution. +func (e Exponential) Median() float64 { + return math.Ln2 / e.Rate +} + +// Mode returns the mode of the probability distribution. +func (Exponential) Mode() float64 { + return 0 +} + +// NumParameters returns the number of parameters in the distribution. +func (Exponential) NumParameters() int { + return 1 +} + +// NumSuffStat returns the number of sufficient statistics for the distribution. +func (Exponential) NumSuffStat() int { + return 1 +} + +// Prob computes the value of the probability density function at x. +func (e Exponential) Prob(x float64) float64 { + return math.Exp(e.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (e Exponential) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return -math.Log(1-p) / e.Rate +} + +// Rand returns a random sample drawn from the distribution. +func (e Exponential) Rand() float64 { + var rnd float64 + if e.Source == nil { + rnd = rand.ExpFloat64() + } else { + rnd = e.Source.ExpFloat64() + } + return rnd / e.Rate +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Rate]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [NaN] +func (e Exponential) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, e.NumParameters()) + } + if len(deriv) != e.NumParameters() { + panic(badLength) + } + if x > 0 { + deriv[0] = 1/e.Rate - x + return deriv + } + if x < 0 { + deriv[0] = 0 + return deriv + } + deriv[0] = math.NaN() + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// Special cases: +// ScoreInput(0) = NaN +func (e Exponential) ScoreInput(x float64) float64 { + if x > 0 { + return -e.Rate + } + if x < 0 { + return 0 + } + return math.NaN() +} + +// Skewness returns the skewness of the distribution. +func (Exponential) Skewness() float64 { + return 2 +} + +// StdDev returns the standard deviation of the probability distribution. +func (e Exponential) StdDev() float64 { + return 1 / e.Rate +} + +// SuffStat computes the sufficient statistics of set of samples to update +// the distribution. The sufficient statistics are stored in place, and the +// effective number of samples are returned. +// +// The exponential distribution has one sufficient statistic, the average rate +// of the samples. +// +// If weights is nil, the weights are assumed to be 1, otherwise panics if +// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). +func (Exponential) SuffStat(suffStat, samples, weights []float64) (nSamples float64) { + if len(weights) != 0 && len(samples) != len(weights) { + panic(badLength) + } + + if len(suffStat) != (Exponential{}).NumSuffStat() { + panic(badSuffStat) + } + + if len(weights) == 0 { + nSamples = float64(len(samples)) + } else { + nSamples = floats.Sum(weights) + } + + mean := stat.Mean(samples, weights) + suffStat[0] = 1 / mean + return nSamples +} + +// Survival returns the survival function (complementary CDF) at x. +func (e Exponential) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return math.Exp(-e.Rate * x) +} + +// setParameters modifies the parameters of the distribution. +func (e *Exponential) setParameters(p []Parameter) { + if len(p) != e.NumParameters() { + panic("exponential: incorrect number of parameters to set") + } + if p[0].Name != "Rate" { + panic("exponential: " + panicNameMismatch) + } + e.Rate = p[0].Value +} + +// Variance returns the variance of the probability distribution. +func (e Exponential) Variance() float64 { + return 1 / (e.Rate * e.Rate) +} + +// parameters returns the parameters of the distribution. +func (e Exponential) parameters(p []Parameter) []Parameter { + nParam := e.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("exponential: improper parameter length") + } + p[0].Name = "Rate" + p[0].Value = e.Rate + return p +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/exponential_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/exponential_test.go new file mode 100644 index 00000000..9c389702 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/exponential_test.go @@ -0,0 +1,71 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "testing" +) + +func TestExponentialProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 1, + cumProb: 0, + logProb: 0, + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: 1, + prob: 1 / (math.E), + cumProb: 0.6321205588285576784044762298385391325541888689682321654921631983025385042551001966428527256540803563, + logProb: -1, + }, + { + loc: 20, + prob: math.Exp(-20), + cumProb: 0.999999997938846377561442172034059619844179023624192724400896307027755338370835976215440646720089072, + logProb: -20, + }, + } + testDistributionProbs(t, Exponential{Rate: 1}, "Exponential", pts) +} + +func TestExponentialFitPrior(t *testing.T) { + testConjugateUpdate(t, func() ConjugateUpdater { return &Exponential{Rate: 13.7} }) +} + +func TestExponentialScore(t *testing.T) { + for _, test := range []*Exponential{ + { + Rate: 1, + }, + { + Rate: 0.35, + }, + { + Rate: 4.6, + }, + } { + testDerivParam(t, test) + } +} + +func TestExponentialFitPanic(t *testing.T) { + e := Exponential{Rate: 2} + defer func() { + r := recover() + if r != nil { + t.Errorf("unexpected panic for Fit call: %v", r) + } + }() + e.Fit(make([]float64, 10), nil) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/f.go b/vendor/gonum.org/v1/gonum/stat/distuv/f.go new file mode 100644 index 00000000..6e689e6e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/f.go @@ -0,0 +1,132 @@ +// Copyright ©2017 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// F implements the F-distribution, a two-parameter continuous distribution +// with support over the positive real numbers. +// +// The F-distribution has density function +// sqrt(((d1*x)^d1) * d2^d2 / ((d1*x+d2)^(d1+d2))) / (x * B(d1/2,d2/2)) +// where B is the beta function. +// +// For more information, see https://en.wikipedia.org/wiki/F-distribution +type F struct { + D1 float64 // Degrees of freedom for the numerator + D2 float64 // Degrees of freedom for the denominator + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (f F) CDF(x float64) float64 { + return mathext.RegIncBeta(f.D1/2, f.D2/2, f.D1*x/(f.D1*x+f.D2)) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +// +// ExKurtosis returns NaN if the D2 parameter is less or equal to 8. +func (f F) ExKurtosis() float64 { + if f.D2 <= 8 { + return math.NaN() + } + return (12 / (f.D2 - 6)) * ((5*f.D2-22)/(f.D2-8) + ((f.D2-4)/f.D1)*((f.D2-2)/(f.D2-8))*((f.D2-2)/(f.D1+f.D2-2))) +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (f F) LogProb(x float64) float64 { + return 0.5*(f.D1*math.Log(f.D1*x)+f.D2*math.Log(f.D2)-(f.D1+f.D2)*math.Log(f.D1*x+f.D2)) - math.Log(x) - mathext.Lbeta(f.D1/2, f.D2/2) +} + +// Mean returns the mean of the probability distribution. +// +// Mean returns NaN if the D2 parameter is less than or equal to 2. +func (f F) Mean() float64 { + if f.D2 <= 2 { + return math.NaN() + } + return f.D2 / (f.D2 - 2) +} + +// Mode returns the mode of the distribution. +// +// Mode returns NaN if the D1 parameter is less than or equal to 2. +func (f F) Mode() float64 { + if f.D1 <= 2 { + return math.NaN() + } + return ((f.D1 - 2) / f.D1) * (f.D2 / (f.D2 + 2)) +} + +// NumParameters returns the number of parameters in the distribution. +func (f F) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (f F) Prob(x float64) float64 { + return math.Exp(f.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (f F) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + y := mathext.InvRegIncBeta(0.5*f.D1, 0.5*f.D2, p) + return f.D2 * y / (f.D1 * (1 - y)) +} + +// Rand returns a random sample drawn from the distribution. +func (f F) Rand() float64 { + u1 := ChiSquared{f.D1, f.Source}.Rand() + u2 := ChiSquared{f.D2, f.Source}.Rand() + return (u1 / f.D1) / (u2 / f.D2) +} + +// Skewness returns the skewness of the distribution. +// +// Skewness returns NaN if the D2 parameter is less than or equal to 6. +func (f F) Skewness() float64 { + if f.D2 <= 6 { + return math.NaN() + } + num := (2*f.D1 + f.D2 - 2) * math.Sqrt(8*(f.D2-4)) + den := (f.D2 - 6) * math.Sqrt(f.D1*(f.D1+f.D2-2)) + return num / den +} + +// StdDev returns the standard deviation of the probability distribution. +// +// StdDev returns NaN if the D2 parameter is less than or equal to 4. +func (f F) StdDev() float64 { + if f.D2 <= 4 { + return math.NaN() + } + return math.Sqrt(f.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (f F) Survival(x float64) float64 { + return 1 - f.CDF(x) +} + +// Variance returns the variance of the probability distribution. +// +// Variance returns NaN if the D2 parameter is less than or equal to 4. +func (f F) Variance() float64 { + if f.D2 <= 4 { + return math.NaN() + } + num := 2 * f.D2 * f.D2 * (f.D1 + f.D2 - 2) + den := f.D1 * (f.D2 - 2) * (f.D2 - 2) * (f.D2 - 4) + return num / den +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/f_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/f_test.go new file mode 100644 index 00000000..7e5dfbea --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/f_test.go @@ -0,0 +1,89 @@ +// Copyright ©2017 The gonum 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 distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestFProb(t *testing.T) { + for _, test := range []struct { + x, d1, d2, want float64 + }{ + // Values calculated with scipy.stats.f + {0.0001, 4, 6, 0.00053315559110558126}, + {0.1, 1, 1, 0.91507658371794609}, + {0.5, 11, 7, 0.66644660411410883}, + {0.9, 20, 15, 0.88293424959522437}, + {1, 1, 1, 0.15915494309189535}, + {2, 15, 12, 0.16611971273429088}, + {5, 4, 8, 0.013599775603702537}, + {10, 12, 9, 0.00032922887567957289}, + {100, 7, 7, 6.08037637806889e-08}, + {1000, 2, 1, 1.1171959870312232e-05}, + } { + pdf := F{test.d1, test.d2, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Prob mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, pdf, test.want) + } + } +} + +func TestFCDF(t *testing.T) { + for _, test := range []struct { + x, d1, d2, want float64 + }{ + // Values calculated with scipy.stats.f + {0.0001, 4, 6, 2.6660741629519019e-08}, + {0.1, 1, 1, 0.19498222904213672}, + {0.5, 11, 7, 0.14625028471336987}, + {0.9, 20, 15, 0.40567939897287852}, + {1, 1, 1, 0.50000000000000011}, + {2, 15, 12, 0.8839384428956264}, + {5, 4, 8, 0.97429642410900219}, + {10, 12, 9, 0.99915733385467187}, + {100, 7, 7, 0.99999823560259171}, + {1000, 2, 1, 0.97764490829950534}, + } { + cdf := F{test.d1, test.d2, nil}.CDF(test.x) + if !floats.EqualWithinAbsOrRel(cdf, test.want, 1e-10, 1e-10) { + t.Errorf("CDF mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, cdf, test.want) + } + } +} + +func TestF(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []F{ + {13, 16, src}, + {42, 31, src}, + {77, 92, src}, + } { + testF(t, b, i) + } +} + +func testF(t *testing.T, f F, i int) { + const ( + tol = 1e-2 + n = 1e5 + bins = 50 + ) + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, f, tol, bins) + checkProbContinuous(t, i, x, f, 1e-3) + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, 1e-1) + checkSkewness(t, i, x, f, 5e-2) + checkQuantileCDFSurvival(t, i, x, f, 5e-3) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go b/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go new file mode 100644 index 00000000..650ad6c8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go @@ -0,0 +1,244 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// Gamma implements the Gamma distribution, a two-parameter continuous distribution +// with support over the positive real numbers. +// +// The gamma distribution has density function +// β^α / Γ(α) x^(α-1)e^(-βx) +// +// For more information, see https://en.wikipedia.org/wiki/Gamma_distribution +type Gamma struct { + // Alpha is the shape parameter of the distribution. Alpha must be greater + // than 0. If Alpha == 1, this is equivalent to an exponential distribution. + Alpha float64 + // Beta is the rate parameter of the distribution. Beta must be greater than 0. + // If Beta == 2, this is equivalent to a Chi-Squared distribution. + Beta float64 + + Source *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (g Gamma) CDF(x float64) float64 { + if x < 0 { + return 0 + } + return mathext.GammaInc(g.Alpha, g.Beta*x) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (g Gamma) ExKurtosis() float64 { + return 6 / g.Alpha +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (g Gamma) LogProb(x float64) float64 { + if x <= 0 { + return math.Inf(-1) + } + a := g.Alpha + b := g.Beta + lg, _ := math.Lgamma(a) + return a*math.Log(b) - lg + (a-1)*math.Log(x) - b*x +} + +// Mean returns the mean of the probability distribution. +func (g Gamma) Mean() float64 { + return g.Alpha / g.Beta +} + +// Mode returns the mode of the normal distribution. +// +// The mode is NaN in the special case where the Alpha (shape) parameter +// is less than 1. +func (g Gamma) Mode() float64 { + if g.Alpha < 1 { + return math.NaN() + } + return (g.Alpha - 1) / g.Beta +} + +// NumParameters returns the number of parameters in the distribution. +func (Gamma) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (g Gamma) Prob(x float64) float64 { + return math.Exp(g.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (g Gamma) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.GammaIncInv(g.Alpha, p) / g.Beta +} + +// Rand returns a random sample drawn from the distribution. +// +// Rand panics if either alpha or beta is <= 0. +func (g Gamma) Rand() float64 { + if g.Beta <= 0 { + panic("gamma: beta <= 0") + } + + unifrnd := rand.Float64 + exprnd := rand.ExpFloat64 + normrnd := rand.NormFloat64 + if g.Source != nil { + unifrnd = g.Source.Float64 + exprnd = g.Source.ExpFloat64 + normrnd = g.Source.NormFloat64 + } + + a := g.Alpha + b := g.Beta + switch { + case a <= 0: + panic("gamma: alpha < 0") + case a == 1: + // Generate from exponential + return exprnd() / b + case a < 0.3: + // Generate using + // Liu, Chuanhai, Martin, Ryan and Syring, Nick. "Simulating from a + // gamma distribution with small shape parameter" + // https://arxiv.org/abs/1302.1884 + // use this reference: http://link.springer.com/article/10.1007/s00180-016-0692-0 + + // Algorithm adjusted to work in log space as much as possible. + lambda := 1/a - 1 + lw := math.Log(a) - 1 - math.Log(1-a) + lr := -math.Log(1 + math.Exp(lw)) + lc, _ := math.Lgamma(a + 1) + for { + e := exprnd() + var z float64 + if e >= -lr { + z = e + lr + } else { + z = -exprnd() / lambda + } + lh := lc - z - math.Exp(-z/a) + var lEta float64 + if z >= 0 { + lEta = lc - z + } else { + lEta = lc + lw + math.Log(lambda) + lambda*z + } + if lh-lEta > -exprnd() { + return math.Exp(-z/a) / b + } + } + case a >= 0.3 && a < 1: + // Generate using: + // Kundu, Debasis, and Rameshwar D. Gupta. "A convenient way of generating + // gamma random variables using generalized exponential distribution." + // Computational Statistics & Data Analysis 51.6 (2007): 2796-2802. + + // TODO(btracey): Change to using Algorithm 3 if we can find the bug in + // the implementation below. + + // Algorithm 2. + alpha := g.Alpha + a := math.Pow(1-expNegOneHalf, alpha) / (math.Pow(1-expNegOneHalf, alpha) + alpha*math.Exp(-1)/math.Pow(2, alpha)) + b := math.Pow(1-expNegOneHalf, alpha) + alpha/math.E/math.Pow(2, alpha) + var x float64 + for { + u := unifrnd() + if u <= a { + x = -2 * math.Log(1-math.Pow(u*b, 1/alpha)) + } else { + x = -math.Log(math.Pow(2, alpha) / alpha * b * (1 - u)) + } + v := unifrnd() + if x <= 1 { + if v <= math.Pow(x, alpha-1)*math.Exp(-x/2)/(math.Pow(2, alpha-1)*math.Pow(1-math.Exp(-x/2), alpha-1)) { + break + } + } else { + if v <= math.Pow(x, alpha-1) { + break + } + } + } + return x / g.Beta + + /* + // Algorithm 3. + d := 1.0334 - 0.0766*math.Exp(2.2942*alpha) + a := math.Pow(2, alpha) * math.Pow(1-math.Exp(-d/2), alpha) + b := alpha * math.Pow(d, alpha-1) * math.Exp(-d) + c := a + b + var x float64 + for { + u := unifrnd() + if u <= a/(a+b) { + x = -2 * math.Log(1-math.Pow(c*u, 1/a)/2) + } else { + x = -math.Log(c * (1 - u) / (alpha * math.Pow(d, alpha-1))) + } + v := unifrnd() + if x <= d { + if v <= (math.Pow(x, alpha-1)*math.Exp(-x/2))/(math.Pow(2, alpha-1)*math.Pow(1-math.Exp(-x/2), alpha-1)) { + break + } + } else { + if v <= math.Pow(d/x, 1-alpha) { + break + } + } + } + return x / g.Beta + */ + case a > 1: + // Generate using: + // Marsaglia, George, and Wai Wan Tsang. "A simple method for generating + // gamma variables." ACM Transactions on Mathematical Software (TOMS) + // 26.3 (2000): 363-372. + d := a - 1.0/3 + c := 1 / (3 * math.Sqrt(d)) + for { + u := -exprnd() + x := normrnd() + v := 1 + x*c + v = v * v * v + if u < 0.5*x*x+d*(1-v+math.Log(v)) { + return d * v / b + } + } + } + panic("unreachable") +} + +// Survival returns the survival function (complementary CDF) at x. +func (g Gamma) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return mathext.GammaIncComp(g.Alpha, g.Beta*x) +} + +// StdDev returns the standard deviation of the probability distribution. +func (g Gamma) StdDev() float64 { + return math.Sqrt(g.Variance()) +} + +// Variance returns the variance of the probability distribution. +func (g Gamma) Variance() float64 { + return g.Alpha / g.Beta / g.Beta +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/gamma_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/gamma_test.go new file mode 100644 index 00000000..6a1a9bf7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/gamma_test.go @@ -0,0 +1,63 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestGamma(t *testing.T) { + // Values a comparison with scipy + for _, test := range []struct { + x, alpha, want float64 + }{ + {0.9, 0.1, 0.046986817861555757}, + {0.9, 0.01, 0.0045384353289090401}, + {0.45, 0.01, 0.014137035997241795}, + } { + pdf := Gamma{Alpha: test.alpha, Beta: 1}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch. Got %v, want %v", pdf, test.want) + } + } + src := rand.New(rand.NewSource(1)) + for i, g := range []Gamma{ + + {Alpha: 0.5, Beta: 0.8, Source: src}, + {Alpha: 0.9, Beta: 6, Source: src}, + {Alpha: 0.9, Beta: 500, Source: src}, + + {Alpha: 1, Beta: 1, Source: src}, + + {Alpha: 1.6, Beta: 0.4, Source: src}, + {Alpha: 2.6, Beta: 1.5, Source: src}, + {Alpha: 5.6, Beta: 0.5, Source: src}, + {Alpha: 30, Beta: 1.7, Source: src}, + {Alpha: 30.2, Beta: 1.7, Source: src}, + } { + testGamma(t, g, i) + } +} + +func testGamma(t *testing.T, f Gamma, i int) { + // TODO(btracey): Replace this when Gamma implements FullDist. + tol := 1e-2 + const n = 1e5 + const bins = 50 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, f, tol, bins) + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, 2e-2) + checkExKurtosis(t, i, x, f, 2e-1) + checkProbContinuous(t, i, x, f, 1e-3) + checkQuantileCDFSurvival(t, i, x, f, 5e-2) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/general.go b/vendor/gonum.org/v1/gonum/stat/distuv/general.go new file mode 100644 index 00000000..3d9cb865 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/general.go @@ -0,0 +1,24 @@ +// Copyright ©2014 The gonum 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 distuv + +import "math" + +// Parameter represents a parameter of a probability distribution +type Parameter struct { + Name string + Value float64 +} + +var ( + badPercentile = "distuv: percentile out of bounds" + badLength = "distuv: slice length mismatch" + badSuffStat = "distuv: wrong suffStat length" + badNoSamples = "distuv: must have at least one sample" +) + +var ( + expNegOneHalf = math.Exp(-0.5) +) diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/general_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/general_test.go new file mode 100644 index 00000000..63a89dd0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/general_test.go @@ -0,0 +1,204 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +type univariateProbPoint struct { + loc float64 + logProb float64 + cumProb float64 + prob float64 +} + +type UniProbDist interface { + Prob(float64) float64 + CDF(float64) float64 + LogProb(float64) float64 + Quantile(float64) float64 + Survival(float64) float64 +} + +func absEq(a, b float64) bool { + // This is expressed as the inverse to catch the + // case a = Inf and b = Inf of the same sign. + return !(math.Abs(a-b) > 1e-14) +} + +// TODO: Implement a better test for Quantile +func testDistributionProbs(t *testing.T, dist UniProbDist, name string, pts []univariateProbPoint) { + for _, pt := range pts { + logProb := dist.LogProb(pt.loc) + if !absEq(logProb, pt.logProb) { + t.Errorf("Log probability doesnt match for "+name+". Expected %v. Found %v", pt.logProb, logProb) + } + prob := dist.Prob(pt.loc) + if !absEq(prob, pt.prob) { + t.Errorf("Probability doesn't match for "+name+". Expected %v. Found %v", pt.prob, prob) + } + cumProb := dist.CDF(pt.loc) + if !absEq(cumProb, pt.cumProb) { + t.Errorf("Cumulative Probability doesn't match for "+name+". Expected %v. Found %v", pt.cumProb, cumProb) + } + if !absEq(dist.Survival(pt.loc), 1-pt.cumProb) { + t.Errorf("Survival doesn't match for %v. Expected %v, Found %v", name, 1-pt.cumProb, dist.Survival(pt.loc)) + } + if pt.prob != 0 { + if math.Abs(dist.Quantile(pt.cumProb)-pt.loc) > 1e-4 { + fmt.Println("true =", pt.loc) + fmt.Println("calculated=", dist.Quantile(pt.cumProb)) + t.Errorf("Quantile doesn't match for "+name+", loc = %v", pt.loc) + } + } + } +} + +type ConjugateUpdater interface { + NumParameters() int + parameters([]Parameter) []Parameter + + NumSuffStat() int + SuffStat([]float64, []float64, []float64) float64 + ConjugateUpdate([]float64, float64, []float64) + + Rand() float64 +} + +func testConjugateUpdate(t *testing.T, newFittable func() ConjugateUpdater) { + for i, test := range []struct { + samps []float64 + weights []float64 + }{ + { + samps: randn(newFittable(), 10), + weights: nil, + }, + { + samps: randn(newFittable(), 10), + weights: ones(10), + }, + { + samps: randn(newFittable(), 10), + weights: randn(&Exponential{Rate: 1}, 10), + }, + } { + // ensure that conjugate produces the same result both incrementally and all at once + incDist := newFittable() + stats := make([]float64, incDist.NumSuffStat()) + prior := make([]float64, incDist.NumParameters()) + for j := range test.samps { + var incWeights, allWeights []float64 + if test.weights != nil { + incWeights = test.weights[j : j+1] + allWeights = test.weights[0 : j+1] + } + nsInc := incDist.SuffStat(stats, test.samps[j:j+1], incWeights) + incDist.ConjugateUpdate(stats, nsInc, prior) + + allDist := newFittable() + nsAll := allDist.SuffStat(stats, test.samps[0:j+1], allWeights) + allDist.ConjugateUpdate(stats, nsAll, make([]float64, allDist.NumParameters())) + if !parametersEqual(incDist.parameters(nil), allDist.parameters(nil), 1e-12) { + t.Errorf("prior doesn't match after incremental update for (%d, %d). Incremental is %v, all at once is %v", i, j, incDist, allDist) + } + + if test.weights == nil { + onesDist := newFittable() + nsOnes := onesDist.SuffStat(stats, test.samps[0:j+1], ones(j+1)) + onesDist.ConjugateUpdate(stats, nsOnes, make([]float64, onesDist.NumParameters())) + if !parametersEqual(onesDist.parameters(nil), incDist.parameters(nil), 1e-14) { + t.Errorf("nil and uniform weighted prior doesn't match for incremental update for (%d, %d). Uniform weighted is %v, nil is %v", i, j, onesDist, incDist) + } + if !parametersEqual(onesDist.parameters(nil), allDist.parameters(nil), 1e-14) { + t.Errorf("nil and uniform weighted prior doesn't match for all at once update for (%d, %d). Uniform weighted is %v, nil is %v", i, j, onesDist, incDist) + } + } + } + } +} + +// randn generates a specified number of random samples +func randn(dist Rander, n int) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = dist.Rand() + } + return x +} + +func ones(n int) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = 1 + } + return x +} + +func parametersEqual(p1, p2 []Parameter, tol float64) bool { + for i, p := range p1 { + if p.Name != p2[i].Name { + return false + } + if math.Abs(p.Value-p2[i].Value) > tol { + return false + } + } + return true +} + +type derivParamTester interface { + LogProb(x float64) float64 + Score(deriv []float64, x float64) []float64 + Quantile(p float64) float64 + NumParameters() int + parameters([]Parameter) []Parameter + setParameters([]Parameter) +} + +func testDerivParam(t *testing.T, d derivParamTester) { + // Tests that the derivative matches for a number of different quantiles + // along the distribution. + nTest := 10 + quantiles := make([]float64, nTest) + floats.Span(quantiles, 0.1, 0.9) + + deriv := make([]float64, d.NumParameters()) + fdDeriv := make([]float64, d.NumParameters()) + + initParams := d.parameters(nil) + init := make([]float64, d.NumParameters()) + for i, v := range initParams { + init[i] = v.Value + } + for _, v := range quantiles { + d.setParameters(initParams) + x := d.Quantile(v) + d.Score(deriv, x) + f := func(p []float64) float64 { + params := d.parameters(nil) + for i, v := range p { + params[i].Value = v + } + d.setParameters(params) + return d.LogProb(x) + } + fd.Gradient(fdDeriv, f, init, nil) + if !floats.EqualApprox(deriv, fdDeriv, 1e-6) { + t.Fatal("Derivative mismatch. Want", fdDeriv, ", got", deriv, ".") + } + d.setParameters(initParams) + d2 := d.Score(nil, x) + if !floats.EqualApprox(d2, deriv, 1e-14) { + t.Errorf("Derivative mismatch when input nil Want %v, got %v", d2, deriv) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go b/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go new file mode 100644 index 00000000..b2eb80ba --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go @@ -0,0 +1,22 @@ +// Copyright ©2015 The gonum 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 distuv + +type LogProber interface { + LogProb(float64) float64 +} + +type Rander interface { + Rand() float64 +} + +type RandLogProber interface { + Rander + LogProber +} + +type Quantiler interface { + Quantile(p float64) float64 +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go b/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go new file mode 100644 index 00000000..716d79f6 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go @@ -0,0 +1,251 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat" +) + +// Laplace represents the Laplace distribution (https://en.wikipedia.org/wiki/Laplace_distribution). +type Laplace struct { + Mu float64 // Mean of the Laplace distribution + Scale float64 // Scale of the Laplace distribution + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (l Laplace) CDF(x float64) float64 { + if x < l.Mu { + return 0.5 * math.Exp((x-l.Mu)/l.Scale) + } + return 1 - 0.5*math.Exp(-(x-l.Mu)/l.Scale) +} + +// Entropy returns the entropy of the distribution. +func (l Laplace) Entropy() float64 { + return 1 + math.Log(2*l.Scale) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (l Laplace) ExKurtosis() float64 { + return 3 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. +// If weights is nil, then all the weights are 1. +// If weights is not nil, then the len(weights) must equal len(samples). +// +// Note: Laplace distribution has no FitPrior because it has no sufficient +// statistics. +func (l *Laplace) Fit(samples, weights []float64) { + if len(samples) != len(weights) { + panic(badLength) + } + + if len(samples) == 0 { + panic(badNoSamples) + } + if len(samples) == 1 { + l.Mu = samples[0] + l.Scale = 0 + return + } + + var ( + sortedSamples []float64 + sortedWeights []float64 + ) + if sort.Float64sAreSorted(samples) { + sortedSamples = samples + sortedWeights = weights + } else { + // Need to copy variables so the input variables aren't effected by the sorting + sortedSamples = make([]float64, len(samples)) + copy(sortedSamples, samples) + sortedWeights := make([]float64, len(samples)) + copy(sortedWeights, weights) + + stat.SortWeighted(sortedSamples, sortedWeights) + } + + // The (weighted) median of the samples is the maximum likelihood estimate + // of the mean parameter + // TODO: Rethink quantile type when stat has more options + l.Mu = stat.Quantile(0.5, stat.Empirical, sortedSamples, sortedWeights) + + sumWeights := floats.Sum(weights) + + // The scale parameter is the average absolute distance + // between the sample and the mean + absError := stat.MomentAbout(1, samples, l.Mu, weights) + + l.Scale = absError / sumWeights +} + +// LogProb computes the natural logarithm of the value of the probability density +// function at x. +func (l Laplace) LogProb(x float64) float64 { + return -math.Ln2 - math.Log(l.Scale) - math.Abs(x-l.Mu)/l.Scale +} + +// MarshalParameters implements the ParameterMarshaler interface +func (l Laplace) MarshalParameters(p []Parameter) { + if len(p) != l.NumParameters() { + panic(badLength) + } + p[0].Name = "Mu" + p[0].Value = l.Mu + p[1].Name = "Scale" + p[1].Value = l.Scale +} + +// Mean returns the mean of the probability distribution. +func (l Laplace) Mean() float64 { + return l.Mu +} + +// Median returns the median of the LaPlace distribution. +func (l Laplace) Median() float64 { + return l.Mu +} + +// Mode returns the mode of the LaPlace distribution. +func (l Laplace) Mode() float64 { + return l.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (l Laplace) NumParameters() int { + return 2 +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (l Laplace) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + if p < 0.5 { + return l.Mu + l.Scale*math.Log(1+2*(p-0.5)) + } + return l.Mu - l.Scale*math.Log(1-2*(p-0.5)) +} + +// Prob computes the value of the probability density function at x. +func (l Laplace) Prob(x float64) float64 { + return math.Exp(l.LogProb(x)) +} + +// Rand returns a random sample drawn from the distribution. +func (l Laplace) Rand() float64 { + var rnd float64 + if l.Source == nil { + rnd = rand.Float64() + } else { + rnd = l.Source.Float64() + } + u := rnd - 0.5 + if u < 0 { + return l.Mu + l.Scale*math.Log(1+2*u) + } + return l.Mu - l.Scale*math.Log(1-2*u) +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Scale]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [0, -0.5/l.Scale] +func (l Laplace) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, l.NumParameters()) + } + if len(deriv) != l.NumParameters() { + panic(badLength) + } + diff := x - l.Mu + if diff > 0 { + deriv[0] = 1 / l.Scale + } else if diff < 0 { + deriv[0] = -1 / l.Scale + } else if diff == 0 { + deriv[0] = 0 + } else { + // must be NaN + deriv[0] = math.NaN() + } + + deriv[1] = math.Abs(diff)/(l.Scale*l.Scale) - 0.5/(l.Scale) + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// Special cases: +// ScoreInput(l.Mu) = 0 +func (l Laplace) ScoreInput(x float64) float64 { + diff := x - l.Mu + if diff == 0 { + return 0 + } + if diff > 0 { + return -1 / l.Scale + } + return 1 / l.Scale +} + +// Skewness returns the skewness of the distribution. +func (Laplace) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the distribution. +func (l Laplace) StdDev() float64 { + return math.Sqrt2 * l.Scale +} + +// Survival returns the survival function (complementary CDF) at x. +func (l Laplace) Survival(x float64) float64 { + if x < l.Mu { + return 1 - 0.5*math.Exp((x-l.Mu)/l.Scale) + } + return 0.5 * math.Exp(-(x-l.Mu)/l.Scale) +} + +// UnmarshalParameters implements the ParameterMarshaler interface +func (l *Laplace) UnmarshalParameters(p []Parameter) { + if len(p) != l.NumParameters() { + panic(badLength) + } + if p[0].Name != "Mu" { + panic("laplace: " + panicNameMismatch) + } + if p[1].Name != "Scale" { + panic("laplace: " + panicNameMismatch) + } + l.Mu = p[0].Value + l.Scale = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (l Laplace) Variance() float64 { + return 2 * l.Scale * l.Scale +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/laplace_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/laplace_test.go new file mode 100644 index 00000000..0cbb2594 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/laplace_test.go @@ -0,0 +1,58 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "testing" +) + +func TestLaplaceProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0.5, + cumProb: 0.5, + logProb: math.Log(0.5), + }, + { + loc: -1, + prob: 1 / (2 * math.E), + cumProb: 0.1839397205857211607977618850807304337229055655158839172539184008487307478724499016785736371729598219, + logProb: math.Log(1 / (2 * math.E)), + }, + { + loc: 1, + prob: 1 / (2 * math.E), + cumProb: 0.8160602794142788392022381149192695662770944344841160827460815991512692521275500983214263628270401781, + logProb: math.Log(1 / (2 * math.E)), + }, + { + loc: -7, + prob: 1 / (2 * math.Pow(math.E, 7)), + cumProb: 0.0004559409827772581040015680422046413132368622637180269204080667109447399446551532646631395032324502210, + logProb: math.Log(1 / (2 * math.Pow(math.E, 7))), + }, + { + loc: 7, + prob: 1 / (2 * math.Pow(math.E, 7)), + cumProb: 0.9995440590172227418959984319577953586867631377362819730795919332890552600553448467353368604967675498, + logProb: math.Log(1 / (2 * math.Pow(math.E, 7))), + }, + { + loc: -20, + prob: math.Exp(-20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869), + cumProb: 1.030576811219278913982970190077910488187903637799551846486122330814582011892279676639955463952790684 * 1e-9, + logProb: -20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869, + }, + { + loc: 20, + prob: math.Exp(-20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869), + cumProb: 0.999999998969423188780721086017029809922089511812096362200448153513877669185417988107720323360044536, + logProb: -20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869, + }, + } + testDistributionProbs(t, Laplace{Mu: 0, Scale: 1}, "Laplace", pts) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go b/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go new file mode 100644 index 00000000..e13afce5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go @@ -0,0 +1,112 @@ +// Copyright ©2015 The gonum 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 distuv + +import ( + "math" + "math/rand" +) + +// LogNormal represents a random variable whose log is normally distributed. +// The probability density function is given by +// 1/(x σ √2π) exp(-(ln(x)-μ)^2)/(2σ^2)) +type LogNormal struct { + Mu float64 + Sigma float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (l LogNormal) CDF(x float64) float64 { + return 0.5 + 0.5*math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma)) +} + +// Entropy returns the differential entropy of the distribution. +func (l LogNormal) Entropy() float64 { + return 0.5 + 0.5*math.Log(2*math.Pi*l.Sigma*l.Sigma) + l.Mu +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (l LogNormal) ExKurtosis() float64 { + s2 := l.Sigma * l.Sigma + return math.Exp(4*s2) + 2*math.Exp(3*s2) + 3*math.Exp(2*s2) - 6 +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (l LogNormal) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + logx := math.Log(x) + normdiff := (logx - l.Mu) / l.Sigma + return -0.5*normdiff*normdiff - logx - math.Log(l.Sigma) - logRoot2Pi +} + +// Mean returns the mean of the probability distribution. +func (l LogNormal) Mean() float64 { + return math.Exp(l.Mu + 0.5*l.Sigma*l.Sigma) +} + +// Median returns the median of the probability distribution. +func (l LogNormal) Median() float64 { + return math.Exp(l.Mu) +} + +// Mode returns the mode of the probability distribution. +func (l LogNormal) Mode() float64 { + return l.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (LogNormal) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (l LogNormal) Prob(x float64) float64 { + return math.Exp(l.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (l LogNormal) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + // Formula from http://www.math.uah.edu/stat/special/LogNormal.html. + return math.Exp(l.Mu + l.Sigma*UnitNormal.Quantile(p)) +} + +// Rand returns a random sample drawn from the distribution. +func (l LogNormal) Rand() float64 { + var rnd float64 + if l.Source == nil { + rnd = rand.NormFloat64() + } else { + rnd = l.Source.NormFloat64() + } + return math.Exp(rnd*l.Sigma + l.Mu) +} + +// Skewness returns the skewness of the distribution. +func (l LogNormal) Skewness() float64 { + s2 := l.Sigma * l.Sigma + return (math.Exp(s2) + 2) * math.Sqrt(math.Exp(s2)-1) +} + +// StdDev returns the standard deviation of the probability distribution. +func (l LogNormal) StdDev() float64 { + return math.Sqrt(l.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (l LogNormal) Survival(x float64) float64 { + return 0.5 * (1 - math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma))) +} + +// Variance returns the variance of the probability distribution. +func (l LogNormal) Variance() float64 { + s2 := l.Sigma * l.Sigma + return (math.Exp(s2) - 1) * math.Exp(2*l.Mu+s2) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/lognormal_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/lognormal_test.go new file mode 100644 index 00000000..a4dc19ad --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/lognormal_test.go @@ -0,0 +1,44 @@ +// Copyright ©2015 The gonum 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 distuv + +import ( + "sort" + "testing" +) + +func TestLognormal(t *testing.T) { + for i, dist := range []LogNormal{ + { + Mu: 0.1, + Sigma: 0.3, + }, + { + Mu: 0.01, + Sigma: 0.01, + }, + { + Mu: 2, + Sigma: 0.01, + }, + } { + f := dist + tol := 1e-2 + const n = 1e5 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkEntropy(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, 2e-1) + checkSkewness(t, i, x, f, 5e-2) + checkMedian(t, i, x, f, tol) + checkQuantileCDFSurvival(t, i, x, f, tol) + checkProbContinuous(t, i, x, f, 1e-10) + checkProbQuantContinuous(t, i, x, f, tol) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/norm.go b/vendor/gonum.org/v1/gonum/stat/distuv/norm.go new file mode 100644 index 00000000..05b86bdd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/norm.go @@ -0,0 +1,254 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" + "gonum.org/v1/gonum/stat" +) + +// UnitNormal is an instantiation of the normal distribution with Mu = 0 and Sigma = 1. +var UnitNormal = Normal{Mu: 0, Sigma: 1} + +// Normal respresents a normal (Gaussian) distribution (https://en.wikipedia.org/wiki/Normal_distribution). +type Normal struct { + Mu float64 // Mean of the normal distribution + Sigma float64 // Standard deviation of the normal distribution + Source *rand.Rand + + // Needs to be Mu and Sigma and not Mean and StdDev because Normal has functions + // Mean and StdDev +} + +// CDF computes the value of the cumulative density function at x. +func (n Normal) CDF(x float64) float64 { + return 0.5 * (1 + math.Erf((x-n.Mu)/(n.Sigma*math.Sqrt2))) +} + +// ConjugateUpdate updates the parameters of the distribution from the sufficient +// statistics of a set of samples. The sufficient statistics, suffStat, have been +// observed with nSamples observations. The prior values of the distribution are those +// currently in the distribution, and have been observed with priorStrength samples. +// +// For the normal distribution, the sufficient statistics are the mean and +// uncorrected standard deviation of the samples. +// The prior is having seen strength[0] samples with mean Normal.Mu +// and strength[1] samples with standard deviation Normal.Sigma. As a result of +// this function, Normal.Mu and Normal.Sigma are updated based on the weighted +// samples, and strength is modified to include the new number of samples observed. +// +// This function panics if len(suffStat) != 2 or len(priorStrength) != 2. +func (n *Normal) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { + + // TODO: Support prior strength with math.Inf(1) to allow updating with + // a known mean/standard deviation + + totalMeanSamples := nSamples + priorStrength[0] + totalSum := suffStat[0]*nSamples + n.Mu*priorStrength[0] + + totalVarianceSamples := nSamples + priorStrength[1] + // sample variance + totalVariance := nSamples * suffStat[1] * suffStat[1] + // add prior variance + totalVariance += priorStrength[1] * n.Sigma * n.Sigma + // add cross variance from the difference of the means + meanDiff := (suffStat[0] - n.Mu) + totalVariance += priorStrength[0] * nSamples * meanDiff * meanDiff / totalMeanSamples + + n.Mu = totalSum / totalMeanSamples + n.Sigma = math.Sqrt(totalVariance / totalVarianceSamples) + floats.AddConst(nSamples, priorStrength) +} + +// Entropy returns the differential entropy of the distribution. +func (n Normal) Entropy() float64 { + return 0.5 * (log2Pi + 1 + 2*math.Log(n.Sigma)) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Normal) ExKurtosis() float64 { + return 0 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. If weights is nil, then all the weights +// are 1. If weights is not nil, then the len(weights) must equal len(samples). +func (n *Normal) Fit(samples, weights []float64) { + suffStat := make([]float64, n.NumSuffStat()) + nSamples := n.SuffStat(suffStat, samples, weights) + n.ConjugateUpdate(suffStat, nSamples, make([]float64, n.NumSuffStat())) +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (n Normal) LogProb(x float64) float64 { + return negLogRoot2Pi - math.Log(n.Sigma) - (x-n.Mu)*(x-n.Mu)/(2*n.Sigma*n.Sigma) +} + +// Mean returns the mean of the probability distribution. +func (n Normal) Mean() float64 { + return n.Mu +} + +// Median returns the median of the normal distribution. +func (n Normal) Median() float64 { + return n.Mu +} + +// Mode returns the mode of the normal distribution. +func (n Normal) Mode() float64 { + return n.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (Normal) NumParameters() int { + return 2 +} + +// NumSuffStat returns the number of sufficient statistics for the distribution. +func (Normal) NumSuffStat() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (n Normal) Prob(x float64) float64 { + return math.Exp(n.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (n Normal) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return n.Mu + n.Sigma*mathext.NormalQuantile(p) +} + +// Rand returns a random sample drawn from the distribution. +func (n Normal) Rand() float64 { + var rnd float64 + if n.Source == nil { + rnd = rand.NormFloat64() + } else { + rnd = n.Source.NormFloat64() + } + return rnd*n.Sigma + n.Mu +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +func (n Normal) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, n.NumParameters()) + } + if len(deriv) != n.NumParameters() { + panic(badLength) + } + deriv[0] = (x - n.Mu) / (n.Sigma * n.Sigma) + deriv[1] = 1 / n.Sigma * (-1 + ((x-n.Mu)/n.Sigma)*((x-n.Mu)/n.Sigma)) + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +func (n Normal) ScoreInput(x float64) float64 { + return -(1 / (2 * n.Sigma * n.Sigma)) * 2 * (x - n.Mu) +} + +// Skewness returns the skewness of the distribution. +func (Normal) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the probability distribution. +func (n Normal) StdDev() float64 { + return n.Sigma +} + +// SuffStat computes the sufficient statistics of a set of samples to update +// the distribution. The sufficient statistics are stored in place, and the +// effective number of samples are returned. +// +// The normal distribution has two sufficient statistics, the mean of the samples +// and the standard deviation of the samples. +// +// If weights is nil, the weights are assumed to be 1, otherwise panics if +// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). +func (Normal) SuffStat(suffStat, samples, weights []float64) (nSamples float64) { + lenSamp := len(samples) + if len(weights) != 0 && len(samples) != len(weights) { + panic(badLength) + } + if len(suffStat) != (Normal{}).NumSuffStat() { + panic(badSuffStat) + } + + if len(weights) == 0 { + nSamples = float64(lenSamp) + } else { + nSamples = floats.Sum(weights) + } + + mean := stat.Mean(samples, weights) + suffStat[0] = mean + + // Use Moment and not StdDev because we want it to be uncorrected + variance := stat.MomentAbout(2, samples, mean, weights) + suffStat[1] = math.Sqrt(variance) + return nSamples +} + +// Survival returns the survival function (complementary CDF) at x. +func (n Normal) Survival(x float64) float64 { + return 0.5 * (1 - math.Erf((x-n.Mu)/(n.Sigma*math.Sqrt2))) +} + +// setParameters modifies the parameters of the distribution. +func (n *Normal) setParameters(p []Parameter) { + if len(p) != n.NumParameters() { + panic("normal: incorrect number of parameters to set") + } + if p[0].Name != "Mu" { + panic("normal: " + panicNameMismatch) + } + if p[1].Name != "Sigma" { + panic("normal: " + panicNameMismatch) + } + n.Mu = p[0].Value + n.Sigma = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (n Normal) Variance() float64 { + return n.Sigma * n.Sigma +} + +// parameters returns the parameters of the distribution. +func (n Normal) parameters(p []Parameter) []Parameter { + nParam := n.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("normal: improper parameter length") + } + p[0].Name = "Mu" + p[0].Value = n.Mu + p[1].Name = "Sigma" + p[1].Value = n.Sigma + return p +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/norm_example_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/norm_example_test.go new file mode 100644 index 00000000..b913282f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/norm_example_test.go @@ -0,0 +1,35 @@ +// Copyright ©2017 The gonum 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 distuv_test + +import ( + "fmt" + + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +func ExampleNormal() { + // Create a normal distribution + dist := distuv.Normal{ + Mu: 2, + Sigma: 5, + } + + data := make([]float64, 1e5) + + // Draw some random values from the standard normal distribution + for i := range data { + data[i] = dist.Rand() + } + + mean, std := stat.MeanStdDev(data, nil) + meanErr := stat.StdErr(std, float64(len(data))) + + fmt.Printf("mean= %1.1f ± %0.1v\n", mean, meanErr) + + // Output: + // mean= 2.0 ± 0.02 +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/norm_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/norm_test.go new file mode 100644 index 00000000..0179e173 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/norm_test.go @@ -0,0 +1,171 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +// TestNormalProbs tests LogProb, Prob, CumProb, and Quantile +func TestNormalProbs(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: oneOverRoot2Pi, + cumProb: 0.5, + logProb: -0.91893853320467274178032973640561763986139747363778341281715, + }, + { + loc: -1, + prob: 0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047, + cumProb: 0.158655253931457051414767454367962077522087033273395609012605, + logProb: math.Log(0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047), + }, + { + loc: 1, + prob: 0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047, + cumProb: 0.841344746068542948585232545632037922477912966726604390987394, + logProb: math.Log(0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047), + }, + { + loc: -7, + prob: 9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12, + cumProb: 1.279812543885835004383623690780832998032844154198717929e-12, + logProb: math.Log(9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12), + }, + { + loc: 7, + prob: 9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12, + cumProb: 0.99999999999872018745611416499561637630921916700196715584580, + logProb: math.Log(9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12), + }, + } + testDistributionProbs(t, Normal{Mu: 0, Sigma: 1}, "normal", pts) + + pts = []univariateProbPoint{ + { + loc: 2, + prob: 0.07978845608028653558798921198687637369517172623298693153318516593413158517986036770025046678146138729, + cumProb: 0.5, + logProb: math.Log(0.07978845608028653558798921198687637369517172623298693153318516593413158517986036770025046678146138729), + }, + { + loc: -3, + prob: 0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095, + cumProb: 0.158655253931457051414767454367962077522087033273395609012605, + logProb: math.Log(0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095), + }, + { + loc: 7, + prob: 0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095, + cumProb: 0.841344746068542948585232545632037922477912966726604390987394, + logProb: math.Log(0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095), + }, + { + loc: -33, + prob: 1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12, + cumProb: 1.279812543885835004383623690780832998032844154198717929e-12, + logProb: math.Log(1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12), + }, + { + loc: 37, + prob: 1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12, + cumProb: 0.99999999999872018745611416499561637630921916700196715584580, + logProb: math.Log(1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12), + }, + } + testDistributionProbs(t, Normal{Mu: 2, Sigma: 5}, "normal", pts) +} + +func TestNormFitPrior(t *testing.T) { + testConjugateUpdate(t, func() ConjugateUpdater { return &Normal{Mu: -10, Sigma: 6} }) +} + +func TestNormScore(t *testing.T) { + for _, test := range []*Normal{ + { + Mu: 0, + Sigma: 1, + }, + { + Mu: 0.32238, + Sigma: 13.69, + }, + } { + testDerivParam(t, test) + } +} + +func TestNormalQuantile(t *testing.T) { + // Values from https://www.johndcook.com/blog/normal_cdf_inverse/ + p := []float64{ + 0.0000001, + 0.00001, + 0.001, + 0.05, + 0.15, + 0.25, + 0.35, + 0.45, + 0.55, + 0.65, + 0.75, + 0.85, + 0.95, + 0.999, + 0.99999, + 0.9999999, + } + ans := []float64{ + -5.199337582187471, + -4.264890793922602, + -3.090232306167813, + -1.6448536269514729, + -1.0364333894937896, + -0.6744897501960817, + -0.38532046640756773, + -0.12566134685507402, + 0.12566134685507402, + 0.38532046640756773, + 0.6744897501960817, + 1.0364333894937896, + 1.6448536269514729, + 3.090232306167813, + 4.264890793922602, + 5.199337582187471, + } + for i, v := range p { + got := UnitNormal.Quantile(v) + if !floats.EqualWithinAbsOrRel(got, ans[i], 1e-10, 1e-10) { + t.Errorf("Quantile mismatch. Case %d, want: %v, got: %v", i, ans[i], got) + } + } +} + +func TestNormFitPanic(t *testing.T) { + n := Normal{Mu: 0, Sigma: 1} + defer func() { + r := recover() + if r != nil { + t.Errorf("unexpected panic for Fit call: %v", r) + } + }() + n.Fit(make([]float64, 10), nil) +} + +func BenchmarkNormalQuantile(b *testing.B) { + n := Normal{Mu: 2, Sigma: 3.1} + ps := make([]float64, 1000) // ensure there are small values + floats.Span(ps, 0, 1) + for i := 0; i < b.N; i++ { + for _, v := range ps { + x := n.Quantile(v) + _ = x + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go b/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go new file mode 100644 index 00000000..84b6b6e2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +const logPi = 1.1447298858494001741 // http://oeis.org/A053510 + +// StudentsT implements the three-parameter Student's T distribution, a distribution +// over the real numbers. +// +// The Student's T distribution has density function +// Γ((ν+1)/2) / (sqrt(νπ) Γ(ν/2) σ) (1 + 1/ν * ((x-μ)/σ)^2)^(-(ν+1)/2) +// +// The Student's T distribution approaches the normal distribution as ν → ∞. +// +// For more information, see https://en.wikipedia.org/wiki/Student%27s_t-distribution, +// specifically https://en.wikipedia.org/wiki/Student%27s_t-distribution#Non-standardized_Student.27s_t-distribution . +// +// The standard Student's T distribution is with Mu = 0, and Sigma = 1. +type StudentsT struct { + // Mu is the location parameter of the distribution, and the mean of the + // distribution + Mu float64 + + // Sigma is the scale parameter of the distribution. It is related to the + // standard deviation by std = Sigma * sqrt(Nu/(Nu-2)) + Sigma float64 + + // Nu is the shape prameter of the distribution, representing the number of + // degrees of the distribution, and one less than the number of observations + // from a Normal distribution. + Nu float64 + + Src *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (s StudentsT) CDF(x float64) float64 { + // transform to standard normal + y := (x - s.Mu) / s.Sigma + if y == 0 { + return 0.5 + } + // For t > 0 + // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) + // t(y) = nu/(y^2 + nu) + // and 1 - F(y) for t < 0 + t := s.Nu / (y*y + s.Nu) + if y > 0 { + return 1 - 0.5*mathext.RegIncBeta(0.5*s.Nu, 0.5, t) + } + return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (s StudentsT) LogProb(x float64) float64 { + g1, _ := math.Lgamma((s.Nu + 1) / 2) + g2, _ := math.Lgamma(s.Nu / 2) + z := (x - s.Mu) / s.Sigma + return g1 - g2 - 0.5*math.Log(s.Nu) - 0.5*logPi - math.Log(s.Sigma) - ((s.Nu+1)/2)*math.Log(1+z*z/s.Nu) +} + +// Mean returns the mean of the probability distribution. +func (s StudentsT) Mean() float64 { + return s.Mu +} + +// Mode returns the mode of the distribution. +func (s StudentsT) Mode() float64 { + return s.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (StudentsT) NumParameters() int { + return 3 +} + +// Prob computes the value of the probability density function at x. +func (s StudentsT) Prob(x float64) float64 { + return math.Exp(s.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (s StudentsT) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + // F(x) = 1 - 0.5 * I_t(x)(nu/2, 1/2) + // t(x) = nu/(t^2 + nu) + if p == 0.5 { + return s.Mu + } + var y float64 + if p > 0.5 { + // Know t > 0 + t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*(1-p)) + y = math.Sqrt(s.Nu * (1 - t) / t) + } else { + t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*p) + y = -math.Sqrt(s.Nu * (1 - t) / t) + } + // Convert out of standard normal + return y*s.Sigma + s.Mu +} + +// Rand returns a random sample drawn from the distribution. +func (s StudentsT) Rand() float64 { + // http://www.math.uah.edu/stat/special/Student.html + n := Normal{0, 1, s.Src}.Rand() + c := Gamma{s.Nu / 2, 0.5, s.Src}.Rand() + z := n / math.Sqrt(c/s.Nu) + return z*s.Sigma + s.Mu +} + +// StdDev returns the standard deviation of the probability distribution. +// +// The standard deviation is undefined for ν <= 1, and this returns math.NaN(). +func (s StudentsT) StdDev() float64 { + return math.Sqrt(s.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (s StudentsT) Survival(x float64) float64 { + // transform to standard normal + y := (x - s.Mu) / s.Sigma + if y == 0 { + return 0.5 + } + // For t > 0 + // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) + // t(y) = nu/(y^2 + nu) + // and 1 - F(y) for t < 0 + t := s.Nu / (y*y + s.Nu) + if y > 0 { + return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) + } + return 1 - 0.5*mathext.RegIncBeta(s.Nu/2, 0.5, t) +} + +// Variance returns the variance of the probability distribution. +// +// The variance is undefined for ν <= 1, and this returns math.NaN(). +func (s StudentsT) Variance() float64 { + if s.Nu < 1 { + return math.NaN() + } + if s.Nu <= 2 { + return math.Inf(1) + } + return s.Sigma * s.Sigma * s.Nu / (s.Nu - 2) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/studentst_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/studentst_test.go new file mode 100644 index 00000000..d3ad225b --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/studentst_test.go @@ -0,0 +1,83 @@ +// Copyright ©2016 The gonum 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 distuv + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestStudentsTProb(t *testing.T) { + for _, test := range []struct { + x, mu, sigma, nu, want float64 + }{ + // Values comparison with scipy. + {0.01, 0, 1, 2.74, 0.364778548181318}, + {-0.01, 0, 1, 2.74, 0.364778548181318}, + {0.4, 0, 1, 1.6, 0.30376391362582678}, + {-0.4, 0, 1, 1.6, 0.30376391362582678}, + {0.2, 15, 5, 10, 0.0024440848858034393}, + } { + pdf := StudentsT{test.mu, test.sigma, test.nu, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch, x = %v, Nu = %v. Got %v, want %v", test.x, test.nu, pdf, test.want) + } + } +} + +func TestStudentsT(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []StudentsT{ + {0, 1, 3.3, src}, + {0, 1, 7.2, src}, + {0, 1, 12, src}, + {0.9, 0.8, 6, src}, + } { + testStudentsT(t, b, i) + } +} + +func testStudentsT(t *testing.T, c StudentsT, i int) { + tol := 1e-2 + const n = 1e5 + const bins = 50 + x := make([]float64, n) + generateSamples(x, c) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, math.Inf(-1), x, c, tol, bins) + checkMean(t, i, x, c, tol) + if c.Nu > 2 { + checkVarAndStd(t, i, x, c, 5e-2) + } + checkProbContinuous(t, i, x, c, 1e-3) + checkQuantileCDFSurvival(t, i, x, c, tol) + checkProbQuantContinuous(t, i, x, c, tol) +} + +func TestStudentsTQuantile(t *testing.T) { + nSteps := 101 + probs := make([]float64, nSteps) + floats.Span(probs, 0, 1) + for i, b := range []StudentsT{ + {0, 1, 3.3, nil}, + {0, 1, 7.2, nil}, + {0, 1, 12, nil}, + {0.9, 0.8, 6, nil}, + } { + for _, p := range probs { + x := b.Quantile(p) + p2 := b.CDF(x) + if !floats.EqualWithinAbsOrRel(p, p2, 1e-10, 1e-10) { + t.Errorf("mismatch between CDF and Quantile. Case %v. Want %v, got %v", i, p, p2) + break + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go b/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go new file mode 100644 index 00000000..157b9ea1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go @@ -0,0 +1,192 @@ +// Copyright ©2017 The gonum 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 distuv + +import ( + "math" + "math/rand" +) + +// Triangle represents a triangle distribution (https://en.wikipedia.org/wiki/Triangular_distribution). +type Triangle struct { + a, b, c float64 + Source *rand.Rand +} + +// NewTriangle constructs a new triangle distribution with lower limit a, upper limit b, and mode c. +// Constraints are a < b and a ≤ c ≤ b. +// This distribution is uncommon in nature, but may be useful for simulation. +func NewTriangle(a, b, c float64) Triangle { + checkTriangleParameters(a, b, c) + return Triangle{a, b, c, nil} +} + +func checkTriangleParameters(a, b, c float64) { + if a >= b { + panic("triangle: constraint of a < b violated") + } + if a > c { + panic("triangle: constraint of a <= c violated") + } + if c > b { + panic("triangle: constraint of c <= b violated") + } +} + +// CDF computes the value of the cumulative density function at x. +func (t Triangle) CDF(x float64) float64 { + switch { + case x <= t.a: + return 0 + case x <= t.c: + d := x - t.a + return (d * d) / ((t.b - t.a) * (t.c - t.a)) + case x < t.b: + d := t.b - x + return 1 - (d*d)/((t.b-t.a)*(t.b-t.c)) + default: + return 1 + } +} + +// Entropy returns the entropy of the distribution. +func (t Triangle) Entropy() float64 { + return 0.5 + math.Log(t.b-t.a) - math.Ln2 +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Triangle) ExKurtosis() float64 { + return -3.0 / 5.0 +} + +// Fit is not appropriate for Triangle, because the distribution is generally used when there is little data. + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (t Triangle) LogProb(x float64) float64 { + return math.Log(t.Prob(x)) +} + +// Mean returns the mean of the probability distribution. +func (t Triangle) Mean() float64 { + return (t.a + t.b + t.c) / 3 +} + +// Median returns the median of the probability distribution. +func (t Triangle) Median() float64 { + if t.c >= (t.a+t.b)/2 { + return t.a + math.Sqrt((t.b-t.a)*(t.c-t.a)/2) + } + return t.b - math.Sqrt((t.b-t.a)*(t.b-t.c)/2) +} + +// Mode returns the mode of the probability distribution. +func (t Triangle) Mode() float64 { + return t.c +} + +// NumParameters returns the number of parameters in the distribution. +func (Triangle) NumParameters() int { + return 3 +} + +// Prob computes the value of the probability density function at x. +func (t Triangle) Prob(x float64) float64 { + switch { + case x < t.a: + return 0 + case x < t.c: + return 2 * (x - t.a) / ((t.b - t.a) * (t.c - t.a)) + case x == t.c: + return 2 / (t.b - t.a) + case x <= t.b: + return 2 * (t.b - x) / ((t.b - t.a) * (t.b - t.c)) + default: + return 0 + } +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (t Triangle) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + + f := (t.c - t.a) / (t.b - t.a) + + if p < f { + return t.a + math.Sqrt(p*(t.b-t.a)*(t.c-t.a)) + } + return t.b - math.Sqrt((1-p)*(t.b-t.a)*(t.b-t.c)) +} + +// Rand returns a random sample drawn from the distribution. +func (t Triangle) Rand() float64 { + var rnd float64 + if t.Source == nil { + rnd = rand.Float64() + } else { + rnd = t.Source.Float64() + } + + return t.Quantile(rnd) +} + +// Skewness returns the skewness of the distribution. +func (t Triangle) Skewness() float64 { + n := math.Sqrt2 * (t.a + t.b - 2*t.c) * (2*t.a - t.b - t.c) * (t.a - 2*t.b + t.c) + d := 5 * math.Pow(t.a*t.a+t.b*t.b+t.c*t.c-t.a*t.b-t.a*t.c-t.b*t.c, 3.0/2.0) + + return n / d +} + +// StdDev returns the standard deviation of the probability distribution. +func (t Triangle) StdDev() float64 { + return math.Sqrt(t.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (t Triangle) Survival(x float64) float64 { + return 1 - t.CDF(x) +} + +// MarshalParameters implements the ParameterMarshaler interface +func (t Triangle) MarshalParameters(p []Parameter) { + if len(p) != t.NumParameters() { + panic("triangle: improper parameter length") + } + p[0].Name = "A" + p[0].Value = t.a + p[1].Name = "B" + p[1].Value = t.b + p[2].Name = "C" + p[2].Value = t.c +} + +// UnmarshalParameters implements the ParameterMarshaler interface +func (t *Triangle) UnmarshalParameters(p []Parameter) { + if len(p) != t.NumParameters() { + panic("triangle: incorrect number of parameters to set") + } + if p[0].Name != "A" { + panic("triangle: " + panicNameMismatch) + } + if p[1].Name != "B" { + panic("triangle: " + panicNameMismatch) + } + if p[2].Name != "C" { + panic("triangle: " + panicNameMismatch) + } + + checkTriangleParameters(p[0].Value, p[1].Value, p[2].Value) + + t.a = p[0].Value + t.b = p[1].Value + t.c = p[2].Value +} + +// Variance returns the variance of the probability distribution. +func (t Triangle) Variance() float64 { + return (t.a*t.a + t.b*t.b + t.c*t.c - t.a*t.b - t.a*t.c - t.b*t.c) / 18 +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/triangle_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/triangle_test.go new file mode 100644 index 00000000..c18ea939 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/triangle_test.go @@ -0,0 +1,101 @@ +// Copyright ©2017 The gonum 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 distuv + +import ( + "math" + "math/rand" + "sort" + "testing" +) + +func TestTriangleConstraint(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("The constraints were violated, but not caught") + } + }() + + // test b < a + NewTriangle(3, 1, 2) + // test c > b + NewTriangle(1, 2, 3) +} + +func TestTriangle(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, test := range []struct { + a, b, c float64 + }{ + { + a: 0.0, + b: 1.0, + c: 0.5, + }, + { + a: 0.1, + b: 0.3, + c: 0.2, + }, + { + a: 1.0, + b: 2.0, + c: 1.5, + }, + { + a: 0.0, + b: 1.0, + c: 0.0, + }, + } { + f := NewTriangle(test.a, test.b, test.c) + f.Source = src + tol := 1e-2 + const n = 1e5 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkEntropy(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, tol) + checkSkewness(t, i, x, f, 5e-2) + checkMedian(t, i, x, f, tol) + checkQuantileCDFSurvival(t, i, x, f, tol) + checkProbContinuous(t, i, x, f, 1e-10) + checkProbQuantContinuous(t, i, x, f, tol) + } +} + +func TestTriangleProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0.5, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: 1, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: 2, + prob: 1.0, + cumProb: 0.5, + logProb: 0, + }, + { + loc: 3, + prob: 0, + cumProb: 1, + logProb: math.Inf(-1), + }, + } + testDistributionProbs(t, NewTriangle(1, 3, 2), "Standard 1,2,3 Triangle", pts) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go b/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go new file mode 100644 index 00000000..0c6c41b7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go @@ -0,0 +1,158 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "math/rand" +) + +// UnitUniform is an instantiation of the uniform distribution with Min = 0 +// and Max = 1. +var UnitUniform = Uniform{Min: 0, Max: 1} + +// Uniform represents a continuous uniform distribution (https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29). +type Uniform struct { + Min float64 + Max float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (u Uniform) CDF(x float64) float64 { + if x < u.Min { + return 0 + } + if x > u.Max { + return 1 + } + return (x - u.Min) / (u.Max - u.Min) +} + +// Uniform doesn't have any of the DLogProbD? because the derivative is 0 everywhere +// except where it's undefined + +// Entropy returns the entropy of the distribution. +func (u Uniform) Entropy() float64 { + return math.Log(u.Max - u.Min) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Uniform) ExKurtosis() float64 { + return -6.0 / 5.0 +} + +// Uniform doesn't have Fit because it's a bad idea to fit a uniform from data. + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (u Uniform) LogProb(x float64) float64 { + if x < u.Min { + return math.Inf(-1) + } + if x > u.Max { + return math.Inf(-1) + } + return -math.Log(u.Max - u.Min) +} + +// MarshalParameters implements the ParameterMarshaler interface +func (u Uniform) MarshalParameters(p []Parameter) { + if len(p) != u.NumParameters() { + panic("uniform: improper parameter length") + } + p[0].Name = "Min" + p[0].Value = u.Min + p[1].Name = "Max" + p[1].Value = u.Max +} + +// Mean returns the mean of the probability distribution. +func (u Uniform) Mean() float64 { + return (u.Max + u.Min) / 2 +} + +// Median returns the median of the probability distribution. +func (u Uniform) Median() float64 { + return (u.Max + u.Min) / 2 +} + +// Uniform doesn't have a mode because it's any value in the distribution + +// NumParameters returns the number of parameters in the distribution. +func (Uniform) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (u Uniform) Prob(x float64) float64 { + if x < u.Min { + return 0 + } + if x > u.Max { + return 0 + } + return 1 / (u.Max - u.Min) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (u Uniform) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return p*(u.Max-u.Min) + u.Min +} + +// Rand returns a random sample drawn from the distribution. +func (u Uniform) Rand() float64 { + var rnd float64 + if u.Source == nil { + rnd = rand.Float64() + } else { + rnd = u.Source.Float64() + } + return rnd*(u.Max-u.Min) + u.Min +} + +// Skewness returns the skewness of the distribution. +func (Uniform) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the probability distribution. +func (u Uniform) StdDev() float64 { + return math.Sqrt(u.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (u Uniform) Survival(x float64) float64 { + if x < u.Min { + return 1 + } + if x > u.Max { + return 0 + } + return (u.Max - x) / (u.Max - u.Min) +} + +// UnmarshalParameters implements the ParameterMarshaler interface +func (u *Uniform) UnmarshalParameters(p []Parameter) { + if len(p) != u.NumParameters() { + panic("uniform: incorrect number of parameters to set") + } + if p[0].Name != "Min" { + panic("uniform: " + panicNameMismatch) + } + if p[1].Name != "Max" { + panic("uniform: " + panicNameMismatch) + } + + u.Min = p[0].Value + u.Max = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (u Uniform) Variance() float64 { + return 1.0 / 12.0 * (u.Max - u.Min) * (u.Max - u.Min) +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go b/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go new file mode 100644 index 00000000..72f7f97a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go @@ -0,0 +1,247 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "math/cmplx" + "math/rand" +) + +// Weibull distribution. Valid range for x is [0,+∞). +type Weibull struct { + // Shape parameter of the distribution. A value of 1 represents + // the exponential distribution. A value of 2 represents the + // Rayleigh distribution. Valid range is (0,+∞). + K float64 + // Scale parameter of the distribution. Valid range is (0,+∞). + Lambda float64 + // Source of random numbers + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (w Weibull) CDF(x float64) float64 { + if x < 0 { + return 0 + } else { + return 1 - cmplx.Abs(cmplx.Exp(w.LogCDF(x))) + } +} + +// Entropy returns the entropy of the distribution. +func (w Weibull) Entropy() float64 { + return eulerGamma*(1-1/w.K) + math.Log(w.Lambda/w.K) + 1 +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (w Weibull) ExKurtosis() float64 { + return (-6*w.gammaIPow(1, 4) + 12*w.gammaIPow(1, 2)*math.Gamma(1+2/w.K) - 3*w.gammaIPow(2, 2) - 4*math.Gamma(1+1/w.K)*math.Gamma(1+3/w.K) + math.Gamma(1+4/w.K)) / math.Pow(math.Gamma(1+2/w.K)-w.gammaIPow(1, 2), 2) +} + +// gammIPow is a shortcut for computing the gamma function to a power. +func (w Weibull) gammaIPow(i, pow float64) float64 { + return math.Pow(math.Gamma(1+i/w.K), pow) +} + +// LogCDF computes the value of the log of the cumulative density function at x. +func (w Weibull) LogCDF(x float64) complex128 { + if x < 0 { + return 0 + } else { + return cmplx.Log(-1) + complex(-math.Pow(x/w.Lambda, w.K), 0) + } +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. Zero is returned if x is less than zero. +// +// Special cases occur when x == 0, and the result depends on the shape +// parameter as follows: +// If 0 < K < 1, LogProb returns +Inf. +// If K == 1, LogProb returns 0. +// If K > 1, LogProb returns -Inf. +func (w Weibull) LogProb(x float64) float64 { + if x < 0 { + return 0 + } else { + return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K) + } +} + +// Survival returns the log of the survival function (complementary CDF) at x. +func (w Weibull) LogSurvival(x float64) float64 { + if x < 0 { + return 0 + } else { + return -math.Pow(x/w.Lambda, w.K) + } +} + +// Mean returns the mean of the probability distribution. +func (w Weibull) Mean() float64 { + return w.Lambda * math.Gamma(1+1/w.K) +} + +// Median returns the median of the normal distribution. +func (w Weibull) Median() float64 { + return w.Lambda * math.Pow(ln2, 1/w.K) +} + +// Mode returns the mode of the normal distribution. +// +// The mode is NaN in the special case where the K (shape) parameter +// is less than 1. +func (w Weibull) Mode() float64 { + if w.K > 1 { + return w.Lambda * math.Pow((w.K-1)/w.K, 1/w.K) + } else if w.K == 1 { + return 0 + } else { + return math.NaN() + } +} + +// NumParameters returns the number of parameters in the distribution. +func (Weibull) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (w Weibull) Prob(x float64) float64 { + if x < 0 { + return 0 + } else { + return math.Exp(w.LogProb(x)) + } +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (w Weibull) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return w.Lambda * math.Pow(-math.Log(1-p), 1/w.K) +} + +// Rand returns a random sample drawn from the distribution. +func (w Weibull) Rand() float64 { + var rnd float64 + if w.Source == nil { + rnd = rand.Float64() + } else { + rnd = w.Source.Float64() + } + return w.Quantile(rnd) +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂K, ∂LogProb / ∂λ]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [NaN, NaN] +func (w Weibull) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, w.NumParameters()) + } + if len(deriv) != w.NumParameters() { + panic(badLength) + } + if x > 0 { + deriv[0] = 1/w.K + math.Log(x) - math.Log(w.Lambda) - (math.Log(x)-math.Log(w.Lambda))*math.Pow(x/w.Lambda, w.K) + deriv[1] = (w.K * (math.Pow(x/w.Lambda, w.K) - 1)) / w.Lambda + return deriv + } + if x < 0 { + deriv[0] = 0 + deriv[1] = 0 + return deriv + } + deriv[0] = math.NaN() + deriv[0] = math.NaN() + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// +// Special cases: +// ScoreInput(0) = NaN +func (w Weibull) ScoreInput(x float64) float64 { + if x > 0 { + return (-w.K*math.Pow(x/w.Lambda, w.K) + w.K - 1) / x + } + if x < 0 { + return 0 + } + return math.NaN() +} + +// Skewness returns the skewness of the distribution. +func (w Weibull) Skewness() float64 { + stdDev := w.StdDev() + firstGamma, firstGammaSign := math.Lgamma(1 + 3/w.K) + logFirst := firstGamma + 3*(math.Log(w.Lambda)-math.Log(stdDev)) + logSecond := math.Log(3) + math.Log(w.Mean()) + 2*math.Log(stdDev) - 3*math.Log(stdDev) + logThird := 3 * (math.Log(w.Mean()) - math.Log(stdDev)) + return float64(firstGammaSign)*math.Exp(logFirst) - math.Exp(logSecond) - math.Exp(logThird) +} + +// StdDev returns the standard deviation of the probability distribution. +func (w Weibull) StdDev() float64 { + return math.Sqrt(w.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (w Weibull) Survival(x float64) float64 { + return math.Exp(w.LogSurvival(x)) +} + +// setParameters modifies the parameters of the distribution. +func (w *Weibull) setParameters(p []Parameter) { + if len(p) != w.NumParameters() { + panic("weibull: incorrect number of parameters to set") + } + if p[0].Name != "K" { + panic("weibull: " + panicNameMismatch) + } + if p[1].Name != "λ" { + panic("weibull: " + panicNameMismatch) + } + w.K = p[0].Value + w.Lambda = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (w Weibull) Variance() float64 { + return math.Pow(w.Lambda, 2) * (math.Gamma(1+2/w.K) - w.gammaIPow(1, 2)) +} + +// parameters returns the parameters of the distribution. +func (w Weibull) parameters(p []Parameter) []Parameter { + nParam := w.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("weibull: improper parameter length") + } + p[0].Name = "K" + p[0].Value = w.K + p[1].Name = "λ" + p[1].Value = w.Lambda + return p + +} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/weibull_test.go b/vendor/gonum.org/v1/gonum/stat/distuv/weibull_test.go new file mode 100644 index 00000000..cd78f49f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/distuv/weibull_test.go @@ -0,0 +1,209 @@ +// Copyright ©2014 The gonum 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 distuv + +import ( + "math" + "testing" +) + +func TestHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.183939720585721, + cumProb: 0.632120558828558, + logProb: -1.693147180559950, + }, + { + loc: 20, + prob: 0.001277118038048, + cumProb: 0.988577109006533, + logProb: -6.663149272336520, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1}, "0.5K Standard Weibull", pts) +} + +func TestExponentialStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 1, + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.367879441171442, + cumProb: 0.632120558828558, + logProb: -1.0, + }, + { + loc: 20, + prob: 0.000000002061154, + cumProb: 0.999999997938846, + logProb: -20.0, + }, + } + testDistributionProbs(t, Weibull{K: 1, Lambda: 1}, "1K (Exponential) Standard Weibull", pts) +} + +func TestRayleighStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.735758882342885, + cumProb: 0.632120558828558, + logProb: -0.306852819440055, + }, + { + loc: 20, + prob: 0, + cumProb: 1, + logProb: -396.31112054588607, + }, + } + testDistributionProbs(t, Weibull{K: 2, Lambda: 1}, "2K (Rayleigh) Standard Weibull", pts) +} + +func TestFiveKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 1.839397205857210, + cumProb: 0.632120558828558, + logProb: 0.609437912434100, + }, + { + loc: 20, + prob: 0, + cumProb: 1, + logProb: -3199986.4076329935, + }, + } + testDistributionProbs(t, Weibull{K: 5, Lambda: 1}, "5K Standard Weibull", pts) +} + +func TestScaledUpHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.180436508682207, + cumProb: 0.558022622759326, + logProb: -1.712376315541750, + }, + { + loc: 20, + prob: 0.002369136850928, + cumProb: 0.974047406098605, + logProb: -6.045229588092130, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1.5}, "0.5K 1.5λ Weibull", pts) +} + +func TestScaledDownHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.171909491538362, + cumProb: 0.756883265565786, + logProb: -1.760787152653070, + }, + { + loc: 20, + prob: 0.000283302579100, + cumProb: 0.998208237166091, + logProb: -8.168995047393730, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 0.5}, "0.5K 0.5λ Weibull", pts) +} + +func TestWeibullScore(t *testing.T) { + for _, test := range []*Weibull{ + { + K: 1, + Lambda: 1, + }, + { + K: 2, + Lambda: 3.6, + }, + { + K: 3.4, + Lambda: 8, + }, + } { + testDerivParam(t, test) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/faithful_test.go b/vendor/gonum.org/v1/gonum/stat/faithful_test.go new file mode 100644 index 00000000..981eff1c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/faithful_test.go @@ -0,0 +1,81 @@ +// Copyright ©2016 The gonum 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 stat + +// faithful is the faithful data set from R. +var faithful = struct{ waiting, eruptions []float64 }{ + waiting: []float64{ + 79, 54, 74, 62, 85, 55, 88, 85, + 51, 85, 54, 84, 78, 47, 83, 52, + 62, 84, 52, 79, 51, 47, 78, 69, + 74, 83, 55, 76, 78, 79, 73, 77, + 66, 80, 74, 52, 48, 80, 59, 90, + 80, 58, 84, 58, 73, 83, 64, 53, + 82, 59, 75, 90, 54, 80, 54, 83, + 71, 64, 77, 81, 59, 84, 48, 82, + 60, 92, 78, 78, 65, 73, 82, 56, + 79, 71, 62, 76, 60, 78, 76, 83, + 75, 82, 70, 65, 73, 88, 76, 80, + 48, 86, 60, 90, 50, 78, 63, 72, + 84, 75, 51, 82, 62, 88, 49, 83, + 81, 47, 84, 52, 86, 81, 75, 59, + 89, 79, 59, 81, 50, 85, 59, 87, + 53, 69, 77, 56, 88, 81, 45, 82, + 55, 90, 45, 83, 56, 89, 46, 82, + 51, 86, 53, 79, 81, 60, 82, 77, + 76, 59, 80, 49, 96, 53, 77, 77, + 65, 81, 71, 70, 81, 93, 53, 89, + 45, 86, 58, 78, 66, 76, 63, 88, + 52, 93, 49, 57, 77, 68, 81, 81, + 73, 50, 85, 74, 55, 77, 83, 83, + 51, 78, 84, 46, 83, 55, 81, 57, + 76, 84, 77, 81, 87, 77, 51, 78, + 60, 82, 91, 53, 78, 46, 77, 84, + 49, 83, 71, 80, 49, 75, 64, 76, + 53, 94, 55, 76, 50, 82, 54, 75, + 78, 79, 78, 78, 70, 79, 70, 54, + 86, 50, 90, 54, 54, 77, 79, 64, + 75, 47, 86, 63, 85, 82, 57, 82, + 67, 74, 54, 83, 73, 73, 88, 80, + 71, 83, 56, 79, 78, 84, 58, 83, + 43, 60, 75, 81, 46, 90, 46, 74, + }, + eruptions: []float64{ + 3.600, 1.800, 3.333, 2.283, 4.533, 2.883, 4.700, 3.600, + 1.950, 4.350, 1.833, 3.917, 4.200, 1.750, 4.700, 2.167, + 1.750, 4.800, 1.600, 4.250, 1.800, 1.750, 3.450, 3.067, + 4.533, 3.600, 1.967, 4.083, 3.850, 4.433, 4.300, 4.467, + 3.367, 4.033, 3.833, 2.017, 1.867, 4.833, 1.833, 4.783, + 4.350, 1.883, 4.567, 1.750, 4.533, 3.317, 3.833, 2.100, + 4.633, 2.000, 4.800, 4.716, 1.833, 4.833, 1.733, 4.883, + 3.717, 1.667, 4.567, 4.317, 2.233, 4.500, 1.750, 4.800, + 1.817, 4.400, 4.167, 4.700, 2.067, 4.700, 4.033, 1.967, + 4.500, 4.000, 1.983, 5.067, 2.017, 4.567, 3.883, 3.600, + 4.133, 4.333, 4.100, 2.633, 4.067, 4.933, 3.950, 4.517, + 2.167, 4.000, 2.200, 4.333, 1.867, 4.817, 1.833, 4.300, + 4.667, 3.750, 1.867, 4.900, 2.483, 4.367, 2.100, 4.500, + 4.050, 1.867, 4.700, 1.783, 4.850, 3.683, 4.733, 2.300, + 4.900, 4.417, 1.700, 4.633, 2.317, 4.600, 1.817, 4.417, + 2.617, 4.067, 4.250, 1.967, 4.600, 3.767, 1.917, 4.500, + 2.267, 4.650, 1.867, 4.167, 2.800, 4.333, 1.833, 4.383, + 1.883, 4.933, 2.033, 3.733, 4.233, 2.233, 4.533, 4.817, + 4.333, 1.983, 4.633, 2.017, 5.100, 1.800, 5.033, 4.000, + 2.400, 4.600, 3.567, 4.000, 4.500, 4.083, 1.800, 3.967, + 2.200, 4.150, 2.000, 3.833, 3.500, 4.583, 2.367, 5.000, + 1.933, 4.617, 1.917, 2.083, 4.583, 3.333, 4.167, 4.333, + 4.500, 2.417, 4.000, 4.167, 1.883, 4.583, 4.250, 3.767, + 2.033, 4.433, 4.083, 1.833, 4.417, 2.183, 4.800, 1.833, + 4.800, 4.100, 3.966, 4.233, 3.500, 4.366, 2.250, 4.667, + 2.100, 4.350, 4.133, 1.867, 4.600, 1.783, 4.367, 3.850, + 1.933, 4.500, 2.383, 4.700, 1.867, 3.833, 3.417, 4.233, + 2.400, 4.800, 2.000, 4.150, 1.867, 4.267, 1.750, 4.483, + 4.000, 4.117, 4.083, 4.267, 3.917, 4.550, 4.083, 2.417, + 4.183, 2.217, 4.450, 1.883, 1.850, 4.283, 3.950, 2.333, + 4.150, 2.350, 4.933, 2.900, 4.583, 3.833, 2.083, 4.367, + 2.133, 4.350, 2.200, 4.450, 3.567, 4.500, 4.150, 3.817, + 3.917, 4.450, 2.000, 4.283, 4.767, 4.533, 1.850, 4.250, + 1.983, 2.250, 4.750, 4.117, 2.150, 4.417, 1.817, 4.467, + }, +} diff --git a/vendor/gonum.org/v1/gonum/stat/moments_bench_test.go b/vendor/gonum.org/v1/gonum/stat/moments_bench_test.go new file mode 100644 index 00000000..6df41394 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/moments_bench_test.go @@ -0,0 +1,611 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// a set of benchmarks to evaluate the performance of the various +// moment statistics: Mean, Variance, StdDev, MeanVariance, MeanStdDev, +// Covariance, Correlation, Skew, ExKurtosis, Moment, MomentAbout, ... +// +// It tests both weighted and unweighted versions by using a slice of +// all ones. + +package stat + +import ( + "math/rand" + "testing" +) + +const ( + small = 10 + medium = 1000 + large = 100000 + huge = 10000000 +) + +// tests for unweighted versions + +func RandomSlice(l int) []float64 { + s := make([]float64, l) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkMean(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Mean(s, wts) + } +} + +func BenchmarkMeanSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMean(b, s, wts) +} + +func benchmarkVariance(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Variance(s, wts) + } +} + +func BenchmarkVarianceSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkVariance(b, s, wts) +} + +func benchmarkStdDev(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + StdDev(s, wts) + } +} + +func BenchmarkStdDevSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkStdDev(b, s, wts) +} + +func benchmarkMeanVariance(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MeanVariance(s, wts) + } +} + +func BenchmarkMeanVarianceSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMeanVariance(b, s, wts) +} + +func benchmarkMeanStdDev(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MeanStdDev(s, wts) + } +} + +func BenchmarkMeanStdDevSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMeanStdDev(b, s, wts) +} + +func benchmarkCovariance(b *testing.B, s1, s2, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Covariance(s1, s2, wts) + } +} + +func BenchmarkCovarianceSmall(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceMedium(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceLarge(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceHuge(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceSmallWeighted(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + wts := RandomSlice(small) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceMediumWeighted(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceLargeWeighted(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + wts := RandomSlice(large) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceHugeWeighted(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkCovariance(b, s1, s2, wts) +} + +func benchmarkCorrelation(b *testing.B, s1, s2, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Correlation(s1, s2, wts) + } +} + +func BenchmarkCorrelationSmall(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationMedium(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationLarge(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationHuge(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationSmallWeighted(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + wts := RandomSlice(small) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationMediumWeighted(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationLargeWeighted(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + wts := RandomSlice(large) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationHugeWeighted(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkCorrelation(b, s1, s2, wts) +} + +func benchmarkSkew(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Skew(s, wts) + } +} + +func BenchmarkSkewSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkSkew(b, s, wts) +} + +func benchmarkExKurtosis(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + ExKurtosis(s, wts) + } +} + +func BenchmarkExKurtosisSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkExKurtosis(b, s, wts) +} + +func benchmarkMoment(b *testing.B, n float64, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Moment(n, s, wts) + } +} + +func BenchmarkMomentSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMoment(b, 5, s, wts) +} + +func benchmarkMomentAbout(b *testing.B, n float64, s []float64, mean float64, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MomentAbout(n, s, mean, wts) + } +} + +func BenchmarkMomentAboutSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMomentAbout(b, 5, s, 0, wts) +} diff --git a/vendor/gonum.org/v1/gonum/stat/pca_example_test.go b/vendor/gonum.org/v1/gonum/stat/pca_example_test.go new file mode 100644 index 00000000..b434a91a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/pca_example_test.go @@ -0,0 +1,60 @@ +// Copyright ©2016 The gonum 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 stat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +func ExamplePC() { + // iris is a truncated sample of the Fisher's Iris dataset. + n := 10 + d := 4 + iris := mat.NewDense(n, d, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }) + + // Calculate the principal component direction vectors + // and variances. + var pc stat.PC + ok := pc.PrincipalComponents(iris, nil) + if !ok { + return + } + fmt.Printf("variances = %.4f\n\n", pc.VarsTo(nil)) + + // Project the data onto the first 2 principal components. + k := 2 + var proj mat.Dense + proj.Mul(iris, pc.VectorsTo(nil).Slice(0, d, 0, k)) + + fmt.Printf("proj = %.4f", mat.Formatted(&proj, mat.Prefix(" "))) + + // Output: + // variances = [0.1666 0.0207 0.0079 0.0019] + // + // proj = ⎡-6.1686 1.4659⎤ + // ⎢-5.6767 1.6459⎥ + // ⎢-5.6699 1.3642⎥ + // ⎢-5.5643 1.3816⎥ + // ⎢-6.1734 1.3309⎥ + // ⎢-6.7278 1.4021⎥ + // ⎢-5.7743 1.1498⎥ + // ⎢-6.0466 1.4714⎥ + // ⎢-5.2709 1.3570⎥ + // ⎣-5.7533 1.6207⎦ +} diff --git a/vendor/gonum.org/v1/gonum/stat/pca_test.go b/vendor/gonum.org/v1/gonum/stat/pca_test.go new file mode 100644 index 00000000..6af1b8c0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/pca_test.go @@ -0,0 +1,188 @@ +// Copyright ©2016 The gonum 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 stat + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +var appengine bool + +func TestPrincipalComponents(t *testing.T) { + if appengine { + t.Skip("non-asm implementation fails test") + } +tests: + for i, test := range []struct { + data mat.Matrix + weights []float64 + wantVecs *mat.Dense + wantVars []float64 + epsilon float64 + }{ + // Test results verified using R. + { + data: mat.NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }), + wantVecs: mat.NewDense(3, 3, []float64{ + 0.5773502691896258, 0.8164965809277261, 0, + 0.577350269189626, -0.4082482904638632, -0.7071067811865476, + 0.5773502691896258, -0.4082482904638631, 0.7071067811865475, + }), + wantVars: []float64{27, 0, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data. + data: mat.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + wantVecs: mat.NewDense(4, 4, []float64{ + -0.6681110197952722, 0.7064764857539533, -0.14026590216895132, -0.18666578956412125, + -0.7166344774801547, -0.6427036135482664, -0.135650285905254, 0.23444848208629923, + -0.164411275166307, 0.11898477441068218, 0.9136367900709548, 0.35224901970831746, + -0.11415613655453069, -0.2714141920887426, 0.35664028439226514, -0.8866286823515034, + }), + wantVars: []float64{0.1665786313282786, 0.02065509475412993, 0.007944620317765855, 0.0019327647109368329}, + epsilon: 1e-12, + }, + { // Truncated iris data to form wide matrix. + data: mat.NewDense(3, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + }), + wantVecs: mat.NewDense(4, 3, []float64{ + -0.5705187254552365, -0.7505979435049239, 0.08084520834544455, + -0.8166537769529318, 0.5615147645527523, -0.032338083338177705, + -0.08709186238359454, -0.3482870890450082, -0.22636658336724505, + 0, 0, -0.9701425001453315, + }), + wantVars: []float64{0.0844692361537822, 0.022197430512884326, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data transposed to check for operation on fat input. + data: mat.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }).T(), + wantVecs: mat.NewDense(10, 4, []float64{ + -0.3366602459946619, -0.1373634006401213, 0.3465102523547623, -0.10290179303893479, + -0.31381852053861975, 0.5197145790632827, 0.5567296129086686, -0.15923062170153618, + -0.30857197637565165, -0.07670930360819002, 0.36159923003337235, 0.3342301027853355, + -0.29527124351656137, 0.16885455995353074, -0.5056204762881208, 0.32580913261444344, + -0.3327611073694004, -0.39365834489416474, 0.04900050959307464, 0.46812879383236555, + -0.34445484362044815, -0.2985206914561878, -0.1009714701361799, -0.16803618186050803, + -0.2986246350957691, -0.4222037823717799, -0.11838613462182519, -0.580283530375069, + -0.325911246223126, 0.024366468758217238, -0.12082035131864265, 0.16756027181337868, + -0.2814284432361538, 0.240812316260054, -0.24061437569068145, -0.365034616264623, + -0.31906138507685167, 0.4423912824105986, -0.2906412122303604, 0.027551046870337714, + }), + wantVars: []float64{41.8851906634233, 0.07762619213464989, 0.010516477775373585, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data unitary weights. + data: mat.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + weights: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + wantVecs: mat.NewDense(4, 4, []float64{ + -0.6681110197952722, 0.7064764857539533, -0.14026590216895132, -0.18666578956412125, + -0.7166344774801547, -0.6427036135482664, -0.135650285905254, 0.23444848208629923, + -0.164411275166307, 0.11898477441068218, 0.9136367900709548, 0.35224901970831746, + -0.11415613655453069, -0.2714141920887426, 0.35664028439226514, -0.8866286823515034, + }), + wantVars: []float64{0.1665786313282786, 0.02065509475412993, 0.007944620317765855, 0.0019327647109368329}, + epsilon: 1e-12, + }, + { // Truncated iris data non-unitary weights. + data: mat.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + weights: []float64{2, 3, 1, 1, 1, 1, 1, 1, 1, 2}, + wantVecs: mat.NewDense(4, 4, []float64{ + -0.618936145422414, 0.763069301531647, 0.124857741232537, 0.138035623677211, + -0.763958271606519, -0.603881770702898, 0.118267155321333, -0.194184052457746, + -0.143552119754944, 0.090014599564871, -0.942209377020044, -0.289018426115945, + -0.112599271966947, -0.212012782487076, -0.287515067921680, 0.927203898682805, + }), + wantVars: []float64{0.129621985550623, 0.022417487771598, 0.006454461065715, 0.002495076601075}, + epsilon: 1e-12, + }, + } { + var pc PC + var vecs *mat.Dense + var vars []float64 + for j := 0; j < 2; j++ { + ok := pc.PrincipalComponents(test.data, test.weights) + vecs = pc.VectorsTo(vecs) + vars = pc.VarsTo(vars) + if !ok { + t.Errorf("unexpected SVD failure for test %d use %d", i, j) + continue tests + } + if !mat.EqualApprox(vecs, test.wantVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected PCA result got:\n%v\nwant:\n%v", + i, j, mat.Formatted(vecs), mat.Formatted(test.wantVecs)) + } + if !approxEqual(vars, test.wantVars, test.epsilon) { + t.Errorf("%d use %d: unexpected variance result got:%v, want:%v", + i, j, vars, test.wantVars) + } + } + } +} + +func approxEqual(a, b []float64, epsilon float64) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if !floats.EqualWithinAbsOrRel(v, b[i], epsilon, epsilon) { + return false + } + } + return true +} diff --git a/vendor/gonum.org/v1/gonum/stat/roc_example_test.go b/vendor/gonum.org/v1/gonum/stat/roc_example_test.go new file mode 100644 index 00000000..9dce80b1 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/roc_example_test.go @@ -0,0 +1,56 @@ +// Copyright ©2016 The gonum 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 stat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/integrate" + "gonum.org/v1/gonum/stat" +) + +func ExampleROC_weighted() { + y := []float64{0, 3, 5, 6, 7.5, 8} + classes := []bool{true, false, true, false, false, false} + weights := []float64{4, 1, 6, 3, 2, 2} + + tpr, fpr := stat.ROC(0, y, classes, weights) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + + // Output: + // true positive rate: [0 0.4 0.4 1 1 1 1] + // false positive rate: [0 0 0.125 0.125 0.5 0.75 1] +} + +func ExampleROC_unweighted() { + y := []float64{0, 3, 5, 6, 7.5, 8} + classes := []bool{true, false, true, false, false, false} + + tpr, fpr := stat.ROC(0, y, classes, nil) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + + // Output: + // true positive rate: [0 0.5 0.5 1 1 1 1] + // false positive rate: [0 0 0.25 0.25 0.5 0.75 1] +} + +func ExampleROC_aUC() { + y := []float64{0.1, 0.35, 0.4, 0.8} + classes := []bool{true, false, true, false} + + tpr, fpr := stat.ROC(0, y, classes, nil) + // compute Area Under Curve + auc := integrate.Trapezoidal(fpr, tpr) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + fmt.Printf("auc: %v\n", auc) + + // Output: + // true positive rate: [0 0.5 0.5 1 1] + // false positive rate: [0 0 0.5 0.5 1] + // auc: 0.75 +} diff --git a/vendor/gonum.org/v1/gonum/stat/roc_test.go b/vendor/gonum.org/v1/gonum/stat/roc_test.go new file mode 100644 index 00000000..99fdae13 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/roc_test.go @@ -0,0 +1,178 @@ +// Copyright ©2016 The gonum 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 stat + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +// Test cases where calculated manually. +func TestROC(t *testing.T) { + cases := []struct { + y []float64 + c []bool + w []float64 + n int + wantTPR []float64 + wantFPR []float64 + }{ + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + wantTPR: []float64{0, 0.5, 0.5, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.25, 0.5, 0.75, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + wantTPR: []float64{0, 0.4, 0.4, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.125, 0.5, 0.75, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(5), + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(9), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.25, 0.25, 0.25, 0.5, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(5), + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(9), + wantTPR: []float64{0, 0.4, 0.4, 0.4, 0.4, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.125, 0.125, 0.125, 0.5, 0.5, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(5), + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(9), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(5), + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(9), + wantTPR: []float64{0, 0.4, 0.4, 0.4, 0.4, 0.4, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.125, 0.125, 0.125, 0.75, 0.75, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + wantTPR: []float64{0, 0.5, 1}, + wantFPR: []float64{0, 0, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + n: int(2), + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + n: int(7), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 0.5, 1}, + wantFPR: []float64{0, 0, 0, 0, 0, 0, 1}, + }, + { + y: []float64{1}, + c: []bool{true}, + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1}, + c: []bool{true}, + n: int(2), + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1}, + c: []bool{false}, + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 10}, + c: []bool{true, false, true, true, false, false, true}, + n: int(5), + wantTPR: []float64{0, 0.75, 0.75, 0.75, 1}, + wantFPR: []float64{0, 1, 1, 1, 1}, + }, + { + y: []float64{}, + c: []bool{}, + wantTPR: nil, + wantFPR: nil, + }, + { + y: []float64{}, + c: []bool{}, + n: int(5), + wantTPR: nil, + wantFPR: nil, + }, + } + for i, test := range cases { + gotTPR, gotFPR := ROC(test.n, test.y, test.c, test.w) + if !floats.Same(gotTPR, test.wantTPR) { + t.Errorf("%d: unexpected TPR got:%v want:%v", i, gotTPR, test.wantTPR) + } + if !floats.Same(gotFPR, test.wantFPR) { + t.Errorf("%d: unexpected FPR got:%v want:%v", i, gotFPR, test.wantFPR) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/samplemv/doc.go b/vendor/gonum.org/v1/gonum/stat/samplemv/doc.go new file mode 100644 index 00000000..ab4f37cc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/samplemv/doc.go @@ -0,0 +1,11 @@ +// Copyright ©2017 The gonum 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 samplemv implements advanced sampling routines from explicit and implicit +// probability distributions. +// +// Each sampling routine is implemented as a stateless function with a +// complementary wrapper type. The wrapper types allow the sampling routines +// to implement interfaces. +package samplemv // import "gonum.org/v1/gonum/stat/samplemv" diff --git a/vendor/gonum.org/v1/gonum/stat/samplemv/metropolishastings.go b/vendor/gonum.org/v1/gonum/stat/samplemv/metropolishastings.go new file mode 100644 index 00000000..d4d210e8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/samplemv/metropolishastings.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum 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 samplemv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/distmv" +) + +var _ Sampler = MetropolisHastingser{} + +// MHProposal defines a proposal distribution for Metropolis Hastings. +type MHProposal interface { + // ConditionalLogProb returns the probability of the first argument + // conditioned on being at the second argument. + // p(x|y) + // ConditionalLogProb panics if the input slices are not the same length. + ConditionalLogProb(x, y []float64) (prob float64) + + // ConditionalRand generates a new random location conditioned being at the + // location y. If the first argument is nil, a new slice is allocated and + // returned. Otherwise, the random location is stored in-place into the first + // argument, and ConditionalRand will panic if the input slice lengths differ. + ConditionalRand(x, y []float64) []float64 +} + +// MetropolisHastingser is a wrapper around the MetropolisHastings sampling type. +// +// BurnIn sets the number of samples to discard before keeping the first sample. +// A properly set BurnIn rate will decorrelate the sampling chain from the initial +// location. The proper BurnIn value will depend on the mixing time of the +// Markov chain defined by the target and proposal distributions. +// +// Rate sets the number of samples to discard in between each kept sample. A +// higher rate will better approximate independently and identically distributed +// samples, while a lower rate will keep more information (at the cost of +// higher correlation between samples). If Rate is 0 it is defaulted to 1. +// +// The initial value is NOT changed during calls to Sample. +type MetropolisHastingser struct { + Initial []float64 + Target distmv.LogProber + Proposal MHProposal + Src *rand.Rand + + BurnIn int + Rate int +} + +// Sample generates rows(batch) samples using the Metropolis Hastings sample +// generation method. The initial location is NOT updated during the call to Sample. +// +// The number of columns in batch must equal len(m.Initial), otherwise Sample +// will panic. +func (m MetropolisHastingser) Sample(batch *mat.Dense) { + burnIn := m.BurnIn + rate := m.Rate + if rate == 0 { + rate = 1 + } + r, c := batch.Dims() + if len(m.Initial) != c { + panic("metropolishastings: length mismatch") + } + + // Use the optimal size for the temporary memory to allow the fewest calls + // to MetropolisHastings. The case where tmp shadows samples must be + // aligned with the logic after burn-in so that tmp does not shadow samples + // during the rate portion. + tmp := batch + if rate > r { + tmp = mat.NewDense(rate, c, nil) + } + rTmp, _ := tmp.Dims() + + // Perform burn-in. + remaining := burnIn + initial := make([]float64, c) + copy(initial, m.Initial) + for remaining != 0 { + newSamp := min(rTmp, remaining) + MetropolisHastings(tmp.Slice(0, newSamp, 0, c).(*mat.Dense), initial, m.Target, m.Proposal, m.Src) + copy(initial, tmp.RawRowView(newSamp-1)) + remaining -= newSamp + } + + if rate == 1 { + MetropolisHastings(batch, initial, m.Target, m.Proposal, m.Src) + return + } + + if rTmp <= r { + tmp = mat.NewDense(rate, c, nil) + } + + // Take a single sample from the chain. + MetropolisHastings(batch.Slice(0, 1, 0, c).(*mat.Dense), initial, m.Target, m.Proposal, m.Src) + + copy(initial, batch.RawRowView(0)) + // For all of the other samples, first generate Rate samples and then actually + // accept the last one. + for i := 1; i < r; i++ { + MetropolisHastings(tmp, initial, m.Target, m.Proposal, m.Src) + v := tmp.RawRowView(rate - 1) + batch.SetRow(i, v) + copy(initial, v) + } +} + +// MetropolisHastings generates rows(batch) samples using the Metropolis Hastings +// algorithm (http://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm), +// with the given target and proposal distributions, starting at the initial location +// and storing the results in-place into samples. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Metropolis-Hastings is a Markov-chain Monte Carlo algorithm that generates +// samples according to the distribution specified by target by using the Markov +// chain implicitly defined by the proposal distribution. At each +// iteration, a proposal point is generated randomly from the current location. +// This proposal point is accepted with probability +// p = min(1, (target(new) * proposal(current|new)) / (target(current) * proposal(new|current))) +// If the new location is accepted, it is stored into batch and becomes the +// new current location. If it is rejected, the current location remains and +// is stored into samples. Thus, a location is stored into batch at every iteration. +// +// The samples in Metropolis Hastings are correlated with one another through the +// Markov chain. As a result, the initial value can have a significant influence +// on the early samples, and so, typically, the first samples generated by the chain +// are ignored. This is known as "burn-in", and can be accomplished with slicing. +// The best choice for burn-in length will depend on the sampling and target +// distributions. +// +// Many choose to have a sampling "rate" where a number of samples +// are ignored in between each kept sample. This helps decorrelate +// the samples from one another, but also reduces the number of available samples. +// A sampling rate can be implemented with successive calls to MetropolisHastings. +func MetropolisHastings(batch *mat.Dense, initial []float64, target distmv.LogProber, proposal MHProposal, src *rand.Rand) { + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + if len(initial) == 0 { + panic("metropolishastings: zero length initial") + } + r, _ := batch.Dims() + current := make([]float64, len(initial)) + copy(current, initial) + proposed := make([]float64, len(initial)) + currentLogProb := target.LogProb(initial) + for i := 0; i < r; i++ { + proposal.ConditionalRand(proposed, current) + proposedLogProb := target.LogProb(proposed) + probTo := proposal.ConditionalLogProb(proposed, current) + probBack := proposal.ConditionalLogProb(current, proposed) + + accept := math.Exp(proposedLogProb + probBack - probTo - currentLogProb) + if accept > f64() { + copy(current, proposed) + currentLogProb = proposedLogProb + } + batch.SetRow(i, current) + } +} + +// ProposalNormal is a sampling distribution for Metropolis-Hastings. It has a +// fixed covariance matrix and changes the mean based on the current sampling +// location. +type ProposalNormal struct { + normal *distmv.Normal +} + +// NewProposalNormal constructs a new ProposalNormal for use as a proposal +// distribution for Metropolis-Hastings. ProposalNormal is a multivariate normal +// distribution (implemented by distmv.Normal) where the covariance matrix is fixed +// and the mean of the distribution changes. +// +// NewProposalNormal returns {nil, false} if the covariance matrix is not positive-definite. +func NewProposalNormal(sigma *mat.SymDense, src *rand.Rand) (*ProposalNormal, bool) { + mu := make([]float64, sigma.Symmetric()) + normal, ok := distmv.NewNormal(mu, sigma, src) + if !ok { + return nil, false + } + p := &ProposalNormal{ + normal: normal, + } + return p, true +} + +// ConditionalLogProb returns the probability of the first argument conditioned on +// being at the second argument. +// p(x|y) +// ConditionalLogProb panics if the input slices are not the same length or +// are not equal to the dimension of the covariance matrix. +func (p *ProposalNormal) ConditionalLogProb(x, y []float64) (prob float64) { + // Either SetMean or LogProb will panic if the slice lengths are innaccurate. + p.normal.SetMean(y) + return p.normal.LogProb(x) +} + +// ConditionalRand generates a new random location conditioned being at the +// location y. If the first argument is nil, a new slice is allocated and +// returned. Otherwise, the random location is stored in-place into the first +// argument, and ConditionalRand will panic if the input slice lengths differ or +// if they are not equal to the dimension of the covariance matrix. +func (p *ProposalNormal) ConditionalRand(x, y []float64) []float64 { + if x == nil { + x = make([]float64, p.normal.Dim()) + } + if len(x) != len(y) { + panic(badLengthMismatch) + } + p.normal.SetMean(y) + p.normal.Rand(x) + return x +} diff --git a/vendor/gonum.org/v1/gonum/stat/samplemv/sample_test.go b/vendor/gonum.org/v1/gonum/stat/samplemv/sample_test.go new file mode 100644 index 00000000..9a3764de --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/samplemv/sample_test.go @@ -0,0 +1,280 @@ +// Copyright ©2016 The gonum 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 samplemv + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distmv" +) + +type lhDist interface { + Quantile(x, p []float64) []float64 + CDF(p, x []float64) []float64 + Dim() int +} + +func TestLatinHypercube(t *testing.T) { + for _, nSamples := range []int{1, 2, 5, 10, 20} { + for _, dist := range []lhDist{ + distmv.NewUniform([]distmv.Bound{{0, 3}}, nil), + distmv.NewUniform([]distmv.Bound{{0, 3}, {-1, 5}, {-4, -1}}, nil), + } { + dim := dist.Dim() + batch := mat.NewDense(nSamples, dim, nil) + LatinHypercube(batch, dist, nil) + // Latin hypercube should have one entry per hyperrow. + present := make([][]bool, nSamples) + for i := range present { + present[i] = make([]bool, dim) + } + cdf := make([]float64, dim) + for i := 0; i < nSamples; i++ { + dist.CDF(cdf, batch.RawRowView(i)) + for j := 0; j < dim; j++ { + p := cdf[j] + quadrant := int(math.Floor(p * float64(nSamples))) + present[quadrant][j] = true + } + } + allPresent := true + for i := 0; i < nSamples; i++ { + for j := 0; j < dim; j++ { + if !present[i][j] { + allPresent = false + } + } + } + if !allPresent { + t.Errorf("All quadrants not present") + } + } + } +} + +func TestImportance(t *testing.T) { + // Test by finding the expected value of a multi-variate normal. + dim := 3 + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + muImp := make([]float64, dim) + sigmaImp := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 3) + } + proposal, ok := distmv.NewNormal(muImp, sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 100000 + batch := mat.NewDense(nSamples, dim, nil) + weights := make([]float64, nSamples) + Importance(batch, weights, target, proposal) + + compareNormal(t, target, batch, weights, 5e-2, 5e-2) +} + +func TestRejection(t *testing.T) { + // Test by finding the expected value of a uniform. + dim := 3 + bounds := make([]distmv.Bound, dim) + for i := 0; i < dim; i++ { + min := rand.NormFloat64() + max := rand.NormFloat64() + if min > max { + min, max = max, min + } + bounds[i].Min = min + bounds[i].Max = max + } + target := distmv.NewUniform(bounds, nil) + mu := target.Mean(nil) + + muImp := make([]float64, dim) + sigmaImp := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 6) + } + proposal, ok := distmv.NewNormal(muImp, sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 1000 + batch := mat.NewDense(nSamples, dim, nil) + weights := make([]float64, nSamples) + _, ok = Rejection(batch, target, proposal, 1000, nil) + if !ok { + t.Error("Bad test, nan samples") + } + + for i := 0; i < dim; i++ { + col := mat.Col(nil, i, batch) + ev := stat.Mean(col, weights) + if math.Abs(ev-mu[i]) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", mu[i], ev) + } + } +} + +func TestMetropolisHastings(t *testing.T) { + // Test by finding the expected value of a normal distribution. + dim := 3 + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + sigmaImp := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 0.25) + } + proposal, ok := NewProposalNormal(sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 100000 + burnin := 5000 + batch := mat.NewDense(nSamples, dim, nil) + initial := make([]float64, dim) + MetropolisHastings(batch, initial, target, proposal, nil) + batch = batch.Slice(burnin, nSamples, 0, dim).(*mat.Dense) + + compareNormal(t, target, batch, nil, 5e-1, 5e-1) +} + +// randomNormal constructs a random Normal distribution. +func randomNormal(dim int) (*distmv.Normal, bool) { + data := make([]float64, dim*dim) + for i := range data { + data[i] = rand.Float64() + } + a := mat.NewDense(dim, dim, data) + var sigma mat.SymDense + sigma.SymOuterK(1, a) + mu := make([]float64, dim) + for i := range mu { + mu[i] = rand.NormFloat64() + } + return distmv.NewNormal(mu, &sigma, nil) +} + +func compareNormal(t *testing.T, want *distmv.Normal, batch *mat.Dense, weights []float64, meanTol, covTol float64) { + dim := want.Dim() + mu := want.Mean(nil) + sigma := want.CovarianceMatrix(nil) + n, _ := batch.Dims() + if weights == nil { + weights = make([]float64, n) + for i := range weights { + weights[i] = 1 + } + } + for i := 0; i < dim; i++ { + col := mat.Col(nil, i, batch) + ev := stat.Mean(col, weights) + if math.Abs(ev-mu[i]) > meanTol { + t.Errorf("Mean mismatch: Want %v, got %v", mu[i], ev) + } + } + + cov := stat.CovarianceMatrix(nil, batch, weights) + if !mat.EqualApprox(cov, sigma, covTol) { + t.Errorf("Covariance matrix mismatch") + } +} + +func TestMetropolisHastingser(t *testing.T) { + for seed, test := range []struct { + dim, burnin, rate, samples int + }{ + {3, 10, 1, 1}, + {3, 10, 2, 1}, + {3, 10, 1, 2}, + {3, 10, 3, 2}, + {3, 10, 7, 4}, + {3, 10, 7, 4}, + + {3, 11, 51, 103}, + {3, 11, 103, 51}, + {3, 51, 11, 103}, + {3, 51, 103, 11}, + {3, 103, 11, 51}, + {3, 103, 51, 11}, + } { + dim := test.dim + + initial := make([]float64, dim) + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + sigmaImp := mat.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 0.25) + } + proposal, ok := NewProposalNormal(sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + // Test the Metropolis Hastingser by generating all the samples, then generating + // the same samples with a burnin and rate. + rand.Seed(int64(seed)) + mh := MetropolisHastingser{ + Initial: initial, + Target: target, + Proposal: proposal, + Src: nil, + BurnIn: 0, + Rate: 0, + } + samples := test.samples + burnin := test.burnin + rate := test.rate + fullBatch := mat.NewDense(1+burnin+rate*(samples-1), dim, nil) + mh.Sample(fullBatch) + mh = MetropolisHastingser{ + Initial: initial, + Target: target, + Proposal: proposal, + Src: nil, + BurnIn: burnin, + Rate: rate, + } + rand.Seed(int64(seed)) + batch := mat.NewDense(samples, dim, nil) + mh.Sample(batch) + + same := true + count := burnin + for i := 0; i < samples; i++ { + if !floats.Equal(batch.RawRowView(i), fullBatch.RawRowView(count)) { + fmt.Println("sample ", i, "is different") + same = false + break + } + count += rate + } + + if !same { + fmt.Printf("%v\n", mat.Formatted(batch)) + fmt.Printf("%v\n", mat.Formatted(fullBatch)) + + t.Errorf("sampling mismatch: dim = %v, burnin = %v, rate = %v, samples = %v", dim, burnin, rate, samples) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/samplemv/samplemv.go b/vendor/gonum.org/v1/gonum/stat/samplemv/samplemv.go new file mode 100644 index 00000000..5b72ca3c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/samplemv/samplemv.go @@ -0,0 +1,274 @@ +// Copyright ©2016 The gonum 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 samplemv + +import ( + "errors" + "math" + "math/rand" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/distmv" +) + +var ( + badLengthMismatch = "samplemv: slice length mismatch" +) + +var ( + _ Sampler = LatinHypercuber{} + _ Sampler = (*Rejectioner)(nil) + _ Sampler = IIDer{} + + _ WeightedSampler = SampleUniformWeighted{} + _ WeightedSampler = Importancer{} +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// Sampler generates a batch of samples according to the rule specified by the +// implementing type. The number of samples generated is equal to rows(batch), +// and the samples are stored in-place into the input. +type Sampler interface { + Sample(batch *mat.Dense) +} + +// WeightedSampler generates a batch of samples and their relative weights +// according to the rule specified by the implementing type. The number of samples +// generated is equal to rows(batch), and the samples and weights +// are stored in-place into the inputs. The length of weights must equal +// rows(batch), otherwise SampleWeighted will panic. +type WeightedSampler interface { + SampleWeighted(batch *mat.Dense, weights []float64) +} + +// SampleUniformWeighted wraps a Sampler type to create a WeightedSampler where all +// weights are equal. +type SampleUniformWeighted struct { + Sampler +} + +// SampleWeighted generates rows(batch) samples from the embedded Sampler type +// and sets all of the weights equal to 1. If rows(batch) and len(weights) +// of weights are not equal, SampleWeighted will panic. +func (w SampleUniformWeighted) SampleWeighted(batch *mat.Dense, weights []float64) { + r, _ := batch.Dims() + if r != len(weights) { + panic(badLengthMismatch) + } + w.Sample(batch) + for i := range weights { + weights[i] = 1 + } +} + +// LatinHypercuber is a wrapper around the LatinHypercube sampling generation +// method. +type LatinHypercuber struct { + Q distmv.Quantiler + Src *rand.Rand +} + +// Sample generates rows(batch) samples using the LatinHypercube generation +// procedure. +func (l LatinHypercuber) Sample(batch *mat.Dense) { + LatinHypercube(batch, l.Q, l.Src) +} + +// LatinHypercube generates rows(batch) samples using Latin hypercube sampling +// from the given distribution. If src is not nil, it will be used to generate +// random numbers, otherwise rand.Float64 will be used. +// +// Latin hypercube sampling divides the cumulative distribution function into equally +// spaced bins and guarantees that one sample is generated per bin. Within each bin, +// the location is randomly sampled. The distmv.NewUnitUniform function can be used +// for easy sampling from the unit hypercube. +func LatinHypercube(batch *mat.Dense, q distmv.Quantiler, src *rand.Rand) { + r, c := batch.Dims() + var f64 func() float64 + var perm func(int) []int + if src != nil { + f64 = src.Float64 + perm = src.Perm + } else { + f64 = rand.Float64 + perm = rand.Perm + } + r64 := float64(r) + for i := 0; i < c; i++ { + p := perm(r) + for j := 0; j < r; j++ { + v := f64()/r64 + float64(j)/r64 + batch.Set(p[j], i, v) + } + } + p := make([]float64, c) + for i := 0; i < r; i++ { + copy(p, batch.RawRowView(i)) + q.Quantile(batch.RawRowView(i), p) + } +} + +// Importancer is a wrapper around the Importance sampling generation method. +type Importancer struct { + Target distmv.LogProber + Proposal distmv.RandLogProber +} + +// SampleWeighted generates rows(batch) samples using the Importance sampling +// generation procedure. +func (l Importancer) SampleWeighted(batch *mat.Dense, weights []float64) { + Importance(batch, weights, l.Target, l.Proposal) +} + +// Importance sampling generates rows(batch) samples from the proposal distribution, +// and stores the locations and importance sampling weights in place. +// +// Importance sampling is a variance reduction technique where samples are +// generated from a proposal distribution, q(x), instead of the target distribution +// p(x). This allows relatively unlikely samples in p(x) to be generated more frequently. +// +// The importance sampling weight at x is given by p(x)/q(x). To reduce variance, +// a good proposal distribution will bound this sampling weight. This implies the +// support of q(x) should be at least as broad as p(x), and q(x) should be "fatter tailed" +// than p(x). +// +// If weights is nil, the weights are not stored. The length of weights must equal +// the length of batch, otherwise Importance will panic. +func Importance(batch *mat.Dense, weights []float64, target distmv.LogProber, proposal distmv.RandLogProber) { + r, _ := batch.Dims() + if r != len(weights) { + panic(badLengthMismatch) + } + for i := 0; i < r; i++ { + v := batch.RawRowView(i) + proposal.Rand(v) + weights[i] = math.Exp(target.LogProb(v) - proposal.LogProb(v)) + } +} + +// ErrRejection is returned when the constant in Rejection is not sufficiently high. +var ErrRejection = errors.New("rejection: acceptance ratio above 1") + +// Rejectioner is a wrapper around the Rejection sampling generation procedure. +// If the rejection sampling fails during the call to Sample, all samples will +// be set to math.NaN() and a call to Err will return a non-nil value. +type Rejectioner struct { + C float64 + Target distmv.LogProber + Proposal distmv.RandLogProber + Src *rand.Rand + + err error + proposed int +} + +// Err returns nil if the most recent call to sample was successful, and returns +// ErrRejection if it was not. +func (r *Rejectioner) Err() error { + return r.err +} + +// Proposed returns the number of samples proposed during the most recent call to +// Sample. +func (r *Rejectioner) Proposed() int { + return r.proposed +} + +// Sample generates rows(batch) using the Rejection sampling generation procedure. +// Rejection sampling may fail if the constant is insufficiently high, as described +// in the function comment for Rejection. If the generation fails, the samples +// are set to math.NaN(), and a call to Err will return a non-nil value. +func (r *Rejectioner) Sample(batch *mat.Dense) { + r.err = nil + r.proposed = 0 + proposed, ok := Rejection(batch, r.Target, r.Proposal, r.C, r.Src) + if !ok { + r.err = ErrRejection + } + r.proposed = proposed +} + +// Rejection generates rows(batch) samples using the rejection sampling algorithm and +// stores them in place into samples. +// Sampling continues until batch is filled. Rejection returns the total number of proposed +// locations and a boolean indicating if the rejection sampling assumption is +// violated (see details below). If the returned boolean is false, all elements +// of samples are set to NaN. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Rejection sampling generates points from the target distribution by using +// the proposal distribution. At each step of the algorithm, the proposaed point +// is accepted with probability +// p = target(x) / (proposal(x) * c) +// where target(x) is the probability of the point according to the target distribution +// and proposal(x) is the probability according to the proposal distribution. +// The constant c must be chosen such that target(x) < proposal(x) * c for all x. +// The expected number of proposed samples is len(samples) * c. +// +// Target may return the true (log of) the probablity of the location, or it may return +// a value that is proportional to the probability (logprob + constant). This is +// useful for cases where the probability distribution is only known up to a normalization +// constant. +func Rejection(batch *mat.Dense, target distmv.LogProber, proposal distmv.RandLogProber, c float64, src *rand.Rand) (nProposed int, ok bool) { + if c < 1 { + panic("rejection: acceptance constant must be greater than 1") + } + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + r, dim := batch.Dims() + v := make([]float64, dim) + var idx int + for { + nProposed++ + proposal.Rand(v) + qx := proposal.LogProb(v) + px := target.LogProb(v) + accept := math.Exp(px-qx) / c + if accept > 1 { + // Invalidate the whole result and return a failure. + for i := 0; i < r; i++ { + for j := 0; j < dim; j++ { + batch.Set(i, j, math.NaN()) + } + } + return nProposed, false + } + if accept > f64() { + batch.SetRow(idx, v) + idx++ + if idx == r { + break + } + } + } + return nProposed, true +} + +// IIDer is a wrapper around the IID sample generation method. +type IIDer struct { + Dist distmv.Rander +} + +// Sample generates a set of identically and independently distributed samples. +func (iid IIDer) Sample(batch *mat.Dense) { + IID(batch, iid.Dist) +} + +// IID generates a set of independently and identically distributed samples from +// the input distribution. +func IID(batch *mat.Dense, d distmv.Rander) { + r, _ := batch.Dims() + for i := 0; i < r; i++ { + d.Rand(batch.RawRowView(i)) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/doc.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/doc.go new file mode 100644 index 00000000..9beb4ddc --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/doc.go @@ -0,0 +1,11 @@ +// Copyright ©2017 The gonum 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 sampleuv implements advanced sampling routines from explicit and implicit +// probability distributions. +// +// Each sampling routine is implemented as a stateless function with a +// complementary wrapper type. The wrapper types allow the sampling routines +// to implement interfaces. +package sampleuv // import "gonum.org/v1/gonum/stat/sampleuv" diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/example_burnin_test.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/example_burnin_test.go new file mode 100644 index 00000000..db1d1c31 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/example_burnin_test.go @@ -0,0 +1,39 @@ +// Copyright ©2015 The gonum 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 sampleuv + +import "gonum.org/v1/gonum/stat/distuv" + +type ProposalDist struct { + Sigma float64 +} + +func (p ProposalDist) ConditionalRand(y float64) float64 { + return distuv.Normal{Mu: y, Sigma: p.Sigma}.Rand() +} + +func (p ProposalDist) ConditionalLogProb(x, y float64) float64 { + return distuv.Normal{Mu: y, Sigma: p.Sigma}.LogProb(x) +} + +func ExampleMetropolisHastings_burnin() { + n := 1000 // The number of samples to generate. + burnin := 50 // Number of samples to ignore at the start. + var initial float64 + // target is the distribution from which we would like to sample. + target := distuv.Weibull{K: 5, Lambda: 0.5} + // proposal is the proposal distribution. Here, we are choosing + // a tight Gaussian distribution around the current location. In + // typical problems, if Sigma is too small, it takes a lot of samples + // to move around the distribution. If Sigma is too large, it can be hard + // to find acceptable samples. + proposal := ProposalDist{Sigma: 0.2} + + samples := make([]float64, n+burnin) + MetropolisHastings(samples, initial, target, proposal, nil) + + // Remove the initial samples through slicing. + samples = samples[burnin:] +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/example_rate_test.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/example_rate_test.go new file mode 100644 index 00000000..86917998 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/example_rate_test.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum 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 sampleuv + +import "gonum.org/v1/gonum/stat/distuv" + +func max(a, b int) int { + if a < b { + return b + } + return a +} + +func ExampleMetropolisHastings_samplingRate() { + // See Burnin example for a description of these quantities. + n := 1000 + burnin := 300 + var initial float64 + target := distuv.Weibull{K: 5, Lambda: 0.5} + proposal := ProposalDist{Sigma: 0.2} + + // Successive samples are correlated with one another through the + // Markov Chain defined by the proposal distribution. To get less + // correlated samples, one may use a sampling rate, in which only + // one sample from every few is accepted from the chain. This can + // be accomplished through a for loop. + rate := 50 + + tmp := make([]float64, max(rate, burnin)) + + // First deal with burnin. + tmp = tmp[:burnin] + MetropolisHastings(tmp, initial, target, proposal, nil) + // The final sample in tmp in the final point in the chain. + // Use it as the new initial location. + initial = tmp[len(tmp)-1] + + // Now, generate samples by using one every rate samples. + tmp = tmp[:rate] + samples := make([]float64, n) + samples[0] = initial + for i := 1; i < len(samples); i++ { + MetropolisHastings(tmp, initial, target, proposal, nil) + initial = tmp[len(tmp)-1] + samples[i] = initial + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/sample.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/sample.go new file mode 100644 index 00000000..1d836390 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/sample.go @@ -0,0 +1,393 @@ +// Copyright ©2015 The gonum 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 sampleuv + +import ( + "errors" + "math" + "math/rand" + + "gonum.org/v1/gonum/stat/distuv" +) + +var ( + badLengthMismatch = "sample: slice length mismatch" +) + +var ( + _ Sampler = LatinHypercuber{} + _ Sampler = MetropolisHastingser{} + _ Sampler = (*Rejectioner)(nil) + _ Sampler = IIDer{} + + _ WeightedSampler = SampleUniformWeighted{} + _ WeightedSampler = Importancer{} +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// Sampler generates a batch of samples according to the rule specified by the +// implementing type. The number of samples generated is equal to len(batch), +// and the samples are stored in-place into the input. +type Sampler interface { + Sample(batch []float64) +} + +// WeightedSampler generates a batch of samples and their relative weights +// according to the rule specified by the implementing type. The number of samples +// generated is equal to len(batch), and the samples and weights +// are stored in-place into the inputs. The length of weights must equal +// len(batch), otherwise SampleWeighted will panic. +type WeightedSampler interface { + SampleWeighted(batch, weights []float64) +} + +// SampleUniformWeighted wraps a Sampler type to create a WeightedSampler where all +// weights are equal. +type SampleUniformWeighted struct { + Sampler +} + +// SampleWeighted generates len(batch) samples from the embedded Sampler type +// and sets all of the weights equal to 1. If len(batch) and len(weights) +// are not equal, SampleWeighted will panic. +func (w SampleUniformWeighted) SampleWeighted(batch, weights []float64) { + if len(batch) != len(weights) { + panic(badLengthMismatch) + } + w.Sample(batch) + for i := range weights { + weights[i] = 1 + } +} + +// LatinHypercuber is a wrapper around the LatinHypercube sampling generation +// method. +type LatinHypercuber struct { + Q distuv.Quantiler + Src *rand.Rand +} + +// Sample generates len(batch) samples using the LatinHypercube generation +// procedure. +func (l LatinHypercuber) Sample(batch []float64) { + LatinHypercube(batch, l.Q, l.Src) +} + +// LatinHypercube generates len(batch) samples using Latin hypercube sampling +// from the given distribution. If src != nil, it will be used to generate +// random numbers, otherwise rand.Float64 will be used. +// +// Latin hypercube sampling divides the cumulative distribution function into equally +// spaced bins and guarantees that one sample is generated per bin. Within each bin, +// the location is randomly sampled. The distuv.UnitUniform variable can be used +// for easy generation from the unit interval. +func LatinHypercube(batch []float64, q distuv.Quantiler, src *rand.Rand) { + n := len(batch) + var perm []int + var f64 func() float64 + if src != nil { + f64 = src.Float64 + perm = src.Perm(n) + } else { + f64 = rand.Float64 + perm = rand.Perm(n) + } + for i := range batch { + v := f64()/float64(n) + float64(i)/float64(n) + batch[perm[i]] = q.Quantile(v) + } +} + +// Importancer is a wrapper around the Importance sampling generation method. +type Importancer struct { + Target distuv.LogProber + Proposal distuv.RandLogProber +} + +// Sample generates len(batch) samples using the Importance sampling generation +// procedure. +func (l Importancer) SampleWeighted(batch, weights []float64) { + Importance(batch, weights, l.Target, l.Proposal) +} + +// Importance sampling generates len(batch) samples from the proposal distribution, +// and stores the locations and importance sampling weights in place. +// +// Importance sampling is a variance reduction technique where samples are +// generated from a proposal distribution, q(x), instead of the target distribution +// p(x). This allows relatively unlikely samples in p(x) to be generated more frequently. +// +// The importance sampling weight at x is given by p(x)/q(x). To reduce variance, +// a good proposal distribution will bound this sampling weight. This implies the +// support of q(x) should be at least as broad as p(x), and q(x) should be "fatter tailed" +// than p(x). +// +// If weights is nil, the weights are not stored. The length of weights must equal +// the length of batch, otherwise Importance will panic. +func Importance(batch, weights []float64, target distuv.LogProber, proposal distuv.RandLogProber) { + if len(batch) != len(weights) { + panic(badLengthMismatch) + } + for i := range batch { + v := proposal.Rand() + batch[i] = v + weights[i] = math.Exp(target.LogProb(v) - proposal.LogProb(v)) + } +} + +// ErrRejection is returned when the constant in Rejection is not sufficiently high. +var ErrRejection = errors.New("rejection: acceptance ratio above 1") + +// Rejectioner is a wrapper around the Rejection sampling generation procedure. +// If the rejection sampling fails during the call to Sample, all samples will +// be set to math.NaN() and a call to Err will return a non-nil value. +type Rejectioner struct { + C float64 + Target distuv.LogProber + Proposal distuv.RandLogProber + Src *rand.Rand + + err error + proposed int +} + +// Err returns nil if the most recent call to sample was successful, and returns +// ErrRejection if it was not. +func (r *Rejectioner) Err() error { + return r.err +} + +// Proposed returns the number of samples proposed during the most recent call to +// Sample. +func (r *Rejectioner) Proposed() int { + return r.proposed +} + +// Sample generates len(batch) using the Rejection sampling generation procedure. +// Rejection sampling may fail if the constant is insufficiently high, as described +// in the function comment for Rejection. If the generation fails, the samples +// are set to math.NaN(), and a call to Err will return a non-nil value. +func (r *Rejectioner) Sample(batch []float64) { + r.err = nil + r.proposed = 0 + proposed, ok := Rejection(batch, r.Target, r.Proposal, r.C, r.Src) + if !ok { + r.err = ErrRejection + } + r.proposed = proposed +} + +// Rejection generates len(batch) samples using the rejection sampling algorithm +// and stores them in place into samples. Sampling continues until batch is +// filled. Rejection returns the total number of proposed locations and a boolean +// indicating if the rejection sampling assumption is violated (see details +// below). If the returned boolean is false, all elements of samples are set to +// NaN. If src is not nil, it will be used to generate random numbers, otherwise +// rand.Float64 will be used. +// +// Rejection sampling generates points from the target distribution by using +// the proposal distribution. At each step of the algorithm, the proposed point +// is accepted with probability +// p = target(x) / (proposal(x) * c) +// where target(x) is the probability of the point according to the target distribution +// and proposal(x) is the probability according to the proposal distribution. +// The constant c must be chosen such that target(x) < proposal(x) * c for all x. +// The expected number of proposed samples is len(samples) * c. +// +// Target may return the true (log of) the probablity of the location, or it may return +// a value that is proportional to the probability (logprob + constant). This is +// useful for cases where the probability distribution is only known up to a normalization +// constant. +func Rejection(batch []float64, target distuv.LogProber, proposal distuv.RandLogProber, c float64, src *rand.Rand) (nProposed int, ok bool) { + if c < 1 { + panic("rejection: acceptance constant must be greater than 1") + } + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + var idx int + for { + nProposed++ + v := proposal.Rand() + qx := proposal.LogProb(v) + px := target.LogProb(v) + accept := math.Exp(px-qx) / c + if accept > 1 { + // Invalidate the whole result and return a failure. + for i := range batch { + batch[i] = math.NaN() + } + return nProposed, false + } + if accept > f64() { + batch[idx] = v + idx++ + if idx == len(batch) { + break + } + } + } + return nProposed, true +} + +// MHProposal defines a proposal distribution for Metropolis Hastings. +type MHProposal interface { + // ConditionalDist returns the probability of the first argument conditioned on + // being at the second argument + // p(x|y) + ConditionalLogProb(x, y float64) (prob float64) + + // ConditionalRand generates a new random location conditioned being at the + // location y. + ConditionalRand(y float64) (x float64) +} + +// MetropolisHastingser is a wrapper around the MetropolisHastings sampling type. +// +// BurnIn sets the number of samples to discard before keeping the first sample. +// A properly set BurnIn rate will decorrelate the sampling chain from the initial +// location. The proper BurnIn value will depend on the mixing time of the +// Markov chain defined by the target and proposal distributions. +// +// Rate sets the number of samples to discard in between each kept sample. A +// higher rate will better approximate independently and identically distributed +// samples, while a lower rate will keep more information (at the cost of +// higher correlation between samples). If Rate is 0 it is defaulted to 1. +// +// The initial value is NOT changed during calls to Sample. +type MetropolisHastingser struct { + Initial float64 + Target distuv.LogProber + Proposal MHProposal + Src *rand.Rand + + BurnIn int + Rate int +} + +// Sample generates len(batch) samples using the Metropolis Hastings sample +// generation method. The initial location is NOT updated during the call to Sample. +func (m MetropolisHastingser) Sample(batch []float64) { + burnIn := m.BurnIn + rate := m.Rate + if rate == 0 { + rate = 1 + } + + // Use the optimal size for the temporary memory to allow the fewest calls + // to MetropolisHastings. The case where tmp shadows samples must be + // aligned with the logic after burn-in so that tmp does not shadow samples + // during the rate portion. + tmp := batch + if rate > len(batch) { + tmp = make([]float64, rate) + } + + // Perform burn-in. + remaining := burnIn + initial := m.Initial + for remaining != 0 { + newSamp := min(len(tmp), remaining) + MetropolisHastings(tmp[newSamp:], initial, m.Target, m.Proposal, m.Src) + initial = tmp[newSamp-1] + remaining -= newSamp + } + + if rate == 1 { + MetropolisHastings(batch, initial, m.Target, m.Proposal, m.Src) + return + } + + if len(tmp) <= len(batch) { + tmp = make([]float64, rate) + } + + // Take a single sample from the chain + MetropolisHastings(batch[0:1], initial, m.Target, m.Proposal, m.Src) + initial = batch[0] + + // For all of the other samples, first generate Rate samples and then actually + // accept the last one. + for i := 1; i < len(batch); i++ { + MetropolisHastings(tmp, initial, m.Target, m.Proposal, m.Src) + v := tmp[rate-1] + batch[i] = v + initial = v + } +} + +// MetropolisHastings generates len(batch) samples using the Metropolis Hastings +// algorithm (http://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm), +// with the given target and proposal distributions, starting at the initial location +// and storing the results in-place into samples. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Metropolis-Hastings is a Markov-chain Monte Carlo algorithm that generates +// samples according to the distribution specified by target by using the Markov +// chain implicitly defined by the proposal distribution. At each +// iteration, a proposal point is generated randomly from the current location. +// This proposal point is accepted with probability +// p = min(1, (target(new) * proposal(current|new)) / (target(current) * proposal(new|current))) +// If the new location is accepted, it is stored into batch and becomes the +// new current location. If it is rejected, the current location remains and +// is stored into samples. Thus, a location is stored into batch at every iteration. +// +// The samples in Metropolis Hastings are correlated with one another through the +// Markov chain. As a result, the initial value can have a significant influence +// on the early samples, and so, typically, the first samples generated by the chain +// are ignored. This is known as "burn-in", and can be accomplished with slicing. +// The best choice for burn-in length will depend on the sampling and target +// distributions. +// +// Many choose to have a sampling "rate" where a number of samples +// are ignored in between each kept sample. This helps decorrelate +// the samples from one another, but also reduces the number of available samples. +// A sampling rate can be implemented with successive calls to MetropolisHastings. +func MetropolisHastings(batch []float64, initial float64, target distuv.LogProber, proposal MHProposal, src *rand.Rand) { + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + current := initial + currentLogProb := target.LogProb(initial) + for i := range batch { + proposed := proposal.ConditionalRand(current) + proposedLogProb := target.LogProb(proposed) + probTo := proposal.ConditionalLogProb(proposed, current) + probBack := proposal.ConditionalLogProb(current, proposed) + + accept := math.Exp(proposedLogProb + probBack - probTo - currentLogProb) + if accept > f64() { + current = proposed + currentLogProb = proposedLogProb + } + batch[i] = current + } +} + +// IIDer is a wrapper around the IID sample generation method. +type IIDer struct { + Dist distuv.Rander +} + +// Sample generates a set of identically and independently distributed samples. +func (iid IIDer) Sample(batch []float64) { + IID(batch, iid.Dist) +} + +// IID generates a set of independently and identically distributed samples from +// the input distribution. +func IID(batch []float64, d distuv.Rander) { + for i := range batch { + batch[i] = d.Rand() + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/sample_test.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/sample_test.go new file mode 100644 index 00000000..49965ec0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/sample_test.go @@ -0,0 +1,99 @@ +// Copyright ©2015 The gonum 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 sampleuv + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +type lhDist interface { + Quantile(float64) float64 + CDF(float64) float64 +} + +func TestLatinHypercube(t *testing.T) { + for _, nSamples := range []int{1, 2, 5, 10, 20} { + samples := make([]float64, nSamples) + for _, dist := range []lhDist{ + distuv.Uniform{Min: 0, Max: 1}, + distuv.Uniform{Min: 0, Max: 10}, + distuv.Normal{Mu: 5, Sigma: 3}, + } { + LatinHypercube(samples, dist, nil) + sort.Float64s(samples) + for i, v := range samples { + p := dist.CDF(v) + if p < float64(i)/float64(nSamples) || p > float64(i+1)/float64(nSamples) { + t.Errorf("probability out of bounds") + } + } + } + } +} + +func TestImportance(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := distuv.Normal{Mu: 0, Sigma: 5} + nSamples := 100000 + x := make([]float64, nSamples) + weights := make([]float64, nSamples) + Importance(x, weights, target, proposal) + ev := stat.Mean(x, weights) + if math.Abs(ev-trueMean) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} + +func TestRejection(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := distuv.Normal{Mu: 0, Sigma: 5} + + nSamples := 20000 + x := make([]float64, nSamples) + Rejection(x, target, proposal, 100, nil) + ev := stat.Mean(x, nil) + if math.Abs(ev-trueMean) > 2e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} + +type condNorm struct { + Sigma float64 +} + +func (c condNorm) ConditionalRand(y float64) float64 { + return distuv.Normal{Mu: y, Sigma: c.Sigma}.Rand() +} + +func (c condNorm) ConditionalLogProb(x, y float64) float64 { + return distuv.Normal{Mu: y, Sigma: c.Sigma}.LogProb(x) +} + +func TestMetropolisHastings(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := condNorm{Sigma: 5} + + burnin := 500 + nSamples := 100000 + burnin + x := make([]float64, nSamples) + MetropolisHastings(x, 100, target, proposal, nil) + // Remove burnin + x = x[burnin:] + ev := stat.Mean(x, nil) + if math.Abs(ev-trueMean) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted.go new file mode 100644 index 00000000..006cafdd --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted.go @@ -0,0 +1,138 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package sampleuv + +import ( + "math/rand" + + "gonum.org/v1/gonum/floats" +) + +// Weighted provides sampling without replacement from a collection of items with +// non-uniform probability. +type Weighted struct { + weights []float64 + // heap is a weight heap. + // + // It keeps a heap-organised sum of remaining + // index weights that are available to be taken + // from. + // + // Each element holds the sum of weights for + // the corresponding index, plus the sum of + // of its children's weights; the children + // of an element i can be found at positions + // 2*(i+1)-1 and 2*(i+1). The root of the + // weight heap is at element 0. + // + // See comments in container/heap for an + // explanation of the layout of a heap. + heap []float64 + src *rand.Rand +} + +// NewWeighted returns a Weighted for the weights w. If src is nil, rand.Rand is +// used as the random source. +// +// Note that sampling from weights with a high variance or overall low absolute +// value sum may result in problems with numerical stability. +func NewWeighted(w []float64, src *rand.Rand) Weighted { + s := Weighted{ + weights: make([]float64, len(w)), + heap: make([]float64, len(w)), + src: src, + } + s.ReweightAll(w) + return s +} + +// Len returns the number of items held by the Weighted, including items +// already taken. +func (s Weighted) Len() int { return len(s.weights) } + +// Take returns an index from the Weighted with probability proportional +// to the weight of the item. The weight of the item is then set to zero. +// Take returns false if there are no items remaining. +func (s Weighted) Take() (idx int, ok bool) { + const small = 1e-12 + if floats.EqualWithinAbsOrRel(s.heap[0], 0, small, small) { + return -1, false + } + + var r float64 + if s.src == nil { + r = s.heap[0] * rand.Float64() + } else { + r = s.heap[0] * s.src.Float64() + } + i := 1 + last := -1 + left := len(s.weights) + for { + if r -= s.weights[i-1]; r <= 0 { + break // Fall within item i-1. + } + i <<= 1 // Move to left child. + if d := s.heap[i-1]; r > d { + r -= d + // If enough r to pass left child + // move to right child state will + // be caught at break above. + i++ + } + if i == last || left < 0 { + // No progression. + return -1, false + } + last = i + left-- + } + + w, idx := s.weights[i-1], i-1 + + s.weights[i-1] = 0 + for i > 0 { + s.heap[i-1] -= w + // The following condition is necessary to + // handle floating point error. If we see + // a heap value below zero, we know we need + // to rebuild it. + if s.heap[i-1] < 0 { + s.reset() + return idx, true + } + i >>= 1 + } + + return idx, true +} + +// Reweight sets the weight of item idx to w. +func (s Weighted) Reweight(idx int, w float64) { + w, s.weights[idx] = s.weights[idx]-w, w + idx++ + for idx > 0 { + s.heap[idx-1] -= w + idx >>= 1 + } +} + +// ReweightAll sets the weight of all items in the Weighted. ReweightAll +// panics if len(w) != s.Len. +func (s Weighted) ReweightAll(w []float64) { + if len(w) != s.Len() { + panic("floats: length of the slices do not match") + } + copy(s.weights, w) + s.reset() +} + +func (s Weighted) reset() { + copy(s.heap, s.weights) + for i := len(s.heap) - 1; i > 0; i-- { + // Sometimes 1-based counting makes sense. + s.heap[((i+1)>>1)-1] += s.heap[i] + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted_test.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted_test.go new file mode 100644 index 00000000..ad2799f9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/weighted_test.go @@ -0,0 +1,267 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package sampleuv + +import ( + "flag" + "math/rand" + "reflect" + "testing" + "time" + + "gonum.org/v1/gonum/floats" +) + +var prob = flag.Bool("prob", false, "enables probabilistic testing of the random weighted sampler") + +const sigChi2 = 16.92 // p = 0.05 df = 9 + +var ( + newExp = func() []float64 { + return []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7, 1 << 8, 1 << 9} + } + exp = newExp() + + obt = []float64{973, 1937, 3898, 7897, 15769, 31284, 62176, 125408, 250295, 500363} +) + +func newTestWeighted() Weighted { + weights := make([]float64, len(obt)) + for i := range weights { + weights[i] = float64(int(1) << uint(i)) + } + return NewWeighted(weights, nil) +} + +func TestWeightedUnseeded(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5] + exp[6], + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5] + exp[6], + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + exp[6], + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + item, ok := newTestWeighted().Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if !reflect.DeepEqual(f, obt) { + t.Fatalf("unexpected selection:\ngot: %#v\nwant:%#v", f, obt) + } + + // Check that this is within statistical expectations - we know this is true for this set. + X := chi2(f, exp) + if X >= sigChi2 { + t.Errorf("H₀: d(Sample) = d(Expect), H₁: d(S) ≠ d(Expect). df = %d, p = 0.05, X² threshold = %.2f, X² = %f", len(f)-1, sigChi2, X) + } +} + +func TestWeightedTimeSeeded(t *testing.T) { + if !*prob { + t.Skip("probabilistic testing not requested") + } + t.Log("Note: This test is stochastic and is expected to fail with probability ≈ 0.05.") + + rand.Seed(time.Now().Unix()) + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + item, ok := newTestWeighted().Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + // Check that our obtained values are within statistical expectations for p = 0.05. + // This will not be true approximately 1 in 20 tests. + X := chi2(f, exp) + if X >= sigChi2 { + t.Errorf("H₀: d(Sample) = d(Expect), H₁: d(S) ≠ d(Expect). df = %d, p = 0.05, X² threshold = %.2f, X² = %f", len(f)-1, sigChi2, X) + } +} + +func TestWeightZero(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 0, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5], + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5], + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + 0, + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + ts.Reweight(6, 0) + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + ts := newTestWeighted() + ts.Reweight(6, 0) + item, ok := ts.Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if f[6] != 0 { + t.Errorf("unexpected selection rate for zero-weighted item: got: %v want:%v", f[6], 0) + } + if reflect.DeepEqual(f[:6], obt[:6]) { + t.Fatalf("unexpected selection: too few elements chosen in range:\ngot: %v\nwant:%v", + f[:6], obt[:6]) + } + if reflect.DeepEqual(f[7:], obt[7:]) { + t.Fatalf("unexpected selection: too few elements chosen in range:\ngot: %v\nwant:%v", + f[7:], obt[7:]) + } +} + +func TestWeightIncrease(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 9 * 2, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5] + exp[9]*2, + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5] + exp[9]*2, + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + exp[9] * 2, + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + ts.Reweight(6, ts.weights[len(ts.weights)-1]*2) + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + ts := newTestWeighted() + ts.Reweight(6, ts.weights[len(ts.weights)-1]*2) + item, ok := ts.Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if f[6] < f[9] { + t.Errorf("unexpected selection rate for re-weighted item: got: %v want:%v", f[6], f[9]) + } + if reflect.DeepEqual(f[:6], obt[:6]) { + t.Fatalf("unexpected selection: too many elements chosen in range:\ngot: %v\nwant:%v", + f[:6], obt[:6]) + } + if reflect.DeepEqual(f[7:], obt[7:]) { + t.Fatalf("unexpected selection: too many elements chosen in range:\ngot: %v\nwant:%v", + f[7:], obt[7:]) + } +} + +func chi2(ob, ex []float64) (sum float64) { + for i := range ob { + x := ob[i] - ex[i] + sum += (x * x) / ex[i] + } + + return sum +} + +func TestWeightedNoResample(t *testing.T) { + const ( + tries = 10 + n = 10e4 + ) + ts := NewWeighted(make([]float64, n), nil) + w := make([]float64, n) + for i := 0; i < tries; i++ { + for j := range w { + w[j] = rand.Float64() * n + } + ts.ReweightAll(w) + taken := make(map[int]struct{}) + var c int + for { + item, ok := ts.Take() + if !ok { + if c != n { + t.Errorf("unexpected number of items: got: %d want: %d", c, int(n)) + } + break + } + c++ + if _, exists := taken[item]; exists { + t.Errorf("unexpected duplicate sample for item: %d", item) + } + taken[item] = struct{}{} + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement.go new file mode 100644 index 00000000..9fbc543c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement.go @@ -0,0 +1,59 @@ +// Copyright ©2017 The gonum 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 sampleuv + +import ( + "math/rand" + "sort" +) + +// WithoutReplacement samples len(idxs) integers from [0, n) without replacement. +// That is, upon return the elements of idxs will be unique integers. If source +// is non-nil it will be used to generate random numbers, otherwise the default +// source from the math/rand package will be used. +// +// WithoutReplacement will panic if len(idxs) > n. +func WithoutReplacement(idxs []int, n int, src *rand.Rand) { + if len(idxs) == 0 { + panic("withoutreplacement: zero length input") + } + if len(idxs) > n { + panic("withoutreplacement: impossible size inputs") + } + + // There are two algorithms. One is to generate a random permutation + // and take the first len(idxs) elements. The second is to generate + // individual random numbers for each element and check uniqueness. The first + // method scales as O(n), and the second scales as O(len(idxs)^2). Choose + // the algorithm accordingly. + if n < len(idxs)*len(idxs) { + var perm []int + if src != nil { + perm = src.Perm(n) + } else { + perm = rand.Perm(n) + } + copy(idxs, perm) + } + + // Instead, generate the random numbers directly. + sorted := make([]int, 0, len(idxs)) + for i := range idxs { + var r int + if src != nil { + r = src.Intn(n - i) + } else { + r = rand.Intn(n - i) + } + for _, v := range sorted { + if r >= v { + r++ + } + } + idxs[i] = r + sorted = append(sorted, r) + sort.Ints(sorted) + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement_test.go b/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement_test.go new file mode 100644 index 00000000..fca5d7d3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/sampleuv/withoutreplacement_test.go @@ -0,0 +1,65 @@ +// Copyright ©2017 The gonum 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 sampleuv + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestWithoutReplacement(t *testing.T) { + for cas, test := range []struct { + N int + K int + Src *rand.Rand + Trials int + Tol float64 + }{ + { + // Test with perm and source. + N: 10, K: 5, Src: rand.New(rand.NewSource(1)), + Trials: 100000, Tol: 1e-3, + }, + { + // Test without perm and with source. + N: 10, K: 3, Src: rand.New(rand.NewSource(1)), + Trials: 100000, Tol: 1e-3, + }, + } { + dist := make([]float64, test.N) + for trial := 0; trial < test.Trials; trial++ { + idxs := make([]int, test.K) + WithoutReplacement(idxs, test.N, test.Src) + + allDiff := true + for i := 0; i < len(idxs); i++ { + v := idxs[i] + for j := i + 1; j < len(idxs); j++ { + if v == idxs[j] { + allDiff = false + break + } + } + } + if !allDiff { + t.Errorf("Cas %d: Repeat in sampling. Idxs =%v", cas, idxs) + } + for _, v := range idxs { + dist[v]++ + } + } + div := 1 / (float64(test.Trials) * float64(test.K)) + floats.Scale(div, dist) + want := make([]float64, test.N) + for i := range want { + want[i] = 1 / float64(test.N) + } + if !floats.EqualApprox(want, dist, test.Tol) { + t.Errorf("Cas %d: biased sampling. Want = %v, got = %v", cas, want, dist) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/spatial/doc.go b/vendor/gonum.org/v1/gonum/stat/spatial/doc.go new file mode 100644 index 00000000..139d22d9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/spatial/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum 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 spatial provides spatial statistical functions. +package spatial // import "gonum.org/v1/gonum/stat/spatial" diff --git a/vendor/gonum.org/v1/gonum/stat/spatial/spatial.go b/vendor/gonum.org/v1/gonum/stat/spatial/spatial.go new file mode 100644 index 00000000..a45fe422 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/spatial/spatial.go @@ -0,0 +1,162 @@ +// Copyright ©2017 The gonum 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 spatial + +import ( + "math" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" +) + +// TODO(kortschak): Implement weighted routines. + +// GetisOrdGStar returns the Local Getis-Ord G*i statistic for element of of the +// weighted data using the provided locality matrix. The returned value is a z-score. +// +// G^*_i = num_i / den_i +// +// num_i = \sum_j (w_{ij} x_j) - \bar X \sum_j w_{ij} +// den_i = S \sqrt(((n \sum_j w_{ij}^2 - (\sum_j w_{ij})^2))/(n - 1)) +// \bar X = (\sum_j x_j) / n +// S = \sqrt((\sum_j x_j^2)/n - (\bar X)^2) +// +// GetisOrdGStar will panic if locality is not a square matrix with dimensions the +// same as the length of data or if i is not a valid index into data. +// +// See doi.org/10.1111%2Fj.1538-4632.1995.tb00912.x. +// +// Weighted Getis-Ord G*i is not currently implemented and GetisOrdGStar will +// panic if weights is not nil. +func GetisOrdGStar(i int, data, weights []float64, locality mat.Matrix) float64 { + if weights != nil { + panic("spatial: weighted data not yet implemented") + } + r, c := locality.Dims() + if r != len(data) || c != len(data) { + panic("spatial: data length mismatch") + } + + n := float64(len(data)) + mean, std := stat.MeanStdDev(data, weights) + var dwd, dww, sw float64 + if doer, ok := locality.(mat.RowNonZeroDoer); ok { + doer.DoRowNonZero(i, func(_, j int, w float64) { + sw += w + dwd += w * data[j] + dww += w * w + }) + } else { + for j, v := range data { + w := locality.At(i, j) + sw += w + dwd += w * v + dww += w * w + } + } + s := std * math.Sqrt((n-1)/n) + + return (dwd - mean*sw) / (s * math.Sqrt((n*dww-sw*sw)/(n-1))) +} + +// GlobalMoransI performs Global Moran's I calculation of spatial autocorrelation +// for the given data using the provided locality matrix. GlobalMoransI returns +// Moran's I, Var(I) and the z-score associated with those values. +// GlobalMoransI will panic if locality is not a square matrix with dimensions the +// same as the length of data. +// +// See https://doi.org/10.1111%2Fj.1538-4632.2007.00708.x. +// +// Weighted Global Moran's I is not currently implemented and GlobalMoransI will +// panic if weights is not nil. +func GlobalMoransI(data, weights []float64, locality mat.Matrix) (i, v, z float64) { + if weights != nil { + panic("spatial: weighted data not yet implemented") + } + if r, c := locality.Dims(); r != len(data) || c != len(data) { + panic("spatial: data length mismatch") + } + mean := stat.Mean(data, nil) + + doer, isDoer := locality.(mat.RowNonZeroDoer) + + // Calculate Moran's I for the data. + var num, den, sum float64 + for i, xi := range data { + zi := xi - mean + den += zi * zi + if isDoer { + doer.DoRowNonZero(i, func(_, j int, w float64) { + sum += w + zj := data[j] - mean + num += w * zi * zj + }) + } else { + for j, xj := range data { + w := locality.At(i, j) + sum += w + zj := xj - mean + num += w * zi * zj + } + } + } + i = (float64(len(data)) / sum) * (num / den) + + // Calculate Moran's E(I) for the data. + e := -1 / float64(len(data)-1) + + // Calculate Moran's Var(I) for the data. + // http://pro.arcgis.com/en/pro-app/tool-reference/spatial-statistics/h-how-spatial-autocorrelation-moran-s-i-spatial-st.htm + // http://pro.arcgis.com/en/pro-app/tool-reference/spatial-statistics/h-global-morans-i-additional-math.htm + var s0, s1, s2 float64 + var var2, var4 float64 + for i, v := range data { + v -= mean + v *= v + var2 += v + var4 += v * v + + var p2 float64 + if isDoer { + doer.DoRowNonZero(i, func(i, j int, wij float64) { + wji := locality.At(j, i) + + s0 += wij + + v := wij + wji + s1 += v * v + + p2 += v + }) + } else { + for j := range data { + wij := locality.At(i, j) + wji := locality.At(j, i) + + s0 += wij + + v := wij + wji + s1 += v * v + + p2 += v + } + } + s2 += p2 * p2 + } + s1 *= 0.5 + + n := float64(len(data)) + a := n * ((n*n-3*n+3)*s1 - n*s2 + 3*s0*s0) + c := (n - 1) * (n - 2) * (n - 3) * s0 * s0 + d := var4 / (var2 * var2) + b := d * ((n*n-n)*s1 - 2*n*s2 + 6*s0*s0) + + v = (a-b)/c - e*e + + // Calculate z-score associated with Moran's I for the data. + z = (i - e) / math.Sqrt(v) + + return i, v, z +} diff --git a/vendor/gonum.org/v1/gonum/stat/spatial/spatial_areal_example_test.go b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_areal_example_test.go new file mode 100644 index 00000000..1f849292 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_areal_example_test.go @@ -0,0 +1,74 @@ +// Copyright ©2017 The gonum 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 spatial_test + +import ( + "fmt" + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/spatial" +) + +// Euclid is a mat.Matrix whose elements refects the Euclidean +// distance between a series of unit-separated points strided +// to be arranged in an x by y grid. +type Euclid struct{ x, y int } + +func (e Euclid) Dims() (r, c int) { return e.x * e.y, e.x * e.y } +func (e Euclid) At(i, j int) float64 { + d := e.x * e.y + if i < 0 || d <= i || j < 0 || d <= j { + panic("bounds error") + } + if i == j { + return 0 + } + x := float64(j%e.x - i%e.x) + y := float64(j/e.x - i/e.x) + return 1 / math.Hypot(x, y) +} +func (e Euclid) T() mat.Matrix { return mat.Transpose{e} } + +func ExampleGlobalMoransI_areal() { + locality := Euclid{10, 10} + + data1 := []float64{ + 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, + 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + } + i1, _, z1 := spatial.GlobalMoransI(data1, nil, locality) + + data2 := []float64{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + } + i2, _, z2 := spatial.GlobalMoransI(data2, nil, locality) + + fmt.Printf("%v scattered points Moran's I=%.4v z-score=%.4v\n", floats.Sum(data1), i1, z1) + fmt.Printf("%v clustered points Moran's I=%.4v z-score=%.4v\n", floats.Sum(data2), i2, z2) + + // Output: + // + // 24 scattered points Moran's I=-0.02999 z-score=-1.913 + // 24 clustered points Moran's I=0.09922 z-score=10.52 +} diff --git a/vendor/gonum.org/v1/gonum/stat/spatial/spatial_example_test.go b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_example_test.go new file mode 100644 index 00000000..e5281a7e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_example_test.go @@ -0,0 +1,142 @@ +// Copyright ©2017 The gonum 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 spatial_test + +import ( + "fmt" + + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat/spatial" +) + +func ExampleGlobalMoransI_linear() { + data := []float64{0, 0, 0, 1, 1, 1, 0, 1, 0, 0} + + // The locality here describes spatial neighbor + // relationships. + locality := mat.NewDense(10, 10, []float64{ + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + }) + + i, _, z := spatial.GlobalMoransI(data, nil, locality) + + fmt.Printf("Moran's I=%.4v z-score=%.4v\n", i, z) + + // Output: + // + // Moran's I=0.1111 z-score=0.6335 +} + +func ExampleGlobalMoransI_banded() { + data := []float64{0, 0, 0, 1, 1, 1, 0, 1, 0, 0} + + // The locality here describes spatial neighbor + // relationships. + // This example uses the band matrix representation + // to improve time and space efficiency. + locality := mat.NewBandDense(10, 10, 1, 1, []float64{ + 0, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 0, + }) + + i, _, z := spatial.GlobalMoransI(data, nil, locality) + + fmt.Printf("Moran's I=%.4v z-score=%.4v\n", i, z) + + // Output: + // + // Moran's I=0.1111 z-score=0.6335 +} + +func ExampleGetisOrdGStar() { + data := []float64{0, 0, 0, 1, 1, 1, 0, 1, 0, 0} + + // The locality here describes spatial neighbor + // relationships including self. + locality := mat.NewDense(10, 10, []float64{ + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + }) + + for i, v := range data { + fmt.Printf("v=%v G*i=% .4v\n", v, spatial.GetisOrdGStar(i, data, nil, locality)) + } + + // Output: + // + // v=0 G*i=-1.225 + // v=0 G*i=-1.604 + // v=0 G*i=-0.2673 + // v=1 G*i= 1.069 + // v=1 G*i= 2.405 + // v=1 G*i= 1.069 + // v=0 G*i= 1.069 + // v=1 G*i=-0.2673 + // v=0 G*i=-0.2673 + // v=0 G*i=-1.225 +} + +func ExampleGetisOrd_band() { + data := []float64{0, 0, 0, 1, 1, 1, 0, 1, 0, 0} + + // The locality here describes spatial neighbor + // relationships including self. + // This example uses the band matrix representation + // to improve time and space efficiency. + locality := mat.NewBandDense(10, 10, 1, 1, []float64{ + 0, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 0, + }) + + for i, v := range data { + fmt.Printf("v=%v G*i=% .4v\n", v, spatial.GetisOrdGStar(i, data, nil, locality)) + } + + // Output: + // + // v=0 G*i=-1.225 + // v=0 G*i=-1.604 + // v=0 G*i=-0.2673 + // v=1 G*i= 1.069 + // v=1 G*i= 2.405 + // v=1 G*i= 1.069 + // v=0 G*i= 1.069 + // v=1 G*i=-0.2673 + // v=0 G*i=-0.2673 + // v=0 G*i=-1.225 +} diff --git a/vendor/gonum.org/v1/gonum/stat/spatial/spatial_test.go b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_test.go new file mode 100644 index 00000000..f91edfdf --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/spatial/spatial_test.go @@ -0,0 +1,293 @@ +// Copyright ©2017 The gonum 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 spatial + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func simpleAdjacency(n, wide int, diag bool) mat.Matrix { + m := mat.NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 1; j <= wide; j++ { + if j > i { + continue + } + m.Set(i-j, i, 1) + m.Set(i, i-j, 1) + } + if diag { + m.Set(i, i, 1) + } + } + return m +} + +func simpleAdjacencyBand(n, wide int, diag bool) mat.Matrix { + m := mat.NewBandDense(n, n, wide, wide, nil) + for i := 0; i < n; i++ { + for j := 1; j <= wide; j++ { + if j > i { + continue + } + m.SetBand(i-j, i, 1) + m.SetBand(i, i-j, 1) + } + if diag { + m.SetBand(i, i, 1) + } + } + return m +} + +var spatialTests = []struct { + from, to float64 + n, wide int + fn func(float64, int, *rand.Rand) float64 + locality func(n, wide int, diag bool) mat.Matrix + + // Values for MoranI and z-score are obtained from + // an R reference implementation. + wantMoranI float64 + wantZ float64 + + // The value for expected number of significant + // segments is obtained from visual inspection + // of the plotted data. + wantSegs int +}{ + // Dense matrix locality. + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, _ int, rnd *rand.Rand) float64 { + return rnd.Float64() + }, + locality: simpleAdjacency, + + wantMoranI: -0.0019631298955953233, + wantZ: -0.03039477405151108, + wantSegs: 0, + }, + { + from: -math.Pi / 2, to: 3 * math.Pi / 2, n: 1000, wide: 1, + fn: func(x float64, _ int, _ *rand.Rand) float64 { + y := math.Sin(x) + if math.Abs(y) > 0.5 { + y *= 1/math.Abs(y) - 1 + } + return y * math.Sin(x*2) + }, + locality: simpleAdjacency, + + wantMoranI: 1.0008149537991464, + wantZ: 31.648547078779092, + wantSegs: 4, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, _ int, rnd *rand.Rand) float64 { + return rnd.NormFloat64() + }, + locality: simpleAdjacency, + + wantMoranI: 0.031195199553564902, + wantZ: 1.0171161514080056, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(x float64, _ int, rnd *rand.Rand) float64 { + if rnd.Float64() < 0.5 { + return rnd.NormFloat64() + 5 + } + return rnd.NormFloat64() + }, + locality: simpleAdjacency, + + wantMoranI: -0.016245135637562223, + wantZ: -0.48157993864993476, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(x float64, i int, rnd *rand.Rand) float64 { + if i%2 == 0 { + return rnd.NormFloat64() + 5 + } + return rnd.NormFloat64() + }, + locality: simpleAdjacency, + + wantMoranI: -0.8565268969272998, + wantZ: -27.027057520918113, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, i int, _ *rand.Rand) float64 { + return float64(i % 2) + }, + locality: simpleAdjacency, + + wantMoranI: -1, + wantZ: -31.559531064275987, + wantSegs: 0, + }, + + // Band matrix locality. + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, _ int, rnd *rand.Rand) float64 { + return rnd.Float64() + }, + locality: simpleAdjacencyBand, + + wantMoranI: -0.0019631298955953233, + wantZ: -0.03039477405151108, + wantSegs: 0, + }, + { + from: -math.Pi / 2, to: 3 * math.Pi / 2, n: 1000, wide: 1, + fn: func(x float64, _ int, _ *rand.Rand) float64 { + y := math.Sin(x) + if math.Abs(y) > 0.5 { + y *= 1/math.Abs(y) - 1 + } + return y * math.Sin(x*2) + }, + locality: simpleAdjacencyBand, + + wantMoranI: 1.0008149537991464, + wantZ: 31.648547078779092, + wantSegs: 4, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, _ int, rnd *rand.Rand) float64 { + return rnd.NormFloat64() + }, + locality: simpleAdjacencyBand, + + wantMoranI: 0.031195199553564902, + wantZ: 1.0171161514080056, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(x float64, _ int, rnd *rand.Rand) float64 { + if rnd.Float64() < 0.5 { + return rnd.NormFloat64() + 5 + } + return rnd.NormFloat64() + }, + locality: simpleAdjacencyBand, + + wantMoranI: -0.016245135637562223, + wantZ: -0.48157993864993476, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(x float64, i int, rnd *rand.Rand) float64 { + if i%2 == 0 { + return rnd.NormFloat64() + 5 + } + return rnd.NormFloat64() + }, + locality: simpleAdjacencyBand, + + wantMoranI: -0.8565268969272998, + wantZ: -27.027057520918113, + wantSegs: 0, + }, + { + from: 0, to: 1, n: 1000, wide: 1, + fn: func(_ float64, i int, _ *rand.Rand) float64 { + return float64(i % 2) + }, + locality: simpleAdjacencyBand, + + wantMoranI: -1, + wantZ: -31.559531064275987, + wantSegs: 0, + }, +} + +func TestGetisOrd(t *testing.T) { + for ti, test := range spatialTests { + rnd := rand.New(rand.NewSource(1)) + data := make([]float64, test.n) + step := (test.to - test.from) / float64(test.n) + for i := range data { + data[i] = test.fn(test.from+step*float64(i), i, rnd) + } + locality := test.locality(test.n, test.wide, true) + + nseg := getisOrdSegments(data, nil, locality) + if nseg != test.wantSegs { + t.Errorf("unexpected number of significant segments for test %d: got:%d want:%d", + ti, nseg, test.wantSegs) + } + } +} + +// getisOrdSegments returns the number of contiguously significant G*i segemtns in +// data. This allows an intuitive validation of the function in lieu of a reference +// implementation. +func getisOrdSegments(data, weight []float64, locality mat.Matrix) int { + const thresh = 2 + var nseg int + segstart := -1 + for i := range data { + gi := GetisOrdGStar(i, data, weight, locality) + if segstart != -1 { + if math.Abs(gi) < thresh { + // Filter short segments. + if i-segstart < 5 { + segstart = -1 + continue + } + + segstart = -1 + nseg++ + } + continue + } + if math.Abs(gi) >= thresh { + segstart = i + } + } + if segstart != -1 && len(data)-segstart >= 5 { + nseg++ + } + return nseg +} + +func TestGlobalMoransI(t *testing.T) { + const tol = 1e-14 + for ti, test := range spatialTests { + rnd := rand.New(rand.NewSource(1)) + data := make([]float64, test.n) + step := (test.to - test.from) / float64(test.n) + for i := range data { + data[i] = test.fn(test.from+step*float64(i), i, rnd) + } + locality := test.locality(test.n, test.wide, false) + + gotI, _, gotZ := GlobalMoransI(data, nil, locality) + + if !floats.EqualWithinAbsOrRel(gotI, test.wantMoranI, tol, tol) { + t.Errorf("unexpected Moran's I value for test %d: got:%v want:%v", ti, gotI, test.wantMoranI) + } + if !floats.EqualWithinAbsOrRel(gotZ, test.wantZ, tol, tol) { + t.Errorf("unexpected Moran's I z-score for test %d: got:%v want:%v", ti, gotZ, test.wantZ) + } + } +} diff --git a/vendor/gonum.org/v1/gonum/stat/stat_test.go b/vendor/gonum.org/v1/gonum/stat/stat_test.go new file mode 100644 index 00000000..bdb24dd3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/stat_test.go @@ -0,0 +1,1569 @@ +// Copyright ©2014 The gonum 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 stat + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func ExampleCircularMean() { + x := []float64{0, 0.25 * math.Pi, 0.75 * math.Pi} + weights := []float64{1, 2, 2.5} + cmean := CircularMean(x, weights) + + fmt.Printf("The circular mean is %.5f.\n", cmean) + // Output: + // The circular mean is 1.37037. +} + +func TestCircularMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + // Values compared against scipy. + { + x: []float64{0, 2 * math.Pi}, + ans: 0, + }, + { + x: []float64{0, 0.5 * math.Pi}, + ans: 0.78539816339744, + }, + { + x: []float64{-1.5 * math.Pi, 0.5 * math.Pi, 2.5 * math.Pi}, + wts: []float64{1, 2, 3}, + ans: 0.5 * math.Pi, + }, + { + x: []float64{0, 0.5 * math.Pi}, + wts: []float64{1, 2}, + ans: 1.10714871779409, + }, + } { + c := CircularMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Circular mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { CircularMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("CircularMean did not panic with x, wts length mismatch") + } +} + +func ExampleCorrelation() { + x := []float64{8, -3, 7, 8, -4} + y := []float64{10, 5, 6, 3, -1} + w := []float64{2, 1.5, 3, 3, 2} + + fmt.Println("Correlation computes the degree to which two datasets move together") + fmt.Println("about their mean. For example, x and y above move similarly.") + + c := Correlation(x, y, w) + fmt.Printf("Correlation is %.5f\n", c) + + // Output: + // Correlation computes the degree to which two datasets move together + // about their mean. For example, x and y above move similarly. + // Correlation is 0.59915 +} + +func TestCorrelation(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + w []float64 + ans float64 + }{ + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: nil, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: []float64{1, 1, 1, 1, 1}, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: []float64{1, 6, 7, 0.8, 2.1}, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: nil, + ans: 0.0093334660769059, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: nil, + ans: 0.0093334660769059, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: []float64{1, 3, 1, 2, 2}, + ans: -0.13966633352689, + }, + } { + c := Correlation(test.x, test.y, test.w) + if math.Abs(test.ans-c) > 1e-14 { + t.Errorf("Correlation mismatch case %d. Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { Correlation(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Correlation did not panic with length mismatch") + } + if !Panics(func() { Correlation(make([]float64, 2), make([]float64, 3), nil) }) { + t.Errorf("Correlation did not panic with length mismatch") + } + if !Panics(func() { Correlation(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Correlation did not panic with weights length mismatch") + } +} + +func ExampleCovariance() { + fmt.Println("Covariance computes the degree to which datasets move together") + fmt.Println("about their mean.") + x := []float64{8, -3, 7, 8, -4} + y := []float64{10, 2, 2, 4, 1} + cov := Covariance(x, y, nil) + fmt.Printf("Cov = %.4f\n", cov) + fmt.Println("If datasets move perfectly together, the variance equals the covariance") + y2 := []float64{12, 1, 11, 12, 0} + cov2 := Covariance(x, y2, nil) + varX := Variance(x, nil) + fmt.Printf("Cov2 is %.4f, VarX is %.4f", cov2, varX) + // Output: + // Covariance computes the degree to which datasets move together + // about their mean. + // Cov = 13.8000 + // If datasets move perfectly together, the variance equals the covariance + // Cov2 is 37.7000, VarX is 37.7000 +} + +func TestCovariance(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + weights []float64 + ans float64 + }{ + { + p: []float64{0.75, 0.1, 0.05}, + q: []float64{0.5, 0.25, 0.25}, + ans: 0.05625, + }, + { + p: []float64{1, 2, 3}, + q: []float64{2, 4, 6}, + ans: 2, + }, + { + p: []float64{1, 2, 3}, + q: []float64{1, 4, 9}, + ans: 4, + }, + { + p: []float64{1, 2, 3}, + q: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 3.2, + }, + { + p: []float64{1, 4, 9}, + q: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 13.142857142857146, + }, + } { + c := Covariance(test.p, test.q, test.weights) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Covariance mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + + // test the panic states + if !Panics(func() { Covariance(make([]float64, 2), make([]float64, 3), nil) }) { + t.Errorf("Covariance did not panic with x, y length mismatch") + } + if !Panics(func() { Covariance(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Covariance did not panic with x, weights length mismatch") + } + +} + +func TestCrossEntropy(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + ans float64 + }{ + { + p: []float64{0.75, 0.1, 0.05}, + q: []float64{0.5, 0.25, 0.25}, + ans: 0.7278045395879426, + }, + { + p: []float64{0.75, 0.1, 0.05, 0, 0, 0}, + q: []float64{0.5, 0.25, 0.25, 0, 0, 0}, + ans: 0.7278045395879426, + }, + { + p: []float64{0.75, 0.1, 0.05, 0, 0, 0.1}, + q: []float64{0.5, 0.25, 0.25, 0, 0, 0}, + ans: math.Inf(1), + }, + { + p: nil, + q: nil, + ans: 0, + }, + } { + c := CrossEntropy(test.p, test.q) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Cross entropy mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { CrossEntropy(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("CrossEntropy did not panic with p, q length mismatch") + } +} + +func ExampleEntropy() { + + p := []float64{0.05, 0.1, 0.9, 0.05} + entP := Entropy(p) + + q := []float64{0.2, 0.4, 0.25, 0.15} + entQ := Entropy(q) + + r := []float64{0.2, 0, 0, 0.5, 0, 0.2, 0.1, 0, 0, 0} + entR := Entropy(r) + + s := []float64{0, 0, 1, 0} + entS := Entropy(s) + + fmt.Println("Entropy is a measure of the amount of uncertainty in a distribution") + fmt.Printf("The second bin of p is very likely to occur. It's entropy is %.4f\n", entP) + fmt.Printf("The distribution of q is more spread out. It's entropy is %.4f\n", entQ) + fmt.Println("Adding buckets with zero probability does not change the entropy.") + fmt.Printf("The entropy of r is: %.4f\n", entR) + fmt.Printf("A distribution with no uncertainty has entropy %.4f\n", entS) + // Output: + // Entropy is a measure of the amount of uncertainty in a distribution + // The second bin of p is very likely to occur. It's entropy is 0.6247 + // The distribution of q is more spread out. It's entropy is 1.3195 + // Adding buckets with zero probability does not change the entropy. + // The entropy of r is: 1.2206 + // A distribution with no uncertainty has entropy 0.0000 +} + +func ExampleExKurtosis() { + fmt.Println(`Kurtosis is a measure of the 'peakedness' of a distribution, and the +excess kurtosis is the kurtosis above or below that of the standard normal +distribution`) + x := []float64{5, 4, -3, -2} + kurt := ExKurtosis(x, nil) + fmt.Printf("ExKurtosis = %.5f\n", kurt) + weights := []float64{1, 2, 3, 5} + wKurt := ExKurtosis(x, weights) + fmt.Printf("Weighted ExKurtosis is %.4f", wKurt) + // Output: + // Kurtosis is a measure of the 'peakedness' of a distribution, and the + // excess kurtosis is the kurtosis above or below that of the standard normal + // distribution + // ExKurtosis = -5.41200 + // Weighted ExKurtosis is -0.6779 +} + +func TestExKurtosis(t *testing.T) { + // the example does a good job, this just has to cover the panic + if !Panics(func() { ExKurtosis(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("ExKurtosis did not panic with x, weights length mismatch") + } +} + +func ExampleGeometricMean() { + x := []float64{8, 2, 9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + gmean := GeometricMean(x, weights) + + logx := make([]float64, len(x)) + for i, v := range x { + logx[i] = math.Log(v) + } + expMeanLog := math.Exp(Mean(logx, weights)) + fmt.Printf("The arithmetic mean is %.4f, but the geometric mean is %.4f.\n", mean, gmean) + fmt.Printf("The exponential of the mean of the logs is %.4f\n", expMeanLog) + // Output: + // The arithmetic mean is 10.1667, but the geometric mean is 8.7637. + // The exponential of the mean of the logs is 8.7637 +} + +func TestGeometricMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + { + x: []float64{2, 8}, + ans: 4, + }, + { + x: []float64{3, 81}, + wts: []float64{2, 1}, + ans: 9, + }, + } { + c := GeometricMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Geometric mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { GeometricMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("GeometricMean did not panic with x, wts length mismatch") + } +} + +func ExampleHarmonicMean() { + x := []float64{8, 2, 9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + hmean := HarmonicMean(x, weights) + + fmt.Printf("The arithmetic mean is %.5f, but the harmonic mean is %.4f.\n", mean, hmean) + // Output: + // The arithmetic mean is 10.16667, but the harmonic mean is 6.8354. +} + +func TestHarmonicMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + { + x: []float64{.5, .125}, + ans: .2, + }, + { + x: []float64{.5, .125}, + wts: []float64{2, 1}, + ans: .25, + }, + } { + c := HarmonicMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Harmonic mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { HarmonicMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("HarmonicMean did not panic with x, wts length mismatch") + } +} + +func TestHistogram(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + dividers []float64 + ans []float64 + }{ + { + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + ans: []float64{1, 1, 1, 1, 2}, + }, + { + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{1, 2, 4, 6, 7, 9}, + weights: []float64{1, 2, 1, 1, 1, 2}, + ans: []float64{1, 2, 1, 1, 3}, + }, + { + x: []float64{1, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + weights: []float64{1, 2}, + ans: []float64{1, 0, 0, 0, 2}, + }, + { + x: []float64{1, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + ans: []float64{1, 0, 0, 0, 1}, + }, + { + x: []float64{}, + dividers: []float64{1, 3}, + ans: []float64{0}, + }, + } { + hist := Histogram(nil, test.dividers, test.x, test.weights) + if !floats.Equal(hist, test.ans) { + t.Errorf("Hist mismatch case %d. Expected %v, Found %v", i, test.ans, hist) + } + // Test with non-zero values + Histogram(hist, test.dividers, test.x, test.weights) + if !floats.Equal(hist, test.ans) { + t.Errorf("Hist mismatch case %d. Expected %v, Found %v", i, test.ans, hist) + } + } + // panic cases + for _, test := range []struct { + name string + x []float64 + weights []float64 + dividers []float64 + count []float64 + }{ + { + name: "len(x) != len(weights)", + x: []float64{1, 3, 5, 6, 7, 8}, + weights: []float64{1, 1, 1, 1}, + }, + { + name: "len(count) != len(dividers) - 1", + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{1, 4, 9}, + count: make([]float64, 6), + }, + { + name: "dividers not sorted", + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{0, -1, 0}, + }, + { + name: "x not sorted", + x: []float64{1, 5, 2, 9, 7, 8}, + dividers: []float64{1, 4, 9}, + }, + { + name: "fewer than 2 dividers", + x: []float64{1, 2, 3}, + dividers: []float64{5}, + }, + { + name: "x too large", + x: []float64{1, 2, 3}, + dividers: []float64{1, 3}, + }, + { + name: "x too small", + x: []float64{1, 2, 3}, + dividers: []float64{2, 3}, + }, + } { + if !Panics(func() { Histogram(test.count, test.dividers, test.x, test.weights) }) { + t.Errorf("Histogram did not panic when %s", test.name) + } + } +} + +func ExampleHistogram() { + x := make([]float64, 101) + for i := range x { + x[i] = 1.1 * float64(i) // x data ranges from 0 to 110 + } + dividers := []float64{0, 7, 20, 100, 1000} + fmt.Println(`Histogram counts the amount of data in the bins specified by +the dividers. In this data set, there are 7 data points less than 7 (between dividers[0] +and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]), +and 0 data points above 1000. Since dividers has length 5, there will be 4 bins.`) + hist := Histogram(nil, dividers, x, nil) + fmt.Printf("Hist = %v\n", hist) + + fmt.Println() + fmt.Println("For ease, the floats Span function can be used to set the dividers") + nBins := 10 + dividers = make([]float64, nBins+1) + min := floats.Min(x) + max := floats.Max(x) + // Increase the maximum divider so that the maximum value of x is contained + // within the last bucket. + max += 1 + floats.Span(dividers, min, max) + // Span includes the min and the max. Trim the dividers to create 10 buckets + hist = Histogram(nil, dividers, x, nil) + fmt.Printf("Hist = %v\n", hist) + fmt.Println() + fmt.Println(`Histogram also works with weighted data, and allows reusing of +the count field in order to avoid extra garbage`) + weights := make([]float64, len(x)) + for i := range weights { + weights[i] = float64(i + 1) + } + Histogram(hist, dividers, x, weights) + fmt.Printf("Weighted Hist = %v\n", hist) + + // Output: + // Histogram counts the amount of data in the bins specified by + // the dividers. In this data set, there are 7 data points less than 7 (between dividers[0] + // and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]), + // and 0 data points above 1000. Since dividers has length 5, there will be 4 bins. + // Hist = [7 12 72 10] + // + // For ease, the floats Span function can be used to set the dividers + // Hist = [11 10 10 10 10 10 10 10 10 10] + // + // Histogram also works with weighted data, and allows reusing of + // the count field in order to avoid extra garbage + // Weighted Hist = [66 165 265 365 465 565 665 765 865 965] +} + +func TestJensenShannon(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + }, + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.5, 0, 0.25, 0.25}, + }, + { + p: []float64{0.5, 0.1, 0, 0.4}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + }, + } { + + m := make([]float64, len(test.p)) + p := test.p + q := test.q + floats.Add(m, p) + floats.Add(m, q) + floats.Scale(0.5, m) + + js1 := 0.5*KullbackLeibler(p, m) + 0.5*KullbackLeibler(q, m) + js2 := JensenShannon(p, q) + + if math.IsNaN(js2) { + t.Errorf("In case %v, JS distance is NaN", i) + } + + if math.Abs(js1-js2) > 1e-14 { + t.Errorf("JS mismatch case %v. Expected %v, found %v.", i, js1, js2) + } + } + if !Panics(func() { JensenShannon(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("JensenShannon did not panic with p, q length mismatch") + } +} + +func TestKolmogorovSmirnov(t *testing.T) { + for i, test := range []struct { + x []float64 + xWeights []float64 + y []float64 + yWeights []float64 + dist float64 + }{ + + { + dist: 0, + }, + { + x: []float64{1}, + dist: 1, + }, + { + y: []float64{1}, + dist: 1, + }, + { + x: []float64{1}, + xWeights: []float64{8}, + dist: 1, + }, + { + y: []float64{1}, + yWeights: []float64{8}, + dist: 1, + }, + { + x: []float64{1}, + xWeights: []float64{8}, + y: []float64{1}, + yWeights: []float64{8}, + dist: 0, + }, + { + x: []float64{1, 1, 1}, + xWeights: []float64{2, 3, 7}, + y: []float64{1}, + yWeights: []float64{8}, + dist: 0, + }, + { + x: []float64{1, 1, 1, 1, 1}, + y: []float64{1, 1, 1}, + yWeights: []float64{2, 5, 2}, + dist: 0, + }, + + { + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + dist: 0, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + yWeights: []float64{1, 1, 1}, + dist: 0, + }, + + { + x: []float64{1, 2, 3}, + xWeights: []float64{1, 1, 1}, + y: []float64{1, 2, 3}, + yWeights: []float64{1, 1, 1}, + dist: 0, + }, + { + x: []float64{1, 2}, + xWeights: []float64{2, 5}, + y: []float64{1, 1, 2, 2, 2, 2, 2}, + dist: 0, + }, + { + x: []float64{1, 1, 2, 2, 2, 2, 2}, + y: []float64{1, 2}, + yWeights: []float64{2, 5}, + dist: 0, + }, + { + x: []float64{1, 1, 2, 2, 2}, + xWeights: []float64{0.5, 1.5, 1, 2, 2}, + y: []float64{1, 2}, + yWeights: []float64{2, 5}, + dist: 0, + }, + { + x: []float64{1, 2, 3, 4}, + y: []float64{5, 6}, + dist: 1, + }, + { + x: []float64{5, 6}, + y: []float64{1, 2, 3, 4}, + dist: 1, + }, + { + x: []float64{5, 6}, + xWeights: []float64{8, 7}, + y: []float64{1, 2, 3, 4}, + dist: 1, + }, + { + x: []float64{5, 6}, + xWeights: []float64{8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{-4, 5, 6}, + xWeights: []float64{0, 8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{-4, -2, -2, 5, 6}, + xWeights: []float64{0, 0, 0, 8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 1, 3}, + dist: 1.0 / 3.0, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 3}, + yWeights: []float64{2, 1}, + dist: 1.0 / 3.0, + }, + { + x: []float64{1, 2, 3}, + xWeights: []float64{2, 2, 2}, + y: []float64{1, 3}, + yWeights: []float64{2, 1}, + dist: 1.0 / 3.0, + }, + { + x: []float64{2, 3, 4}, + y: []float64{1, 5}, + dist: 1.0 / 2.0, + }, + { + x: []float64{1, 2, math.NaN()}, + y: []float64{1, 1, 3}, + dist: math.NaN(), + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 1, math.NaN()}, + dist: math.NaN(), + }, + } { + dist := KolmogorovSmirnov(test.x, test.xWeights, test.y, test.yWeights) + if math.Abs(dist-test.dist) > 1e-14 && !(math.IsNaN(test.dist) && math.IsNaN(dist)) { + t.Errorf("Distance mismatch case %v: Expected: %v, Found: %v", i, test.dist, dist) + } + } + // panic cases + for _, test := range []struct { + name string + x []float64 + xWeights []float64 + y []float64 + yWeights []float64 + }{ + { + name: "len(x) != len(xWeights)", + x: []float64{1, 3, 5, 6, 7, 8}, + xWeights: []float64{1, 1, 1, 1}, + }, + { + name: "len(y) != len(yWeights)", + x: []float64{1, 3, 5, 6, 7, 8}, + y: []float64{1, 3, 5, 6, 7, 8}, + yWeights: []float64{1, 1, 1, 1}, + }, + { + name: "x not sorted", + x: []float64{10, 3, 5, 6, 7, 8}, + y: []float64{1, 3, 5, 6, 7, 8}, + }, + { + name: "y not sorted", + x: []float64{1, 3, 5, 6, 7, 8}, + y: []float64{10, 3, 5, 6, 7, 8}, + }, + } { + if !Panics(func() { KolmogorovSmirnov(test.x, test.xWeights, test.y, test.yWeights) }) { + t.Errorf("KolmogorovSmirnov did not panic when %s", test.name) + } + } +} + +func ExampleKullbackLeibler() { + + p := []float64{0.05, 0.1, 0.9, 0.05} + q := []float64{0.2, 0.4, 0.25, 0.15} + s := []float64{0, 0, 1, 0} + + klPQ := KullbackLeibler(p, q) + klPS := KullbackLeibler(p, s) + klPP := KullbackLeibler(p, p) + + fmt.Println("Kullback-Leibler is one measure of the difference between two distributions") + fmt.Printf("The K-L distance between p and q is %.4f\n", klPQ) + fmt.Println("It is impossible for s and p to be the same distribution, because") + fmt.Println("the first bucket has zero probability in s and non-zero in p. Thus,") + fmt.Printf("the K-L distance between them is %.4f\n", klPS) + fmt.Printf("The K-L distance between identical distributions is %.4f\n", klPP) + + // Kullback-Leibler is one measure of the difference between two distributions + // The K-L distance between p and q is 0.8900 + // It is impossible for s and p to be the same distribution, because + // the first bucket has zero probability in s and non-zero in p. Thus, + // the K-L distance between them is +Inf + // The K-L distance between identical distributions is 0.0000 +} + +func TestKullbackLeibler(t *testing.T) { + if !Panics(func() { KullbackLeibler(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("KullbackLeibler did not panic with p, q length mismatch") + } +} + +var linearRegressionTests = []struct { + name string + + x, y []float64 + weights []float64 + origin bool + + alpha float64 + beta float64 + r float64 + + tol float64 +}{ + { + name: "faithful", + + x: faithful.waiting, + y: faithful.eruptions, + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful). + alpha: -1.87402, + beta: 0.07563, + r: 0.8114608, + + tol: 1e-5, + }, + { + name: "faithful through origin", + + x: faithful.waiting, + y: faithful.eruptions, + origin: true, + + // Values calculated by R using lm(eruptions ~ waiting - 1, data=faithful). + alpha: 0, + beta: 0.05013, + r: 0.9726036, + + tol: 1e-5, + }, + { + name: "faithful explicit weights", + + x: faithful.waiting, + y: faithful.eruptions, + weights: func() []float64 { + w := make([]float64, len(faithful.eruptions)) + for i := range w { + w[i] = 1 + } + return w + }(), + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful). + alpha: -1.87402, + beta: 0.07563, + r: 0.8114608, + + tol: 1e-5, + }, + { + name: "faithful non-uniform weights", + + x: faithful.waiting, + y: faithful.eruptions, + weights: faithful.waiting, // Just an arbitrary set of non-uniform weights. + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful, weights=faithful$waiting). + alpha: -1.79268, + beta: 0.07452, + r: 0.7840372, + + tol: 1e-5, + }, +} + +func TestLinearRegression(t *testing.T) { + for _, test := range linearRegressionTests { + alpha, beta := LinearRegression(test.x, test.y, test.weights, test.origin) + var r float64 + if test.origin { + r = RNoughtSquared(test.x, test.y, test.weights, beta) + } else { + r = RSquared(test.x, test.y, test.weights, alpha, beta) + ests := make([]float64, len(test.y)) + for i, x := range test.x { + ests[i] = alpha + beta*x + } + rvals := RSquaredFrom(ests, test.y, test.weights) + if r != rvals { + t.Errorf("%s: RSquared and RSquaredFrom mismatch: %v != %v", test.name, r, rvals) + } + } + if !floats.EqualWithinAbsOrRel(alpha, test.alpha, test.tol, test.tol) { + t.Errorf("%s: unexpected alpha estimate: want:%v got:%v", test.name, test.alpha, alpha) + } + if !floats.EqualWithinAbsOrRel(beta, test.beta, test.tol, test.tol) { + t.Errorf("%s: unexpected beta estimate: want:%v got:%v", test.name, test.beta, beta) + } + if !floats.EqualWithinAbsOrRel(r, test.r, test.tol, test.tol) { + t.Errorf("%s: unexpected r estimate: want:%v got:%v", test.name, test.r, r) + } + } +} + +func TestChiSquare(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{16, 18, 16, 14, 12, 12}, + q: []float64{16, 16, 16, 16, 16, 8}, + res: 3.5, + }, + { + p: []float64{16, 18, 16, 14, 12, 12}, + q: []float64{8, 20, 20, 16, 12, 12}, + res: 9.25, + }, + { + p: []float64{40, 60, 30, 45}, + q: []float64{50, 50, 50, 50}, + res: 12.5, + }, + { + p: []float64{40, 60, 30, 45, 0, 0}, + q: []float64{50, 50, 50, 50, 0, 0}, + res: 12.5, + }, + } { + resultpq := ChiSquare(test.p, test.q) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("ChiSquare distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + } + if !Panics(func() { ChiSquare(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("ChiSquare did not panic with length mismatch") + } +} + +// Panics returns true if the called function panics during evaluation. +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestBhattacharyya(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + res: 0.15597338718671386, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + res: 0.46322207765351153, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + res: 0.3552520032137785, + }, + } { + resultpq := Bhattacharyya(test.p, test.q) + resultqp := Bhattacharyya(test.q, test.p) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("Bhattacharyya distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + if math.Abs(resultpq-resultqp) > 1e-10 { + t.Errorf("Bhattacharyya distance is assymmetric in case %d.", i) + } + } + // Bhattacharyya should panic if the inputs have different length + if !Panics(func() { Bhattacharyya(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Bhattacharyya did not panic with length mismatch") + } +} + +func TestHellinger(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + res: 0.3800237367441919, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + res: 0.6088900771170487, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + res: 0.5468118803484205, + }, + } { + resultpq := Hellinger(test.p, test.q) + resultqp := Hellinger(test.q, test.p) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("Hellinger distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + if math.Abs(resultpq-resultqp) > 1e-10 { + t.Errorf("Hellinger distance is assymmetric in case %d.", i) + } + } + if !Panics(func() { Hellinger(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Hellinger did not panic with length mismatch") + } +} + +func ExampleMean() { + x := []float64{8.2, -6, 5, 7} + mean := Mean(x, nil) + fmt.Printf("The mean of the samples is %.4f\n", mean) + w := []float64{2, 6, 3, 5} + weightedMean := Mean(x, w) + fmt.Printf("The weighted mean of the samples is %.4f\n", weightedMean) + x2 := []float64{8.2, 8.2, -6, -6, -6, -6, -6, -6, 5, 5, 5, 7, 7, 7, 7, 7} + mean2 := Mean(x2, nil) + fmt.Printf("The mean of x2 is %.4f\n", mean2) + fmt.Println("The weights act as if there were more samples of that number") + // Output: + // The mean of the samples is 3.5500 + // The weighted mean of the samples is 1.9000 + // The mean of x2 is 1.9000 + // The weights act as if there were more samples of that number +} +func TestMean(t *testing.T) { + if !Panics(func() { Mean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Mean did not panic with x, weights length mismatch") + } +} + +func TestMode(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + count float64 + }{ + {}, + { + x: []float64{1, 6, 1, 9, -2}, + ans: 1, + count: 2, + }, + { + x: []float64{1, 6, 1, 9, -2}, + weights: []float64{1, 7, 3, 5, 0}, + ans: 6, + count: 7, + }, + } { + m, count := Mode(test.x, test.weights) + if test.ans != m { + t.Errorf("Mode mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + if test.count != count { + t.Errorf("Mode count mismatch case %d. Expected %v, found %v", i, test.count, count) + } + } + if !Panics(func() { Mode(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Mode did not panic with x, weights length mismatch") + } +} + +func TestMoment(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + moment float64 + ans float64 + }{ + { + x: []float64{6, 2, 4, 8, 10}, + moment: 5, + ans: 0, + }, + { + x: []float64{6, 2, 4, 8, 10}, + weights: []float64{1, 2, 2, 2, 1}, + moment: 5, + ans: 121.875, + }, + } { + m := Moment(test.moment, test.x, test.weights) + if math.Abs(test.ans-m) > 1e-14 { + t.Errorf("Moment mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + } + if !Panics(func() { Moment(1, make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Moment did not panic with x, weights length mismatch") + } +} + +func TestMomentAbout(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + moment float64 + mean float64 + ans float64 + }{ + { + x: []float64{6, 2, 4, 8, 9}, + mean: 3, + moment: 5, + ans: 2.2288e3, + }, + { + x: []float64{6, 2, 4, 8, 9}, + weights: []float64{1, 2, 2, 2, 1}, + mean: 3, + moment: 5, + ans: 1.783625e3, + }, + } { + m := MomentAbout(test.moment, test.x, test.mean, test.weights) + if math.Abs(test.ans-m) > 1e-14 { + t.Errorf("MomentAbout mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + } + if !Panics(func() { MomentAbout(1, make([]float64, 3), 0, make([]float64, 2)) }) { + t.Errorf("MomentAbout did not panic with x, weights length mismatch") + } +} + +func TestCDF(t *testing.T) { + cumulantKinds := []CumulantKind{Empirical} + for i, test := range []struct { + q []float64 + x []float64 + weights []float64 + ans [][]float64 + }{ + {}, + { + q: []float64{0, 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1}, + x: []float64{1, 2, 3, 4, 5}, + ans: [][]float64{{0, 0, 0.2, 0.2, 0.4, 0.6, 0.6, 0.8, 1, 1}}, + }, + { + q: []float64{0, 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1}, + x: []float64{1, 2, 3, 4, 5}, + weights: []float64{1, 1, 1, 1, 1}, + ans: [][]float64{{0, 0, 0.2, 0.2, 0.4, 0.6, 0.6, 0.8, 1, 1}}, + }, + { + q: []float64{0, 0.9, 1}, + x: []float64{math.NaN()}, + ans: [][]float64{{math.NaN(), math.NaN(), math.NaN()}}, + }, + } { + copyX := make([]float64, len(test.x)) + copy(copyX, test.x) + var copyW []float64 + if test.weights != nil { + copyW = make([]float64, len(test.weights)) + copy(copyW, test.weights) + } + for j, q := range test.q { + for k, kind := range cumulantKinds { + v := CDF(q, kind, test.x, test.weights) + if !floats.Equal(copyX, test.x) && !math.IsNaN(v) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, q) + } + if !floats.Equal(copyW, test.weights) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, q) + } + if v != test.ans[k][j] && !(math.IsNaN(v) && math.IsNaN(test.ans[k][j])) { + t.Errorf("mismatch case %d kind %d percentile %v. Expected: %v, found: %v", i, k, q, test.ans[k][j], v) + } + } + } + } + + // these test cases should all result in a panic + for i, test := range []struct { + name string + q float64 + kind CumulantKind + x []float64 + weights []float64 + }{ + { + name: "len(x) != len(weights)", + q: 1.5, + kind: Empirical, + x: []float64{1, 2, 3, 4, 5}, + weights: []float64{1, 2, 3}, + }, + { + name: "unsorted x", + q: 1.5, + kind: Empirical, + x: []float64{3, 2, 1}, + }, + { + name: "unknown CumulantKind", + q: 1.5, + kind: CumulantKind(1000), // bogus + x: []float64{1, 2, 3}, + }, + } { + if !Panics(func() { CDF(test.q, test.kind, test.x, test.weights) }) { + t.Errorf("did not panic as expected with %s for case %d kind %d percentile %v x %v weights %v", test.name, i, test.kind, test.q, test.x, test.weights) + } + } + +} + +func TestQuantile(t *testing.T) { + cumulantKinds := []CumulantKind{Empirical} + for i, test := range []struct { + p []float64 + x []float64 + w []float64 + ans [][]float64 + }{ + { + p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + w: nil, + ans: [][]float64{{1, 1, 1, 2, 5, 5, 6, 9, 9, 10, 10}}, + }, + { + p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + w: []float64{3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + ans: [][]float64{{1, 1, 1, 2, 5, 5, 6, 9, 9, 10, 10}}, + }, + { + p: []float64{0.5}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, math.NaN(), 10}, + ans: [][]float64{{math.NaN()}}, + }, + } { + copyX := make([]float64, len(test.x)) + copy(copyX, test.x) + var copyW []float64 + if test.w != nil { + copyW = make([]float64, len(test.w)) + copy(copyW, test.w) + } + for j, p := range test.p { + for k, kind := range cumulantKinds { + v := Quantile(p, kind, test.x, test.w) + if !floats.Same(copyX, test.x) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, p) + } + if !floats.Same(copyW, test.w) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, p) + } + if v != test.ans[k][j] && !(math.IsNaN(v) && math.IsNaN(test.ans[k][j])) { + t.Errorf("mismatch case %d kind %d percentile %v. Expected: %v, found: %v", i, k, p, test.ans[k][j], v) + } + } + } + } + // panic cases + for _, test := range []struct { + name string + p float64 + c CumulantKind + x []float64 + w []float64 + }{ + { + name: "p < 0", + c: Empirical, + p: -1, + }, + { + name: "p > 1", + c: Empirical, + p: 2, + }, + { + name: "p is NaN", + c: Empirical, + p: math.NaN(), + }, + { + name: "len(x) != len(weights)", + c: Empirical, + p: .5, + x: make([]float64, 4), + w: make([]float64, 2), + }, + { + name: "x not sorted", + c: Empirical, + p: .5, + x: []float64{3, 2, 1}, + }, + { + name: "CumulantKind is unknown", + c: CumulantKind(1000), + p: .5, + x: []float64{1, 2, 3}, + }, + } { + if !Panics(func() { Quantile(test.p, test.c, test.x, test.w) }) { + t.Errorf("Quantile did not panic when %s", test.name) + } + } +} + +func ExampleStdDev() { + x := []float64{8, 2, -9, 15, 4} + stdev := StdDev(x, nil) + fmt.Printf("The standard deviation of the samples is %.4f\n", stdev) + + weights := []float64{2, 2, 6, 7, 1} + weightedStdev := StdDev(x, weights) + fmt.Printf("The weighted standard deviation of the samples is %.4f\n", weightedStdev) + // Output: + // The standard deviation of the samples is 8.8034 + // The weighted standard deviation of the samples is 10.5733 +} + +func ExampleStdErr() { + x := []float64{8, 2, -9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + stdev := StdDev(x, weights) + nSamples := floats.Sum(weights) + stdErr := StdErr(stdev, nSamples) + fmt.Printf("The standard deviation is %.4f and there are %g samples, so the mean\nis likely %.4f ± %.4f.", stdev, nSamples, mean, stdErr) + // Output: + // The standard deviation is 10.5733 and there are 18 samples, so the mean + // is likely 4.1667 ± 2.4921. +} + +func TestSkew(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + weights: nil, + ans: -0.581456499151665, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{1, 1, 1, 1, 1}, + ans: -0.581456499151665, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{2, 1, 2, 1, 1}, + ans: -1.12066646837198, + }, + } { + skew := Skew(test.x, test.weights) + if math.Abs(skew-test.ans) > 1e-14 { + t.Errorf("Skew mismatch case %d. Expected %v, Found %v", i, test.ans, skew) + } + } + if !Panics(func() { Skew(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Skew did not panic with x, weights length mismatch") + } +} + +func TestSortWeighted(t *testing.T) { + for i, test := range []struct { + x []float64 + w []float64 + ansx []float64 + answ []float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + ansx: []float64{3, 4, 7, 8, 8}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + answ: []float64{1, 1, 1, .5, .5}, + }, + } { + SortWeighted(test.x, test.w) + if !floats.Same(test.x, test.ansx) { + t.Errorf("SortWeighted mismatch case %d. Expected x %v, Found x %v", i, test.ansx, test.x) + } + if !(test.w == nil) && !floats.Same(test.w, test.answ) { + t.Errorf("SortWeighted mismatch case %d. Expected w %v, Found w %v", i, test.answ, test.w) + } + } + if !Panics(func() { SortWeighted(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } +} + +func TestSortWeightedLabeled(t *testing.T) { + for i, test := range []struct { + x []float64 + l []bool + w []float64 + ansx []float64 + ansl []bool + answ []float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + ansx: []float64{3, 4, 7, 8, 8}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + answ: []float64{1, 1, 1, .5, .5}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + l: []bool{false, false, true, false, true}, + ansx: []float64{3, 4, 7, 8, 8}, + ansl: []bool{false, true, true, false, false}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + l: []bool{false, false, true, false, true}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + ansl: []bool{false, true, true, false, false}, + answ: []float64{1, 1, 1, .5, .5}, + }, + } { + SortWeightedLabeled(test.x, test.l, test.w) + if !floats.Same(test.x, test.ansx) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected x %v, Found x %v", i, test.ansx, test.x) + } + if (test.l != nil) && !reflect.DeepEqual(test.l, test.ansl) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected l %v, Found l %v", i, test.ansl, test.l) + } + if (test.w != nil) && !floats.Same(test.w, test.answ) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected w %v, Found w %v", i, test.answ, test.w) + } + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 2), make([]float64, 3)) }) { + t.Errorf("SortWeighted did not panic with x, labels length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 2), nil) }) { + t.Errorf("SortWeighted did not panic with x, labels length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 3), make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), nil, make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } +} + +func TestVariance(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + }{ + { + x: []float64{8, -3, 7, 8, -4}, + weights: nil, + ans: 37.7, + }, + { + x: []float64{8, -3, 7, 8, -4}, + weights: []float64{1, 1, 1, 1, 1}, + ans: 37.7, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{2, 1, 2, 1, 1}, + ans: 4.2857142857142865, + }, + { + x: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 13.142857142857146, + }, + { + x: []float64{1, 2, 3}, + weights: []float64{1, 1.5, 1}, + ans: .8, + }, + } { + variance := Variance(test.x, test.weights) + if math.Abs(variance-test.ans) > 1e-14 { + t.Errorf("Variance mismatch case %d. Expected %v, Found %v", i, test.ans, variance) + } + } + if !Panics(func() { Variance(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Variance did not panic with x, weights length mismatch") + } + +} + +func ExampleVariance() { + x := []float64{8, 2, -9, 15, 4} + variance := Variance(x, nil) + fmt.Printf("The variance of the samples is %.4f\n", variance) + + weights := []float64{2, 2, 6, 7, 1} + weightedVariance := Variance(x, weights) + fmt.Printf("The weighted variance of the samples is %.4f\n", weightedVariance) + // Output: + // The variance of the samples is 77.5000 + // The weighted variance of the samples is 111.7941 +} + +func TestStdScore(t *testing.T) { + for i, test := range []struct { + x float64 + u float64 + s float64 + z float64 + }{ + { + x: 4, + u: -6, + s: 5, + z: 2, + }, + { + x: 1, + u: 0, + s: 1, + z: 1, + }, + } { + z := StdScore(test.x, test.u, test.s) + if math.Abs(z-test.z) > 1e-14 { + t.Errorf("StdScore mismatch case %d. Expected %v, Found %v", i, test.z, z) + } + } + +} diff --git a/vendor/gonum.org/v1/gonum/stat/statmat_test.go b/vendor/gonum.org/v1/gonum/stat/statmat_test.go new file mode 100644 index 00000000..5ac809ef --- /dev/null +++ b/vendor/gonum.org/v1/gonum/stat/statmat_test.go @@ -0,0 +1,463 @@ +// Copyright ©2014 The gonum 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 stat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mat" +) + +func TestCovarianceMatrix(t *testing.T) { + // An alternative way to test this is to call the Variance and + // Covariance functions and ensure that the results are identical. + for i, test := range []struct { + data *mat.Dense + weights []float64 + ans *mat.Dense + }{ + { + data: mat.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + ans: mat.NewDense(2, 2, []float64{ + 2.5, 3, + 3, 10, + }), + }, { + data: mat.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + ans: mat.NewDense(2, 2, []float64{ + .8, 3.2, + 3.2, 13.142857142857146, + }), + }, + } { + // Make a copy of the data to check that it isn't changing. + r := test.data.RawMatrix() + d := make([]float64, len(r.Data)) + copy(d, r.Data) + + w := make([]float64, len(test.weights)) + if test.weights != nil { + copy(w, test.weights) + } + for _, cov := range []*mat.SymDense{nil, {}} { + c := CovarianceMatrix(cov, test.data, test.weights) + if !mat.Equal(c, test.ans) { + t.Errorf("%d: expected cov %v, found %v", i, test.ans, c) + } + if !floats.Equal(d, r.Data) { + t.Errorf("%d: data was modified during execution", i) + } + if !floats.Equal(w, test.weights) { + t.Errorf("%d: weights was modified during execution", i) + } + + // compare with call to Covariance + _, cols := c.Dims() + for ci := 0; ci < cols; ci++ { + for cj := 0; cj < cols; cj++ { + x := mat.Col(nil, ci, test.data) + y := mat.Col(nil, cj, test.data) + cov := Covariance(x, y, test.weights) + if math.Abs(cov-c.At(ci, cj)) > 1e-14 { + t.Errorf("CovMat does not match at (%v, %v). Want %v, got %v.", ci, cj, cov, c.At(ci, cj)) + } + } + } + } + + } + if !Panics(func() { CovarianceMatrix(nil, mat.NewDense(5, 2, nil), []float64{}) }) { + t.Errorf("CovarianceMatrix did not panic with weight size mismatch") + } + if !Panics(func() { CovarianceMatrix(mat.NewSymDense(1, nil), mat.NewDense(5, 2, nil), nil) }) { + t.Errorf("CovarianceMatrix did not panic with preallocation size mismatch") + } + if !Panics(func() { CovarianceMatrix(nil, mat.NewDense(2, 2, []float64{1, 2, 3, 4}), []float64{1, -1}) }) { + t.Errorf("CovarianceMatrix did not panic with negative weights") + } +} + +func TestCorrelationMatrix(t *testing.T) { + for i, test := range []struct { + data *mat.Dense + weights []float64 + ans *mat.Dense + }{ + { + data: mat.NewDense(3, 3, []float64{ + 1, 2, 3, + 3, 4, 5, + 5, 6, 7, + }), + weights: nil, + ans: mat.NewDense(3, 3, []float64{ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + }), + }, + { + data: mat.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + ans: mat.NewDense(2, 2, []float64{ + 1, 0.6, + 0.6, 1, + }), + }, { + data: mat.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + ans: mat.NewDense(2, 2, []float64{ + 1, 0.9868703275903379, + 0.9868703275903379, 1, + }), + }, + } { + // Make a copy of the data to check that it isn't changing. + r := test.data.RawMatrix() + d := make([]float64, len(r.Data)) + copy(d, r.Data) + + w := make([]float64, len(test.weights)) + if test.weights != nil { + copy(w, test.weights) + } + for _, corr := range []*mat.SymDense{nil, {}} { + c := CorrelationMatrix(corr, test.data, test.weights) + if !mat.Equal(c, test.ans) { + t.Errorf("%d: expected corr %v, found %v", i, test.ans, c) + } + if !floats.Equal(d, r.Data) { + t.Errorf("%d: data was modified during execution", i) + } + if !floats.Equal(w, test.weights) { + t.Errorf("%d: weights was modified during execution", i) + } + + // compare with call to Covariance + _, cols := c.Dims() + for ci := 0; ci < cols; ci++ { + for cj := 0; cj < cols; cj++ { + x := mat.Col(nil, ci, test.data) + y := mat.Col(nil, cj, test.data) + corr := Correlation(x, y, test.weights) + if math.Abs(corr-c.At(ci, cj)) > 1e-14 { + t.Errorf("CorrMat does not match at (%v, %v). Want %v, got %v.", ci, cj, corr, c.At(ci, cj)) + } + } + } + } + + } + if !Panics(func() { CorrelationMatrix(nil, mat.NewDense(5, 2, nil), []float64{}) }) { + t.Errorf("CorrelationMatrix did not panic with weight size mismatch") + } + if !Panics(func() { CorrelationMatrix(mat.NewSymDense(1, nil), mat.NewDense(5, 2, nil), nil) }) { + t.Errorf("CorrelationMatrix did not panic with preallocation size mismatch") + } + if !Panics(func() { CorrelationMatrix(nil, mat.NewDense(2, 2, []float64{1, 2, 3, 4}), []float64{1, -1}) }) { + t.Errorf("CorrelationMatrix did not panic with negative weights") + } +} + +func TestCorrCov(t *testing.T) { + // test both Cov2Corr and Cov2Corr + for i, test := range []struct { + data *mat.Dense + weights []float64 + }{ + { + data: mat.NewDense(3, 3, []float64{ + 1, 2, 3, + 3, 4, 5, + 5, 6, 7, + }), + weights: nil, + }, + { + data: mat.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + }, { + data: mat.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + }, + } { + corr := CorrelationMatrix(nil, test.data, test.weights) + cov := CovarianceMatrix(nil, test.data, test.weights) + + r := cov.Symmetric() + + // Get the diagonal elements from cov to determine the sigmas. + sigmas := make([]float64, r) + for i := range sigmas { + sigmas[i] = math.Sqrt(cov.At(i, i)) + } + + covFromCorr := mat.NewSymDense(corr.Symmetric(), nil) + covFromCorr.CopySym(corr) + corrToCov(covFromCorr, sigmas) + + corrFromCov := mat.NewSymDense(cov.Symmetric(), nil) + corrFromCov.CopySym(cov) + covToCorr(corrFromCov) + + if !mat.EqualApprox(corr, corrFromCov, 1e-14) { + t.Errorf("%d: corrToCov did not match direct Correlation calculation. Want: %v, got: %v. ", i, corr, corrFromCov) + } + if !mat.EqualApprox(cov, covFromCorr, 1e-14) { + t.Errorf("%d: covToCorr did not match direct Covariance calculation. Want: %v, got: %v. ", i, cov, covFromCorr) + } + + if !Panics(func() { corrToCov(mat.NewSymDense(2, nil), []float64{}) }) { + t.Errorf("CorrelationMatrix did not panic with sigma size mismatch") + } + } +} + +func TestMahalanobis(t *testing.T) { + // Comparison with scipy. + for cas, test := range []struct { + x, y *mat.VecDense + Sigma *mat.SymDense + ans float64 + }{ + { + x: mat.NewVecDense(3, []float64{1, 2, 3}), + y: mat.NewVecDense(3, []float64{0.8, 1.1, -1}), + Sigma: mat.NewSymDense(3, + []float64{ + 0.8, 0.3, 0.1, + 0.3, 0.7, -0.1, + 0.1, -0.1, 7}), + ans: 1.9251757377680914, + }, + } { + var chol mat.Cholesky + ok := chol.Factorize(test.Sigma) + if !ok { + panic("bad test") + } + ans := Mahalanobis(test.x, test.y, &chol) + if math.Abs(ans-test.ans) > 1e-14 { + t.Errorf("Cas %d: got %v, want %v", cas, ans, test.ans) + } + } +} + +// benchmarks + +func randMat(r, c int) mat.Matrix { + x := make([]float64, r*c) + for i := range x { + x[i] = rand.Float64() + } + return mat.NewDense(r, c, x) +} + +func benchmarkCovarianceMatrix(b *testing.B, m mat.Matrix) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(nil, m, nil) + } +} +func benchmarkCovarianceMatrixWeighted(b *testing.B, m mat.Matrix) { + r, _ := m.Dims() + wts := make([]float64, r) + for i := range wts { + wts[i] = 0.5 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(nil, m, wts) + } +} +func benchmarkCovarianceMatrixInPlace(b *testing.B, m mat.Matrix) { + _, c := m.Dims() + res := mat.NewSymDense(c, nil) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(res, m, nil) + } +} + +func BenchmarkCovarianceMatrixSmallxSmall(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrix(b, x) +} +func BenchmarkCovarianceMatrixSmallxMedium(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmall(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrix(b, x) +} +func BenchmarkCovarianceMatrixMediumxMedium(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmall(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmall(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixSmallxSmallWeighted(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrixWeighted(b, x) +} +func BenchmarkCovarianceMatrixSmallxMediumWeighted(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmallWeighted(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrixWeighted(b, x) +} +func BenchmarkCovarianceMatrixMediumxMediumWeighted(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmallWeighted(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmallWeighted(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixSmallxSmallInPlace(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrixInPlace(b, x) +} +func BenchmarkCovarianceMatrixSmallxMediumInPlace(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmallInPlace(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrixInPlace(b, x) +} +func BenchmarkCovarianceMatrixMediumxMediumInPlace(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmallInPlace(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmallInPlace(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovToCorr(b *testing.B) { + // generate a 10x10 covariance matrix + m := randMat(small, small) + c := CovarianceMatrix(nil, m, nil) + cc := mat.NewSymDense(c.Symmetric(), nil) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + cc.CopySym(c) + b.StartTimer() + covToCorr(cc) + } +} + +func BenchmarkCorrToCov(b *testing.B) { + // generate a 10x10 correlation matrix + m := randMat(small, small) + c := CorrelationMatrix(nil, m, nil) + cc := mat.NewSymDense(c.Symmetric(), nil) + sigma := make([]float64, small) + for i := range sigma { + sigma[i] = 2 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + cc.CopySym(c) + b.StartTimer() + corrToCov(cc, sigma) + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/autogen.go b/vendor/gonum.org/v1/gonum/unit/autogen.go new file mode 100644 index 00000000..829c7318 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/autogen.go @@ -0,0 +1,363 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "go/format" + "log" + "os" + "path/filepath" + "strings" + "text/template" +) + +type Unit struct { + Name string + Receiver string + Offset int // From normal (for example, mass base unit is kg, not kg) + PrintString string // print string for the unit (kg for mass) + ExtraConstant []Constant + Suffix string + Singular string + TypeComment string // Text to comment the type + Dimensions []Dimension + ErForm string //For Xxxer interface +} + +type Dimension struct { + Name string + Power int +} + +const ( + TimeName string = "TimeDim" + LengthName string = "LengthDim" + MassName string = "MassDim" +) + +type Constant struct { + Name string + Value string +} + +type Prefix struct { + Name string + Power int +} + +var Prefixes = []Prefix{ + { + Name: "Yotta", + Power: 24, + }, + { + Name: "Zetta", + Power: 21, + }, + { + Name: "Exa", + Power: 18, + }, + { + Name: "Peta", + Power: 15, + }, + { + Name: "Tera", + Power: 12, + }, + { + Name: "Giga", + Power: 9, + }, + { + Name: "Mega", + Power: 6, + }, + { + Name: "Kilo", + Power: 3, + }, + { + Name: "Hecto", + Power: 2, + }, + { + Name: "Deca", + Power: 1, + }, + { + Name: "", + Power: 0, + }, + { + Name: "Deci", + Power: -1, + }, + { + Name: "Centi", + Power: -2, + }, + { + Name: "Milli", + Power: -3, + }, + { + Name: "Micro", + Power: -6, + }, + { + Name: "Nano", + Power: -9, + }, + { + Name: "Pico", + Power: -12, + }, + { + Name: "Femto", + Power: -15, + }, + { + Name: "Atto", + Power: -18, + }, + { + Name: "Zepto", + Power: -21, + }, + { + Name: "Yocto", + Power: -24, + }, +} + +var Units = []Unit{ + { + Name: "Mass", + Receiver: "m", + Offset: -3, + PrintString: "kg", + Suffix: "gram", + Singular: "Gram", + TypeComment: "Mass represents a mass in kilograms", + Dimensions: []Dimension{ + { + Name: MassName, + Power: 1, + }, + }, + }, + { + Name: "Length", + Receiver: "l", + PrintString: "m", + Suffix: "meter", + Singular: "Meter", + TypeComment: "Length represents a length in meters", + Dimensions: []Dimension{ + { + Name: LengthName, + Power: 1, + }, + }, + }, + { + Name: "Time", + Receiver: "t", + PrintString: "s", + Suffix: "second", + Singular: "Second", + TypeComment: "Time represents a time in seconds", + ExtraConstant: []Constant{ + { + Name: "Hour", + Value: "3600", + }, + { + Name: "Minute", + Value: "60", + }, + }, + Dimensions: []Dimension{ + { + Name: TimeName, + Power: 1, + }, + }, + ErForm: "Timer", + }, +} + +var gopath string +var unitPkgPath string + +func init() { + gopath = os.Getenv("GOPATH") + if gopath == "" { + log.Fatal("no gopath") + } + + unitPkgPath = filepath.Join(gopath, "src", "gonum.org", "v1", "gonum", "unit") +} + +// Generate generates a file for each of the units +func main() { + for _, unit := range Units { + generate(unit) + } +} + +const headerTemplate = `// Code generated by "go generate gonum.org/v1/gonum/unit”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 unit + +import ( + "errors" + "fmt" + "math" +) + +// {{.TypeComment}} +type {{.Name}} float64 +` + +var header = template.Must(template.New("header").Parse(headerTemplate)) + +const constTemplate = ` +const( + {{$unit := .Unit}} + {{range $unit.ExtraConstant}} {{.Name}} {{$unit.Name}} = {{.Value}} + {{end}} + {{$prefixes := .Prefixes}} + {{range $prefixes}} {{if .Name}} {{.Name}}{{$unit.Suffix}} {{else}} {{$unit.Singular}} {{end}} {{$unit.Name}} = {{if .Power}} 1e{{.Power}} {{else}} 1.0 {{end}} + {{end}} +) +` + +var prefix = template.Must(template.New("prefix").Parse(constTemplate)) + +const methodTemplate = ` +// Unit converts the {{.Name}} to a *Unit +func ({{.Receiver}} {{.Name}}) Unit() *Unit { + return New(float64({{.Receiver}}), Dimensions{ + {{range .Dimensions}} {{.Name}}: {{.Power}}, + {{end}} + }) +} + +// {{.Name}} allows {{.Name}} to implement a {{if .ErForm}}{{.ErForm}}{{else}}{{.Name}}er{{end}} interface +func ({{.Receiver}} {{.Name}}) {{.Name}}() {{.Name}} { + return {{.Receiver}} +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func ({{.Receiver}} *{{.Name}}) From(u Uniter) error { + if !DimensionsMatch(u, {{.Singular}}){ + *{{.Receiver}} = {{.Name}}(math.NaN()) + return errors.New("Dimension mismatch") + } + *{{.Receiver}} = {{.Name}}(u.Unit().Value()) + return nil +} +` + +var methods = template.Must(template.New("methods").Parse(methodTemplate)) + +const formatTemplate = ` +func ({{.Receiver}} {{.Name}}) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", {{.Receiver}}, float64({{.Receiver}})) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64({{.Receiver}})) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64({{.Receiver}})) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64({{.Receiver}})) + default: + fmt.Fprintf(fs, "%"+string(c), float64({{.Receiver}})) + } + fmt.Fprint(fs, " {{.PrintString}}") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g {{.PrintString}})", c, {{.Receiver}}, float64({{.Receiver}})) + } +} +` + +var form = template.Must(template.New("format").Parse(formatTemplate)) + +func generate(unit Unit) { + lowerName := strings.ToLower(unit.Name) + filename := filepath.Join(unitPkgPath, lowerName+".go") + f, err := os.Create(filename) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + // Need to define new prefixes because text/template can't do math. + // Need to do math because kilogram = 1 not 10^3 + + prefixes := make([]Prefix, len(Prefixes)) + for i, p := range Prefixes { + prefixes[i].Name = p.Name + prefixes[i].Power = p.Power + unit.Offset + } + + data := struct { + Prefixes []Prefix + Unit Unit + }{ + prefixes, + unit, + } + + buf := bytes.NewBuffer(make([]byte, 0)) + + err = header.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + err = prefix.Execute(buf, data) + if err != nil { + log.Fatal(err) + } + + err = methods.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + err = form.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + b, err := format.Source(buf.Bytes()) + if err != nil { + f.Write(buf.Bytes()) // This is here to debug bad format + log.Fatalf("error formatting: %s", err) + } + + f.Write(b) +} diff --git a/vendor/gonum.org/v1/gonum/unit/consts.go b/vendor/gonum.org/v1/gonum/unit/consts.go new file mode 100644 index 00000000..908d478e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/consts.go @@ -0,0 +1,29 @@ +// Copyright ©2017 The gonum 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 unit + +const ( + Yotta = 1e24 + Zetta = 1e21 + Exa = 1e18 + Peta = 1e15 + Tera = 1e12 + Giga = 1e9 + Mega = 1e6 + Kilo = 1e3 + Hecto = 1e2 + Deca = 1e1 + + Deci = 1e-1 + Centi = 1e-2 + Milli = 1e-3 + Micro = 1e-6 + Nano = 1e-9 + Pico = 1e-12 + Femto = 1e-15 + Atto = 1e-18 + Zepto = 1e-21 + Yocto = 1e-24 +) diff --git a/vendor/gonum.org/v1/gonum/unit/dimless.go b/vendor/gonum.org/v1/gonum/unit/dimless.go new file mode 100644 index 00000000..5c6ce36e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/dimless.go @@ -0,0 +1,66 @@ +// Copyright ©2013 The gonum 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 unit + +import ( + "errors" + "fmt" + "math" +) + +// Dimless represents a dimensionless constant +type Dimless float64 + +const ( + One Dimless = 1.0 +) + +// Unit converts the Dimless to a unit +func (d Dimless) Unit() *Unit { + return New(float64(d), Dimensions{}) +} + +// Dimless allows Dimless to implement a Dimlesser interface +func (d Dimless) Dimless() Dimless { + return d +} + +// From converts the unit to a dimless. Returns an error if there +// is a mismatch in dimension +func (d *Dimless) From(u *Unit) error { + if !DimensionsMatch(u, One) { + (*d) = Dimless(math.NaN()) + return errors.New("Dimension mismatch") + } + (*d) = Dimless(u.Unit().Value()) + return nil +} + +func (d Dimless) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", d, float64(d)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(d)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(d)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(d)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(d)) + } + default: + fmt.Fprintf(fs, "%%!%c(%T=%g)", c, d, float64(d)) + return + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/doc.go b/vendor/gonum.org/v1/gonum/unit/doc.go new file mode 100644 index 00000000..97ca4386 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/doc.go @@ -0,0 +1,83 @@ +// Copyright ©2013 The gonum 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:generate go run autogen.go + +// Package unit provides a set of types and constants that facilitate +// the use of the International System of Units (SI). +// +// Unit provides two main functionalities. +// +// 1) +// It provides a number of types representing either an SI base unit +// or a common combination of base units, named for the unit it +// represents (Length, Mass, Pressure, etc.). Each type has +// a float64 as the underlying unit, and its value represents the +// number of that underlying unit (Kilogram, Meter, Pascal, etc.). +// For example, +// height := 1.6 * unit.Meter +// acc := unit.Acceleration(9.8) +// creates a variable named 'height' with a value of 1.6 meters, and +// a variable named 'acc' with a value of 9.8 meters per second squared. +// These types can be used to add compile-time safety to code. For +// example, +// func UnitDensity(t unit.Temperature, pressure unit.Pressure) (unit.Density){ +// ... +// } +// func main(){ +// t := 300 * unit.Kelvin +// p := 5 * unit.Bar +// rho := UnitDensity(p, t) // compile-time error +// } +// gives a compile-time error (temperature type does not match pressure type) +// while the corresponding code using float64 runs without error. +// func Float64Density(temperature, pressure float64) (float64){ +// ... +// } +// func main(){ +// t := 300.0 // degrees kelvin +// p := 50000.0 // Pascals +// rho := Float64Density(p, t) // no error +// } +// Many types have constants defined representing named SI units (Meter, +// Kilogram, etc. ) or SI derived units (Bar, Hz, etc.). The Unit package +// additionally provides untyped constants for SI prefixes, so the following +// are all equivalent. +// l := 0.001 * unit.Meter +// k := 1 * unit.Milli * unit.Meter +// j := unit.Length(0.001) +// +// 2) +// Unit provides the type "Unit", meant to represent a general dimensional +// value. unit.Unit can be used to help prevent errors of dimensionality +// when multiplying or dividing dimensional numbers. This package also +// provides the "Uniter" interface which is satisfied by any type which can +// be converted to a unit. New varibles of type Unit can be created with +// the New function and the Dimensions map. For example, the code +// acc := New(9.81, Dimensions{LengthDim:1, TimeDim: -2}) +// creates a variable "acc" which has a value of 9.81 m/s^2. Methods of +// unit can be used to modify this value, for example: +// acc.Mul(1.0 * unit.Kilogram).Mul(1 * unit.Meter) +// To convert the unit back into a typed float64 value, the From methods +// of the dimensional types should be used. From will return an error if the +// dimensions do not match. +// var energy unit.Energy +// err := (*energy).From(acc) +// Domain-specific problems may need custom dimensions, and for this purpose +// NewDimension should be used to help avoid accidental overlap between +// packages. For example, results from a blood test may be measured in +// "White blood cells per slide". In this case, NewDimension should be +// used to create a 'WhiteBloodCell' dimension. NewDimension takes in a +// string which will be used for printing that dimension, and will return +// a unique dimension number. NewDimension should not be +// used, however, to create the unit of 'Slide', because in this case slide +// is just a measurement of area. Instead, a constant could be defined. +// const Slide unit.Area = 0.001875 // m^2 +// Please note that Unit cannot catch all errors related to dimensionality. +// Different physical ideas are sometimes expressed with the same dimensions +// and Unit is incapable of catching these mismatches. For example, energy and +// torque are both expressed as force times distance (Newton-meters in SI), +// but it is wrong to say that a torque of 10 N-m is the same as 10 J, even +// though the dimensions agree. +package unit // import "gonum.org/v1/gonum/unit" diff --git a/vendor/gonum.org/v1/gonum/unit/length.go b/vendor/gonum.org/v1/gonum/unit/length.go new file mode 100644 index 00000000..f7ffde23 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/length.go @@ -0,0 +1,90 @@ +// Code generated by "go generate gonum.org/v1/gonum/unit”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 unit + +import ( + "errors" + "fmt" + "math" +) + +// Length represents a length in meters +type Length float64 + +const ( + Yottameter Length = 1e24 + Zettameter Length = 1e21 + Exameter Length = 1e18 + Petameter Length = 1e15 + Terameter Length = 1e12 + Gigameter Length = 1e9 + Megameter Length = 1e6 + Kilometer Length = 1e3 + Hectometer Length = 1e2 + Decameter Length = 1e1 + Meter Length = 1.0 + Decimeter Length = 1e-1 + Centimeter Length = 1e-2 + Millimeter Length = 1e-3 + Micrometer Length = 1e-6 + Nanometer Length = 1e-9 + Picometer Length = 1e-12 + Femtometer Length = 1e-15 + Attometer Length = 1e-18 + Zeptometer Length = 1e-21 + Yoctometer Length = 1e-24 +) + +// Unit converts the Length to a *Unit +func (l Length) Unit() *Unit { + return New(float64(l), Dimensions{ + LengthDim: 1, + }) +} + +// Length allows Length to implement a Lengther interface +func (l Length) Length() Length { + return l +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (l *Length) From(u Uniter) error { + if !DimensionsMatch(u, Meter) { + *l = Length(math.NaN()) + return errors.New("Dimension mismatch") + } + *l = Length(u.Unit().Value()) + return nil +} + +func (l Length) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", l, float64(l)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(l)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(l)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(l)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(l)) + } + fmt.Fprint(fs, " m") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g m)", c, l, float64(l)) + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/mass.go b/vendor/gonum.org/v1/gonum/unit/mass.go new file mode 100644 index 00000000..2b127046 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/mass.go @@ -0,0 +1,90 @@ +// Code generated by "go generate gonum.org/v1/gonum/unit”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 unit + +import ( + "errors" + "fmt" + "math" +) + +// Mass represents a mass in kilograms +type Mass float64 + +const ( + Yottagram Mass = 1e21 + Zettagram Mass = 1e18 + Exagram Mass = 1e15 + Petagram Mass = 1e12 + Teragram Mass = 1e9 + Gigagram Mass = 1e6 + Megagram Mass = 1e3 + Kilogram Mass = 1.0 + Hectogram Mass = 1e-1 + Decagram Mass = 1e-2 + Gram Mass = 1e-3 + Decigram Mass = 1e-4 + Centigram Mass = 1e-5 + Milligram Mass = 1e-6 + Microgram Mass = 1e-9 + Nanogram Mass = 1e-12 + Picogram Mass = 1e-15 + Femtogram Mass = 1e-18 + Attogram Mass = 1e-21 + Zeptogram Mass = 1e-24 + Yoctogram Mass = 1e-27 +) + +// Unit converts the Mass to a *Unit +func (m Mass) Unit() *Unit { + return New(float64(m), Dimensions{ + MassDim: 1, + }) +} + +// Mass allows Mass to implement a Masser interface +func (m Mass) Mass() Mass { + return m +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (m *Mass) From(u Uniter) error { + if !DimensionsMatch(u, Gram) { + *m = Mass(math.NaN()) + return errors.New("Dimension mismatch") + } + *m = Mass(u.Unit().Value()) + return nil +} + +func (m Mass) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", m, float64(m)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(m)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(m)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(m)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(m)) + } + fmt.Fprint(fs, " kg") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g kg)", c, m, float64(m)) + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/time.go b/vendor/gonum.org/v1/gonum/unit/time.go new file mode 100644 index 00000000..ef70fb8a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/time.go @@ -0,0 +1,93 @@ +// Code generated by "go generate gonum.org/v1/gonum/unit”; DO NOT EDIT. + +// Copyright ©2014 The gonum 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 unit + +import ( + "errors" + "fmt" + "math" +) + +// Time represents a time in seconds +type Time float64 + +const ( + Hour Time = 3600 + Minute Time = 60 + + Yottasecond Time = 1e24 + Zettasecond Time = 1e21 + Exasecond Time = 1e18 + Petasecond Time = 1e15 + Terasecond Time = 1e12 + Gigasecond Time = 1e9 + Megasecond Time = 1e6 + Kilosecond Time = 1e3 + Hectosecond Time = 1e2 + Decasecond Time = 1e1 + Second Time = 1.0 + Decisecond Time = 1e-1 + Centisecond Time = 1e-2 + Millisecond Time = 1e-3 + Microsecond Time = 1e-6 + Nanosecond Time = 1e-9 + Picosecond Time = 1e-12 + Femtosecond Time = 1e-15 + Attosecond Time = 1e-18 + Zeptosecond Time = 1e-21 + Yoctosecond Time = 1e-24 +) + +// Unit converts the Time to a *Unit +func (t Time) Unit() *Unit { + return New(float64(t), Dimensions{ + TimeDim: 1, + }) +} + +// Time allows Time to implement a Timer interface +func (t Time) Time() Time { + return t +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (t *Time) From(u Uniter) error { + if !DimensionsMatch(u, Second) { + *t = Time(math.NaN()) + return errors.New("Dimension mismatch") + } + *t = Time(u.Unit().Value()) + return nil +} + +func (t Time) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", t, float64(t)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(t)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(t)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(t)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(t)) + } + fmt.Fprint(fs, " s") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g s)", c, t, float64(t)) + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/unit_test.go b/vendor/gonum.org/v1/gonum/unit/unit_test.go new file mode 100644 index 00000000..258df365 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/unit_test.go @@ -0,0 +1,352 @@ +// Copyright ©2013 The gonum 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 unit + +import ( + "fmt" + "math" + "testing" +) + +var formatTests = []struct { + unit Uniter + format string + expect string +}{ + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%f", "9.810000 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%1.f", "10 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%.1f", "9.8 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2, LengthDim: 0}), "%f", "9.810000 kg s^-2"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%e", "6.626070e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%.3e", "6.626e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%v", "6.62606957e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%s", "%!s(*Unit=6.62606957e-34 kg^2 s^-1)"}, + {Dimless(math.E), "%v", "2.718281828459045"}, + {Dimless(math.E), "%#v", "unit.Dimless(2.718281828459045)"}, + {Dimless(math.E), "%s", "%!s(unit.Dimless=2.718281828459045)"}, + {Mass(1), "%v", "1 kg"}, + {Mass(1), "%#v", "unit.Mass(1)"}, + {Mass(1), "%s", "%!s(unit.Mass=1 kg)"}, + {Length(1.61619926e-35), "%v", "1.61619926e-35 m"}, + {Length(1.61619926e-35), "%#v", "unit.Length(1.61619926e-35)"}, + {Length(1.61619926e-35), "%s", "%!s(unit.Length=1.61619926e-35 m)"}, + {Time(15.2), "%v", "15.2 s"}, + {Time(15.2), "%#v", "unit.Time(15.2)"}, + {Time(15.2), "%s", "%!s(unit.Time=15.2 s)"}, +} + +func TestFormat(t *testing.T) { + for _, ts := range formatTests { + if r := fmt.Sprintf(ts.format, ts.unit); r != ts.expect { + t.Errorf("Format %q: got: %q expected: %q", ts.format, r, ts.expect) + } + } +} + +func TestGoStringFormat(t *testing.T) { + expect1 := `&unit.Unit{dimensions:unit.Dimensions{4:2, 6:-1}, formatted:"", value:6.62606957e-34}` + expect2 := `&unit.Unit{dimensions:unit.Dimensions{6:-1, 4:2}, formatted:"", value:6.62606957e-34}` + if r := fmt.Sprintf("%#v", New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1})); r != expect1 && r != expect2 { + t.Errorf("Format %q: got: %q expected: %q", "%#v", r, expect1) + } +} + +var initializationTests = []struct { + unit *Unit + expValue float64 + expMap map[Dimension]int +}{ + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), 9.81, Dimensions{MassDim: 1, TimeDim: -2}}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2, LengthDim: 0, CurrentDim: 0}), 9.81, Dimensions{MassDim: 1, TimeDim: -2}}, +} + +func TestInitialization(t *testing.T) { + for _, ts := range initializationTests { + if ts.expValue != ts.unit.value { + t.Errorf("Value wrong on initialization: got: %v expected: %v", ts.unit.value, ts.expValue) + } + if len(ts.expMap) != len(ts.unit.dimensions) { + t.Errorf("Map mismatch: got: %#v expected: %#v", ts.unit.dimensions, ts.expMap) + } + for key, val := range ts.expMap { + if ts.unit.dimensions[key] != val { + t.Errorf("Map mismatch: got: %#v expected: %#v", ts.unit.dimensions, ts.expMap) + } + } + } +} + +var dimensionEqualityTests = []struct { + name string + a Uniter + b Uniter + shouldMatch bool +}{ + {"same_empty", New(1.0, Dimensions{}), New(1.0, Dimensions{}), true}, + {"same_one", New(1.0, Dimensions{TimeDim: 1}), New(1.0, Dimensions{TimeDim: 1}), true}, + {"same_mult", New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), true}, + {"diff_one_empty", New(1.0, Dimensions{}), New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), false}, + {"diff_same_dim", New(1.0, Dimensions{TimeDim: 1}), New(1.0, Dimensions{TimeDim: 2}), false}, + {"diff_same_pow", New(1.0, Dimensions{LengthDim: 1}), New(1.0, Dimensions{TimeDim: 1}), false}, + {"diff_numdim", New(1.0, Dimensions{TimeDim: 1, LengthDim: 2}), New(1.0, Dimensions{TimeDim: 2}), false}, + {"diff_one_same_dim", New(1.0, Dimensions{LengthDim: 1, TimeDim: 1}), New(1.0, Dimensions{LengthDim: 1, TimeDim: 2}), false}, +} + +func TestDimensionEquality(t *testing.T) { + for _, ts := range dimensionEqualityTests { + if DimensionsMatch(ts.a, ts.b) != ts.shouldMatch { + t.Errorf("Dimension comparison incorrect for case %s. got: %v, expected: %v", ts.name, !ts.shouldMatch, ts.shouldMatch) + } + } +} + +type UnitStructer interface { + UnitStruct() *UnitStruct +} + +type UnitStruct struct { + current int + length int + luminosity int + mass int + temperature int + time int + chemamt int // For mol + value float64 +} + +// Check if the dimensions of two units are the same +func DimensionsMatchStruct(aU, bU UnitStructer) bool { + a := aU.UnitStruct() + b := bU.UnitStruct() + if a.length != b.length { + return false + } + if a.time != b.time { + return false + } + if a.mass != b.mass { + return false + } + if a.current != b.current { + return false + } + if a.temperature != b.temperature { + return false + } + if a.luminosity != b.luminosity { + return false + } + if a.chemamt != b.chemamt { + return false + } + return true +} + +func (u *UnitStruct) UnitStruct() *UnitStruct { + return u +} + +func (u *UnitStruct) Add(aU UnitStructer) *UnitStruct { + a := aU.UnitStruct() + if !DimensionsMatchStruct(a, u) { + panic("dimension mismatch") + } + u.value += a.value + return u +} + +func (u *UnitStruct) Mul(aU UnitStructer) *UnitStruct { + a := aU.UnitStruct() + u.length += a.length + u.time += a.time + u.mass += a.mass + u.current += a.current + u.temperature += a.temperature + u.luminosity += a.luminosity + u.chemamt += a.chemamt + u.value *= a.value + return u +} + +var u3 *UnitStruct + +func BenchmarkAddStruct(b *testing.B) { + u1 := &UnitStruct{current: 1, chemamt: 5, value: 10} + u2 := &UnitStruct{current: 1, chemamt: 5, value: 100} + for i := 0; i < b.N; i++ { + u2.Add(u1) + } +} + +func BenchmarkMulStruct(b *testing.B) { + u1 := &UnitStruct{current: 1, chemamt: 5, value: 10} + u2 := &UnitStruct{mass: 1, time: 1, value: 100} + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +type UnitMapper interface { + UnitMap() *UnitMap +} + +type dimensionMap int + +const ( + LengthB dimensionMap = iota + TimeB + MassB + CurrentB + TemperatureB + LuminosityB + ChemAmtB +) + +type UnitMap struct { + dimension map[dimensionMap]int + value float64 +} + +// Check if the dimensions of two units are the same +func DimensionsMatchMap(aU, bU UnitMapper) bool { + a := aU.UnitMap() + b := bU.UnitMap() + if len(a.dimension) != len(b.dimension) { + panic("Unequal dimension") + } + for key, dimA := range a.dimension { + dimB, ok := b.dimension[key] + if !ok || dimA != dimB { + panic("Unequal dimension") + } + } + return true +} + +func (u *UnitMap) UnitMap() *UnitMap { + return u +} + +func (u *UnitMap) Add(aU UnitMapper) *UnitMap { + a := aU.UnitMap() + if !DimensionsMatchMap(a, u) { + panic("dimension mismatch") + } + u.value += a.value + return u +} + +func (u *UnitMap) Mul(aU UnitMapper) *UnitMap { + a := aU.UnitMap() + for key, val := range a.dimension { + u.dimension[key] += val + } + u.value *= a.value + return u +} + +var sink float64 + +func BenchmarkAddFloat(b *testing.B) { + sink = 0 + c := 10.0 + for i := 0; i < b.N; i++ { + sink += c + } +} + +func BenchmarkMulFloat(b *testing.B) { + sink = 0 + c := 10.0 + for i := 0; i < b.N; i++ { + sink *= c + } +} + +func BenchmarkAddMapSmall(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[CurrentB] = 1 + u1.dimension[ChemAmtB] = 5 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[CurrentB] = 1 + u2.dimension[ChemAmtB] = 5 + for i := 0; i < b.N; i++ { + u2.Add(u1) + } +} + +func BenchmarkMulMapSmallDiff(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[MassB] = 1 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapSmallSame(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[LengthB] = 2 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapLargeDiff(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + u1.dimension[MassB] = 1 + u1.dimension[ChemAmtB] = 1 + u1.dimension[TemperatureB] = 1 + u1.dimension[LuminosityB] = 1 + u1.dimension[TimeB] = 1 + u1.dimension[CurrentB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[MassB] = 1 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapLargeSame(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 2 + u1.dimension[MassB] = 2 + u1.dimension[ChemAmtB] = 2 + u1.dimension[TemperatureB] = 2 + u1.dimension[LuminosityB] = 2 + u1.dimension[TimeB] = 2 + u1.dimension[CurrentB] = 2 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[LengthB] = 3 + u2.dimension[MassB] = 3 + u2.dimension[ChemAmtB] = 3 + u2.dimension[TemperatureB] = 3 + u2.dimension[LuminosityB] = 3 + u2.dimension[TimeB] = 3 + u2.dimension[CurrentB] = 3 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} diff --git a/vendor/gonum.org/v1/gonum/unit/unitexample_test.go b/vendor/gonum.org/v1/gonum/unit/unitexample_test.go new file mode 100644 index 00000000..d81faae7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/unitexample_test.go @@ -0,0 +1,29 @@ +// Copyright ©2017 The gonum 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 unit_test + +import ( + "fmt" + + "gonum.org/v1/gonum/unit" +) + +func ExampleNew() { + // Create an acceleration of 3 m/s^2 + accel := unit.New(3.0, unit.Dimensions{unit.LengthDim: 1, unit.TimeDim: -2}) + fmt.Println(accel) + + // Output: 3 m s^-2 +} + +func ExampleNewDimension() { + // Create a "trees" dimension + // Typically, this should be used within an init function + treeDim := unit.NewDimension("tree") + countPerArea := unit.New(0.1, unit.Dimensions{treeDim: 1, unit.LengthDim: -2}) + fmt.Println(countPerArea) + + // Output: 0.1 tree m^-2 +} diff --git a/vendor/gonum.org/v1/gonum/unit/unittype.go b/vendor/gonum.org/v1/gonum/unit/unittype.go new file mode 100644 index 00000000..21311fd9 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/unit/unittype.go @@ -0,0 +1,342 @@ +// Copyright ©2013 The gonum 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 unit + +import ( + "bytes" + "fmt" + "sort" +) + +// Uniter is a type that can be converted to a Unit. +type Uniter interface { + Unit() *Unit +} + +// Dimension is a type representing an SI base dimension or a distinct +// orthogonal dimension. Non-SI dimensions can be created using the NewDimension +// function, typically within an init function. +type Dimension int + +// String returns the string for the dimension. +func (d Dimension) String() string { + switch { + case d == reserved: + return "reserved" + case d < Dimension(len(symbols)): + return symbols[d] + default: + panic("unit: illegal dimension") + } +} + +const ( + // SI Base Units + reserved Dimension = iota + CurrentDim + LengthDim + LuminousIntensityDim + MassDim + TemperatureDim + TimeDim + // Other common SI Dimensions + AngleDim // e.g. radians +) + +var ( + symbols = []string{ + CurrentDim: "A", + LengthDim: "m", + LuminousIntensityDim: "cd", + MassDim: "kg", + TemperatureDim: "K", + TimeDim: "s", + AngleDim: "rad", + } + + // dimensions guarantees there aren't two identical symbols + // SI symbol list from http://lamar.colostate.edu/~hillger/basic.htm + dimensions = map[string]Dimension{ + "A": CurrentDim, + "m": LengthDim, + "cd": LuminousIntensityDim, + "kg": MassDim, + "K": TemperatureDim, + "s": TimeDim, + "rad": AngleDim, + + // Reserve common SI symbols + // base units + "mol": reserved, + // prefixes + "Y": reserved, + "Z": reserved, + "E": reserved, + "P": reserved, + "T": reserved, + "G": reserved, + "M": reserved, + "k": reserved, + "h": reserved, + "da": reserved, + "d": reserved, + "c": reserved, + "μ": reserved, + "n": reserved, + "p": reserved, + "f": reserved, + "a": reserved, + "z": reserved, + "y": reserved, + // SI Derived units with special symbols + "sr": reserved, + "F": reserved, + "C": reserved, + "S": reserved, + "H": reserved, + "V": reserved, + "Ω": reserved, + "J": reserved, + "N": reserved, + "Hz": reserved, + "lx": reserved, + "lm": reserved, + "Wb": reserved, + "W": reserved, + "Pa": reserved, + "Bq": reserved, + "Gy": reserved, + "Sv": reserved, + "kat": reserved, + // Units in use with SI + "ha": reserved, + "L": reserved, + "l": reserved, + // Units in Use Temporarily with SI + "bar": reserved, + "b": reserved, + "Ci": reserved, + "R": reserved, + "rd": reserved, + "rem": reserved, + } +) + +// Dimensions represent the dimensionality of the unit in powers +// of that dimension. If a key is not present, the power of that +// dimension is zero. Dimensions is used in conjunction with New. +type Dimensions map[Dimension]int + +func (d Dimensions) String() string { + // Map iterates randomly, but print should be in a fixed order. Can't use + // dimension number, because for user-defined dimension that number may + // not be fixed from run to run. + atoms := make(unitPrinters, 0, len(d)) + for dimension, power := range d { + if power != 0 { + atoms = append(atoms, atom{dimension, power}) + } + } + sort.Sort(atoms) + var b bytes.Buffer + for i, a := range atoms { + if i > 0 { + b.WriteByte(' ') + } + fmt.Fprintf(&b, "%s", a.Dimension) + if a.pow != 1 { + fmt.Fprintf(&b, "^%d", a.pow) + } + } + + return b.String() +} + +type atom struct { + Dimension + pow int +} + +type unitPrinters []atom + +func (u unitPrinters) Len() int { + return len(u) +} + +func (u unitPrinters) Less(i, j int) bool { + // Order first by positive powers, then by name. + if u[i].pow*u[j].pow < 0 { + return u[i].pow > 0 + } + return u[i].String() < u[j].String() +} + +func (u unitPrinters) Swap(i, j int) { + u[i], u[j] = u[j], u[i] +} + +// NewDimension creates a new orthogonal dimension with the given symbol, and +// returns the value of that dimension. The input symbol must not overlap with +// any of the any of the SI base units or other symbols of common use in SI ("kg", +// "J", etc.), and must not overlap with any other dimensions created by calls +// to NewDimension. The SymbolExists function can check if the symbol exists. +// NewDimension will panic if the input symbol matches an existing symbol. +// +// NewDimension should only be called for unit types that are actually orthogonal +// to the base dimensions defined in this package. Please see the package-level +// documentation for further explanation. +func NewDimension(symbol string) Dimension { + _, ok := dimensions[symbol] + if ok { + panic("unit: dimension string \"" + symbol + "\" already used") + } + d := Dimension(len(symbols)) + symbols = append(symbols, symbol) + dimensions[symbol] = d + return d +} + +// SymoblExists returns whether the given symbol is already in use. +func SymbolExists(symbol string) bool { + _, ok := dimensions[symbol] + return ok +} + +// Unit represents a dimensional value. The dimensions will typically be in SI +// units, but can also include dimensions created with NewDimension. The Unit type +// is most useful for ensuring dimensional consistency when manipulating types +// with different units, for example, by multiplying an acceleration with a +// mass to get a force. Please see the package documentation for further explanation. +type Unit struct { + dimensions Dimensions + formatted string + value float64 +} + +// New creates a new variable of type Unit which has the value and dimensions +// specified by the inputs. The built-in dimensions are always in SI units +// (meters, kilograms, etc.). +func New(value float64, d Dimensions) *Unit { + u := &Unit{ + dimensions: make(map[Dimension]int), + value: value, + } + for key, val := range d { + if val != 0 { + u.dimensions[key] = val + } + } + return u +} + +// DimensionsMatch checks if the dimensions of two Uniters are the same. +func DimensionsMatch(a, b Uniter) bool { + aUnit := a.Unit() + bUnit := b.Unit() + if len(aUnit.dimensions) != len(bUnit.dimensions) { + return false + } + for key, val := range aUnit.dimensions { + if bUnit.dimensions[key] != val { + return false + } + } + return true +} + +// Add adds the function argument to the receiver. Panics if the units of +// the receiver and the argument don't match. +func (u *Unit) Add(uniter Uniter) *Unit { + a := uniter.Unit() + if !DimensionsMatch(u, a) { + panic("unit: mismatched dimensions in addition") + } + u.value += a.value + return u +} + +// Unit implements the Uniter interface +func (u *Unit) Unit() *Unit { + return u +} + +// Mul multiply the receiver by the input changing the dimensions +// of the receiver as appropriate. The input is not changed. +func (u *Unit) Mul(uniter Uniter) *Unit { + a := uniter.Unit() + for key, val := range a.dimensions { + if d := u.dimensions[key]; d == -val { + delete(u.dimensions, key) + } else { + u.dimensions[key] = d + val + } + } + u.formatted = "" + u.value *= a.value + return u +} + +// Div divides the receiver by the argument changing the +// dimensions of the receiver as appropriate. +func (u *Unit) Div(uniter Uniter) *Unit { + a := uniter.Unit() + u.value /= a.value + for key, val := range a.dimensions { + if d := u.dimensions[key]; d == val { + delete(u.dimensions, key) + } else { + u.dimensions[key] = d - val + } + } + u.formatted = "" + return u +} + +// Value return the raw value of the unit as a float64. Use of this +// method is, in general, not recommended, though it can be useful +// for printing. Instead, the From type of a specific dimension +// should be used to guarantee dimension consistency. +func (u *Unit) Value() float64 { + return u.value +} + +// Format makes Unit satisfy the fmt.Formatter interface. The unit is formatted +// with dimensions appended. If the power if the dimension is not zero or one, +// symbol^power is appended, if the power is one, just the symbol is appended +// and if the power is zero, nothing is appended. Dimensions are appended +// in order by symbol name with positive powers ahead of negative powers. +func (u *Unit) Format(fs fmt.State, c rune) { + if u == nil { + fmt.Fprint(fs, "") + } + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "&%#v", *u) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, u.value) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, u.value) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, u.value) + default: + fmt.Fprintf(fs, "%"+string(c), u.value) + } + default: + fmt.Fprintf(fs, "%%!%c(*Unit=%g)", c, u) + return + } + if u.formatted == "" && len(u.dimensions) > 0 { + u.formatted = u.dimensions.String() + } + fmt.Fprintf(fs, " %s", u.formatted) +} From a74edc5121a05347df9a782119403cc42c5cda38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 16:22:15 +0800 Subject: [PATCH 6/8] test order difficulty --- gateway/wallet_service.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gateway/wallet_service.go b/gateway/wallet_service.go index efd2bfdb..91892a21 100644 --- a/gateway/wallet_service.go +++ b/gateway/wallet_service.go @@ -412,9 +412,6 @@ type AddTokenReq struct { Decimals string `json:"decimals"` } -type OrderDifficultyReq struct { -} - type OrderDifficultyRes struct { Difficulty common.Hash `json:"difficulty"` } @@ -554,7 +551,7 @@ func (w *WalletServiceImpl) GetPriceQuote(query PriceQuoteQuery) (result PriceQu return rst, nil } -func (w *WalletServiceImpl) GetOrderDifficulty(req OrderDifficultyReq) (result OrderDifficultyRes, err error) { +func (w *WalletServiceImpl) GetOrderDifficulty() (result OrderDifficultyRes, err error) { diff, err1 := order_difficulty.GetDifficulty() return OrderDifficultyRes{Difficulty: diff}, err1 } From 29242a64695078f63bc0bf472801c3557716954e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 16:59:21 +0800 Subject: [PATCH 7/8] test order difficulty --- config/relay.toml | 6 ++++ gateway/gateway.go | 14 +++++---- gateway/order_difficulty/difficulty.go | 32 ++++++++++----------- gateway/order_difficulty/difficulty_test.go | 14 ++++----- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/config/relay.toml b/config/relay.toml index 05c0f98c..e45392ca 100644 --- a/config/relay.toml +++ b/config/relay.toml @@ -132,3 +132,9 @@ title = "miner" [cloud_watch] enabled = false region = "" + +[order_difficulty] + base_difficulty = "0x0000000000000000000000000000000000000000000000000000000000000010" + threshold = 20 + cal_count = 100 + duration = 2 \ No newline at end of file diff --git a/gateway/gateway.go b/gateway/gateway.go index f1e3f4ff..73e865ce 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -24,6 +24,7 @@ import ( "errors" "fmt" "github.com/Loopring/relay-cluster/accountmanager" + "github.com/Loopring/relay-cluster/gateway/order_difficulty" "github.com/Loopring/relay-cluster/ordermanager/manager" "github.com/Loopring/relay-cluster/ordermanager/viewer" "github.com/Loopring/relay-lib/broadcast" @@ -36,8 +37,8 @@ import ( "github.com/Loopring/relay-lib/types" "github.com/ethereum/go-ethereum/common" "math/big" - "time" "strings" + "time" ) type Gateway struct { @@ -85,7 +86,7 @@ func Initialize(filterOptions *GatewayFiltersOptions, options *GateWayOptions, o gateway.marketCap = marketCap // new pow filter - powFilter := &PowFilter{Difficulty: types.HexToBigint(filterOptions.PowFilter.Difficulty)} + powFilter := &PowFilter{} // new base filter baseFilter := &BaseFilter{ @@ -400,7 +401,6 @@ func (f *CutoffFilter) filter(o *types.Order) (bool, error) { } type PowFilter struct { - Difficulty *big.Int } func (f *PowFilter) filter(o *types.Order) (bool, error) { @@ -410,9 +410,11 @@ func (f *PowFilter) filter(o *types.Order) (bool, error) { } pow := GetPow(o.V, o.R, o.S, o.PowNonce) - - if pow.Cmp(f.Difficulty) < 0 { - return false, fmt.Errorf("invalid pow") + if diffHex, err := order_difficulty.GetDifficulty(); nil == err { + diff := types.HexToBigint(diffHex) + if pow.Cmp(diff) < 0 { + return false, fmt.Errorf("invalid pow") + } } return true, nil } diff --git a/gateway/order_difficulty/difficulty.go b/gateway/order_difficulty/difficulty.go index 08c42f6a..50f508dd 100644 --- a/gateway/order_difficulty/difficulty.go +++ b/gateway/order_difficulty/difficulty.go @@ -48,7 +48,7 @@ type OrderDifficultyEvaluator struct { } type OrderDifficulty struct { - Difficulty common.Hash + Difficulty string OrdersNum int64 TimeStamp int64 } @@ -68,8 +68,8 @@ func (evaluator *OrderDifficultyEvaluator) getDiffCacheKey(createTime int64) (ke } func NewOrderDifficultyEvaluator(config OrderDifficultyConfig) *OrderDifficultyEvaluator { - if nil == config.BaseDifficulty { - config.BaseDifficulty = big.NewInt(0) + if "" == config.BaseDifficulty { + config.BaseDifficulty = "0x10" } if 0 == config.CalCount { config.CalCount = 1000 @@ -81,12 +81,13 @@ func NewOrderDifficultyEvaluator(config OrderDifficultyConfig) *OrderDifficultyE config.Threshold = 10 } evaluator := &OrderDifficultyEvaluator{calCount: config.CalCount, duration: config.Duration} - evaluator.evaluator = &LinearEvaluator{baseDifficulty: config.BaseDifficulty, threshold: config.Threshold} + baseDifficulty := types.HexToBigint(config.BaseDifficulty) + evaluator.evaluator = &LinearEvaluator{baseDifficulty: baseDifficulty, threshold: config.Threshold} return evaluator } type OrderDifficultyConfig struct { - BaseDifficulty *big.Int + BaseDifficulty string Threshold int64 CalCount int64 Duration int64 @@ -99,9 +100,8 @@ func (evaluator *OrderDifficultyEvaluator) Start() { log.Errorf("erro:%s", err.Error()) } else { if _, err1 := GetDifficulty(); nil != err1 { - println("##########") - diff := common.BytesToHash(evaluator.evaluator.getBaseDifficulty().Bytes()) - cache.Set(OrderDifficultyKey, []byte(diff.Hex()), int64(10000)) + diffHex := types.BigintToHex(evaluator.evaluator.getBaseDifficulty()) + cache.Set(OrderDifficultyKey, []byte(diffHex), int64(10000)) } //now := time.Now().Unix() //orderCntList := []*OrderDifficulty{} @@ -118,8 +118,8 @@ func (evaluator *OrderDifficultyEvaluator) Start() { select { case <-time.After(time.Duration(evaluator.duration) * time.Second): now := time.Now().Unix() - if diffHash, err := GetDifficulty(); nil == err { - currentDiff := diffHash + if diffHex, err := GetDifficulty(); nil == err { + currentDiff := diffHex orderDiff := &OrderDifficulty{} cacheKey, _ := evaluator.getOrderCacheKey(now) orderDiff.OrdersNum = 0 @@ -215,7 +215,7 @@ func (evaluator *LinearEvaluator) CalcAndSaveDifficulty(orderCntList []*OrderDif return evaluator.nextDifficulty(orderList) } -func NewOrderDiff(ordersNum int64, diff common.Hash) *OrderDifficulty { +func NewOrderDiff(ordersNum int64, diff string) *OrderDifficulty { return &OrderDifficulty{OrdersNum: ordersNum, Difficulty: diff} } @@ -229,8 +229,8 @@ func (evaluator *LinearEvaluator) nextDifficulty(orderCntList []*OrderDifficulty return evaluator.baseDifficulty } else { currentDiff := new(big.Int).Set(evaluator.baseDifficulty) - if currentDiffBytes, err := GetDifficulty(); nil == err { - currentDiff = new(big.Int).SetBytes(currentDiffBytes.Bytes()) + if currentDiffHex, err := GetDifficulty(); nil == err { + currentDiff = types.HexToBigint(currentDiffHex) } addRatio := big.NewInt(3) if nextOrderDiff.OrdersNum > int64(float64(evaluator.threshold)*1.5) { @@ -242,10 +242,10 @@ func (evaluator *LinearEvaluator) nextDifficulty(orderCntList []*OrderDifficulty } } -func GetDifficulty() (common.Hash, error) { +func GetDifficulty() (string, error) { if data, err := cache.Get(OrderDifficultyKey); nil == err { - return common.HexToHash(string(data)), nil + return string(data), nil } else { - return common.Hash{}, err + return "0x0", err } } diff --git a/gateway/order_difficulty/difficulty_test.go b/gateway/order_difficulty/difficulty_test.go index 9dd69d6d..defff98c 100644 --- a/gateway/order_difficulty/difficulty_test.go +++ b/gateway/order_difficulty/difficulty_test.go @@ -24,8 +24,8 @@ import ( "github.com/Loopring/relay-lib/cache" "github.com/Loopring/relay-lib/cache/redis" "github.com/Loopring/relay-lib/log" + "github.com/Loopring/relay-lib/types" "github.com/Loopring/relay-lib/zklock" - "github.com/ethereum/go-ethereum/common" "go.uber.org/zap" "math/big" "testing" @@ -70,14 +70,10 @@ func TestEvaluator(t *testing.T) { func TestLinearEvaluator_CalcAndSaveDifficulty(t *testing.T) { evaluator := order_difficulty.NewLinearEvaluator(big.NewInt(100), 200) cntList := make([]*order_difficulty.OrderDifficulty, 0) - cntList = append(cntList, order_difficulty.NewOrderDiff(100, common.BytesToHash(big.NewInt(100).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(900, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(900, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(400, common.BytesToHash(big.NewInt(200).Bytes()))) - cntList = append(cntList, order_difficulty.NewOrderDiff(600, common.BytesToHash(big.NewInt(200).Bytes()))) + cntList = append(cntList, order_difficulty.NewOrderDiff(100, types.BigintToHex(big.NewInt(100)))) + cntList = append(cntList, order_difficulty.NewOrderDiff(900, types.BigintToHex(big.NewInt(200)))) + cntList = append(cntList, order_difficulty.NewOrderDiff(900, types.BigintToHex(big.NewInt(200)))) + cntList = append(cntList, order_difficulty.NewOrderDiff(400, types.BigintToHex(big.NewInt(200)))) //cntList = append(cntList, order_difficulty.NewOrderDiff(700, common.BytesToHash(big.NewInt(200).Bytes()))) //cntList = append(cntList, order_difficulty.NewOrderDiff(700, common.BytesToHash(big.NewInt(200).Bytes()))) println(evaluator.CalcAndSaveDifficulty(cntList, 10).String()) From 3d8f95539ab19a8a606c83395e0188ca877a863d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=BA=A2=E9=9B=A8?= Date: Fri, 21 Sep 2018 17:07:41 +0800 Subject: [PATCH 8/8] fix compile bug --- gateway/wallet_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/wallet_service.go b/gateway/wallet_service.go index 91892a21..77803e10 100644 --- a/gateway/wallet_service.go +++ b/gateway/wallet_service.go @@ -413,7 +413,7 @@ type AddTokenReq struct { } type OrderDifficultyRes struct { - Difficulty common.Hash `json:"difficulty"` + Difficulty string `json:"difficulty"` } type WalletServiceImpl struct {